]> gerrit.simantics Code Review - simantics/sysdyn.git/blob
372820ac4098511bea442fd8ccd98b7599ea01d1
[simantics/sysdyn.git] /
1 /*******************************************************************************\r
2  * Copyright (c) 2010, 2012 Association for Decentralized Information Management in\r
3  * 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.sysdyn.ui.elements.connections;\r
13 \r
14 import java.awt.BasicStroke;\r
15 import java.awt.Color;\r
16 import java.awt.Font;\r
17 import java.awt.Shape;\r
18 import java.awt.Stroke;\r
19 import java.awt.geom.Path2D;\r
20 import java.awt.geom.Rectangle2D;\r
21 import java.beans.PropertyChangeEvent;\r
22 import java.beans.PropertyChangeListener;\r
23 import java.util.HashMap;\r
24 import java.util.Map;\r
25 \r
26 import org.simantics.db.Resource;\r
27 import org.simantics.g2d.diagram.DiagramHints;\r
28 import org.simantics.g2d.diagram.DiagramMutator;\r
29 import org.simantics.g2d.diagram.DiagramUtils;\r
30 import org.simantics.g2d.diagram.IDiagram;\r
31 import org.simantics.g2d.diagram.handler.PickRequest.PickPolicy;\r
32 import org.simantics.g2d.diagram.handler.Topology;\r
33 import org.simantics.g2d.diagram.handler.Topology.Connection;\r
34 import org.simantics.g2d.element.ElementClass;\r
35 import org.simantics.g2d.element.ElementHints;\r
36 import org.simantics.g2d.element.ElementUtils;\r
37 import org.simantics.g2d.element.IElement;\r
38 import org.simantics.g2d.element.SceneGraphNodeKey;\r
39 import org.simantics.g2d.element.handler.EdgeVisuals;\r
40 import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd;\r
41 import org.simantics.g2d.element.handler.Pick;\r
42 import org.simantics.g2d.element.handler.SceneGraph;\r
43 import org.simantics.g2d.element.handler.TerminalLayout;\r
44 import org.simantics.g2d.element.handler.Transform;\r
45 import org.simantics.g2d.element.handler.impl.ConfigurableEdgeVisuals;\r
46 import org.simantics.g2d.element.handler.impl.ConnectionSelectionOutline;\r
47 import org.simantics.g2d.element.handler.impl.FillColorImpl;\r
48 import org.simantics.g2d.element.handler.impl.ParentImpl;\r
49 import org.simantics.g2d.element.handler.impl.SimpleElementLayers;\r
50 import org.simantics.g2d.element.handler.impl.TextColorImpl;\r
51 import org.simantics.g2d.element.handler.impl.TextFontImpl;\r
52 import org.simantics.g2d.element.handler.impl.TextImpl;\r
53 import org.simantics.g2d.elementclass.connection.EdgeClass.EdgeHandler;\r
54 import org.simantics.g2d.elementclass.connection.EdgeClass.FixedTransform;\r
55 import org.simantics.g2d.utils.Alignment;\r
56 import org.simantics.scenegraph.g2d.G2DParentNode;\r
57 import org.simantics.scenegraph.utils.NodeUtil;\r
58 import org.simantics.sysdyn.ui.editor.routing.DependencyRouter;\r
59 import org.simantics.utils.datastructures.Callback;\r
60 import org.simantics.utils.datastructures.Pair;\r
61 import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
62 \r
63 public class DependencyEdgeClass {\r
64 \r
65         private static class NodePick implements Pick {\r
66 \r
67             private static final long serialVersionUID = 1L;\r
68             \r
69             public static NodePick INSTANCE = new NodePick();\r
70 \r
71             @Override\r
72             public boolean pickTest(IElement e, Shape s, PickPolicy policy) {\r
73                 Rectangle2D pickRect = null;\r
74                 if (s instanceof Rectangle2D)\r
75                     pickRect = (Rectangle2D) s;\r
76                 else\r
77                     // FIXME: suboptimal, but works.\r
78                     pickRect = s.getBounds2D();\r
79 \r
80             DependencyNode node = e.getHint(SysdynEdgeSceneGraph.KEY_SG_NODE);\r
81             if(node == null) {\r
82                 return false;\r
83             }\r
84             return Arcs.hitTest(node.getBeginBounds(), node.getEndBounds(), node.getAngle(), pickRect.getCenterX(), pickRect.getCenterY(), 1.7);\r
85             \r
86             }\r
87 \r
88         }\r
89         \r
90     public static final ElementClass CLASS =\r
91         ElementClass.compile(\r
92                 SysdynEdgeSceneGraph.INSTANCE,\r
93                 EdgeHandler.INSTANCE,\r
94                 ConfigurableEdgeVisuals.DEFAULT,\r
95                 FillColorImpl.BLACK,\r
96                 FixedTransform.INSTANCE,\r
97                 TextImpl.INSTANCE,\r
98                 TextColorImpl.BLACK,\r
99                 TextFontImpl.DEFAULT,\r
100                 NodePick.INSTANCE,\r
101                 ConnectionSelectionOutline.INSTANCE,\r
102                 SimpleElementLayers.INSTANCE,\r
103                 ParentImpl.INSTANCE\r
104         ).setId("EdgeClass.STRAIGHT");\r
105 \r
106     public static class SysdynEdgeSceneGraph implements SceneGraph {\r
107 \r
108         private static final long serialVersionUID = 2914383071126238996L;\r
109 \r
110         public static final SysdynEdgeSceneGraph INSTANCE = new SysdynEdgeSceneGraph();\r
111 \r
112         public static final Stroke ARROW_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER);\r
113 \r
114         public static final Key KEY_SG_NODE = new SceneGraphNodeKey(DependencyNode.class, "EDGE_NODE");\r
115         \r
116         @Override\r
117         public void init(IElement e, G2DParentNode parent) {\r
118             DependencyNode node = ElementUtils.getOrCreateNode(e, parent, KEY_SG_NODE, "edge_" + e.hashCode(), DependencyNode.class);\r
119             \r
120             Font font = ElementUtils.getTextFont(e);\r
121             Color color = ElementUtils.getTextColor(e);\r
122             \r
123             HashMap<String, Object> properties = e.getHint(DiagramHints.PROPERTIES);\r
124             Pair<?, ?> polarityPair =  (Pair<?, ?>)properties.get("polarity");\r
125             Pair<?, ?> polarityLocationPair =  (Pair<?, ?>)properties.get("polarityLocation");\r
126             \r
127             String location;\r
128             if(polarityLocationPair == null)\r
129                 location = DependencyNode.INSIDE;\r
130             else\r
131                 location = (String) polarityLocationPair.second;\r
132             \r
133             String text = polarityPair != null ? (String)  polarityPair.second : "";\r
134             node.init(text, location, font, color, 0, 0, 0.235);\r
135             \r
136             update(e);\r
137         }\r
138 \r
139         @Override\r
140         public void cleanup(IElement e) {\r
141             ElementUtils.removePossibleNode(e, KEY_SG_NODE);\r
142         }\r
143         \r
144         public void update(final IElement e) {\r
145                 \r
146             DependencyNode node = e.getHint(KEY_SG_NODE);\r
147             if(node == null) return;\r
148             final IDiagram diagram = ElementUtils.peekDiagram(e);\r
149             \r
150             node.setFieldListener(new PropertyChangeListener() {\r
151 \r
152                 @Override\r
153                 public void propertyChange(final PropertyChangeEvent event) {\r
154                         \r
155                                         String field = event.getPropertyName();\r
156                             Map<String, Pair<Resource, Object>> properties = e.getHint(DiagramHints.PROPERTIES);\r
157                             if(properties == null) return;\r
158                             final Pair<Resource, Object> property = properties.get(field);\r
159                             if(property == null) return;\r
160 \r
161                         DiagramUtils.mutateDiagram(diagram, new Callback<DiagramMutator>() {\r
162                                                 \r
163                                                 @Override\r
164                                                 public void run(DiagramMutator mutator) {\r
165                                                         mutator.modifyProperty(e, property.first, event.getNewValue());\r
166                                                 }\r
167                                                 \r
168                                         });\r
169                         \r
170                 }\r
171                 \r
172                         });\r
173 \r
174 \r
175 \r
176             Shape beginTerminalShape = null;\r
177             Shape endTerminalShape = null;\r
178             if (diagram != null) {\r
179                 Topology topology = diagram.getDiagramClass().getAtMostOneItemOfClass(Topology.class);\r
180                 if (topology != null) {\r
181                     Connection beginConnection = topology.getConnection(e, EdgeEnd.Begin);\r
182                     Connection endConnection = topology.getConnection(e, EdgeEnd.End);\r
183                     beginTerminalShape = getCanvasTerminalShape(beginConnection);\r
184                     endTerminalShape = getCanvasTerminalShape(endConnection);\r
185                 }\r
186             }\r
187             \r
188             if(beginTerminalShape == null || endTerminalShape == null) return;\r
189             \r
190             EdgeVisuals vh = e.getElementClass().getSingleItem(EdgeVisuals.class);\r
191             Stroke stroke = vh.getStroke(e);\r
192             Font font = ElementUtils.getTextFont(e);\r
193             Color color = ElementUtils.getTextColor(e);\r
194 //            Color fillColor = ElementUtils.getFillColor(e);\r
195             Color borderColor = ElementUtils.getBorderColor(e, Color.BLACK);\r
196 //            String text = ElementUtils.getText(e);\r
197             Alignment hAlign = ElementUtils.getHintOrDefault(e, ElementHints.KEY_HORIZONTAL_ALIGN, Alignment.CENTER);\r
198             node.setBackgroundColor(null);\r
199             node.setBorderColor(borderColor);\r
200             node.setHorizontalAlignment((byte) hAlign.ordinal());\r
201             node.setPadding(0, 0);\r
202             node.setBorderWidth((float) 0);\r
203             node.setEditable(false);\r
204             node.setFont(font);\r
205             \r
206             node.setBeginBounds(beginTerminalShape.getBounds2D());\r
207             node.setEndBounds(endTerminalShape.getBounds2D());\r
208             node.setStroke(stroke);\r
209             node.setColor(color);\r
210             node.setShapes(DependencyRouter.createArrowShape(node.getShapes(), node.getBeginBounds(), node.getEndBounds(), node.getAngle()));\r
211 \r
212             Map<String, Pair<Resource, Object>> properties = e.getHint(DiagramHints.PROPERTIES);\r
213             if(properties != null) {\r
214                         for(Map.Entry<String, Pair<Resource, Object>> entry : properties.entrySet()) {\r
215                                 NodeUtil.setPropertyIfSupported(entry.getKey(), entry.getValue().second, node);                         \r
216 //                              node.setProperty(entry.getKey(), entry.getValue().second);\r
217 //                              System.out.println("setProperty " + entry.getKey() + " => " + entry.getValue().second);\r
218                         }\r
219             }\r
220             EdgeHandler eh = e.getElementClass().getAtMostOneItemOfClass(EdgeHandler.class);\r
221             Path2D path = eh.getPath(e);\r
222             if(path == null)\r
223                 path = new Path2D.Double();\r
224             else\r
225                 path.reset();\r
226             path.append(node.getShapes().first, false);\r
227             eh.setPath(e, path);\r
228 \r
229         }\r
230 \r
231         private static Shape getCanvasTerminalShape(Connection connection) {\r
232             if (connection != null && connection.node != null && connection.terminal != null) {\r
233                 TerminalLayout layout = connection.node.getElementClass().getAtMostOneItemOfClass(TerminalLayout.class);\r
234                 if (layout != null) {\r
235                     //return layout.getTerminalShape(connection.node, connection.terminal);\r
236                     Shape shp = layout.getTerminalShape(connection.node, connection.terminal);\r
237                     Transform tr = connection.node.getElementClass().getAtMostOneItemOfClass(Transform.class);\r
238                     if (tr == null)\r
239                         return shp;\r
240 \r
241                     return tr.getTransform(connection.node).createTransformedShape(shp);\r
242                     \r
243                 }\r
244             }\r
245             return null;\r
246         }\r
247 \r
248     }\r
249   \r
250 }\r