]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph.swing/src/org/simantics/scenegraph/swing/SymbolMonitorClass.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scenegraph.swing / src / org / simantics / scenegraph / swing / SymbolMonitorClass.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.scenegraph.swing;\r
13 \r
14 import java.awt.Rectangle;\r
15 import java.awt.Shape;\r
16 import java.awt.geom.AffineTransform;\r
17 import java.awt.geom.Path2D;\r
18 import java.awt.geom.Rectangle2D;\r
19 import java.util.Collection;\r
20 import java.util.EnumSet;\r
21 import java.util.Map;\r
22 \r
23 import org.simantics.g2d.element.ElementClass;\r
24 import org.simantics.g2d.element.ElementHints;\r
25 import org.simantics.g2d.element.IElement;\r
26 import org.simantics.g2d.element.SceneGraphNodeKey;\r
27 import org.simantics.g2d.element.handler.ElementHandler;\r
28 import org.simantics.g2d.element.handler.InternalSize;\r
29 import org.simantics.g2d.element.handler.Outline;\r
30 import org.simantics.g2d.element.handler.SceneGraph;\r
31 import org.simantics.g2d.element.handler.StaticSymbol;\r
32 import org.simantics.g2d.element.handler.Transform;\r
33 import org.simantics.g2d.element.handler.impl.SimpleElementLayers;\r
34 import org.simantics.g2d.element.handler.impl.StaticSymbolImpl;\r
35 import org.simantics.g2d.elementclass.MonitorHandler;\r
36 import org.simantics.g2d.image.Image;\r
37 import org.simantics.g2d.image.ProviderUtils;\r
38 import org.simantics.g2d.image.impl.AbstractImage;\r
39 import org.simantics.scenegraph.Node;\r
40 import org.simantics.scenegraph.g2d.G2DParentNode;\r
41 import org.simantics.utils.datastructures.cache.IFactory;\r
42 import org.simantics.utils.datastructures.cache.IProvider;\r
43 import org.simantics.utils.datastructures.cache.ProvisionException;\r
44 import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
45 \r
46 /**\r
47  * @author Tuukka Lehtonen\r
48  */\r
49 public class SymbolMonitorClass {\r
50 \r
51     public static final Key  KEY_SG_NODE             = new SceneGraphNodeKey(Node.class, "SYMBOL_MONITOR_SG_NODE");\r
52 \r
53     public static class MonitorHandlerImpl implements MonitorHandler {\r
54         private static final long          serialVersionUID = -4258875745321808416L;\r
55         public static final MonitorHandler INSTANCE         = new MonitorHandlerImpl();\r
56     }\r
57 \r
58     public static void update(IElement e) {\r
59         SymbolMonitorSGNode node = e.getElementClass().getAtMostOneItemOfClass(SymbolMonitorSGNode.class);\r
60         node.update(e);\r
61     }\r
62 \r
63     public static void cleanup(IElement e) {\r
64         SymbolMonitorSGNode node = e.getElementClass().getAtMostOneItemOfClass(SymbolMonitorSGNode.class);\r
65         node.cleanup(e);\r
66     }\r
67 \r
68     static final Rectangle2D DEFAULT_BOX = new Rectangle2D.Double(0, 0, 0, 0);\r
69 \r
70     static Shape createMonitor(IElement e) {\r
71 \r
72         return DEFAULT_BOX;\r
73 \r
74     }\r
75 \r
76     static Path2D makePath(double x, double y, double w, double h) {\r
77         Path2D path = new Path2D.Double();\r
78         path.moveTo(x, y);\r
79         path.lineTo(x+w, y);\r
80         path.lineTo(x+w, y+h);\r
81         path.lineTo(x, y+h);\r
82         path.closePath();\r
83         return path;\r
84     }\r
85 \r
86     public static final Shape BOX_SHAPE = new Rectangle(-1, -1, 2, 2);\r
87 \r
88     public static class SymbolMonitorSGNode implements SceneGraph, InternalSize, Outline {\r
89 \r
90         private static final long serialVersionUID = -106278359626957687L;\r
91 \r
92         static final SymbolMonitorSGNode INSTANCE = new SymbolMonitorSGNode();\r
93 \r
94         @Override\r
95         public void init(final IElement e, final G2DParentNode parent) {\r
96             // Create node if it doesn't exist yet\r
97             SymbolMonitorNode node = (SymbolMonitorNode)e.getHint(KEY_SG_NODE);\r
98             if(node == null || node.getBounds() == null || node.getParent() != parent) {\r
99                 // FIXME : symbol monitor node is not disposed properly, so currently this code is commented out.\r
100                 //node = parent.addNode(ElementUtils.generateNodeId(e), SymbolMonitorNode.class);\r
101                 //e.setHint(KEY_SG_NODE, node);\r
102             }\r
103             update(e);\r
104         }\r
105 \r
106         public void update(IElement e) {\r
107         }\r
108 \r
109         @Override\r
110         public void cleanup(IElement e) {\r
111             SymbolMonitorNode node = (SymbolMonitorNode)e.removeHint(KEY_SG_NODE);\r
112             if (node != null)\r
113                 node.remove();\r
114         }\r
115 \r
116         @Override\r
117         public Rectangle2D getBounds(IElement e, Rectangle2D size) {\r
118             Rectangle2D shape = new Rectangle2D.Double(0, 0, 0, 0);\r
119 \r
120             SymbolMonitorNode node = (SymbolMonitorNode)e.getHint(KEY_SG_NODE);\r
121             if(node != null && node.getBounds() != null) {\r
122                 shape = node.getBounds().getBounds2D();\r
123             }\r
124 \r
125             if(size != null) size.setRect(shape);\r
126             return shape;\r
127         }\r
128 \r
129         @Override\r
130         public Shape getElementShape(IElement e) {\r
131             Shape shape = new Rectangle2D.Double(0, 0, 0, 0);\r
132 \r
133             SymbolMonitorNode node = (SymbolMonitorNode)e.getHint(KEY_SG_NODE);\r
134             if(node != null && node.getBounds() != null) {\r
135                 shape = node.getBounds();\r
136             }\r
137 \r
138             return shape;\r
139         }\r
140 \r
141     }\r
142 \r
143     public static class Transformer implements Transform {\r
144 \r
145         private static final long serialVersionUID = -3704887325602085677L;\r
146 \r
147         public static final Transformer INSTANCE = new Transformer(null);\r
148 \r
149         Double aspectRatio;\r
150 \r
151         public Transformer() {\r
152             this(null);\r
153         }\r
154 \r
155         public Transformer(Double aspectRatio) {\r
156             this.aspectRatio = aspectRatio;\r
157         }\r
158 \r
159         @Override\r
160         public AffineTransform getTransform(IElement e) {\r
161             AffineTransform at = e.getHint(ElementHints.KEY_TRANSFORM);\r
162 \r
163             IElement parentElement = e.getHint(ElementHints.KEY_PARENT_ELEMENT);\r
164             if (parentElement == null)\r
165                 return at;\r
166 \r
167             Transform parentTransform = parentElement.getElementClass().getSingleItem(Transform.class);\r
168             assert(parentTransform!=null);\r
169 \r
170             AffineTransform result = (AffineTransform)at.clone();\r
171             result.preConcatenate(parentTransform.getTransform(parentElement));\r
172 \r
173             return result;\r
174         }\r
175 \r
176         @Override\r
177         public void setTransform(IElement e, AffineTransform at) {\r
178             e.setHint(ElementHints.KEY_TRANSFORM, at.clone());\r
179         }\r
180 \r
181     }\r
182 \r
183     static class MonitorImageFactory implements IFactory<Image> {\r
184 \r
185         private double staticScaleX = 1, staticScaleY = 1;\r
186 \r
187         public MonitorImageFactory(double staticScaleX, double staticScaleY) {\r
188             this.staticScaleX = staticScaleX;\r
189             this.staticScaleY = staticScaleY;\r
190         }\r
191 \r
192         @Override\r
193         public Image get() throws ProvisionException {\r
194 \r
195             return new AbstractImage() {\r
196 \r
197                 Shape path = BOX_SHAPE;\r
198 \r
199                 @Override\r
200                 public Rectangle2D getBounds() {\r
201                     return path.getBounds2D();\r
202                 }\r
203 \r
204                 @Override\r
205                 public EnumSet<Feature> getFeatures() {\r
206                     return EnumSet.of(Feature.Vector);\r
207                 }\r
208 \r
209                 @Override\r
210                 public Shape getOutline() {\r
211                     return path;\r
212                 }\r
213 \r
214                 @Override\r
215                 public Node init(G2DParentNode parent) {\r
216                     SymbolMonitorNode node = parent.getOrCreateNode(""+hashCode(), SymbolMonitorNode.class);\r
217                     node.setText("");\r
218                     node.setBounds(new Rectangle2D.Double(0, 0, 50, 22));\r
219                     node.setText("Drop Me");\r
220                     node.setTransform(AffineTransform.getScaleInstance(staticScaleX, staticScaleY));\r
221                     return node;\r
222                 }\r
223             };\r
224         }\r
225     }\r
226 \r
227     static final IProvider<Image> MONITOR_IMAGE =\r
228         ProviderUtils.reference(\r
229                 ProviderUtils.cache(\r
230                         ProviderUtils.rasterize(\r
231                                 new MonitorImageFactory(0.5, 0.5)\r
232                         )));\r
233 \r
234     static final StaticSymbol MONITOR_SYMBOL = new StaticSymbolImpl( MONITOR_IMAGE.get() );\r
235 \r
236     public static final ElementClass MONITOR_CLASS =\r
237         ElementClass.compile(\r
238                 MonitorHandlerImpl.INSTANCE,\r
239                 Transformer.INSTANCE,\r
240                 SymbolMonitorSGNode.INSTANCE,\r
241                 SimpleElementLayers.INSTANCE,\r
242                 MONITOR_SYMBOL\r
243         );\r
244 \r
245     // staticScale{X,Y} define the scale of the static monitor image\r
246     public static ElementClass create(IElement parentElement, Map<String, String> substitutions, Collection<Object> path, double staticScaleX, double staticScaleY, ElementHandler... extraHandlers) {\r
247         // Bit of a hack to be able to define the scale\r
248         IProvider<Image> staticMonitorSymbolProvider = ProviderUtils.reference(\r
249                 ProviderUtils.cache(\r
250                         ProviderUtils\r
251                         .rasterize(\r
252                                 new MonitorImageFactory(staticScaleX, staticScaleY))));\r
253         StaticSymbol staticMonitorSymbol = new StaticSymbolImpl( staticMonitorSymbolProvider.get() );\r
254         return ElementClass.compile(\r
255                 MonitorHandlerImpl.INSTANCE,\r
256                 Transformer.INSTANCE,\r
257                 SymbolMonitorSGNode.INSTANCE,\r
258                 SimpleElementLayers.INSTANCE,\r
259                 staticMonitorSymbol\r
260         ).newClassWith(extraHandlers);\r
261     }\r
262 \r
263 }\r