1 package org.simantics.diagram.elements;
3 import java.awt.BasicStroke;
4 import java.awt.geom.AffineTransform;
5 import java.awt.geom.Rectangle2D;
8 import org.simantics.diagram.elements.ResizeNode.ResizeListener;
9 import org.simantics.diagram.elements.ResizeNode.TranslateEdge;
10 import org.simantics.g2d.canvas.Hints;
11 import org.simantics.g2d.diagram.DiagramUtils;
12 import org.simantics.g2d.diagram.IDiagram;
13 import org.simantics.g2d.element.ElementHints;
14 import org.simantics.g2d.element.ElementUtils;
15 import org.simantics.g2d.element.IElement;
16 import org.simantics.g2d.element.SceneGraphNodeKey;
17 import org.simantics.g2d.element.handler.PropertySetter;
18 import org.simantics.g2d.element.handler.SceneGraph;
19 import org.simantics.scenegraph.g2d.G2DNode;
20 import org.simantics.scenegraph.g2d.G2DParentNode;
21 import org.simantics.utils.datastructures.hints.IHintContext.Key;
24 * Scenegraph for resizing rectangular elements. Contains an invisible ResizeNode and
25 * handlers for setting bounds and transforms according to resize commands.
27 * @author Teemu Lempinen
30 public class ResizeRectangularSceneGraph implements SceneGraph {
32 private static final long serialVersionUID = -972741261034892976L;
34 public static final ResizeRectangularSceneGraph INSTANCE = new ResizeRectangularSceneGraph();
36 public static final Key KEY_SG_NODE = new SceneGraphNodeKey(ResizeNode.class, "RESIZE_RECTANGULAR_SG_NODE");
38 private Key resizedNodeKey;
39 private Key transformKey;
40 private Key boundsKey;
41 private TranslateEdge xTranslateEdge;
42 private TranslateEdge yTranslateEdge;
45 public ResizeRectangularSceneGraph() {
49 public ResizeRectangularSceneGraph(Key sgNode) {
50 this(sgNode, TranslateEdge.WEST, TranslateEdge.NORTH, ElementHints.KEY_TRANSFORM, ElementHints.KEY_BOUNDS);
53 public ResizeRectangularSceneGraph(Key sgNode, TranslateEdge xTranslateEdge, TranslateEdge yTranslateEdge, Key transformKey, Key boundsKey) {
54 this.resizedNodeKey = sgNode;
55 this.xTranslateEdge = xTranslateEdge;
56 this.yTranslateEdge = yTranslateEdge;
57 this.transformKey = transformKey;
58 this.boundsKey = boundsKey;
62 public void init(final IElement e, G2DParentNode parent) {
64 if(!ElementUtils.getHintOrDefault(e, ElementHints.KEY_RESIZABLE, false))
67 ResizeNode node = (ResizeNode) e.getHint(KEY_SG_NODE);
69 node = parent.addNode(ResizeNode.class);
71 e.setHint(KEY_SG_NODE, node);
73 node.setStroke(new BasicStroke(1f));
74 node.setZIndex(-1500);
76 // Add a resize listener for updating bounds and transform information to graph after resizing
77 node.setResizeListener(new ResizeListener() {
80 public void elementResized(Rectangle2D newBounds, AffineTransform transform, boolean synchronizeToBackend) {
81 Map<Key, Object> hints = e.getHints();
82 AffineTransform at = new AffineTransform((AffineTransform) hints.get(transformKey));
83 at.concatenate(transform);
84 hints.put(transformKey, at);
85 hints.put(boundsKey, newBounds);
86 hints.put(Hints.KEY_DIRTY, Hints.VALUE_SG_DIRTY);
88 if(synchronizeToBackend) {
89 IDiagram diagram = ElementUtils.getDiagram(e);
90 DiagramUtils.synchronizeHintsToBackend(diagram, e);
97 node.setxTranslateEdge(xTranslateEdge);
98 node.setYTranslateEdge(yTranslateEdge);
100 AffineTransform at = ElementUtils.getTransform(e);
101 Rectangle2D b = null; //= (Rectangle2D)e.getHint(ElementHints.KEY_BOUNDS);
104 if(resizedNodeKey != null) {
105 Object resizedNode = e.getHint(resizedNodeKey);
106 if(resizedNode != null && resizedNode instanceof G2DNode) {
107 G2DNode n = (G2DNode)resizedNode;
108 b = n.getBoundsInLocal();
109 AffineTransform nodeTransform = n.getTransform();
110 at = new AffineTransform(nodeTransform);
116 b = ElementUtils.getElementBounds(e);
118 Rectangle2D bounds = new Rectangle2D.Double(b.getX(), b.getY(), b.getWidth(), b.getHeight());
120 node.setBounds(bounds);
123 node.setTransform(at);
129 public void update(IElement e) {
130 PropertySetter setter = e.getElementClass().getSingleItem(PropertySetter.class);
131 setter.syncPropertiesToNode(e);
135 public void cleanup(IElement e) {
136 ElementUtils.removePossibleNode(e, KEY_SG_NODE);
141 * Set the edge for X-axis translation. If this edge
142 * is dragged during resize, the x-translation for
143 * axis is also changed keeping the other edge in place.
145 * @param xTranslateEdge TranslateEdge NONE, EAST or WEST
147 public void setXTranslateEdge(TranslateEdge xTranslateEdge) {
148 this.xTranslateEdge = xTranslateEdge;
152 * Set the edge for Y-axis translation. If this edge
153 * is dragged during resize, the y-translation for
154 * axis is also changed keeping the other edge in place.
156 * @param xTranslateEdge TranslateEdge NONE, NORTH or SOUTH
158 public void setYTranslateEdge(TranslateEdge yTranslateEdge) {
159 this.yTranslateEdge = yTranslateEdge;