1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.g2d.participant;
14 import java.awt.BasicStroke;
15 import java.awt.Color;
16 import java.awt.Cursor;
17 import java.awt.Shape;
18 import java.awt.geom.Path2D;
19 import java.awt.geom.Point2D;
20 import java.awt.geom.Rectangle2D;
22 import org.simantics.g2d.canvas.ICanvasContext;
23 import org.simantics.g2d.canvas.IMouseCursorContext;
24 import org.simantics.g2d.canvas.IMouseCursorHandle;
25 import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;
26 import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
27 import org.simantics.g2d.canvas.impl.SGNodeReflection.SGCleanup;
28 import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;
29 import org.simantics.g2d.diagram.DiagramHints;
30 import org.simantics.g2d.diagram.handler.PickContext;
31 import org.simantics.g2d.diagram.participant.Selection;
32 import org.simantics.g2d.diagram.participant.pointertool.AbstractMode;
33 import org.simantics.g2d.participant.MouseUtil.MouseInfo;
34 import org.simantics.scenegraph.g2d.G2DParentNode;
35 import org.simantics.scenegraph.g2d.events.Event;
36 import org.simantics.scenegraph.g2d.events.MouseEvent;
37 import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;
38 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonEvent;
39 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseClickEvent;
40 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;
41 import org.simantics.scenegraph.g2d.events.command.CommandEvent;
42 import org.simantics.scenegraph.g2d.events.command.Commands;
43 import org.simantics.scenegraph.g2d.nodes.ShapeNode;
44 import org.simantics.utils.ObjectUtils;
45 import org.simantics.utils.page.MarginUtils;
48 * ZoomToAreaHandler starts an area zoom mode when a ZOOM_TO_AREA command is
51 * @author Tuukka Lehtonen
53 public class ZoomToAreaHandler extends AbstractCanvasParticipant {
55 public final static Cursor ZOOM_CURSOR = new Cursor(Cursor.CROSSHAIR_CURSOR);
57 @EventHandler(priority = 0)
58 public boolean handleZoomToArea(CommandEvent event) {
59 if (Commands.ZOOM_TO_AREA.equals( event.command )) {
60 if (!getContext().containsItemByClass(ZoomToAreaMode.class)) {
61 getContext().add( new ZoomToAreaMode() );
69 class ZoomToAreaMode extends AbstractMode {
71 @Dependency TransformUtil util;
72 @Dependency Selection selection;
73 @Dependency PickContext pickContext;
74 @Dependency KeyUtil keyUtil;
75 @Dependency MouseUtil mouseUtil;
76 @Dependency CanvasBoundsParticipant canvasBounds;
78 public final BasicStroke STROKE = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10f, new float[] {4,2}, 0);
80 public static final int PAINT_PRIORITY = 30;
82 Point2D startingPoint;
84 IMouseCursorHandle cursor;
86 public ZoomToAreaMode() {
91 public void addedToContext(ICanvasContext ctx) {
92 super.addedToContext(ctx);
93 IMouseCursorContext mctx = getContext().getMouseCursorContext();
95 cursor = mctx.setCursor(getMouseId(), ZOOM_CURSOR);
96 MouseInfo mi = mouseUtil.getMouseInfo(getMouseId());
98 currentPoint = mi.canvasPosition;
102 public void removedFromContext(ICanvasContext ctx) {
103 if (cursor != null) {
107 super.removedFromContext(ctx);
110 @EventHandler(priority = 10)
111 public boolean handleEvent(Event e) {
112 if (e instanceof CommandEvent) {
113 CommandEvent ce = (CommandEvent) e;
114 if (ce.command.equals( Commands.CANCEL )){
119 } else if (e instanceof MouseMovedEvent) {
120 MouseMovedEvent event = (MouseMovedEvent) e;
121 if (event.mouseId != getMouseId()) return false;
122 Point2D canvasPos = util.controlToCanvas(event.controlPosition, null);
123 if (!ObjectUtils.objectEquals(currentPoint, canvasPos))
125 currentPoint = canvasPos;
130 } else if (e instanceof MouseButtonEvent) {
131 MouseButtonEvent event = (MouseButtonEvent) e;
133 if (event.mouseId != getMouseId()) return false;
134 if (event.button != MouseEvent.LEFT_BUTTON) return false;
136 // Eat all other mouse button events besides press and click.
137 // Must use mouse clicks here because otherwise selection
138 // participants etc. might alter selections on the next incoming
139 // mouse click event, which only confuses the user.
140 if (e instanceof MouseClickEvent) {
141 Point2D canvasPos = util.controlToCanvas(event.controlPosition, null);
142 currentPoint = canvasPos;
144 if (startingPoint == null) {
145 // Start marking the box
146 startingPoint = currentPoint;
151 Rectangle2D area = new Rectangle2D.Double();
152 area.setFrameFromDiagonal(startingPoint, currentPoint);
154 Rectangle2D controlArea = canvasBounds.getControlBounds();
155 util.fitArea(controlArea, area, PanZoomRotateHandler.getZoomToFitMargins(getHintStack()));
167 * Get selection box in control coordinates
168 * @return control coordinates
170 protected Rectangle2D getBox() {
171 if (startingPoint == null)
173 Point2D p1 = startingPoint;
174 Point2D p2 = currentPoint;
175 double ax = p1.getX();
176 double ay = p1.getY();
177 double bx = p2.getX();
178 double by = p2.getY();
189 return new Rectangle2D.Double(ax, ay, bx - ax, by - ay);
192 protected Path2D getCrossHair(Rectangle2D controlBounds) {
193 Point2D controlPos = util.canvasToControl(currentPoint, null);
194 Path2D path = new Path2D.Double();
195 path.moveTo(controlBounds.getMinX(), controlPos.getY());
196 path.lineTo(controlBounds.getMaxX(), controlPos.getY());
197 path.moveTo(controlPos.getX(), controlBounds.getMinY());
198 path.lineTo(controlPos.getX(), controlBounds.getMaxY());
202 public synchronized Color getToolColor()
204 Color c = getHint(DiagramHints.KEY_SELECTION_FRAME_COLOR);
205 if (c!=null) return c;
209 protected ShapeNode node = null;
212 public void initSG(G2DParentNode parent) {
213 node = parent.addNode("zoom to area", ShapeNode.class);
214 node.setZIndex(PAINT_PRIORITY);
215 node.setStroke(STROKE);
216 node.setScaleStroke(true);
217 node.setColor(getToolColor());
221 void update(Shape shape) {
223 node.setShape(shape);
228 public void cleanupSG() {