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