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