]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.diagram/src/org/simantics/diagram/elements/ResizeRectangularSceneGraph.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / elements / ResizeRectangularSceneGraph.java
diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/elements/ResizeRectangularSceneGraph.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/elements/ResizeRectangularSceneGraph.java
new file mode 100644 (file)
index 0000000..4c22c3a
--- /dev/null
@@ -0,0 +1,162 @@
+package org.simantics.diagram.elements;\r
+\r
+import java.awt.BasicStroke;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Rectangle2D;\r
+import java.util.Map;\r
+\r
+import org.simantics.diagram.elements.ResizeNode.ResizeListener;\r
+import org.simantics.diagram.elements.ResizeNode.TranslateEdge;\r
+import org.simantics.g2d.canvas.Hints;\r
+import org.simantics.g2d.diagram.DiagramUtils;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.element.ElementHints;\r
+import org.simantics.g2d.element.ElementUtils;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.SceneGraphNodeKey;\r
+import org.simantics.g2d.element.handler.PropertySetter;\r
+import org.simantics.g2d.element.handler.SceneGraph;\r
+import org.simantics.scenegraph.g2d.G2DNode;\r
+import org.simantics.scenegraph.g2d.G2DParentNode;\r
+import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
+\r
+/**\r
+ * Scenegraph for resizing rectangular elements. Contains an invisible ResizeNode and \r
+ * handlers for setting bounds and transforms according to resize commands.\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ResizeRectangularSceneGraph implements SceneGraph {\r
+\r
+       private static final long serialVersionUID = -972741261034892976L;\r
+\r
+       public static final ResizeRectangularSceneGraph INSTANCE = new ResizeRectangularSceneGraph();\r
+\r
+       public static final Key KEY_SG_NODE = new SceneGraphNodeKey(ResizeNode.class, "RESIZE_RECTANGULAR_SG_NODE");\r
+\r
+       private Key resizedNodeKey;\r
+       private Key transformKey;\r
+       private Key boundsKey;\r
+       private TranslateEdge xTranslateEdge;\r
+       private TranslateEdge yTranslateEdge;\r
+       \r
+       \r
+       public ResizeRectangularSceneGraph() {\r
+           this(null);\r
+       }\r
+       \r
+       public ResizeRectangularSceneGraph(Key sgNode) {\r
+           this(sgNode, TranslateEdge.WEST, TranslateEdge.NORTH, ElementHints.KEY_TRANSFORM, ElementHints.KEY_BOUNDS);\r
+       }\r
+       \r
+    public ResizeRectangularSceneGraph(Key sgNode, TranslateEdge xTranslateEdge, TranslateEdge yTranslateEdge, Key transformKey, Key boundsKey) {\r
+        this.resizedNodeKey = sgNode; \r
+        this.xTranslateEdge = xTranslateEdge;\r
+        this.yTranslateEdge = yTranslateEdge;\r
+        this.transformKey = transformKey;\r
+        this.boundsKey = boundsKey;\r
+    }\r
+\r
+       @Override\r
+       public void init(final IElement e, G2DParentNode parent) {\r
+           \r
+           if(!ElementUtils.getHintOrDefault(e, ElementHints.KEY_RESIZABLE, false))\r
+               return;\r
+               \r
+               ResizeNode node = (ResizeNode) e.getHint(KEY_SG_NODE);\r
+               if (node == null) {\r
+                       node = parent.addNode(ResizeNode.class);\r
+                       \r
+                       e.setHint(KEY_SG_NODE, node);\r
+\r
+                       node.setStroke(new BasicStroke(1f));\r
+                       node.setZIndex(-1500);\r
+\r
+                       // Add a resize listener for updating bounds and transform information to graph after resizing\r
+                       node.setResizeListener(new ResizeListener() {\r
+\r
+                               @Override\r
+                               public void elementResized(Rectangle2D newBounds, AffineTransform transform, boolean synchronizeToBackend) {\r
+                                       Map<Key, Object> hints = e.getHints();\r
+                                       AffineTransform at = new AffineTransform((AffineTransform) hints.get(transformKey));\r
+                                       at.concatenate(transform);\r
+                                       hints.put(transformKey, at);\r
+                                       hints.put(boundsKey, newBounds);\r
+                                       hints.put(Hints.KEY_DIRTY, Hints.VALUE_SG_DIRTY);\r
+                                       e.setHints(hints);\r
+                                       if(synchronizeToBackend) {\r
+                                               IDiagram diagram = ElementUtils.getDiagram(e);\r
+                                               DiagramUtils.synchronizeHintsToBackend(diagram, e);\r
+                                       }\r
+                               }\r
+                       });\r
+               }\r
+\r
+               if(node != null) {\r
+                   node.setxTranslateEdge(xTranslateEdge);\r
+                   node.setYTranslateEdge(yTranslateEdge);\r
+                   \r
+                   AffineTransform at = ElementUtils.getTransform(e);\r
+                   Rectangle2D b = null; //= (Rectangle2D)e.getHint(ElementHints.KEY_BOUNDS);\r
+                   \r
+                   if(b == null) {\r
+                       if(resizedNodeKey != null) {\r
+                           Object resizedNode = e.getHint(resizedNodeKey);\r
+                           if(resizedNode != null && resizedNode instanceof G2DNode) {\r
+                               G2DNode n = (G2DNode)resizedNode;\r
+                               b = n.getBoundsInLocal();\r
+                               AffineTransform nodeTransform = n.getTransform();\r
+                               at = new AffineTransform(nodeTransform);\r
+                           }\r
+                       }\r
+                   }\r
+                   \r
+                   if(b == null)\r
+                       b = ElementUtils.getElementBounds(e);\r
+                   \r
+                   Rectangle2D bounds = new Rectangle2D.Double(b.getX(), b.getY(), b.getWidth(), b.getHeight()); \r
+                   \r
+                   node.setBounds(bounds);\r
+                   \r
+                   if(at != null)\r
+                       node.setTransform(at);\r
+               }\r
+               \r
+               update(e);\r
+       }\r
+       \r
+       public void update(IElement e) {\r
+               PropertySetter setter = e.getElementClass().getSingleItem(PropertySetter.class);\r
+               setter.syncPropertiesToNode(e);\r
+       }\r
+\r
+       @Override\r
+       public void cleanup(IElement e) {\r
+               ElementUtils.removePossibleNode(e, KEY_SG_NODE);\r
+       }\r
+       \r
+       \r
+       /**\r
+        * Set the edge for X-axis translation. If this edge\r
+        * is dragged during resize, the x-translation for\r
+        * axis is also changed keeping the other edge in place.\r
+        * \r
+        * @param xTranslateEdge TranslateEdge NONE, EAST or WEST\r
+        */\r
+       public void setXTranslateEdge(TranslateEdge xTranslateEdge) {\r
+           this.xTranslateEdge = xTranslateEdge;\r
+       }\r
+       \r
+       /**\r
+     * Set the edge for Y-axis translation. If this edge\r
+     * is dragged during resize, the y-translation for\r
+     * axis is also changed keeping the other edge in place.\r
+     * \r
+     * @param xTranslateEdge TranslateEdge NONE, NORTH or SOUTH\r
+     */\r
+    public void setYTranslateEdge(TranslateEdge yTranslateEdge) {\r
+        this.yTranslateEdge = yTranslateEdge;\r
+    }\r
+\r
+}\r