]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 package org.simantics.diagram.elements;\r
2 \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
7 \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
22 \r
23 /**\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
26  * \r
27  * @author Teemu Lempinen\r
28  *\r
29  */\r
30 public class ResizeRectangularSceneGraph implements SceneGraph {\r
31 \r
32         private static final long serialVersionUID = -972741261034892976L;\r
33 \r
34         public static final ResizeRectangularSceneGraph INSTANCE = new ResizeRectangularSceneGraph();\r
35 \r
36         public static final Key KEY_SG_NODE = new SceneGraphNodeKey(ResizeNode.class, "RESIZE_RECTANGULAR_SG_NODE");\r
37 \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
43         \r
44         \r
45         public ResizeRectangularSceneGraph() {\r
46             this(null);\r
47         }\r
48         \r
49         public ResizeRectangularSceneGraph(Key sgNode) {\r
50             this(sgNode, TranslateEdge.WEST, TranslateEdge.NORTH, ElementHints.KEY_TRANSFORM, ElementHints.KEY_BOUNDS);\r
51         }\r
52         \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
59     }\r
60 \r
61         @Override\r
62         public void init(final IElement e, G2DParentNode parent) {\r
63             \r
64             if(!ElementUtils.getHintOrDefault(e, ElementHints.KEY_RESIZABLE, false))\r
65                 return;\r
66                 \r
67                 ResizeNode node = (ResizeNode) e.getHint(KEY_SG_NODE);\r
68                 if (node == null) {\r
69                         node = parent.addNode(ResizeNode.class);\r
70                         \r
71                         e.setHint(KEY_SG_NODE, node);\r
72 \r
73                         node.setStroke(new BasicStroke(1f));\r
74                         node.setZIndex(-1500);\r
75 \r
76                         // Add a resize listener for updating bounds and transform information to graph after resizing\r
77                         node.setResizeListener(new ResizeListener() {\r
78 \r
79                                 @Override\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
87                                         e.setHints(hints);\r
88                                         if(synchronizeToBackend) {\r
89                                                 IDiagram diagram = ElementUtils.getDiagram(e);\r
90                                                 DiagramUtils.synchronizeHintsToBackend(diagram, e);\r
91                                         }\r
92                                 }\r
93                         });\r
94                 }\r
95 \r
96                 if(node != null) {\r
97                     node.setxTranslateEdge(xTranslateEdge);\r
98                     node.setYTranslateEdge(yTranslateEdge);\r
99                     \r
100                     AffineTransform at = ElementUtils.getTransform(e);\r
101                     Rectangle2D b = null; //= (Rectangle2D)e.getHint(ElementHints.KEY_BOUNDS);\r
102                     \r
103                     if(b == null) {\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
111                             }\r
112                         }\r
113                     }\r
114                     \r
115                     if(b == null)\r
116                         b = ElementUtils.getElementBounds(e);\r
117                     \r
118                     Rectangle2D bounds = new Rectangle2D.Double(b.getX(), b.getY(), b.getWidth(), b.getHeight()); \r
119                     \r
120                     node.setBounds(bounds);\r
121                     \r
122                     if(at != null)\r
123                         node.setTransform(at);\r
124                 }\r
125                 \r
126                 update(e);\r
127         }\r
128         \r
129         public void update(IElement e) {\r
130                 PropertySetter setter = e.getElementClass().getSingleItem(PropertySetter.class);\r
131                 setter.syncPropertiesToNode(e);\r
132         }\r
133 \r
134         @Override\r
135         public void cleanup(IElement e) {\r
136                 ElementUtils.removePossibleNode(e, KEY_SG_NODE);\r
137         }\r
138         \r
139         \r
140         /**\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
144          * \r
145          * @param xTranslateEdge TranslateEdge NONE, EAST or WEST\r
146          */\r
147         public void setXTranslateEdge(TranslateEdge xTranslateEdge) {\r
148             this.xTranslateEdge = xTranslateEdge;\r
149         }\r
150         \r
151         /**\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
155      * \r
156      * @param xTranslateEdge TranslateEdge NONE, NORTH or SOUTH\r
157      */\r
158     public void setYTranslateEdge(TranslateEdge yTranslateEdge) {\r
159         this.yTranslateEdge = yTranslateEdge;\r
160     }\r
161 \r
162 }\r