]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/participant/ZoomToAreaHandler.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / participant / ZoomToAreaHandler.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.g2d.participant;\r
13 \r
14 import java.awt.BasicStroke;\r
15 import java.awt.Color;\r
16 import java.awt.Cursor;\r
17 import java.awt.Shape;\r
18 import java.awt.geom.Path2D;\r
19 import java.awt.geom.Point2D;\r
20 import java.awt.geom.Rectangle2D;\r
21 \r
22 import org.simantics.g2d.canvas.ICanvasContext;\r
23 import org.simantics.g2d.canvas.IMouseCursorContext;\r
24 import org.simantics.g2d.canvas.IMouseCursorHandle;\r
25 import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;\r
26 import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;\r
27 import org.simantics.g2d.canvas.impl.SGNodeReflection.SGCleanup;\r
28 import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;\r
29 import org.simantics.g2d.diagram.DiagramHints;\r
30 import org.simantics.g2d.diagram.handler.PickContext;\r
31 import org.simantics.g2d.diagram.participant.Selection;\r
32 import org.simantics.g2d.diagram.participant.pointertool.AbstractMode;\r
33 import org.simantics.g2d.participant.MouseUtil.MouseInfo;\r
34 import org.simantics.scenegraph.g2d.G2DParentNode;\r
35 import org.simantics.scenegraph.g2d.events.Event;\r
36 import org.simantics.scenegraph.g2d.events.MouseEvent;\r
37 import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;\r
38 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonEvent;\r
39 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseClickEvent;\r
40 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;\r
41 import org.simantics.scenegraph.g2d.events.command.CommandEvent;\r
42 import org.simantics.scenegraph.g2d.events.command.Commands;\r
43 import org.simantics.scenegraph.g2d.nodes.ShapeNode;\r
44 import org.simantics.utils.ObjectUtils;\r
45 import org.simantics.utils.page.MarginUtils;\r
46 \r
47 /**\r
48  * ZoomToAreaHandler starts an area zoom mode when a ZOOM_TO_AREA command is\r
49  * issued.\r
50  *\r
51  * @author Tuukka Lehtonen\r
52  */\r
53 public class ZoomToAreaHandler extends AbstractCanvasParticipant {\r
54 \r
55     public final static Cursor ZOOM_CURSOR = new Cursor(Cursor.CROSSHAIR_CURSOR);\r
56 \r
57     @EventHandler(priority = 0)\r
58     public boolean handleZoomToArea(CommandEvent event) {\r
59         if (Commands.ZOOM_TO_AREA.equals( event.command )) {\r
60             if (!getContext().containsItemByClass(ZoomToAreaMode.class)) {\r
61                 getContext().add( new ZoomToAreaMode() );\r
62                 setDirty();\r
63             }\r
64             return true;\r
65         }\r
66         return false;\r
67     }\r
68 \r
69     class ZoomToAreaMode extends AbstractMode {\r
70 \r
71         @Dependency TransformUtil util;\r
72         @Dependency Selection selection;\r
73         @Dependency PickContext pickContext;\r
74         @Dependency KeyUtil keyUtil;\r
75         @Dependency MouseUtil mouseUtil;\r
76         @Dependency CanvasBoundsParticipant canvasBounds;\r
77 \r
78         public final BasicStroke STROKE = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10f, new float[] {4,2}, 0);\r
79 \r
80         public static final int PAINT_PRIORITY = 30;\r
81 \r
82         Point2D startingPoint;\r
83         Point2D currentPoint;\r
84         IMouseCursorHandle cursor;\r
85 \r
86         public ZoomToAreaMode() {\r
87             super(0);\r
88         }\r
89 \r
90         @Override\r
91         public void addedToContext(ICanvasContext ctx) {\r
92             super.addedToContext(ctx);\r
93             IMouseCursorContext mctx = getContext().getMouseCursorContext();\r
94             if (mctx != null)\r
95                 cursor = mctx.setCursor(getMouseId(), ZOOM_CURSOR);\r
96             MouseInfo mi = mouseUtil.getMouseInfo(getMouseId());\r
97             if (mi != null)\r
98                 currentPoint = mi.canvasPosition;\r
99         }\r
100 \r
101         @Override\r
102         public void removedFromContext(ICanvasContext ctx) {\r
103             if (cursor != null) {\r
104                 cursor.remove();\r
105                 cursor = null;\r
106             }\r
107             super.removedFromContext(ctx);\r
108         }\r
109 \r
110         @EventHandler(priority = 10)\r
111         public boolean handleEvent(Event e) {\r
112             if (e instanceof CommandEvent) {\r
113                 CommandEvent ce = (CommandEvent) e;\r
114                 if (ce.command.equals( Commands.CANCEL )){\r
115                     setDirty();\r
116                     remove();\r
117                     return true;\r
118                 }\r
119             } else if (e instanceof MouseMovedEvent) {\r
120                 MouseMovedEvent event = (MouseMovedEvent) e;\r
121                 if (event.mouseId != getMouseId()) return false;\r
122                 Point2D canvasPos = util.controlToCanvas(event.controlPosition, null);\r
123                 if (!ObjectUtils.objectEquals(currentPoint, canvasPos))\r
124                 {\r
125                     currentPoint = canvasPos;\r
126                     update(getBox());\r
127                     setDirty();\r
128                 }\r
129                 return false;\r
130             } else if (e instanceof MouseButtonEvent) {\r
131                 MouseButtonEvent event = (MouseButtonEvent) e;\r
132 \r
133                 if (event.mouseId != getMouseId()) return false;\r
134                 if (event.button != MouseEvent.LEFT_BUTTON) return false;\r
135 \r
136                 // Eat all other mouse button events besides press and click.\r
137                 // Must use mouse clicks here because otherwise selection\r
138                 // participants etc. might alter selections on the next incoming\r
139                 // mouse click event, which only confuses the user.\r
140                 if (e instanceof MouseClickEvent) {\r
141                     Point2D canvasPos = util.controlToCanvas(event.controlPosition, null);\r
142                     currentPoint = canvasPos;\r
143 \r
144                     if (startingPoint == null) {\r
145                         // Start marking the box\r
146                         startingPoint = currentPoint;\r
147                         setDirty();\r
148                         return true;\r
149                     }\r
150 \r
151                     Rectangle2D area = new Rectangle2D.Double();\r
152                     area.setFrameFromDiagonal(startingPoint, currentPoint);\r
153 \r
154                     Rectangle2D controlArea = canvasBounds.getControlBounds();\r
155                     util.fitArea(controlArea, area, PanZoomRotateHandler.getZoomToFitMargins(getHintStack()));\r
156 \r
157                     setDirty();\r
158                     remove();\r
159                     return true;\r
160                 }\r
161                 return true;\r
162             }\r
163             return false;\r
164         }\r
165 \r
166         /**\r
167          * Get selection box in control coordinates\r
168          * @return control coordinates\r
169          */\r
170         protected Rectangle2D getBox() {\r
171             if (startingPoint == null)\r
172                 return null;\r
173             Point2D p1 = startingPoint;\r
174             Point2D p2 = currentPoint;\r
175             double ax = p1.getX();\r
176             double ay = p1.getY();\r
177             double bx = p2.getX();\r
178             double by = p2.getY();\r
179             if (bx < ax) {\r
180                 double temp = ax;\r
181                 ax = bx;\r
182                 bx = temp;\r
183             }\r
184             if (by < ay) {\r
185                 double temp = ay;\r
186                 ay = by;\r
187                 by = temp;\r
188             }\r
189             return new Rectangle2D.Double(ax, ay, bx - ax, by - ay);\r
190         }\r
191 \r
192         protected Path2D getCrossHair(Rectangle2D controlBounds) {\r
193             Point2D controlPos = util.canvasToControl(currentPoint, null);\r
194             Path2D path = new Path2D.Double();\r
195             path.moveTo(controlBounds.getMinX(), controlPos.getY());\r
196             path.lineTo(controlBounds.getMaxX(), controlPos.getY());\r
197             path.moveTo(controlPos.getX(), controlBounds.getMinY());\r
198             path.lineTo(controlPos.getX(), controlBounds.getMaxY());\r
199             return path;\r
200         }\r
201 \r
202         public synchronized Color getToolColor()\r
203         {\r
204             Color c = getHint(DiagramHints.KEY_SELECTION_FRAME_COLOR);\r
205             if (c!=null) return c;\r
206             return Color.BLACK;\r
207         }\r
208 \r
209         protected ShapeNode node = null;\r
210 \r
211         @SGInit\r
212         public void initSG(G2DParentNode parent) {\r
213             node = parent.addNode("zoom to area", ShapeNode.class);\r
214             node.setZIndex(PAINT_PRIORITY);\r
215             node.setStroke(STROKE);\r
216             node.setScaleStroke(true);\r
217             node.setColor(getToolColor());\r
218             node.setFill(false);\r
219         }\r
220 \r
221         void update(Shape shape) {\r
222             if (node != null) {\r
223                 node.setShape(shape);\r
224             }\r
225         }\r
226 \r
227         @SGCleanup\r
228         public void cleanupSG() {\r
229             if (node != null) {\r
230                 node.remove();\r
231                 node = null;\r
232             }\r
233         }\r
234     }\r
235 \r
236 }\r