]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - 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
diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/participant/ZoomToAreaHandler.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/participant/ZoomToAreaHandler.java
new file mode 100644 (file)
index 0000000..e727564
--- /dev/null
@@ -0,0 +1,236 @@
+/*******************************************************************************\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
+package org.simantics.g2d.participant;\r
+\r
+import java.awt.BasicStroke;\r
+import java.awt.Color;\r
+import java.awt.Cursor;\r
+import java.awt.Shape;\r
+import java.awt.geom.Path2D;\r
+import java.awt.geom.Point2D;\r
+import java.awt.geom.Rectangle2D;\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.canvas.impl.SGNodeReflection.SGCleanup;\r
+import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;\r
+import org.simantics.g2d.diagram.DiagramHints;\r
+import org.simantics.g2d.diagram.handler.PickContext;\r
+import org.simantics.g2d.diagram.participant.Selection;\r
+import org.simantics.g2d.diagram.participant.pointertool.AbstractMode;\r
+import org.simantics.g2d.participant.MouseUtil.MouseInfo;\r
+import org.simantics.scenegraph.g2d.G2DParentNode;\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.MouseEvent.MouseButtonEvent;\r
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseClickEvent;\r
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;\r
+import org.simantics.scenegraph.g2d.events.command.CommandEvent;\r
+import org.simantics.scenegraph.g2d.events.command.Commands;\r
+import org.simantics.scenegraph.g2d.nodes.ShapeNode;\r
+import org.simantics.utils.ObjectUtils;\r
+import org.simantics.utils.page.MarginUtils;\r
+\r
+/**\r
+ * ZoomToAreaHandler starts an area zoom mode when a ZOOM_TO_AREA command is\r
+ * issued.\r
+ *\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class ZoomToAreaHandler extends AbstractCanvasParticipant {\r
+\r
+    public final static Cursor ZOOM_CURSOR = new Cursor(Cursor.CROSSHAIR_CURSOR);\r
+\r
+    @EventHandler(priority = 0)\r
+    public boolean handleZoomToArea(CommandEvent event) {\r
+        if (Commands.ZOOM_TO_AREA.equals( event.command )) {\r
+            if (!getContext().containsItemByClass(ZoomToAreaMode.class)) {\r
+                getContext().add( new ZoomToAreaMode() );\r
+                setDirty();\r
+            }\r
+            return true;\r
+        }\r
+        return false;\r
+    }\r
+\r
+    class ZoomToAreaMode extends AbstractMode {\r
+\r
+        @Dependency TransformUtil util;\r
+        @Dependency Selection selection;\r
+        @Dependency PickContext pickContext;\r
+        @Dependency KeyUtil keyUtil;\r
+        @Dependency MouseUtil mouseUtil;\r
+        @Dependency CanvasBoundsParticipant canvasBounds;\r
+\r
+        public final BasicStroke STROKE = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10f, new float[] {4,2}, 0);\r
+\r
+        public static final int PAINT_PRIORITY = 30;\r
+\r
+        Point2D startingPoint;\r
+        Point2D currentPoint;\r
+        IMouseCursorHandle cursor;\r
+\r
+        public ZoomToAreaMode() {\r
+            super(0);\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(getMouseId(), ZOOM_CURSOR);\r
+            MouseInfo mi = mouseUtil.getMouseInfo(getMouseId());\r
+            if (mi != null)\r
+                currentPoint = mi.canvasPosition;\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
+        @EventHandler(priority = 10)\r
+        public boolean handleEvent(Event e) {\r
+            if (e instanceof CommandEvent) {\r
+                CommandEvent ce = (CommandEvent) e;\r
+                if (ce.command.equals( Commands.CANCEL )){\r
+                    setDirty();\r
+                    remove();\r
+                    return true;\r
+                }\r
+            } else if (e instanceof MouseMovedEvent) {\r
+                MouseMovedEvent event = (MouseMovedEvent) e;\r
+                if (event.mouseId != getMouseId()) return false;\r
+                Point2D canvasPos = util.controlToCanvas(event.controlPosition, null);\r
+                if (!ObjectUtils.objectEquals(currentPoint, canvasPos))\r
+                {\r
+                    currentPoint = canvasPos;\r
+                    update(getBox());\r
+                    setDirty();\r
+                }\r
+                return false;\r
+            } else if (e instanceof MouseButtonEvent) {\r
+                MouseButtonEvent event = (MouseButtonEvent) e;\r
+\r
+                if (event.mouseId != getMouseId()) return false;\r
+                if (event.button != MouseEvent.LEFT_BUTTON) return false;\r
+\r
+                // Eat all other mouse button events besides press and click.\r
+                // Must use mouse clicks here because otherwise selection\r
+                // participants etc. might alter selections on the next incoming\r
+                // mouse click event, which only confuses the user.\r
+                if (e instanceof MouseClickEvent) {\r
+                    Point2D canvasPos = util.controlToCanvas(event.controlPosition, null);\r
+                    currentPoint = canvasPos;\r
+\r
+                    if (startingPoint == null) {\r
+                        // Start marking the box\r
+                        startingPoint = currentPoint;\r
+                        setDirty();\r
+                        return true;\r
+                    }\r
+\r
+                    Rectangle2D area = new Rectangle2D.Double();\r
+                    area.setFrameFromDiagonal(startingPoint, currentPoint);\r
+\r
+                    Rectangle2D controlArea = canvasBounds.getControlBounds();\r
+                    util.fitArea(controlArea, area, PanZoomRotateHandler.getZoomToFitMargins(getHintStack()));\r
+\r
+                    setDirty();\r
+                    remove();\r
+                    return true;\r
+                }\r
+                return true;\r
+            }\r
+            return false;\r
+        }\r
+\r
+        /**\r
+         * Get selection box in control coordinates\r
+         * @return control coordinates\r
+         */\r
+        protected Rectangle2D getBox() {\r
+            if (startingPoint == null)\r
+                return null;\r
+            Point2D p1 = startingPoint;\r
+            Point2D p2 = currentPoint;\r
+            double ax = p1.getX();\r
+            double ay = p1.getY();\r
+            double bx = p2.getX();\r
+            double by = p2.getY();\r
+            if (bx < ax) {\r
+                double temp = ax;\r
+                ax = bx;\r
+                bx = temp;\r
+            }\r
+            if (by < ay) {\r
+                double temp = ay;\r
+                ay = by;\r
+                by = temp;\r
+            }\r
+            return new Rectangle2D.Double(ax, ay, bx - ax, by - ay);\r
+        }\r
+\r
+        protected Path2D getCrossHair(Rectangle2D controlBounds) {\r
+            Point2D controlPos = util.canvasToControl(currentPoint, null);\r
+            Path2D path = new Path2D.Double();\r
+            path.moveTo(controlBounds.getMinX(), controlPos.getY());\r
+            path.lineTo(controlBounds.getMaxX(), controlPos.getY());\r
+            path.moveTo(controlPos.getX(), controlBounds.getMinY());\r
+            path.lineTo(controlPos.getX(), controlBounds.getMaxY());\r
+            return path;\r
+        }\r
+\r
+        public synchronized Color getToolColor()\r
+        {\r
+            Color c = getHint(DiagramHints.KEY_SELECTION_FRAME_COLOR);\r
+            if (c!=null) return c;\r
+            return Color.BLACK;\r
+        }\r
+\r
+        protected ShapeNode node = null;\r
+\r
+        @SGInit\r
+        public void initSG(G2DParentNode parent) {\r
+            node = parent.addNode("zoom to area", ShapeNode.class);\r
+            node.setZIndex(PAINT_PRIORITY);\r
+            node.setStroke(STROKE);\r
+            node.setScaleStroke(true);\r
+            node.setColor(getToolColor());\r
+            node.setFill(false);\r
+        }\r
+\r
+        void update(Shape shape) {\r
+            if (node != null) {\r
+                node.setShape(shape);\r
+            }\r
+        }\r
+\r
+        @SGCleanup\r
+        public void cleanupSG() {\r
+            if (node != null) {\r
+                node.remove();\r
+                node = null;\r
+            }\r
+        }\r
+    }\r
+\r
+}\r