]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/participant/MousePanZoomInteractor.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / participant / MousePanZoomInteractor.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 /*\r
13  *\r
14  * @author Toni Kalajainen\r
15  */\r
16 package org.simantics.g2d.participant;\r
17 \r
18 import java.awt.Cursor;\r
19 import java.awt.geom.Point2D;\r
20 \r
21 import org.simantics.g2d.canvas.ICanvasContext;\r
22 import org.simantics.g2d.canvas.IMouseCursorContext;\r
23 import org.simantics.g2d.canvas.IMouseCursorHandle;\r
24 import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;\r
25 import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;\r
26 import org.simantics.g2d.participant.MouseUtil.MouseInfo;\r
27 import org.simantics.scenegraph.g2d.events.Event;\r
28 import org.simantics.scenegraph.g2d.events.MouseEvent;\r
29 import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;\r
30 import org.simantics.scenegraph.g2d.events.KeyEvent.KeyReleasedEvent;\r
31 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent;\r
32 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent;\r
33 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;\r
34 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseWheelMovedEvent;\r
35 import org.simantics.scenegraph.g2d.nodes.NavigationNode;\r
36 import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
37 import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;\r
38 \r
39 /**\r
40  * Mouse pan & zoom\r
41  * \r
42  * Keyboard pan & zoom & zoom to fit etc\r
43  * \r
44  * This interactor depends on : - TransformUtil - MouseUtil - KeyUtil -\r
45  * PanZoomRotateHandler\r
46  * \r
47  * TODO Add rotate mode\r
48  * \r
49  * @deprecated this logic has been moved into scenegraph {@link NavigationNode}.\r
50  *             Using this participant will cause double navigation.\r
51  */\r
52 @Deprecated\r
53 public class MousePanZoomInteractor extends AbstractCanvasParticipant {\r
54 \r
55     @Dependency TransformUtil util;\r
56     @Dependency MouseUtil mice;\r
57     @Dependency KeyUtil keys;\r
58     @Dependency PanZoomRotateHandler pzr;\r
59 \r
60     /** Event priority for initiating pan / zoom */\r
61     public final static int MOUSE_PAN_PRIORITY = Integer.MAX_VALUE - 2000;\r
62 \r
63     /** Event priority when panning is enabled */\r
64     public final static int PAN_PRIORITY = Integer.MAX_VALUE - 1000;\r
65     public final static int ZOOM_PRIORITY = Integer.MAX_VALUE - 1000 +1;\r
66 \r
67     /** Cursor when panning */\r
68     public final static Cursor PAN_CURSOR = new Cursor(Cursor.MOVE_CURSOR);\r
69 \r
70     /** Cursor when panning */\r
71     public final static Cursor ZOOM_CURSOR = new Cursor(Cursor.N_RESIZE_CURSOR);\r
72 \r
73     /** Is pan enabled */\r
74     public final static Key KEY_MOUSE_PAN_ENABLED = new KeyOf(Boolean.class);\r
75 \r
76     /** Is zoom enabled */\r
77     public final static Key KEY_MOUSE_ZOOM_ENABLED = new KeyOf(Boolean.class);\r
78 \r
79     /** are mouse wheel action enabled */\r
80     public final static Key KEY_MOUSE_WHEEL_ZOOM_PAN_ENABLED = new KeyOf(Boolean.class);\r
81 \r
82     /** The speed of mouse zoom , eg 0..100..X */\r
83     public final static Key KEY_MOUSE_ZOOM_SPEED = new KeyOf(Double.class);\r
84 \r
85     /** Default mouse zoom speed */\r
86     public final static double DEFAULT_MOUSE_ZOOM_SPEED = 100;\r
87 \r
88     /** The speed of mouse zoom , eg 0..100..X */\r
89     public final static Key KEY_MOUSE_WHEEL_ZOOM_SPEED = new KeyOf(Double.class);\r
90 \r
91     /** Default mouse zoom speed */\r
92     public final static double DEFAULT_MOUSE_WHEEL_ZOOM_SPEED = 1000;\r
93 \r
94     /** The speed of mouse zoom , eg 0..100..X */\r
95     public final static Key KEY_MOUSE_WHEEL_TRANSLATE_AMOUNT = new KeyOf(Double.class);\r
96 \r
97     /** Default mouse zoom speed */\r
98     public final static double DEFAULT_MOUSE_WHEEL_TRANSLATE_AMOUNT = 10;\r
99 \r
100     @Override\r
101     public void addedToContext(ICanvasContext ctx) {\r
102         super.addedToContext(ctx);\r
103         // Set Default values\r
104         setHint(KEY_MOUSE_ZOOM_SPEED, DEFAULT_MOUSE_ZOOM_SPEED);\r
105         setHint(KEY_MOUSE_ZOOM_ENABLED, true);\r
106         setHint(KEY_MOUSE_PAN_ENABLED, true);\r
107         setHint(KEY_MOUSE_WHEEL_ZOOM_PAN_ENABLED, true);\r
108         setHint(KEY_MOUSE_WHEEL_ZOOM_SPEED, DEFAULT_MOUSE_WHEEL_ZOOM_SPEED);\r
109         setHint(KEY_MOUSE_WHEEL_TRANSLATE_AMOUNT, DEFAULT_MOUSE_WHEEL_TRANSLATE_AMOUNT);\r
110     }\r
111 \r
112     /**\r
113      * Inits mouse pan and zoom interactors.\r
114      * Eats mouse presses if shift is pressed.\r
115      * \r
116      * @param e\r
117      * @return\r
118      */\r
119     @EventHandler(priority = MOUSE_PAN_PRIORITY)\r
120     public boolean handleEvent(MouseEvent e) {\r
121         assertDependencies();\r
122         if (e.context instanceof MouseUtil)\r
123             return false;\r
124 \r
125         if ((e instanceof MouseButtonPressedEvent) && (e.stateMask & MouseEvent.SHIFT_MASK) != 0 && ((MouseButtonPressedEvent)e).button==MouseEvent.LEFT_BUTTON)\r
126             return true;\r
127 \r
128         // Mouse pan & zoom\r
129         if (e instanceof MouseMovedEvent) {\r
130             MouseMovedEvent mme = (MouseMovedEvent) e;\r
131             MouseInfo mi = mice.getMouseInfo(mme.mouseId);\r
132             if (mi == null)\r
133                 return false;\r
134             if ((e.stateMask & MouseEvent.SHIFT_MASK) != 0 & mi.isMouseButtonPressed(MouseEvent.LEFT_BUTTON))\r
135             {\r
136                 if (!isPanEnabled())\r
137                     return false;\r
138                 if (!isPanning()) {\r
139                     getContext().add( new PanMode(mme.mouseId, mme.controlPosition, MouseEvent.LEFT_BUTTON) );\r
140                 }\r
141                 return true;\r
142             }\r
143             if (mi.isMouseButtonPressed(MouseEvent.MIDDLE_BUTTON))\r
144             {\r
145                 if (!isPanEnabled())\r
146                     return false;\r
147                 if (!isPanning()) {\r
148                     getContext().add( new PanMode(mme.mouseId, mme.controlPosition, MouseEvent.MIDDLE_BUTTON) );\r
149                 }\r
150                 return true;\r
151             }\r
152             if ((e.stateMask & MouseEvent.SHIFT_MASK) != 0 & mi.isMouseButtonPressed(MouseEvent.RIGHT_BUTTON))\r
153             {\r
154                 if (!isZoomEnabled())\r
155                     return false;\r
156                 if (!isZooming()) {\r
157                     Point2D diagramPosition = util.getInverseTransform().transform(mme.controlPosition, new Point2D.Double());\r
158 \r
159                     getContext().add( new ZoomMode(mme.mouseId, mme.controlPosition, diagramPosition, MouseEvent.RIGHT_BUTTON) );\r
160                 }\r
161                 return true;\r
162             }\r
163         }\r
164 \r
165         // Mouse wheel zoom / scroll\r
166         if (e instanceof MouseWheelMovedEvent) {\r
167             if (!isMouseWheelZoomPanEnabled())\r
168                 return false;\r
169             MouseWheelMovedEvent we = (MouseWheelMovedEvent) e;\r
170             //if (!mm.isMouseButtonPressed(we.mouseId, MouseEvent.MIDDLE_BUTTON))\r
171             /*\r
172             if (!ctrl())\r
173                         {\r
174                                 if (we.scrollType == MouseWheelMovedEvent.WHEEL_UNIT_SCROLL)\r
175                                 {\r
176                                         double dy = we.wheelRotation * getMouseWheelTranslateAmount();\r
177                                         if (shift())\r
178                                                 util.translateWithControlCoordinates(new Point2D.Double(dy, 0));\r
179                                         else\r
180                                                 util.translateWithControlCoordinates(new Point2D.Double(0, dy));\r
181                                         return true;\r
182                                 }\r
183                         } else\r
184              */\r
185             {\r
186                 if (we.scrollType == MouseWheelMovedEvent.WHEEL_UNIT_SCROLL)\r
187                 {\r
188                     double dy = we.wheelRotation;\r
189                     double zoom = getMouseWheelZoomSpeed();\r
190                     double base = 1.00 + (zoom / 10000);\r
191                     double scaleFactor = Math.pow(base, dy);\r
192 \r
193                     scaleFactor = pzr.limitScaleFactor(scaleFactor);\r
194                     util.zoomAroundControlPoint(scaleFactor, we.controlPosition);\r
195                     //ti.zoom(scaleFactor);\r
196                     return true;\r
197                 }\r
198             }\r
199         }\r
200         return false;\r
201     }\r
202 \r
203     public boolean isPanEnabled()\r
204     {\r
205         Boolean h = getHint(KEY_MOUSE_PAN_ENABLED);\r
206         if (h==null) return false;\r
207         return h;\r
208     }\r
209 \r
210     public boolean isPanning()\r
211     {\r
212         return !getContext().getItemsByClass(PanMode.class).isEmpty();\r
213     }\r
214 \r
215     public boolean isZooming()\r
216     {\r
217         return !getContext().getItemsByClass(ZoomMode.class).isEmpty();\r
218     }\r
219 \r
220     public boolean isZoomEnabled()\r
221     {\r
222         Boolean h = getHint(KEY_MOUSE_ZOOM_ENABLED);\r
223         if (h==null) return false;\r
224         return h;\r
225     }\r
226 \r
227     public boolean isMouseWheelZoomPanEnabled()\r
228     {\r
229         Boolean h = getHint(KEY_MOUSE_WHEEL_ZOOM_PAN_ENABLED);\r
230         if (h==null) return false;\r
231         return h;\r
232     }\r
233 \r
234     /**\r
235      * is Shift key down\r
236      * @return\r
237      */\r
238     /*public boolean shift()\r
239         {\r
240                 return keys.isKeyPressed(KeyEvent.VK_SHIFT);\r
241         }\r
242 \r
243         public boolean ctrl()\r
244         {\r
245                 return keys.isKeyPressed(KeyEvent.VK_CONTROL);\r
246         }*/\r
247 \r
248     public double getMouseZoomSpeed()\r
249     {\r
250         Double h = getHint(KEY_MOUSE_ZOOM_SPEED);\r
251         if (h==null) return DEFAULT_MOUSE_ZOOM_SPEED;\r
252         return h;\r
253     }\r
254 \r
255     public double getMouseWheelZoomSpeed()\r
256     {\r
257         Double h = getHint(KEY_MOUSE_WHEEL_ZOOM_SPEED);\r
258         if (h==null) return DEFAULT_MOUSE_WHEEL_ZOOM_SPEED;\r
259         return h;\r
260     }\r
261 \r
262     public double getMouseWheelTranslateAmount()\r
263     {\r
264         Double h = getHint(KEY_MOUSE_WHEEL_TRANSLATE_AMOUNT);\r
265         if (h==null) return DEFAULT_MOUSE_WHEEL_TRANSLATE_AMOUNT;\r
266         return h;\r
267     }\r
268 \r
269     /**\r
270      * Shift and left mouse button is pressed, do panning\r
271      */\r
272     class PanMode extends AbstractCanvasParticipant\r
273     {\r
274         @Dependency TransformUtil util;\r
275         final int mouseId;\r
276         int releaseButton;\r
277         // Mouse system coordinates\r
278         Point2D mousePos;\r
279         IMouseCursorHandle cursor;\r
280 \r
281         public PanMode(int mouseId, Point2D mousePos, int releaseButton) {\r
282             super();\r
283             this.mouseId = mouseId;\r
284             this.mousePos = new Point2D.Double(mousePos.getX(), mousePos.getY());\r
285             this.releaseButton = releaseButton;\r
286         }\r
287 \r
288         @Override\r
289         public void addedToContext(ICanvasContext ctx) {\r
290             super.addedToContext(ctx);\r
291             IMouseCursorContext mctx = getContext().getMouseCursorContext();\r
292             if (mctx!=null)\r
293                 cursor = mctx.setCursor(mouseId, PAN_CURSOR);\r
294         }\r
295 \r
296         @EventHandler(priority = PAN_PRIORITY)\r
297         public boolean handleEvent(Event e) {\r
298             if (e instanceof MouseButtonReleasedEvent) {\r
299                 MouseButtonReleasedEvent mpe = (MouseButtonReleasedEvent) e;\r
300                 if (mpe.button == releaseButton && mpe.mouseId == mouseId)\r
301                 {\r
302                     remove();\r
303                     return false;\r
304                 }\r
305             }\r
306 \r
307             if (e instanceof KeyReleasedEvent) {\r
308                 KeyReleasedEvent ke = (KeyReleasedEvent) e;\r
309                 if (ke.keyCode == java.awt.event.KeyEvent.VK_SHIFT)\r
310                 {\r
311                     remove();\r
312                     return false;\r
313                 }\r
314             }\r
315 \r
316             if (e instanceof MouseMovedEvent) {\r
317                 if (e.getContext() instanceof MouseUtil) return true;\r
318                 MouseMovedEvent mme = (MouseMovedEvent) e;\r
319                 if (mme.mouseId == mouseId) {\r
320                     Point2D oldPos = mousePos;\r
321                     Point2D newPos = mme.controlPosition;\r
322 \r
323                     double dx = newPos.getX() - oldPos.getX();\r
324                     double dy = newPos.getY() - oldPos.getY();\r
325                     if (dx==0 && dy==0) return true;\r
326 \r
327                     this.mousePos.setLocation(newPos);\r
328 \r
329                     util.translateWithControlCoordinates(new Point2D.Double(dx, dy));\r
330                     return true;\r
331                 }\r
332             }\r
333 \r
334             return false;\r
335         }\r
336 \r
337         @Override\r
338         public void removedFromContext(ICanvasContext ctx) {\r
339             if (cursor!=null) {\r
340                 cursor.remove();\r
341                 cursor = null;\r
342             }\r
343             super.removedFromContext(ctx);\r
344         }\r
345 \r
346     }\r
347 \r
348     /**\r
349      * Shift and right mouse button is pressed, do zooming\r
350      */\r
351     class ZoomMode extends AbstractCanvasParticipant\r
352     {\r
353         final int mouseId;\r
354         int releaseButton;\r
355 \r
356         // Mouse system coordinates\r
357         Point2D prevMousePos;\r
358         Point2D origControlMousePos;\r
359         Point2D origDiagramMousePos;\r
360         IMouseCursorHandle cursor;\r
361 \r
362         public ZoomMode(int mouseId, Point2D controlMousePos, Point2D mouseDiagramPos, int releaseButton) {\r
363             super();\r
364             this.mouseId = mouseId;\r
365             this.prevMousePos = (Point2D) controlMousePos.clone();\r
366             this.origControlMousePos = (Point2D) controlMousePos.clone();\r
367             this.origDiagramMousePos = (Point2D) mouseDiagramPos.clone();\r
368             this.releaseButton = releaseButton;\r
369         }\r
370 \r
371         @Override\r
372         public void addedToContext(ICanvasContext ctx) {\r
373             super.addedToContext(ctx);\r
374             IMouseCursorContext mctx = getContext().getMouseCursorContext();\r
375             if (mctx!=null)\r
376                 cursor = mctx.setCursor(mouseId, ZOOM_CURSOR);\r
377         }\r
378 \r
379         @EventHandler(priority = ZOOM_PRIORITY)\r
380         public boolean handleEvent(Event e) {\r
381             if (e instanceof MouseButtonReleasedEvent) {\r
382                 MouseButtonReleasedEvent mpe = (MouseButtonReleasedEvent) e;\r
383                 if (mpe.button == releaseButton && mpe.mouseId == mouseId)\r
384                 {\r
385                     remove();\r
386                     return false;\r
387                 }\r
388             }\r
389 \r
390             if (e instanceof KeyReleasedEvent) {\r
391                 KeyReleasedEvent ke = (KeyReleasedEvent) e;\r
392                 if (ke.keyCode == java.awt.event.KeyEvent.VK_SHIFT)\r
393                 {\r
394                     remove();\r
395                     return false;\r
396                 }\r
397             }\r
398 \r
399             if (e instanceof MouseMovedEvent) {\r
400                 if (e.getContext() instanceof MouseUtil) return true;\r
401                 MouseMovedEvent mme = (MouseMovedEvent) e;\r
402                 if (mme.mouseId == mouseId) {\r
403                     Point2D oldPos = prevMousePos;\r
404                     Point2D newPos = mme.controlPosition;\r
405 \r
406                     double dy = newPos.getY() - oldPos.getY();\r
407 //                                      double dx = newPos.getX() - oldPos.getX();\r
408                     this.prevMousePos.setLocation(newPos);\r
409 \r
410                     double zoomSpeed = getMouseZoomSpeed();\r
411                     double base = 1.00 + (zoomSpeed / 10000);\r
412                     double scaleFactor = Math.pow(base, -dy);\r
413 \r
414                     scaleFactor = pzr.limitScaleFactor(scaleFactor);\r
415                     util.zoomAroundDiagramPoint(scaleFactor, origDiagramMousePos);\r
416                     return true;\r
417                 }\r
418             }\r
419 \r
420             return false;\r
421         }\r
422 \r
423         @Override\r
424         public void removedFromContext(ICanvasContext ctx) {\r
425             if (cursor!=null) {\r
426                 cursor.remove();\r
427                 cursor = null;\r
428             }\r
429 \r
430             super.removedFromContext(ctx);\r
431         }\r
432     }\r
433 \r
434 }\r