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 *******************************************************************************/
14 * @author Toni Kalajainen
16 package org.simantics.g2d.participant;
18 import java.awt.Cursor;
19 import java.awt.geom.Point2D;
21 import org.simantics.g2d.canvas.ICanvasContext;
22 import org.simantics.g2d.canvas.IMouseCursorContext;
23 import org.simantics.g2d.canvas.IMouseCursorHandle;
24 import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;
25 import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
26 import org.simantics.g2d.participant.MouseUtil.MouseInfo;
27 import org.simantics.scenegraph.g2d.events.Event;
28 import org.simantics.scenegraph.g2d.events.MouseEvent;
29 import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;
30 import org.simantics.scenegraph.g2d.events.KeyEvent.KeyReleasedEvent;
31 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent;
32 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent;
33 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;
34 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseWheelMovedEvent;
35 import org.simantics.scenegraph.g2d.nodes.NavigationNode;
36 import org.simantics.utils.datastructures.hints.IHintContext.Key;
37 import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;
42 * Keyboard pan & zoom & zoom to fit etc
44 * This interactor depends on : - TransformUtil - MouseUtil - KeyUtil -
45 * PanZoomRotateHandler
47 * TODO Add rotate mode
49 * @deprecated this logic has been moved into scenegraph {@link NavigationNode}.
50 * Using this participant will cause double navigation.
53 public class MousePanZoomInteractor extends AbstractCanvasParticipant {
55 @Dependency TransformUtil util;
56 @Dependency MouseUtil mice;
57 @Dependency KeyUtil keys;
58 @Dependency PanZoomRotateHandler pzr;
60 /** Event priority for initiating pan / zoom */
61 public final static int MOUSE_PAN_PRIORITY = Integer.MAX_VALUE - 2000;
63 /** Event priority when panning is enabled */
64 public final static int PAN_PRIORITY = Integer.MAX_VALUE - 1000;
65 public final static int ZOOM_PRIORITY = Integer.MAX_VALUE - 1000 +1;
67 /** Cursor when panning */
68 public final static Cursor PAN_CURSOR = new Cursor(Cursor.MOVE_CURSOR);
70 /** Cursor when panning */
71 public final static Cursor ZOOM_CURSOR = new Cursor(Cursor.N_RESIZE_CURSOR);
74 public final static Key KEY_MOUSE_PAN_ENABLED = new KeyOf(Boolean.class);
76 /** Is zoom enabled */
77 public final static Key KEY_MOUSE_ZOOM_ENABLED = new KeyOf(Boolean.class);
79 /** are mouse wheel action enabled */
80 public final static Key KEY_MOUSE_WHEEL_ZOOM_PAN_ENABLED = new KeyOf(Boolean.class);
82 /** The speed of mouse zoom , eg 0..100..X */
83 public final static Key KEY_MOUSE_ZOOM_SPEED = new KeyOf(Double.class);
85 /** Default mouse zoom speed */
86 public final static double DEFAULT_MOUSE_ZOOM_SPEED = 100;
88 /** The speed of mouse zoom , eg 0..100..X */
89 public final static Key KEY_MOUSE_WHEEL_ZOOM_SPEED = new KeyOf(Double.class);
91 /** Default mouse zoom speed */
92 public final static double DEFAULT_MOUSE_WHEEL_ZOOM_SPEED = 1000;
94 /** The speed of mouse zoom , eg 0..100..X */
95 public final static Key KEY_MOUSE_WHEEL_TRANSLATE_AMOUNT = new KeyOf(Double.class);
97 /** Default mouse zoom speed */
98 public final static double DEFAULT_MOUSE_WHEEL_TRANSLATE_AMOUNT = 10;
101 public void addedToContext(ICanvasContext ctx) {
102 super.addedToContext(ctx);
103 // Set Default values
104 setHint(KEY_MOUSE_ZOOM_SPEED, DEFAULT_MOUSE_ZOOM_SPEED);
105 setHint(KEY_MOUSE_ZOOM_ENABLED, true);
106 setHint(KEY_MOUSE_PAN_ENABLED, true);
107 setHint(KEY_MOUSE_WHEEL_ZOOM_PAN_ENABLED, true);
108 setHint(KEY_MOUSE_WHEEL_ZOOM_SPEED, DEFAULT_MOUSE_WHEEL_ZOOM_SPEED);
109 setHint(KEY_MOUSE_WHEEL_TRANSLATE_AMOUNT, DEFAULT_MOUSE_WHEEL_TRANSLATE_AMOUNT);
113 * Inits mouse pan and zoom interactors.
114 * Eats mouse presses if shift is pressed.
119 @EventHandler(priority = MOUSE_PAN_PRIORITY)
120 public boolean handleEvent(MouseEvent e) {
121 assertDependencies();
122 if (e.context instanceof MouseUtil)
125 if ((e instanceof MouseButtonPressedEvent) && (e.stateMask & MouseEvent.SHIFT_MASK) != 0 && ((MouseButtonPressedEvent)e).button==MouseEvent.LEFT_BUTTON)
129 if (e instanceof MouseMovedEvent) {
130 MouseMovedEvent mme = (MouseMovedEvent) e;
131 MouseInfo mi = mice.getMouseInfo(mme.mouseId);
134 if ((e.stateMask & MouseEvent.SHIFT_MASK) != 0 & mi.isMouseButtonPressed(MouseEvent.LEFT_BUTTON))
139 getContext().add( new PanMode(mme.mouseId, mme.controlPosition, MouseEvent.LEFT_BUTTON) );
143 if (mi.isMouseButtonPressed(MouseEvent.MIDDLE_BUTTON))
148 getContext().add( new PanMode(mme.mouseId, mme.controlPosition, MouseEvent.MIDDLE_BUTTON) );
152 if ((e.stateMask & MouseEvent.SHIFT_MASK) != 0 & mi.isMouseButtonPressed(MouseEvent.RIGHT_BUTTON))
154 if (!isZoomEnabled())
157 Point2D diagramPosition = util.getInverseTransform().transform(mme.controlPosition, new Point2D.Double());
159 getContext().add( new ZoomMode(mme.mouseId, mme.controlPosition, diagramPosition, MouseEvent.RIGHT_BUTTON) );
165 // Mouse wheel zoom / scroll
166 if (e instanceof MouseWheelMovedEvent) {
167 if (!isMouseWheelZoomPanEnabled())
169 MouseWheelMovedEvent we = (MouseWheelMovedEvent) e;
170 //if (!mm.isMouseButtonPressed(we.mouseId, MouseEvent.MIDDLE_BUTTON))
174 if (we.scrollType == MouseWheelMovedEvent.WHEEL_UNIT_SCROLL)
176 double dy = we.wheelRotation * getMouseWheelTranslateAmount();
178 util.translateWithControlCoordinates(new Point2D.Double(dy, 0));
180 util.translateWithControlCoordinates(new Point2D.Double(0, dy));
186 if (we.scrollType == MouseWheelMovedEvent.WHEEL_UNIT_SCROLL)
188 double dy = we.wheelRotation;
189 double zoom = getMouseWheelZoomSpeed();
190 double base = 1.00 + (zoom / 10000);
191 double scaleFactor = Math.pow(base, dy);
193 scaleFactor = pzr.limitScaleFactor(scaleFactor);
194 util.zoomAroundControlPoint(scaleFactor, we.controlPosition);
195 //ti.zoom(scaleFactor);
203 public boolean isPanEnabled()
205 Boolean h = getHint(KEY_MOUSE_PAN_ENABLED);
206 if (h==null) return false;
210 public boolean isPanning()
212 return !getContext().getItemsByClass(PanMode.class).isEmpty();
215 public boolean isZooming()
217 return !getContext().getItemsByClass(ZoomMode.class).isEmpty();
220 public boolean isZoomEnabled()
222 Boolean h = getHint(KEY_MOUSE_ZOOM_ENABLED);
223 if (h==null) return false;
227 public boolean isMouseWheelZoomPanEnabled()
229 Boolean h = getHint(KEY_MOUSE_WHEEL_ZOOM_PAN_ENABLED);
230 if (h==null) return false;
238 /*public boolean shift()
240 return keys.isKeyPressed(KeyEvent.VK_SHIFT);
243 public boolean ctrl()
245 return keys.isKeyPressed(KeyEvent.VK_CONTROL);
248 public double getMouseZoomSpeed()
250 Double h = getHint(KEY_MOUSE_ZOOM_SPEED);
251 if (h==null) return DEFAULT_MOUSE_ZOOM_SPEED;
255 public double getMouseWheelZoomSpeed()
257 Double h = getHint(KEY_MOUSE_WHEEL_ZOOM_SPEED);
258 if (h==null) return DEFAULT_MOUSE_WHEEL_ZOOM_SPEED;
262 public double getMouseWheelTranslateAmount()
264 Double h = getHint(KEY_MOUSE_WHEEL_TRANSLATE_AMOUNT);
265 if (h==null) return DEFAULT_MOUSE_WHEEL_TRANSLATE_AMOUNT;
270 * Shift and left mouse button is pressed, do panning
272 class PanMode extends AbstractCanvasParticipant
274 @Dependency TransformUtil util;
277 // Mouse system coordinates
279 IMouseCursorHandle cursor;
281 public PanMode(int mouseId, Point2D mousePos, int releaseButton) {
283 this.mouseId = mouseId;
284 this.mousePos = new Point2D.Double(mousePos.getX(), mousePos.getY());
285 this.releaseButton = releaseButton;
289 public void addedToContext(ICanvasContext ctx) {
290 super.addedToContext(ctx);
291 IMouseCursorContext mctx = getContext().getMouseCursorContext();
293 cursor = mctx.setCursor(mouseId, PAN_CURSOR);
296 @EventHandler(priority = PAN_PRIORITY)
297 public boolean handleEvent(Event e) {
298 if (e instanceof MouseButtonReleasedEvent) {
299 MouseButtonReleasedEvent mpe = (MouseButtonReleasedEvent) e;
300 if (mpe.button == releaseButton && mpe.mouseId == mouseId)
307 if (e instanceof KeyReleasedEvent) {
308 KeyReleasedEvent ke = (KeyReleasedEvent) e;
309 if (ke.keyCode == java.awt.event.KeyEvent.VK_SHIFT)
316 if (e instanceof MouseMovedEvent) {
317 if (e.getContext() instanceof MouseUtil) return true;
318 MouseMovedEvent mme = (MouseMovedEvent) e;
319 if (mme.mouseId == mouseId) {
320 Point2D oldPos = mousePos;
321 Point2D newPos = mme.controlPosition;
323 double dx = newPos.getX() - oldPos.getX();
324 double dy = newPos.getY() - oldPos.getY();
325 if (dx==0 && dy==0) return true;
327 this.mousePos.setLocation(newPos);
329 util.translateWithControlCoordinates(new Point2D.Double(dx, dy));
338 public void removedFromContext(ICanvasContext ctx) {
343 super.removedFromContext(ctx);
349 * Shift and right mouse button is pressed, do zooming
351 class ZoomMode extends AbstractCanvasParticipant
356 // Mouse system coordinates
357 Point2D prevMousePos;
358 Point2D origControlMousePos;
359 Point2D origDiagramMousePos;
360 IMouseCursorHandle cursor;
362 public ZoomMode(int mouseId, Point2D controlMousePos, Point2D mouseDiagramPos, int releaseButton) {
364 this.mouseId = mouseId;
365 this.prevMousePos = (Point2D) controlMousePos.clone();
366 this.origControlMousePos = (Point2D) controlMousePos.clone();
367 this.origDiagramMousePos = (Point2D) mouseDiagramPos.clone();
368 this.releaseButton = releaseButton;
372 public void addedToContext(ICanvasContext ctx) {
373 super.addedToContext(ctx);
374 IMouseCursorContext mctx = getContext().getMouseCursorContext();
376 cursor = mctx.setCursor(mouseId, ZOOM_CURSOR);
379 @EventHandler(priority = ZOOM_PRIORITY)
380 public boolean handleEvent(Event e) {
381 if (e instanceof MouseButtonReleasedEvent) {
382 MouseButtonReleasedEvent mpe = (MouseButtonReleasedEvent) e;
383 if (mpe.button == releaseButton && mpe.mouseId == mouseId)
390 if (e instanceof KeyReleasedEvent) {
391 KeyReleasedEvent ke = (KeyReleasedEvent) e;
392 if (ke.keyCode == java.awt.event.KeyEvent.VK_SHIFT)
399 if (e instanceof MouseMovedEvent) {
400 if (e.getContext() instanceof MouseUtil) return true;
401 MouseMovedEvent mme = (MouseMovedEvent) e;
402 if (mme.mouseId == mouseId) {
403 Point2D oldPos = prevMousePos;
404 Point2D newPos = mme.controlPosition;
406 double dy = newPos.getY() - oldPos.getY();
407 // double dx = newPos.getX() - oldPos.getX();
408 this.prevMousePos.setLocation(newPos);
410 double zoomSpeed = getMouseZoomSpeed();
411 double base = 1.00 + (zoomSpeed / 10000);
412 double scaleFactor = Math.pow(base, -dy);
414 scaleFactor = pzr.limitScaleFactor(scaleFactor);
415 util.zoomAroundDiagramPoint(scaleFactor, origDiagramMousePos);
424 public void removedFromContext(ICanvasContext ctx) {
430 super.removedFromContext(ctx);