--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+/*\r
+ *\r
+ * @author Toni Kalajainen\r
+ */\r
+package org.simantics.g2d.participant;\r
+\r
+import java.awt.Cursor;\r
+import java.awt.geom.Point2D;\r
+\r
+import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.g2d.canvas.IMouseCursorContext;\r
+import org.simantics.g2d.canvas.IMouseCursorHandle;\r
+import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;\r
+import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;\r
+import org.simantics.g2d.participant.MouseUtil.MouseInfo;\r
+import org.simantics.scenegraph.g2d.events.Event;\r
+import org.simantics.scenegraph.g2d.events.MouseEvent;\r
+import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;\r
+import org.simantics.scenegraph.g2d.events.KeyEvent.KeyReleasedEvent;\r
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent;\r
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent;\r
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;\r
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseWheelMovedEvent;\r
+import org.simantics.scenegraph.g2d.nodes.NavigationNode;\r
+import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
+import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;\r
+\r
+/**\r
+ * Mouse pan & zoom\r
+ * \r
+ * Keyboard pan & zoom & zoom to fit etc\r
+ * \r
+ * This interactor depends on : - TransformUtil - MouseUtil - KeyUtil -\r
+ * PanZoomRotateHandler\r
+ * \r
+ * TODO Add rotate mode\r
+ * \r
+ * @deprecated this logic has been moved into scenegraph {@link NavigationNode}.\r
+ * Using this participant will cause double navigation.\r
+ */\r
+@Deprecated\r
+public class MousePanZoomInteractor extends AbstractCanvasParticipant {\r
+\r
+ @Dependency TransformUtil util;\r
+ @Dependency MouseUtil mice;\r
+ @Dependency KeyUtil keys;\r
+ @Dependency PanZoomRotateHandler pzr;\r
+\r
+ /** Event priority for initiating pan / zoom */\r
+ public final static int MOUSE_PAN_PRIORITY = Integer.MAX_VALUE - 2000;\r
+\r
+ /** Event priority when panning is enabled */\r
+ public final static int PAN_PRIORITY = Integer.MAX_VALUE - 1000;\r
+ public final static int ZOOM_PRIORITY = Integer.MAX_VALUE - 1000 +1;\r
+\r
+ /** Cursor when panning */\r
+ public final static Cursor PAN_CURSOR = new Cursor(Cursor.MOVE_CURSOR);\r
+\r
+ /** Cursor when panning */\r
+ public final static Cursor ZOOM_CURSOR = new Cursor(Cursor.N_RESIZE_CURSOR);\r
+\r
+ /** Is pan enabled */\r
+ public final static Key KEY_MOUSE_PAN_ENABLED = new KeyOf(Boolean.class);\r
+\r
+ /** Is zoom enabled */\r
+ public final static Key KEY_MOUSE_ZOOM_ENABLED = new KeyOf(Boolean.class);\r
+\r
+ /** are mouse wheel action enabled */\r
+ public final static Key KEY_MOUSE_WHEEL_ZOOM_PAN_ENABLED = new KeyOf(Boolean.class);\r
+\r
+ /** The speed of mouse zoom , eg 0..100..X */\r
+ public final static Key KEY_MOUSE_ZOOM_SPEED = new KeyOf(Double.class);\r
+\r
+ /** Default mouse zoom speed */\r
+ public final static double DEFAULT_MOUSE_ZOOM_SPEED = 100;\r
+\r
+ /** The speed of mouse zoom , eg 0..100..X */\r
+ public final static Key KEY_MOUSE_WHEEL_ZOOM_SPEED = new KeyOf(Double.class);\r
+\r
+ /** Default mouse zoom speed */\r
+ public final static double DEFAULT_MOUSE_WHEEL_ZOOM_SPEED = 1000;\r
+\r
+ /** The speed of mouse zoom , eg 0..100..X */\r
+ public final static Key KEY_MOUSE_WHEEL_TRANSLATE_AMOUNT = new KeyOf(Double.class);\r
+\r
+ /** Default mouse zoom speed */\r
+ public final static double DEFAULT_MOUSE_WHEEL_TRANSLATE_AMOUNT = 10;\r
+\r
+ @Override\r
+ public void addedToContext(ICanvasContext ctx) {\r
+ super.addedToContext(ctx);\r
+ // Set Default values\r
+ setHint(KEY_MOUSE_ZOOM_SPEED, DEFAULT_MOUSE_ZOOM_SPEED);\r
+ setHint(KEY_MOUSE_ZOOM_ENABLED, true);\r
+ setHint(KEY_MOUSE_PAN_ENABLED, true);\r
+ setHint(KEY_MOUSE_WHEEL_ZOOM_PAN_ENABLED, true);\r
+ setHint(KEY_MOUSE_WHEEL_ZOOM_SPEED, DEFAULT_MOUSE_WHEEL_ZOOM_SPEED);\r
+ setHint(KEY_MOUSE_WHEEL_TRANSLATE_AMOUNT, DEFAULT_MOUSE_WHEEL_TRANSLATE_AMOUNT);\r
+ }\r
+\r
+ /**\r
+ * Inits mouse pan and zoom interactors.\r
+ * Eats mouse presses if shift is pressed.\r
+ * \r
+ * @param e\r
+ * @return\r
+ */\r
+ @EventHandler(priority = MOUSE_PAN_PRIORITY)\r
+ public boolean handleEvent(MouseEvent e) {\r
+ assertDependencies();\r
+ if (e.context instanceof MouseUtil)\r
+ return false;\r
+\r
+ if ((e instanceof MouseButtonPressedEvent) && (e.stateMask & MouseEvent.SHIFT_MASK) != 0 && ((MouseButtonPressedEvent)e).button==MouseEvent.LEFT_BUTTON)\r
+ return true;\r
+\r
+ // Mouse pan & zoom\r
+ if (e instanceof MouseMovedEvent) {\r
+ MouseMovedEvent mme = (MouseMovedEvent) e;\r
+ MouseInfo mi = mice.getMouseInfo(mme.mouseId);\r
+ if (mi == null)\r
+ return false;\r
+ if ((e.stateMask & MouseEvent.SHIFT_MASK) != 0 & mi.isMouseButtonPressed(MouseEvent.LEFT_BUTTON))\r
+ {\r
+ if (!isPanEnabled())\r
+ return false;\r
+ if (!isPanning()) {\r
+ getContext().add( new PanMode(mme.mouseId, mme.controlPosition, MouseEvent.LEFT_BUTTON) );\r
+ }\r
+ return true;\r
+ }\r
+ if (mi.isMouseButtonPressed(MouseEvent.MIDDLE_BUTTON))\r
+ {\r
+ if (!isPanEnabled())\r
+ return false;\r
+ if (!isPanning()) {\r
+ getContext().add( new PanMode(mme.mouseId, mme.controlPosition, MouseEvent.MIDDLE_BUTTON) );\r
+ }\r
+ return true;\r
+ }\r
+ if ((e.stateMask & MouseEvent.SHIFT_MASK) != 0 & mi.isMouseButtonPressed(MouseEvent.RIGHT_BUTTON))\r
+ {\r
+ if (!isZoomEnabled())\r
+ return false;\r
+ if (!isZooming()) {\r
+ Point2D diagramPosition = util.getInverseTransform().transform(mme.controlPosition, new Point2D.Double());\r
+\r
+ getContext().add( new ZoomMode(mme.mouseId, mme.controlPosition, diagramPosition, MouseEvent.RIGHT_BUTTON) );\r
+ }\r
+ return true;\r
+ }\r
+ }\r
+\r
+ // Mouse wheel zoom / scroll\r
+ if (e instanceof MouseWheelMovedEvent) {\r
+ if (!isMouseWheelZoomPanEnabled())\r
+ return false;\r
+ MouseWheelMovedEvent we = (MouseWheelMovedEvent) e;\r
+ //if (!mm.isMouseButtonPressed(we.mouseId, MouseEvent.MIDDLE_BUTTON))\r
+ /*\r
+ if (!ctrl())\r
+ {\r
+ if (we.scrollType == MouseWheelMovedEvent.WHEEL_UNIT_SCROLL)\r
+ {\r
+ double dy = we.wheelRotation * getMouseWheelTranslateAmount();\r
+ if (shift())\r
+ util.translateWithControlCoordinates(new Point2D.Double(dy, 0));\r
+ else\r
+ util.translateWithControlCoordinates(new Point2D.Double(0, dy));\r
+ return true;\r
+ }\r
+ } else\r
+ */\r
+ {\r
+ if (we.scrollType == MouseWheelMovedEvent.WHEEL_UNIT_SCROLL)\r
+ {\r
+ double dy = we.wheelRotation;\r
+ double zoom = getMouseWheelZoomSpeed();\r
+ double base = 1.00 + (zoom / 10000);\r
+ double scaleFactor = Math.pow(base, dy);\r
+\r
+ scaleFactor = pzr.limitScaleFactor(scaleFactor);\r
+ util.zoomAroundControlPoint(scaleFactor, we.controlPosition);\r
+ //ti.zoom(scaleFactor);\r
+ return true;\r
+ }\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+\r
+ public boolean isPanEnabled()\r
+ {\r
+ Boolean h = getHint(KEY_MOUSE_PAN_ENABLED);\r
+ if (h==null) return false;\r
+ return h;\r
+ }\r
+\r
+ public boolean isPanning()\r
+ {\r
+ return !getContext().getItemsByClass(PanMode.class).isEmpty();\r
+ }\r
+\r
+ public boolean isZooming()\r
+ {\r
+ return !getContext().getItemsByClass(ZoomMode.class).isEmpty();\r
+ }\r
+\r
+ public boolean isZoomEnabled()\r
+ {\r
+ Boolean h = getHint(KEY_MOUSE_ZOOM_ENABLED);\r
+ if (h==null) return false;\r
+ return h;\r
+ }\r
+\r
+ public boolean isMouseWheelZoomPanEnabled()\r
+ {\r
+ Boolean h = getHint(KEY_MOUSE_WHEEL_ZOOM_PAN_ENABLED);\r
+ if (h==null) return false;\r
+ return h;\r
+ }\r
+\r
+ /**\r
+ * is Shift key down\r
+ * @return\r
+ */\r
+ /*public boolean shift()\r
+ {\r
+ return keys.isKeyPressed(KeyEvent.VK_SHIFT);\r
+ }\r
+\r
+ public boolean ctrl()\r
+ {\r
+ return keys.isKeyPressed(KeyEvent.VK_CONTROL);\r
+ }*/\r
+\r
+ public double getMouseZoomSpeed()\r
+ {\r
+ Double h = getHint(KEY_MOUSE_ZOOM_SPEED);\r
+ if (h==null) return DEFAULT_MOUSE_ZOOM_SPEED;\r
+ return h;\r
+ }\r
+\r
+ public double getMouseWheelZoomSpeed()\r
+ {\r
+ Double h = getHint(KEY_MOUSE_WHEEL_ZOOM_SPEED);\r
+ if (h==null) return DEFAULT_MOUSE_WHEEL_ZOOM_SPEED;\r
+ return h;\r
+ }\r
+\r
+ public double getMouseWheelTranslateAmount()\r
+ {\r
+ Double h = getHint(KEY_MOUSE_WHEEL_TRANSLATE_AMOUNT);\r
+ if (h==null) return DEFAULT_MOUSE_WHEEL_TRANSLATE_AMOUNT;\r
+ return h;\r
+ }\r
+\r
+ /**\r
+ * Shift and left mouse button is pressed, do panning\r
+ */\r
+ class PanMode extends AbstractCanvasParticipant\r
+ {\r
+ @Dependency TransformUtil util;\r
+ final int mouseId;\r
+ int releaseButton;\r
+ // Mouse system coordinates\r
+ Point2D mousePos;\r
+ IMouseCursorHandle cursor;\r
+\r
+ public PanMode(int mouseId, Point2D mousePos, int releaseButton) {\r
+ super();\r
+ this.mouseId = mouseId;\r
+ this.mousePos = new Point2D.Double(mousePos.getX(), mousePos.getY());\r
+ this.releaseButton = releaseButton;\r
+ }\r
+\r
+ @Override\r
+ public void addedToContext(ICanvasContext ctx) {\r
+ super.addedToContext(ctx);\r
+ IMouseCursorContext mctx = getContext().getMouseCursorContext();\r
+ if (mctx!=null)\r
+ cursor = mctx.setCursor(mouseId, PAN_CURSOR);\r
+ }\r
+\r
+ @EventHandler(priority = PAN_PRIORITY)\r
+ public boolean handleEvent(Event e) {\r
+ if (e instanceof MouseButtonReleasedEvent) {\r
+ MouseButtonReleasedEvent mpe = (MouseButtonReleasedEvent) e;\r
+ if (mpe.button == releaseButton && mpe.mouseId == mouseId)\r
+ {\r
+ remove();\r
+ return false;\r
+ }\r
+ }\r
+\r
+ if (e instanceof KeyReleasedEvent) {\r
+ KeyReleasedEvent ke = (KeyReleasedEvent) e;\r
+ if (ke.keyCode == java.awt.event.KeyEvent.VK_SHIFT)\r
+ {\r
+ remove();\r
+ return false;\r
+ }\r
+ }\r
+\r
+ if (e instanceof MouseMovedEvent) {\r
+ if (e.getContext() instanceof MouseUtil) return true;\r
+ MouseMovedEvent mme = (MouseMovedEvent) e;\r
+ if (mme.mouseId == mouseId) {\r
+ Point2D oldPos = mousePos;\r
+ Point2D newPos = mme.controlPosition;\r
+\r
+ double dx = newPos.getX() - oldPos.getX();\r
+ double dy = newPos.getY() - oldPos.getY();\r
+ if (dx==0 && dy==0) return true;\r
+\r
+ this.mousePos.setLocation(newPos);\r
+\r
+ util.translateWithControlCoordinates(new Point2D.Double(dx, dy));\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ @Override\r
+ public void removedFromContext(ICanvasContext ctx) {\r
+ if (cursor!=null) {\r
+ cursor.remove();\r
+ cursor = null;\r
+ }\r
+ super.removedFromContext(ctx);\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * Shift and right mouse button is pressed, do zooming\r
+ */\r
+ class ZoomMode extends AbstractCanvasParticipant\r
+ {\r
+ final int mouseId;\r
+ int releaseButton;\r
+\r
+ // Mouse system coordinates\r
+ Point2D prevMousePos;\r
+ Point2D origControlMousePos;\r
+ Point2D origDiagramMousePos;\r
+ IMouseCursorHandle cursor;\r
+\r
+ public ZoomMode(int mouseId, Point2D controlMousePos, Point2D mouseDiagramPos, int releaseButton) {\r
+ super();\r
+ this.mouseId = mouseId;\r
+ this.prevMousePos = (Point2D) controlMousePos.clone();\r
+ this.origControlMousePos = (Point2D) controlMousePos.clone();\r
+ this.origDiagramMousePos = (Point2D) mouseDiagramPos.clone();\r
+ this.releaseButton = releaseButton;\r
+ }\r
+\r
+ @Override\r
+ public void addedToContext(ICanvasContext ctx) {\r
+ super.addedToContext(ctx);\r
+ IMouseCursorContext mctx = getContext().getMouseCursorContext();\r
+ if (mctx!=null)\r
+ cursor = mctx.setCursor(mouseId, ZOOM_CURSOR);\r
+ }\r
+\r
+ @EventHandler(priority = ZOOM_PRIORITY)\r
+ public boolean handleEvent(Event e) {\r
+ if (e instanceof MouseButtonReleasedEvent) {\r
+ MouseButtonReleasedEvent mpe = (MouseButtonReleasedEvent) e;\r
+ if (mpe.button == releaseButton && mpe.mouseId == mouseId)\r
+ {\r
+ remove();\r
+ return false;\r
+ }\r
+ }\r
+\r
+ if (e instanceof KeyReleasedEvent) {\r
+ KeyReleasedEvent ke = (KeyReleasedEvent) e;\r
+ if (ke.keyCode == java.awt.event.KeyEvent.VK_SHIFT)\r
+ {\r
+ remove();\r
+ return false;\r
+ }\r
+ }\r
+\r
+ if (e instanceof MouseMovedEvent) {\r
+ if (e.getContext() instanceof MouseUtil) return true;\r
+ MouseMovedEvent mme = (MouseMovedEvent) e;\r
+ if (mme.mouseId == mouseId) {\r
+ Point2D oldPos = prevMousePos;\r
+ Point2D newPos = mme.controlPosition;\r
+\r
+ double dy = newPos.getY() - oldPos.getY();\r
+// double dx = newPos.getX() - oldPos.getX();\r
+ this.prevMousePos.setLocation(newPos);\r
+\r
+ double zoomSpeed = getMouseZoomSpeed();\r
+ double base = 1.00 + (zoomSpeed / 10000);\r
+ double scaleFactor = Math.pow(base, -dy);\r
+\r
+ scaleFactor = pzr.limitScaleFactor(scaleFactor);\r
+ util.zoomAroundDiagramPoint(scaleFactor, origDiagramMousePos);\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ @Override\r
+ public void removedFromContext(ICanvasContext ctx) {\r
+ if (cursor!=null) {\r
+ cursor.remove();\r
+ cursor = null;\r
+ }\r
+\r
+ super.removedFromContext(ctx);\r
+ }\r
+ }\r
+\r
+}\r