]> gerrit.simantics Code Review - simantics/sysdyn.git/blob
19e93e0d7c9c60c589ca1ed40f695230a41237d3
[simantics/sysdyn.git] /
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 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.editor.participant;\r
13 \r
14 import java.awt.geom.AffineTransform;\r
15 import java.awt.geom.Point2D;\r
16 import java.util.ArrayList;\r
17 import java.util.Deque;\r
18 import java.util.Iterator;\r
19 import java.util.List;\r
20 \r
21 import org.simantics.db.Resource;\r
22 import org.simantics.db.WriteGraph;\r
23 import org.simantics.db.common.utils.OrderedSetUtils;\r
24 import org.simantics.db.exception.DatabaseException;\r
25 import org.simantics.diagram.content.ConnectionUtil;\r
26 import org.simantics.diagram.participant.ConnectionBuilder;\r
27 import org.simantics.diagram.participant.ControlPoint;\r
28 import org.simantics.diagram.stubs.DiagramResource;\r
29 import org.simantics.diagram.stubs.G2DResource;\r
30 import org.simantics.diagram.ui.DiagramModelHints;\r
31 import org.simantics.g2d.diagram.IDiagram;\r
32 import org.simantics.g2d.diagram.handler.Topology.Terminal;\r
33 import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil;\r
34 import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil.TerminalInfo;\r
35 import org.simantics.g2d.element.ElementClass;\r
36 import org.simantics.g2d.element.ElementClasses;\r
37 import org.simantics.g2d.element.ElementHints;\r
38 import org.simantics.g2d.element.ElementUtils;\r
39 import org.simantics.g2d.element.IElement;\r
40 import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd;\r
41 import org.simantics.g2d.element.impl.Element;\r
42 import org.simantics.g2d.elementclass.FlagClass;\r
43 import org.simantics.layer0.Layer0;\r
44 import org.simantics.structural2.modelingRules.ConnectionJudgement;\r
45 import org.simantics.structural2.modelingRules.IModelingRules;\r
46 import org.simantics.sysdyn.ui.elements.SysdynElementClasses;\r
47 import org.simantics.sysdyn.ui.elements.ValveFactory;\r
48 import org.simantics.sysdyn.ui.elements.connections.ConnectionClasses;\r
49 import org.simantics.utils.datastructures.Pair;\r
50 \r
51 public class SysdynConnectionBuilder extends ConnectionBuilder{\r
52 \r
53         public SysdynConnectionBuilder(IDiagram diagram) {\r
54                 super(diagram);\r
55         }\r
56 \r
57     /**\r
58      * @param graph\r
59      * @param judgment\r
60      * @param controlPoints\r
61      * @param startTerminal\r
62      * @param endTerminal\r
63      * @throws DatabaseException\r
64      */\r
65     public void create(WriteGraph graph, ConnectionJudgement judgment, Deque<ControlPoint> controlPoints,\r
66             TerminalInfo startTerminal, TerminalInfo endTerminal) throws DatabaseException {\r
67         // If needs a valve, we will create two separate connections\r
68         if(needsValve(startTerminal, endTerminal)) {\r
69                 createValveAndConnections(graph, judgment, controlPoints, startTerminal, endTerminal);\r
70         } \r
71         // If no need for valve, just call createConnection with false on createValve parameter\r
72         else {\r
73                 createConnection(graph, judgment, controlPoints, startTerminal, endTerminal, false);\r
74         }\r
75     }\r
76     /**\r
77      * @param graph\r
78      * @param judgment\r
79      * @param controlPoints\r
80      * @param startTerminal\r
81      * @param endTerminal\r
82      * @throws DatabaseException\r
83      */\r
84     public TerminalInfo createConnection(WriteGraph graph, ConnectionJudgement judgment, Deque<ControlPoint> controlPoints,\r
85             TerminalInfo startTerminal, TerminalInfo endTerminal, boolean createValve) throws DatabaseException {\r
86         TerminalInfo newValve = null;\r
87 \r
88         this.cu = new ConnectionUtil(graph);\r
89 \r
90         // 1. Get diagram connection to construct.\r
91         Resource connection = getOrCreateConnection(graph, startTerminal, endTerminal);\r
92 \r
93         // 2. Add branch points\r
94         List<Pair<ControlPoint, Resource>> bps = createBranchPoints(graph, connection, controlPoints);\r
95         \r
96         // 3. Create edges between branch points.\r
97         Resource firstBranchPoint = null;\r
98         Resource lastBranchPoint = null;\r
99         if (!bps.isEmpty()) {\r
100             Iterator<Pair<ControlPoint, Resource>> it = bps.iterator();\r
101             Pair<ControlPoint, Resource> prev = it.next();\r
102             firstBranchPoint = prev.second;\r
103             while (it.hasNext()) {\r
104                 Pair<ControlPoint, Resource> next = it.next();\r
105                 cu.connect(prev.second, next.second);\r
106                 prev = next;\r
107             }\r
108             lastBranchPoint = prev.second;\r
109         }\r
110 \r
111         // 4. Connect start/end terminals if those exist.\r
112         // If first/lastBranchPoint != null, connect to those.\r
113         // Otherwise connect the start/end terminals together.\r
114         Connector startConnector = null;\r
115         Connector endConnector = null;\r
116         IElement startFlag = null;\r
117         IElement endFlag = null;\r
118 \r
119         if (startTerminal != null) {\r
120             startConnector = createConnectorForNode(graph, connection, startTerminal, EdgeEnd.Begin, judgment);\r
121         } else if (createFlags) {\r
122             startFlag = createFlag(graph, connection, EdgeEnd.Begin, controlPoints.getFirst(), FlagClass.Type.In, "");\r
123                         ArrayList<Terminal> terminals = new ArrayList<Terminal>();\r
124                         ElementUtils.getTerminals(startFlag, terminals, false);\r
125                         Terminal st = terminals.get(1);\r
126             startConnector = createConnectorForNode(graph, connection, (Resource) ElementUtils.getObject(startFlag),\r
127                     st, EdgeEnd.Begin, judgment);\r
128         }\r
129 \r
130         if (endTerminal != null) {\r
131             endConnector = createConnectorForNode(graph, connection, endTerminal, EdgeEnd.End, judgment);\r
132         } else if (createFlags) {\r
133                 if(createValve)\r
134                 endFlag = createValveElement(graph, connection, EdgeEnd.End, controlPoints.getLast());\r
135                 else\r
136                         endFlag = createFlag(graph, connection, EdgeEnd.End, controlPoints.getLast(), FlagClass.Type.Out, "");\r
137                         ArrayList<Terminal> terminals = new ArrayList<Terminal>();\r
138                         ElementUtils.getTerminals(endFlag, terminals, false);\r
139                         Terminal et = terminals.get(0);\r
140             endConnector = createConnectorForNode(graph, connection, (Resource) ElementUtils.getObject(endFlag),\r
141                     et, EdgeEnd.End, judgment);\r
142             \r
143             if(createValve) {\r
144                 newValve = new TerminalInfo();\r
145                 newValve.e = endFlag;\r
146                 newValve.t = terminals.get(1);\r
147                 newValve.posElem = TerminalUtil.getTerminalPosOnElement(endFlag, newValve.t);\r
148                 newValve.posDia = TerminalUtil.getTerminalPosOnDiagram(endFlag, newValve.t);\r
149             }\r
150         }\r
151 \r
152         if (firstBranchPoint == null || lastBranchPoint == null) {\r
153             cu.connect(startConnector.getConnector(), endConnector.getConnector());\r
154         } else {\r
155             cu.connect(startConnector.getConnector(), firstBranchPoint);\r
156             cu.connect(lastBranchPoint, endConnector.getConnector());\r
157         }\r
158 \r
159         // 5. Finally, set connection type according to modelling rules\r
160         IModelingRules modelingRules = diagram.getHint(DiagramModelHints.KEY_MODELING_RULES);\r
161         if (judgment.connectionType != null && modelingRules != null) {\r
162             modelingRules.setConnectionType(graph, connection, judgment.connectionType);\r
163         }\r
164 \r
165         this.cu = null;\r
166         return newValve;\r
167     }\r
168     \r
169     \r
170     /**\r
171      * @param graph\r
172      * @param connection\r
173      * @param end\r
174      * @param cp\r
175      * @param type\r
176      * @return an element describing the new created flag resource\r
177      * @throws DatabaseException\r
178      */\r
179     public IElement createValveElement(WriteGraph graph, Resource connection, EdgeEnd end, ControlPoint cp) throws DatabaseException {\r
180         ElementClass valveClass = elementClassProvider.get(SysdynElementClasses.VALVE);\r
181         IElement valveElement = Element.spawnNew(valveClass);\r
182         Resource valveClassResource = ElementUtils.checkedAdapt(valveClass, Resource.class);\r
183 \r
184         Layer0 L0 = Layer0.getInstance(graph);\r
185         G2DResource G2D = G2DResource.getInstance(graph);\r
186         DiagramResource DIA = DiagramResource.getInstance(graph);\r
187 \r
188         Resource valve = graph.newResource();\r
189         graph.claim(valve, L0.InstanceOf, null, valveClassResource);\r
190         graph.claim(valve, L0.PartOf, diagramResource);\r
191         valveElement.setHint(ElementHints.KEY_OBJECT, valve);\r
192 \r
193         OrderedSetUtils.add(graph, diagramResource, valve);\r
194 \r
195         AffineTransform at = AffineTransform.getTranslateInstance(cp.getPosition().getX(), cp.getPosition().getY());\r
196         valveElement.setHint(ElementHints.KEY_TRANSFORM, at);\r
197         double[] matrix = new double[6];\r
198         at.getMatrix(matrix);\r
199         graph.claimLiteral(valve, DIA.HasTransform, G2D.Transform, matrix);\r
200 \r
201         // Put the element on all the currently active layers if possible.\r
202         if (layerManager != null) {\r
203             layerManager.removeFromAllLayers(graph, valve);\r
204             layerManager.putElementOnVisibleLayers(diagram, graph, valve);\r
205         }\r
206 \r
207         return valveElement;\r
208     }\r
209     \r
210     private boolean needsValve(TerminalInfo startTerminal, TerminalInfo endTerminal) {\r
211                 if (!elementClassProvider.get(ElementClasses.CONNECTION)\r
212                                 .equals(elementClassProvider.get(ConnectionClasses.FLOW))) \r
213                         return false;\r
214                 if(startTerminal != null && startTerminal.e != null && startTerminal.e.getElementClass().getId().equals(ValveFactory.class.getSimpleName())) {\r
215                         return false;\r
216                 } else if(endTerminal != null && endTerminal.e != null && endTerminal.e.getElementClass().getId().equals(ValveFactory.class.getSimpleName())) {\r
217                         return false;\r
218                 }\r
219                 return true;\r
220     }\r
221     \r
222     private void createValveAndConnections(WriteGraph graph, ConnectionJudgement judgment, Deque<ControlPoint> controlPoints,\r
223             TerminalInfo startTerminal, TerminalInfo endTerminal) throws DatabaseException {\r
224         \r
225                 ControlPoint cpfirst = controlPoints.getFirst();\r
226                 ControlPoint cplast = controlPoints.getLast();\r
227 \r
228                 // Set the position in the middle of the route\r
229                 double startX = cpfirst.getPosition().getX();\r
230                 double startY = cpfirst.getPosition().getY();\r
231                 double x = cplast.getPosition().getX();\r
232                 double y = cplast.getPosition().getY();\r
233                 Point2D pos = new Point2D.Double(startX - (startX - x) / 2, startY - (startY - y) / 2);\r
234                 \r
235                 // Replace the last control point with the control point in the middle\r
236         controlPoints.getLast().setPosition(pos);\r
237 \r
238         // Create a connection to a new valve and get the new valve\r
239         TerminalInfo newValve = createConnection(graph, judgment, controlPoints, startTerminal, null, true);\r
240         \r
241                 // Replace the last control point with the original control point\r
242         controlPoints.getLast().setPosition(x, y);\r
243         \r
244         // Create a connection starting from the new valve\r
245                 createConnection(graph, judgment, controlPoints, newValve, endTerminal, false);\r
246     }\r
247 }\r