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