]> gerrit.simantics Code Review - simantics/sysdyn.git/commitdiff
Removed old Connect tool that used diagram mutator. New Connect tool does not use...
authorlempinen <lempinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Wed, 29 Dec 2010 12:08:15 +0000 (12:08 +0000)
committerlempinen <lempinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Wed, 29 Dec 2010 12:08:15 +0000 (12:08 +0000)
git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@19226 ac1ea38d-2e2b-0410-8846-a27921b304fc

org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/DiagramViewer.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/SysdynConnectionAdvisor.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/ConnectTool.java [deleted file]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/PointerInteractor.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/SysdynConnectTool.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/SysdynConnectionBuilder.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/SysdynElementClassProviders.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/routing/DependencyRouter.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynElementClasses.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/ExpressionUtils.java

index 85b88f8af83b40e9b51144c5135a35f5ee9513ee..b0b181cf4c18c0cc3e203fc7f40ace123308616d 100644 (file)
@@ -39,7 +39,7 @@ import org.simantics.g2d.diagram.DiagramHints;
 import org.simantics.g2d.diagram.participant.DeleteHandler;\r
 import org.simantics.g2d.diagram.participant.ElementPainter;\r
 import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor;\r
-import org.simantics.g2d.element.ElementClassProviders;\r
+import org.simantics.g2d.element.ElementClass;\r
 import org.simantics.g2d.element.ElementClasses;\r
 import org.simantics.g2d.element.ElementHints;\r
 import org.simantics.g2d.element.IElement;\r
@@ -55,8 +55,10 @@ import org.simantics.structural2.modelingRules.IModelingRules;
 import org.simantics.sysdyn.SysdynResource;\r
 import org.simantics.sysdyn.ui.editor.participant.CreateVariablesShortcutParticipant;\r
 import org.simantics.sysdyn.ui.editor.participant.SysdynComponentCopyAdvisor;\r
+import org.simantics.sysdyn.ui.editor.participant.SysdynElementClassProviders;\r
 import org.simantics.sysdyn.ui.editor.participant.SysdynPopulateElementDropParticipant;\r
 import org.simantics.sysdyn.ui.elements2.CloudFactory;\r
+import org.simantics.sysdyn.ui.elements2.SysdynElementClasses;\r
 import org.simantics.sysdyn.ui.elements2.SysdynElementFactory;\r
 import org.simantics.sysdyn.ui.elements2.connections.ConnectionClasses;\r
 import org.simantics.sysdyn.ui.elements2.connections.SysdynConnectionClass;\r
@@ -99,11 +101,13 @@ public class DiagramViewer extends org.simantics.modeling.ui.diagramEditor.Diagr
        @Override\r
        protected IElementClassProvider createElementClassProvider(ReadGraph graph) {\r
                SysdynResource sr = SysdynResource.getInstance(graph);\r
-               return ElementClassProviders.mappedProvider(\r
-                               ElementClasses.CONNECTION, SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.FlowConnection)),\r
+               ElementClass dependencyClass = SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.DependencyConnection));\r
+               return SysdynElementClassProviders.mappedProvider(\r
+                               ElementClasses.CONNECTION, dependencyClass,\r
                                ElementClasses.FLAG, CloudFactory.createElementClass(sr.CloudSymbol, SysdynElementFactory.createTerminals(graph, sr.CloudSymbol)),\r
                                ConnectionClasses.FLOW, SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.FlowConnection)),\r
-                               ConnectionClasses.DEPENDENCY, SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.DependencyConnection))\r
+                               ConnectionClasses.DEPENDENCY, dependencyClass,\r
+                               SysdynElementClasses.VALVE,  CloudFactory.createElementClass(sr.ValveSymbol, SysdynElementFactory.createTerminals(graph, sr.ValveSymbol))\r
                );\r
 \r
 \r
index f9c3e21d96741e72b7aecf698fb12b1f974bb0fc..e21d6abb6d0d081659ffba18e5d7c3cb89cf0ae4 100644 (file)
@@ -26,6 +26,7 @@ import org.simantics.g2d.connection.IConnectionAdvisor;
 import org.simantics.g2d.diagram.handler.Topology.Terminal;\r
 import org.simantics.g2d.element.ElementUtils;\r
 import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
 import org.simantics.structural.stubs.StructuralResource2;\r
 import org.simantics.structural2.modelingRules.CPIgnore;\r
 import org.simantics.structural2.modelingRules.ConnectionJudgement;\r
@@ -77,26 +78,26 @@ public class SysdynConnectionAdvisor  implements IConnectionAdvisor {
                                @Override\r
                                public Object perform(ReadGraph g) throws DatabaseException {\r
                                        if(element1 != null && term1 != null && element2 != null && term2 != null) {\r
-                                               SysdynResource sr = SysdynResource.getInstance(g);\r
+                                               StaticObjectAdapter soa = element1.getElementClass().getSingleItem(StaticObjectAdapter.class);\r
+                                               Resource startElementResource = soa.adapt(Resource.class);\r
+                                               soa = element2.getElementClass().getSingleItem(StaticObjectAdapter.class);\r
+                                               Resource endElementResource = soa.adapt(Resource.class);\r
+                                               \r
                                                DiagramResource dr = DiagramResource.getInstance(g);\r
                                                StructuralResource2 str2  = StructuralResource2.getInstance(g);\r
                                                Resource terminal2 = ((ResourceTerminal) term2).getResource();\r
+                                               SysdynResource sr = SysdynResource.getInstance(g);\r
+\r
                                                Resource connectionVariable = g.getPossibleObject(terminal2, dr.HasConnectionVariable);\r
                                                if(!g.hasStatement(connectionVariable, str2.Binds, sr.IsHeadOfTerminal)) {\r
                                                        return null;\r
                                                }\r
-\r
-                                               // Only one incoming dependency allowed in inputs. That dependency must be from a module\r
-                                               Object obj1 = ElementUtils.getObject(element1);\r
-                                               Object obj2 = ElementUtils.getObject(element2);\r
-                                               if(obj1 instanceof Resource && obj2 instanceof Resource) {\r
-                                                       Resource startElementResource = (Resource)obj1;\r
-                                                       Resource endElementResource = (Resource)obj2;\r
-                                                       if(g.isInstanceOf(endElementResource, sr.InputSymbol)) {\r
-                                                               if(g.isInheritedFrom(startElementResource, sr.ModuleSymbol)) return null;\r
-                                                               if(g.getObjects(endElementResource, sr.IsHeadOfTerminal).size() > 0) return null;\r
-                                                       }\r
+                                               \r
+                                               if(g.isInstanceOf(endElementResource, sr.InputSymbol)) {\r
+                                                       if(g.isInheritedFrom(startElementResource, sr.ModuleSymbol)) return null;\r
+                                                       if(g.getObjects(endElementResource, sr.IsHeadOfTerminal).size() > 0) return null;\r
                                                }\r
+                                               \r
                                        }\r
 \r
                                        ArrayList<IConnectionPoint> cps = new ArrayList<IConnectionPoint>();\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/ConnectTool.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/ConnectTool.java
deleted file mode 100644 (file)
index c90d117..0000000
+++ /dev/null
@@ -1,726 +0,0 @@
-/*******************************************************************************\r
- * Copyright (c) 2010 Association for Decentralized Information Management in\r
- * Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.sysdyn.ui.editor.participant;\r
-\r
-import java.awt.AlphaComposite;\r
-import java.awt.Composite;\r
-import java.awt.geom.Point2D;\r
-import java.util.ArrayDeque;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Deque;\r
-import java.util.HashMap;\r
-import java.util.List;\r
-\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.common.request.Queries;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.request.Read;\r
-import org.simantics.diagram.query.DiagramRequests;\r
-import org.simantics.g2d.canvas.ICanvasContext;\r
-import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;\r
-import org.simantics.g2d.canvas.impl.SGNodeReflection.SGCleanup;\r
-import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;\r
-import org.simantics.g2d.command.CommandEvent;\r
-import org.simantics.g2d.command.Commands;\r
-import org.simantics.g2d.connection.IConnectionAdvisor;\r
-import org.simantics.g2d.connection.handler.ConnectionHandler;\r
-import org.simantics.g2d.diagram.DiagramHints;\r
-import org.simantics.g2d.diagram.DiagramMutator;\r
-import org.simantics.g2d.diagram.DiagramUtils;\r
-import org.simantics.g2d.diagram.IDiagram;\r
-import org.simantics.g2d.diagram.handler.PickContext;\r
-import org.simantics.g2d.diagram.handler.Topology;\r
-import org.simantics.g2d.diagram.handler.Topology.Connection;\r
-import org.simantics.g2d.diagram.handler.Topology.Terminal;\r
-import org.simantics.g2d.diagram.handler.TransactionContext.TransactionType;\r
-import org.simantics.g2d.diagram.impl.Diagram;\r
-import org.simantics.g2d.diagram.impl.MutatedDiagram;\r
-import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant;\r
-import org.simantics.g2d.diagram.participant.ElementPainter;\r
-import org.simantics.g2d.diagram.participant.TerminalPainter;\r
-import org.simantics.g2d.diagram.participant.TerminalPainter.TerminalHoverStrategy;\r
-import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor;\r
-import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil.TerminalInfo;\r
-import org.simantics.g2d.element.ElementClass;\r
-import org.simantics.g2d.element.ElementHints;\r
-import org.simantics.g2d.element.ElementUtils;\r
-import org.simantics.g2d.element.IElement;\r
-import org.simantics.g2d.element.SceneGraphNodeKey;\r
-import org.simantics.g2d.element.handler.Parent;\r
-import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd;\r
-import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
-import org.simantics.g2d.elementclass.BranchPoint;\r
-import org.simantics.g2d.elementclass.FlagClass;\r
-import org.simantics.g2d.event.Event;\r
-import org.simantics.g2d.event.KeyEvent;\r
-import org.simantics.g2d.event.MouseEvent;\r
-import org.simantics.g2d.event.EventHandlerReflection.EventHandler;\r
-import org.simantics.g2d.event.KeyEvent.KeyPressedEvent;\r
-import org.simantics.g2d.event.MouseEvent.MouseButtonEvent;\r
-import org.simantics.g2d.event.MouseEvent.MouseButtonPressedEvent;\r
-import org.simantics.g2d.event.MouseEvent.MouseMovedEvent;\r
-import org.simantics.g2d.participant.KeyUtil;\r
-import org.simantics.g2d.participant.MouseUtil;\r
-import org.simantics.g2d.participant.TransformUtil;\r
-import org.simantics.g2d.snap.ISnapAdvisor;\r
-import org.simantics.scenegraph.Node;\r
-import org.simantics.scenegraph.g2d.G2DParentNode;\r
-import org.simantics.sysdyn.SysdynResource;\r
-import org.simantics.sysdyn.ui.elements2.ValveFactory;\r
-import org.simantics.ui.SimanticsUI;\r
-import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
-\r
-public class ConnectTool extends AbstractDiagramParticipant {\r
-\r
-\r
-       public static final Key KEY_SG_NODE = new SceneGraphNodeKey(Node.class, "CONNECT_SG_NODE");\r
-\r
-       @Dependency TransformUtil util;\r
-       @Dependency ElementPainter diagramPainter;\r
-       @Dependency PickContext pickContext;\r
-       @Dependency PointerInteractor pi;\r
-       @Dependency MouseUtil mouseUtil;\r
-       @Dependency KeyUtil keys;\r
-\r
-       boolean               createFlags;\r
-       Point2D               startPos;\r
-\r
-       IElement              startElement;\r
-       Terminal              startTerminal;\r
-\r
-       IElement              endElement;\r
-       Terminal              endTerminal;\r
-\r
-       IDiagram              inputDiagram;\r
-       MutatedDiagram        ghostDiagram;\r
-       Topology              topology;\r
-\r
-       ElementClass          connectionClass;\r
-\r
-       ConnectionHandler     connectionHandler;\r
-       IElement              connection;\r
-       Deque<IElement>       edges                 = new ArrayDeque<IElement>();\r
-       Deque<IElement>       controlPoints         = new ArrayDeque<IElement>();\r
-       int                   mouseId;\r
-\r
-       Collection<Terminal>  terminals             = new ArrayList<Terminal>();\r
-\r
-       TerminalHoverStrategy originalStrategy = null;\r
-       TerminalHoverStrategy terminalHoverStrategy = new TerminalHoverStrategy() {\r
-               @Override\r
-               public boolean highlightEnabled() {\r
-                       return true;\r
-               }\r
-\r
-               @Override\r
-               public boolean highlight(TerminalInfo ti) {\r
-                       IConnectionAdvisor advisor = diagram.getHint(DiagramHints.CONNECTION_ADVISOR);\r
-                       return canConnect(advisor, ti.e, ti.t) != null;\r
-               }\r
-       };\r
-\r
-       public ConnectTool(IDiagram diagram, ElementClass connectionClass, IElement startElement, Terminal startTerminal, int mouseId, Point2D mouseDiagramPos)\r
-       {\r
-               this.inputDiagram = diagram;\r
-               this.connectionClass = connectionClass;\r
-               this.mouseId = mouseId;\r
-               this.startPos = mouseDiagramPos;\r
-               this.startElement = startElement;\r
-               this.startTerminal = startTerminal;\r
-       }\r
-\r
-       @Override\r
-       public void addedToContext(ICanvasContext ctx) {\r
-\r
-               super.addedToContext(ctx);\r
-\r
-               // Force terminals to always be highlighted.\r
-               originalStrategy = getHint(TerminalPainter.TERMINAL_HOVER_STRATEGY);\r
-               setHint(TerminalPainter.TERMINAL_HOVER_STRATEGY, terminalHoverStrategy);\r
-\r
-               // See if flags should be created or not\r
-               this.createFlags = Boolean.TRUE.equals(inputDiagram.getHint(DiagramHints.KEY_USE_CONNECTION_FLAGS));\r
-\r
-               // Mutate current diagram and add the connection to the mutated copy.\r
-               ghostDiagram = Diagram.mutate(inputDiagram);\r
-               topology = ghostDiagram.getDiagramClass().getSingleItem(Topology.class);\r
-\r
-               IElement firstElement = null;\r
-               Terminal firstTerminal = null;\r
-\r
-               // Where is start terminal?\r
-               if (startElement != null && startTerminal != null) {\r
-                       // Whoomp, there it is. Is it already a part of an existing connection?\r
-                       assert ElementUtils.peekDiagram(startElement) == inputDiagram;\r
-                       IElement possibleConnection = getConnectionFromPart(startElement);\r
-                       if (possibleConnection != null) {\r
-                               // TODO: broken.\r
-                               connection = ghostDiagram.getMutatedCorrespondence(possibleConnection);\r
-                       } else {\r
-                               connection = createConnection(connectionClass);\r
-                               ghostDiagram.addElement(connection);\r
-                       }\r
-\r
-                       connectionHandler = connection.getElementClass().getSingleItem(ConnectionHandler.class);\r
-                       assert connectionHandler != null;\r
-\r
-                       firstElement = ghostDiagram.getMutatedCorrespondence(startElement);\r
-                       firstTerminal = startTerminal;\r
-               } else {\r
-                       connection = createConnection(connectionClass);\r
-                       connectionHandler = connection.getElementClass().getSingleItem(ConnectionHandler.class);\r
-                       assert connectionHandler != null;\r
-                       ghostDiagram.addElement(connection);\r
-\r
-                       firstElement = createBranchPointOrFlag(startPos, EdgeEnd.Begin);\r
-                       ArrayList<Terminal> terminals = new ArrayList<Terminal>();\r
-                       ElementUtils.getTerminals(firstElement, terminals, false);\r
-                       firstTerminal = terminals.get(1);\r
-                       startElement = firstElement;\r
-                       startTerminal = firstTerminal;\r
-               }\r
-\r
-               IElement secondElement = connectionHandler.newBranchPoint(connection);\r
-               controlPoints.add(secondElement);\r
-               //        ghostDiagram.addElement(secondElement);\r
-               ElementUtils.setPos(secondElement, startPos);\r
-               Terminal secondTerminal = ElementUtils.getSingleTerminal(secondElement);\r
-\r
-               IElement edge = connectionHandler.newEdge(connection);\r
-               edges.add(edge);\r
-               //        ghostDiagram.addElement(edge);\r
-\r
-               topology.connect(edge, EdgeEnd.Begin, firstElement, firstTerminal);\r
-               topology.connect(edge, EdgeEnd.End, secondElement, secondTerminal);\r
-\r
-       }\r
-\r
-\r
-\r
-       private void createValveIfNecessary(Point2D point) {\r
-               if (!isCurrentConnectionFlow()) return;\r
-               \r
-               if(startElement != null && startElement.getElementClass().getId().equals(ValveFactory.class.getSimpleName())) {\r
-                       return;\r
-               } else if(endElement != null && endElement.getElementClass().getId().equals(ValveFactory.class.getSimpleName())) {\r
-                       return;\r
-               }\r
-\r
-               ArrayList<Terminal> terminals = new ArrayList<Terminal>();\r
-\r
-               if(endElement != null) {\r
-                       // Disconnect from end element\r
-                       topology.disconnect(edges.peekLast(), EdgeEnd.End, ghostDiagram.getMutatedCorrespondence(endElement), endTerminal);\r
-               }  else {\r
-                       IElement lastBp = controlPoints.pollLast();\r
-                       ElementUtils.getTerminals(lastBp, terminals, true);\r
-                       topology.disconnect(edges.peekLast(), EdgeEnd.End, lastBp, terminals.get(0));\r
-                       connectionHandler.removeBranchPoint(connection, lastBp);\r
-               }\r
-\r
-\r
-               // Set the position in the middle of the route\r
-               double startX = startPos.getX();\r
-               double startY = startPos.getY();\r
-               double x = point.getX();\r
-               double y = point.getY();\r
-               Point2D pos = new Point2D.Double((startX + x) / 2, (startY + y) / 2);\r
-               \r
-               // Create the valve\r
-               IElement end = createValve(pos);\r
-\r
-               ElementUtils.getTerminals(end, terminals, true);\r
-               topology.connect(edges.peekLast(), EdgeEnd.End, end, terminals.get(0));\r
-               DiagramUtils.validateAndFix(ghostDiagram, getContext());\r
-\r
-\r
-               IElement firstElement = end;\r
-               Terminal firstTerminal = terminals.get(1);\r
-\r
-\r
-               IElement possibleConnection = getConnectionFromPart(firstElement);\r
-               if (possibleConnection != null) {\r
-                       // TODO: broken.\r
-                       connection = ghostDiagram.getMutatedCorrespondence(possibleConnection);\r
-               } else {\r
-                       connection = createConnection(connectionClass);\r
-                       ghostDiagram.addElement(connection);\r
-               }\r
-\r
-               connectionHandler = connection.getElementClass().getSingleItem(ConnectionHandler.class);\r
-\r
-\r
-\r
-\r
-               IElement edge = connectionHandler.newEdge(connection);\r
-               edges.add(edge);\r
-\r
-               topology.connect(edge, EdgeEnd.Begin, firstElement, firstTerminal);\r
-               \r
-               if (endElement != null) {\r
-                       IConnectionAdvisor advisor = diagram.getHint(DiagramHints.CONNECTION_ADVISOR);\r
-                       Object canConnect = canConnect(advisor, ghostDiagram.getMutatedCorrespondence(endElement), endTerminal);\r
-                       if(canConnect != null) {\r
-                               connection.setHint(ElementHints.KEY_CONNECTION_TYPE, canConnect);\r
-                       }\r
-                       topology.connect(edge, EdgeEnd.End, ghostDiagram.getMutatedCorrespondence(endElement), endTerminal);\r
-               } else {\r
-                       IElement secondElement = connectionHandler.newBranchPoint(connection);\r
-                       controlPoints.add(secondElement);\r
-                       ElementUtils.setPos(secondElement, pos);\r
-                       Terminal secondTerminal = ElementUtils.getSingleTerminal(secondElement);\r
-                       IConnectionAdvisor advisor = diagram.getHint(DiagramHints.CONNECTION_ADVISOR);\r
-                       Object canConnect = canConnect(advisor, null, null);\r
-                       if(canConnect != null) {\r
-                               connection.setHint(ElementHints.KEY_CONNECTION_TYPE, canConnect);\r
-                       }\r
-                       \r
-                       topology.connect(edge, EdgeEnd.End, secondElement, secondTerminal);\r
-               }\r
-               DiagramUtils.validateAndFix(ghostDiagram, getContext());\r
-\r
-       }\r
-\r
-       @Override\r
-       public void removedFromContext(ICanvasContext ctx) {\r
-\r
-               if (getHint(TerminalPainter.TERMINAL_HOVER_STRATEGY) == terminalHoverStrategy) {\r
-                       if (originalStrategy != null)\r
-                               setHint(TerminalPainter.TERMINAL_HOVER_STRATEGY, originalStrategy);\r
-                       else\r
-                               removeHint(TerminalPainter.TERMINAL_HOVER_STRATEGY);\r
-               }\r
-\r
-               ghostDiagram.destroy();\r
-\r
-               super.removedFromContext(ctx);\r
-       }\r
-\r
-       final static Composite ALPHA_COMPOSITE = AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.75f);\r
-       public static final int PAINT_PRIORITY = ElementPainter.ELEMENT_PAINT_PRIORITY + 5;\r
-\r
-       protected G2DParentNode node = null;\r
-\r
-       @SGInit\r
-       public void initSG(G2DParentNode parent) {\r
-               node = parent.addNode(G2DParentNode.class);\r
-               node.setZIndex(PAINT_PRIORITY);\r
-               update();\r
-       }\r
-\r
-       public void update() {\r
-               if (ghostDiagram != null) {\r
-                       diagramPainter.paintDiagram(node, ghostDiagram, ghostDiagram.getDifferences(), KEY_SG_NODE);\r
-               }\r
-       }\r
-\r
-       @SGCleanup\r
-       public void cleanupSG() {\r
-               node.remove();\r
-               node = null;\r
-       }\r
-\r
-       boolean cancelPreviousBend() {\r
-               if (!routePointsAllowed())\r
-                       return false;\r
-\r
-               // If not at the first branch point, remove the last branch\r
-               // point and edge. Otherwise, cancel action\r
-               if (controlPoints.size() < 2) {\r
-                       DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR);\r
-                       mutator.clear();\r
-                       update();\r
-                       remove();\r
-                       return true;\r
-               }\r
-               // Cancel prev bend\r
-               IElement lastControlPoint = controlPoints.removeLast();\r
-               IElement prevControlPoint = controlPoints.peekLast();\r
-               IElement lastEdge = edges.removeLast();\r
-               for (Terminal t : ElementUtils.getTerminals(lastControlPoint, terminals, true))\r
-                       topology.disconnect(lastEdge, EdgeEnd.End, lastControlPoint, t);\r
-               for (Terminal t : ElementUtils.getTerminals(prevControlPoint, terminals, true))\r
-                       topology.disconnect(lastEdge, EdgeEnd.Begin, prevControlPoint, t);\r
-               connectionHandler.removeBranchPoint(connection, lastControlPoint);\r
-               connectionHandler.removeEdge(connection, lastEdge);\r
-               Point2D mousePos = mouseUtil.getMouseInfo(mouseId).canvasPosition;\r
-               ElementUtils.setPos(controlPoints.peekLast(), mousePos);\r
-               DiagramUtils.validateAndFix(ghostDiagram, getContext());\r
-               update();\r
-               setDirty();\r
-               return true;\r
-       }\r
-\r
-       @EventHandler(priority = 20)\r
-       public boolean handleEvent(Event e) {\r
-               // Back-space, cancel prev bend\r
-               if (e instanceof KeyPressedEvent) {\r
-                       KeyEvent ke = (KeyEvent) e;\r
-                       if (ke.keyCode == java.awt.event.KeyEvent.VK_BACK_SPACE) {\r
-                               return cancelPreviousBend();\r
-                       }\r
-               }\r
-               if (e instanceof CommandEvent) {\r
-                       CommandEvent ce = (CommandEvent) e;\r
-                       if (ce.command.equals(Commands.CANCEL))\r
-                       {\r
-                               DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR);\r
-                               mutator.clear();\r
-                               update();\r
-                               remove();\r
-                               return true;\r
-                       }\r
-               }\r
-               if (e instanceof MouseMovedEvent) {\r
-                       MouseMovedEvent me = (MouseMovedEvent) e;\r
-                       Point2D mouseControlPos = me.controlPosition;\r
-                       Point2D mouseCanvasPos = util.controlToCanvas(mouseControlPos, new Point2D.Double());\r
-\r
-                       ISnapAdvisor snapAdvisor = getHint(DiagramHints.SNAP_ADVISOR);\r
-                       if (snapAdvisor != null)\r
-                               snapAdvisor.snap(mouseCanvasPos);\r
-\r
-                       List<TerminalInfo> tiList = ((org.simantics.sysdyn.ui.editor.participant.PointerInteractor)pi).pickTerminals(me.controlPosition);\r
-                       TerminalInfo ti = null;\r
-\r
-                       IConnectionAdvisor advisor = diagram.getHint(DiagramHints.CONNECTION_ADVISOR);\r
-                       for(TerminalInfo info : tiList) {\r
-                               if(advisor == null || info.e == null || info.t == null)\r
-                                       continue;\r
-                               Object canConnect = canConnect(advisor, info.e, info.t);\r
-                               if (canConnect != null) {\r
-                                       connection.setHint(ElementHints.KEY_CONNECTION_TYPE, canConnect);\r
-                                       ti = info;\r
-                               }\r
-                       }\r
-\r
-                       if (ti != null && !(ti.e == startElement && ti.t == startTerminal)) {\r
-                               if (endElement == null) {\r
-                                       endElement = ti.e;\r
-                                       endTerminal = ti.t;\r
-\r
-                                       IElement lastControlPoint = controlPoints.pollLast();\r
-                                       topology.disconnect(edges.peekLast(), EdgeEnd.End, lastControlPoint, ElementUtils.getSingleTerminal(lastControlPoint));\r
-                                       connectionHandler.removeBranchPoint(connection, lastControlPoint);\r
-\r
-                                       topology.connect(edges.peekLast(), EdgeEnd.End, ghostDiagram.getMutatedCorrespondence(endElement), endTerminal);\r
-                                       DiagramUtils.validateAndFix(ghostDiagram, getContext());\r
-                               } else if (!ti.e.equals(endElement) || !ti.t.equals(endTerminal)) {\r
-                                       topology.disconnect(edges.peekLast(), EdgeEnd.End, ghostDiagram.getMutatedCorrespondence(endElement), endTerminal);\r
-\r
-                                       endElement = ti.e;\r
-                                       endTerminal = ti.t;\r
-\r
-                                       topology.connect(edges.peekLast(), EdgeEnd.End, ghostDiagram.getMutatedCorrespondence(endElement), endTerminal);\r
-                                       DiagramUtils.validateAndFix(ghostDiagram, getContext());\r
-                               }\r
-\r
-                               update();\r
-                               setDirty();\r
-                               return false;\r
-                       }\r
-\r
-                       {\r
-                               connection.removeHint(ElementHints.KEY_CONNECTION_TYPE);\r
-                               if (endElement != null) {\r
-                                       topology.disconnect(edges.peekLast(), EdgeEnd.End, ghostDiagram.getMutatedCorrespondence(endElement), endTerminal);\r
-\r
-                                       endElement = null;\r
-                                       endTerminal = null;\r
-\r
-                                       IElement bp = connectionHandler.newBranchPoint(connection);\r
-                                       controlPoints.add(bp);\r
-                                       //                    ghostDiagram.addElement(bp);\r
-                                       ElementUtils.setPos(controlPoints.peekLast(), mouseCanvasPos);\r
-\r
-                                       topology.connect(edges.peekLast(), EdgeEnd.End, bp, ElementUtils.getSingleTerminal(bp));\r
-                               } else {\r
-                                       ElementUtils.setPos(controlPoints.peekLast(), mouseCanvasPos);\r
-                               }\r
-                               DiagramUtils.validateAndFix(ghostDiagram, getContext());\r
-\r
-                               update();\r
-                               setDirty();\r
-                       }\r
-\r
-               }\r
-\r
-               if (e instanceof MouseButtonPressedEvent) {\r
-                       MouseButtonEvent me = (MouseButtonEvent) e;\r
-                       if (me.button==MouseEvent.LEFT_BUTTON && me.mouseId==mouseId) {\r
-                               Point2D mouseControlPos = me.controlPosition;\r
-                               final Point2D mouseCanvasPos = util.getInverseTransform().transform(mouseControlPos, new Point2D.Double());\r
-\r
-                               ISnapAdvisor snapAdvisor = getHint(DiagramHints.SNAP_ADVISOR);\r
-                               if (snapAdvisor != null)\r
-                                       snapAdvisor.snap(mouseCanvasPos);\r
-\r
-                               // Clicked on a terminal .. End connection, End mode\r
-                               if (endElement != null) {\r
-                                       attachToBranchPoint();\r
-                                       createValveIfNecessary(mouseCanvasPos);\r
-                                       commitDiagram();\r
-                                       update();\r
-                                       remove(); // Remove ConnectTool participant\r
-                                       return true;\r
-                               }  else {\r
-                                       if (isCurrentConnectionFlow() && startElement != null && startTerminal != null) {\r
-                                               \r
-                                               IConnectionAdvisor advisor = diagram.getHint(DiagramHints.CONNECTION_ADVISOR);\r
-                                               Object canConnect = canConnect(advisor, null, null);\r
-                                               if (canConnect != null)\r
-                                                       connection.setHint(ElementHints.KEY_CONNECTION_TYPE, canConnect);\r
-                                               \r
-                                               createValveIfNecessary(mouseCanvasPos);\r
-\r
-                                               // Finish connection in thin air only if the\r
-                                               // connection was started from a valid terminal.\r
-                                               if (createFlags) {\r
-                                                       // Replace the last branch point with a flag.\r
-                                                       IElement lastBp = controlPoints.pollLast();\r
-                                                       topology.disconnect(edges.peekLast(), EdgeEnd.End, lastBp, ElementUtils.getSingleTerminal(lastBp));\r
-                                                       connectionHandler.removeBranchPoint(connection, lastBp);\r
-\r
-                                                       IElement end = createFlag(mouseCanvasPos, EdgeEnd.End);\r
-                                                       ArrayList<Terminal> terminals = new ArrayList<Terminal>();\r
-                                                       ElementUtils.getTerminals(end, terminals, false);\r
-                                                       Terminal endTerminal = terminals.get(0);\r
-                                                       topology.connect(edges.peekLast(), EdgeEnd.End, end, endTerminal);\r
-                                               }\r
-\r
-                                               DiagramUtils.validateAndFix(ghostDiagram, getContext());\r
-                                               commitDiagram();\r
-                                               update();\r
-                                               remove(); // Remove ConnectTool participant\r
-                                               return true;\r
-                                       } \r
-                               }\r
-\r
-                       }\r
-               }\r
-\r
-               // Don't let any events slip to creator participant\r
-               if (e instanceof MouseEvent) {\r
-                       MouseEvent me = (MouseEvent) e;\r
-                       return me.mouseId == mouseId;\r
-               }\r
-\r
-               return false;\r
-       }\r
-\r
-\r
-\r
-\r
-       private boolean isCurrentConnectionFlow() {\r
-               // Could this check be done better?\r
-               Boolean isFlow = false;\r
-               try {\r
-                       isFlow = SimanticsUI.getSession().syncRequest(new Read<Boolean>() {\r
-\r
-                               @Override\r
-                               public Boolean perform(ReadGraph graph)\r
-                               throws DatabaseException {\r
-                                       SysdynResource sr = SysdynResource.getInstance(graph);\r
-                                       StaticObjectAdapter soa = connectionClass.getSingleItem(StaticObjectAdapter.class);\r
-                                       Resource conntype = soa.adapt(Resource.class);\r
-                                       return conntype.equals(sr.FlowConnection);\r
-                               }\r
-\r
-                       });\r
-               } catch (DatabaseException e1) {\r
-                       e1.printStackTrace();\r
-               }\r
-               return isFlow;\r
-       }\r
-\r
-\r
-       private void attachToBranchPoint() {\r
-               DiagramUtils.inDiagramTransaction(diagram, TransactionType.WRITE, new Runnable() {\r
-\r
-                       @Override\r
-                       public void run() {\r
-\r
-                               // We are attaching to a branch point - some reordering is needed!\r
-                               if (endElement.getElementClass().containsClass(BranchPoint.class)) {\r
-\r
-                                       // Scrap everything we have and reconstruct\r
-                                       DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR);\r
-                                       mutator.clear();\r
-\r
-                                       HashMap<IElement, IElement> bps = new HashMap<IElement, IElement>();\r
-                                       for(IElement bp : controlPoints) {\r
-                                               IElement nbp = mutator.newBranchPoint(endElement);\r
-                                               Point2D pos = ElementUtils.getPos(bp);\r
-                                               ElementUtils.setPos(nbp, pos);\r
-                                               bps.put(bp, nbp);\r
-                                       }\r
-\r
-                                       for(IElement edge : edges) {\r
-                                               IElement newEdge = mutator.newEdge(endElement);\r
-\r
-                                               // Disconnect and remove old edge\r
-                                               Connection b = mutator.getConnection(edge, EdgeEnd.Begin);\r
-                                               Connection e = mutator.getConnection(edge, EdgeEnd.End);\r
-\r
-                                               IElement mappedB = bps.get(b.node) != null ? bps.get(b.node) : b.node;\r
-                                               IElement mappedE = bps.get(e.node) != null ? bps.get(e.node) : e.node;\r
-\r
-                                               mutator.connect(newEdge, b.end, mappedB, b.terminal);\r
-                                               mutator.connect(newEdge, e.end, mappedE, e.terminal);\r
-                                       }\r
-                               }\r
-                       }\r
-               });\r
-       }\r
-\r
-       private void commitDiagram() {\r
-               DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR);\r
-               mutator.commit();\r
-       }\r
-\r
-       FlagClass.Type endToFlagType(EdgeEnd end) {\r
-               switch (end) {\r
-               case Begin: return FlagClass.Type.In;\r
-               case End: return FlagClass.Type.Out;\r
-               default: throw new IllegalArgumentException("unrecognized edge end: " + end);\r
-               }\r
-       }\r
-\r
-       IElement createConnection(ElementClass element) {\r
-               DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR);\r
-               return mutator.newConnection(element);\r
-       }\r
-\r
-       IElement createFlag(Point2D pos, EdgeEnd connectionEnd) {\r
-\r
-               DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR);\r
-               IElement e = mutator.newFlag();\r
-\r
-               //        FlagHandler fh = e.getElementClass().getSingleItem(FlagHandler.class);\r
-               //        fh.setType(e, endToFlagType(connectionEnd));\r
-               //fh.setMode(e, FlagClass.Mode.Internal);\r
-               ElementUtils.setPos(e, pos);\r
-\r
-               ghostDiagram.addElement(e);\r
-\r
-               return e;\r
-\r
-       }\r
-\r
-       IElement createValve(Point2D pos) {\r
-               DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR);\r
-\r
-               ElementClass ec = null;\r
-               try {\r
-                       Resource r = SimanticsUI\r
-                       .getSession()\r
-                       .syncRequest(\r
-                                       Queries\r
-                                       .resource(SysdynResource.URIs.ValveSymbol));\r
-                       ec = SimanticsUI.getSession().syncRequest(\r
-                                       DiagramRequests.getElementClass(r, diagram));\r
-\r
-               } catch (DatabaseException e1) {\r
-                       e1.printStackTrace();\r
-               }\r
-\r
-               if(ec == null) return null;\r
-\r
-               IElement e = mutator.newElement(ec);\r
-\r
-               ElementUtils.setPos(e, pos);\r
-\r
-               ghostDiagram.addElement(e);\r
-\r
-               return e;\r
-       }\r
-\r
-       /**\r
-        * Try to get a connection element from a connection part element.\r
-        *\r
-        * @param e a potential connection part\r
-        * @return <code>null</code> if e is not part a part of a connection.\r
-        */\r
-       IElement getConnectionFromPart(IElement e) {\r
-               Parent parent = e.getElementClass().getAtMostOneItemOfClass(Parent.class);\r
-               if (parent == null)\r
-                       return null;\r
-               IElement p = parent.getParent(e);\r
-               if (!p.getElementClass().containsClass(ConnectionHandler.class))\r
-                       return null;\r
-               return p;\r
-       }\r
-\r
-       IElement createBranchPointOrFlag(Point2D pos, EdgeEnd connectionEnd) {\r
-               IElement e = null;\r
-               if (createFlags) {\r
-                       e = createFlag(pos, connectionEnd);\r
-               } else {\r
-                       e = connectionHandler.newBranchPoint(connection);\r
-                       ElementUtils.setPos(e, pos);\r
-               }\r
-               return e;\r
-       }\r
-\r
-       boolean routePointsAllowed() {\r
-               return Boolean.TRUE.equals(diagram.getHint(DiagramHints.KEY_ALLOW_ROUTE_POINTS));\r
-       }\r
-\r
-       Object canConnect(final IConnectionAdvisor advisor, final IElement endElement, final Terminal endTerminal) {\r
-               if(startElement.equals(endElement)) return null;\r
-\r
-               if(endElement == null && endTerminal == null)\r
-                       return advisor.canBeConnected(null, startElement, startTerminal, endElement, endTerminal);\r
-\r
-               try {\r
-                       return SimanticsUI.getSession().syncRequest(new Read<Object>() {\r
-\r
-                               @Override\r
-                               public Object perform(ReadGraph g) throws DatabaseException {\r
-\r
-                                       // Checking if connection type can be connected to the intended endElement\r
-                                       SysdynResource sr = SysdynResource.getInstance(g);\r
-                                       if(connection != null) {\r
-                                               StaticObjectAdapter soa = connectionClass.getSingleItem(StaticObjectAdapter.class);\r
-                                               Resource conntype = soa.adapt(Resource.class);\r
-                                               soa = endElement.getElementClass().getSingleItem(StaticObjectAdapter.class);\r
-                                               Resource end = soa.adapt(Resource.class);\r
-                                               if(conntype.equals(sr.DependencyConnection)) {\r
-                                                       if(end.equals(sr.CloudSymbol)) return null;\r
-                                                       soa = startElement.getElementClass().getSingleItem(StaticObjectAdapter.class);\r
-                                                       Resource start = soa.adapt(Resource.class);\r
-                                                       if(g.isInheritedFrom(start, sr.ModuleSymbol) && !end.equals(sr.InputSymbol)) return null;\r
-                                               } else if (conntype.equals(sr.FlowConnection)) {\r
-                                                       if(!(end.equals(sr.StockSymbol) || end.equals(sr.ValveSymbol) || end.equals(sr.CloudSymbol))) return null;\r
-                                               } else {\r
-                                                       return null;\r
-                                               }\r
-                                       }\r
-\r
-\r
-                                       if (advisor == null)\r
-                                               return Boolean.TRUE;     \r
-                                       return advisor.canBeConnected(g, startElement, startTerminal, endElement, endTerminal);\r
-                               }\r
-\r
-                       });\r
-               } catch(DatabaseException e) {\r
-                       e.printStackTrace();\r
-                       return null;\r
-               }\r
-\r
-       }\r
-\r
-\r
-}\r
index 633b47ac67bca1a96380ede331aff824b7d838f9..58860991bda6739f20607258867fd9cfee0f3fc6 100644 (file)
@@ -16,6 +16,7 @@ import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;\r
 import java.util.List;\r
 \r
+import org.simantics.diagram.participant.ConnectTool2;\r
 import org.simantics.g2d.canvas.Hints;\r
 import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;\r
 import org.simantics.g2d.canvas.impl.DependencyReflection.Reference;\r
@@ -26,17 +27,19 @@ import org.simantics.g2d.diagram.participant.Selection;
 import org.simantics.g2d.diagram.participant.TerminalPainter;\r
 import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil;\r
 import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil.TerminalInfo;\r
-import org.simantics.g2d.element.ElementClass;\r
+import org.simantics.g2d.element.ElementClasses;\r
 import org.simantics.g2d.element.IElement;\r
 import org.simantics.g2d.element.IElementClassProvider;\r
-import org.simantics.g2d.event.MouseEvent;\r
 import org.simantics.g2d.event.EventHandlerReflection.EventHandler;\r
+import org.simantics.g2d.event.MouseEvent;\r
 import org.simantics.g2d.event.MouseEvent.MouseButtonPressedEvent;\r
 import org.simantics.g2d.participant.KeyUtil;\r
 import org.simantics.g2d.participant.MouseUtil;\r
 import org.simantics.g2d.participant.TransformUtil;\r
 import org.simantics.g2d.routing.RouterFactory;\r
 import org.simantics.g2d.utils.GeometryUtils;\r
+import org.simantics.sysdyn.ui.editor.participant.SysdynElementClassProviders.ISysdynElementClassProvider;\r
+import org.simantics.sysdyn.ui.editor.routing.DependencyRouter;\r
 import org.simantics.sysdyn.ui.elements2.AuxiliaryFactory;\r
 import org.simantics.sysdyn.ui.elements2.CloudFactory;\r
 import org.simantics.sysdyn.ui.elements2.InputFactory;\r
@@ -66,7 +69,7 @@ public class PointerInteractor extends org.simantics.g2d.diagram.participant.poi
     @Dependency PickContext pickContext;\r
     @Dependency MouseUtil mice;\r
     @Reference TerminalPainter terminalPainter;\r
-\r
+    \r
     public PointerInteractor(boolean clickSelect, boolean boxSelect, boolean dragElement, boolean dndDragElement, boolean connect, boolean doubleClickEdit, IElementClassProvider newConnectionClassProvider) {\r
         super(clickSelect, boxSelect, dragElement, dndDragElement, connect, doubleClickEdit, newConnectionClassProvider);\r
     }\r
@@ -85,29 +88,36 @@ public class PointerInteractor extends org.simantics.g2d.diagram.participant.poi
         if((me.stateMask & MouseEvent.ALT_MASK) == 0) return false;\r
         \r
         if(elementClassProvider != null) {\r
-            ConnectTool bsi = null;\r
+            ConnectTool2 bsi = null;\r
             if (ti != null) {\r
                \r
                 IElement terminalElement = ti.e;\r
                 \r
-                ElementClass connectionClass = null;\r
+//                ElementClass connectionClass = null;\r
                 if( me.button == MouseEvent.LEFT_BUTTON) {\r
                     if(terminalElement.getElementClass().getId().equals(CloudFactory.class.getSimpleName())) return false;\r
-                    diagram.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(false, false));\r
-                    connectionClass = elementClassProvider.get(ConnectionClasses.DEPENDENCY);\r
+//                    diagram.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(false, false));\r
+                    diagram.setHint(DiagramHints.ROUTE_ALGORITHM, new DependencyRouter());\r
+//                 connectionClass = elementClassProvider.get(ConnectionClasses.DEPENDENCY);\r
+                    ISysdynElementClassProvider secp = (ISysdynElementClassProvider)elementClassProvider;\r
+                    secp.put(ElementClasses.CONNECTION, elementClassProvider.get(ConnectionClasses.DEPENDENCY));\r
                     \r
                 } else if (me.button == MouseEvent.RIGHT_BUTTON) {\r
                        String id  = terminalElement.getElementClass().getId();\r
                     if(id.equals(AuxiliaryFactory.class.getSimpleName())\r
                                || id.equals(InputFactory.class.getSimpleName())\r
                                || id.equals(ModuleFactory.class.getSimpleName())) return false;\r
-                    diagram.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(true, true));\r
-                    connectionClass = elementClassProvider.get(ConnectionClasses.FLOW);\r
+                    diagram.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(true, false));\r
+//                    connectionClass = elementClassProvider.get(ConnectionClasses.FLOW);\r
+                    ISysdynElementClassProvider secp = (ISysdynElementClassProvider)elementClassProvider;\r
+                    secp.put(ElementClasses.CONNECTION, elementClassProvider.get(ConnectionClasses.FLOW));\r
+                    \r
                 }\r
                 \r
                 IConnectionAdvisor advisor = diagram.getHint(DiagramHints.CONNECTION_ADVISOR);\r
                 if (advisor == null || (advisor != null && advisor.canBeginConnection(null, ti.e, ti.t))) {\r
-                    bsi = new ConnectTool(diagram, connectionClass, ti.e, ti.t, me.mouseId, curCanvasPos);\r
+//                    bsi = new ConnectTool(diagram, connectionClass, ti.e, ti.t, me.mouseId, curCanvasPos);\r
+                       bsi = new SysdynConnectTool(ti, me.mouseId, curCanvasPos);\r
                 }\r
             }  \r
             else if (me.button == MouseEvent.RIGHT_BUTTON) {\r
@@ -119,7 +129,10 @@ public class PointerInteractor extends org.simantics.g2d.diagram.participant.poi
                 */\r
                 // Start connection out of thin air, without a terminal.\r
                diagram.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(true, true));\r
-                bsi = new ConnectTool(diagram, elementClassProvider.get(ConnectionClasses.FLOW), null, null, me.mouseId, curCanvasPos);\r
+//                bsi = new ConnectTool(diagram, elementClassProvider.get(ConnectionClasses.FLOW), null, null, me.mouseId, curCanvasPos);\r
+                ISysdynElementClassProvider secp = (ISysdynElementClassProvider)elementClassProvider;\r
+                secp.put(ElementClasses.CONNECTION, elementClassProvider.get(ConnectionClasses.FLOW));\r
+               bsi = new SysdynConnectTool(null, me.mouseId, curCanvasPos); // FIXME\r
             }\r
             \r
             if (bsi != null) {\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/SysdynConnectTool.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/SysdynConnectTool.java
new file mode 100644 (file)
index 0000000..d1a98df
--- /dev/null
@@ -0,0 +1,398 @@
+package org.simantics.sysdyn.ui.editor.participant;\r
+\r
+import java.awt.BasicStroke;\r
+import java.awt.Color;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Path2D;\r
+import java.awt.geom.Point2D;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.Deque;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.UndoContext;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.UndoWriteRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.diagram.participant.ConnectTool2;\r
+import org.simantics.diagram.participant.ConnectionBuilder;\r
+import org.simantics.diagram.participant.ControlPoint;\r
+import org.simantics.diagram.ui.DiagramModelHints;\r
+import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;\r
+import org.simantics.g2d.connection.IConnectionAdvisor;\r
+import org.simantics.g2d.diagram.DiagramHints;\r
+import org.simantics.g2d.diagram.DiagramUtils;\r
+import org.simantics.g2d.diagram.handler.Topology.Terminal;\r
+import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil;\r
+import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil.TerminalInfo;\r
+import org.simantics.g2d.element.ElementClass;\r
+import org.simantics.g2d.element.ElementClasses;\r
+import org.simantics.g2d.element.ElementUtils;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd;\r
+import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
+import org.simantics.g2d.element.impl.Element;\r
+import org.simantics.g2d.elementclass.BranchPoint;\r
+import org.simantics.g2d.elementclass.BranchPointClass;\r
+import org.simantics.g2d.elementclass.FlagClass;\r
+import org.simantics.g2d.event.MouseEvent.MouseButtonEvent;\r
+import org.simantics.g2d.event.MouseEvent.MouseButtonPressedEvent;\r
+import org.simantics.g2d.event.MouseEvent.MouseMovedEvent;\r
+import org.simantics.g2d.routing.ConnectionDirectionUtil;\r
+import org.simantics.g2d.routing.Constants;\r
+import org.simantics.g2d.routing.IConnection;\r
+import org.simantics.g2d.routing.IRouter2;\r
+import org.simantics.g2d.routing.TrivialRouter2;\r
+import org.simantics.g2d.snap.ISnapAdvisor;\r
+import org.simantics.g2d.utils.GeometryUtils;\r
+import org.simantics.scenegraph.g2d.G2DParentNode;\r
+import org.simantics.scenegraph.g2d.nodes.ShapeNode;\r
+import org.simantics.structural2.modelingRules.ConnectionJudgement;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.sysdyn.ui.elements2.connections.ConnectionClasses;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.utils.datastructures.Callback;\r
+import org.simantics.utils.ui.ExceptionUtils;\r
+\r
+public class SysdynConnectTool extends ConnectTool2 {\r
+       \r
+    public SysdynConnectTool(TerminalInfo startTerminal, int mouseId,\r
+                       Point2D startCanvasPos) {\r
+               super(startTerminal, mouseId, startCanvasPos);\r
+       }\r
+\r
+\r
+       @SGInit\r
+    public void initSG(G2DParentNode parent) {\r
+        ghostNode = parent.addNode(G2DParentNode.class);\r
+        ghostNode.setZIndex(PAINT_PRIORITY);\r
+\r
+        ShapeNode pathNode = ghostNode.getOrCreateNode("path", ShapeNode.class);\r
+        pathNode.setColor(Color.BLACK);\r
+        pathNode.setStroke(new BasicStroke(1f));\r
+        pathNode.setScaleStroke(true);\r
+        pathNode.setZIndex(0);\r
+\r
+        G2DParentNode points = ghostNode.getOrCreateNode("points", G2DParentNode.class);\r
+        points.setZIndex(1);\r
+\r
+        updateSG();\r
+    }\r
+\r
+    \r
+    protected TerminalInfo createFlag(EdgeEnd connectionEnd) {\r
+        ElementClass flagClass = elementClassProvider.get(ElementClasses.FLAG);\r
+        IElement e = Element.spawnNew(flagClass);\r
+\r
+        e.setHint(FlagClass.KEY_FLAG_TYPE, endToFlagType(connectionEnd));\r
+        e.setHint(FlagClass.KEY_FLAG_MODE, FlagClass.Mode.Internal);\r
+\r
+        TerminalInfo ti = new TerminalInfo();\r
+        ti.e = e;\r
+        \r
+        // start: this part changed to support overlapping terminals\r
+               ArrayList<Terminal> terminals = new ArrayList<Terminal>();\r
+               ElementUtils.getTerminals(e, terminals, false);\r
+               ti.t = terminals.get(0);\r
+               // end\r
+               \r
+        ti.posElem = TerminalUtil.getTerminalPosOnElement(e, ti.t);\r
+        ti.posDia = TerminalUtil.getTerminalPosOnDiagram(e, ti.t);\r
+\r
+        return ti;\r
+    }\r
+    \r
+    static class Segment {\r
+        public final ControlPoint begin;\r
+        public final ControlPoint end;\r
+        public Path2D             path;\r
+\r
+        public Segment(ControlPoint begin, ControlPoint end) {\r
+            this.begin = begin;\r
+            this.end = end;\r
+        }\r
+\r
+        @Override\r
+        public String toString() {\r
+            return "Segment[begin=" + begin + ", end=" + end + ", path=" + path + "]";\r
+        }\r
+    }\r
+    \r
+    private List<Segment> toSegments(Deque<ControlPoint> points) {\r
+        if (points.isEmpty())\r
+            return Collections.emptyList();\r
+\r
+        List<Segment> segments = new ArrayList<Segment>();\r
+\r
+        Iterator<ControlPoint> it = points.iterator();\r
+        ControlPoint prev = it.next();\r
+        while (it.hasNext()) {\r
+            ControlPoint next = it.next();\r
+            segments.add(new Segment(prev, next));\r
+            prev = next;\r
+        }\r
+\r
+        return segments;\r
+    }\r
+    \r
+    protected void updateSG() {\r
+        if (controlPoints.isEmpty())\r
+            return;\r
+\r
+        // Route connection segments separately\r
+        IRouter2 router = ElementUtils.getHintOrDefault(diagram, DiagramHints.ROUTE_ALGORITHM, TrivialRouter2.INSTANCE);\r
+        final List<Segment> segments = toSegments(controlPoints);\r
+        //System.out.println("controlpoints: " + controlPoints);\r
+        //System.out.println("segments: " + segments);\r
+        router.route(new IConnection() {\r
+            @Override\r
+            public Collection<? extends Object> getSegments() {\r
+                return segments;\r
+            }\r
+\r
+            @Override\r
+            public Connector getBegin(Object seg) {\r
+                return getConnector(((Segment) seg).begin);\r
+            }\r
+\r
+            @Override\r
+            public Connector getEnd(Object seg) {\r
+                return getConnector(((Segment) seg).end);\r
+            }\r
+\r
+            private Connector getConnector(ControlPoint cp) {\r
+                Connector c = new Connector();\r
+                c.x = cp.getPosition().getX();\r
+                c.y = cp.getPosition().getY();\r
+\r
+                TerminalInfo ti = cp.getAttachedTerminal();\r
+                if (ti != null && (ti == startFlag || ti != endFlag)) {\r
+                    //System.out.println("CP1: " + cp);\r
+                    c.parentObstacle = DiagramUtils.getObstacleShape(ti.e);\r
+                    ConnectionDirectionUtil.determineAllowedDirections(c);\r
+                } else {\r
+                    //System.out.println("CP2: " + cp);\r
+                    c.parentObstacle = GeometryUtils.transformRectangle(AffineTransform.getTranslateInstance(c.x, c.y),\r
+                            BranchPointClass.DEFAULT_IMAGE2.getBounds());\r
+                    c.allowedDirections = toAllowedDirections(cp.getDirection());\r
+                }\r
+\r
+                return c;\r
+            }\r
+\r
+            @Override\r
+            public void setPath(Object seg, Path2D path) {\r
+                ((Segment) seg).path = (Path2D) path.clone();\r
+            }\r
+\r
+            private int toAllowedDirections(BranchPoint.Direction direction) {\r
+                switch (direction) {\r
+                    case Any:\r
+                        return 0xf;\r
+                    case Horizontal:\r
+                        return Constants.EAST_FLAG | Constants.WEST_FLAG;\r
+                    case Vertical:\r
+                        return Constants.NORTH_FLAG | Constants.SOUTH_FLAG;\r
+                    default:\r
+                        throw new IllegalArgumentException("unrecognized direction: " + direction);\r
+                }\r
+            }\r
+        });\r
+\r
+        // Combine the routed paths\r
+        Path2D path = new Path2D.Double();\r
+        for (Segment seg : segments) {\r
+            //System.out.println("SEG: " + seg);\r
+            if (seg.path != null)\r
+                path.append(seg.path.getPathIterator(null), true);\r
+        }\r
+        \r
+        // Create scene graph to visualize the connection.\r
+        ShapeNode pathNode = ghostNode.getOrCreateNode("path", ShapeNode.class);\r
+        pathNode.setShape(path);\r
+        \r
+        /*\r
+         * Removed Points\r
+         */\r
+        \r
+        setDirty();\r
+    }\r
+    \r
+    \r
+    @Override\r
+       protected Object canConnect(final IConnectionAdvisor advisor, final IElement endElement, final Terminal endTerminal) {\r
+        final IElement se = startTerminal != null ? startTerminal.e : startFlag.e;\r
+        final Terminal st = startTerminal != null ? startTerminal.t : null;\r
+\r
+               if(se.equals(endElement)) return null;\r
+\r
+               if(endElement == null && endTerminal == null)\r
+                       return advisor.canBeConnected(null, se, st, endElement, endTerminal);\r
+\r
+               try {\r
+                       return SimanticsUI.getSession().syncRequest(new Read<Object>() {\r
+\r
+                               @Override\r
+                               public Object perform(ReadGraph g) throws DatabaseException {\r
+\r
+                                       // Checking if connection type can be connected to the intended endElement\r
+                                       SysdynResource sr = SysdynResource.getInstance(g);\r
+                                       StaticObjectAdapter soa = endElement.getElementClass().getSingleItem(StaticObjectAdapter.class);\r
+                                       Resource end = soa.adapt(Resource.class);\r
+                                       ElementClass dependency = elementClassProvider.get(ConnectionClasses.DEPENDENCY);\r
+                                       ElementClass flow = elementClassProvider.get(ConnectionClasses.FLOW);\r
+                                       ElementClass currentConnection = elementClassProvider.get(ElementClasses.CONNECTION);\r
+                                       if(currentConnection.equals(dependency)) {\r
+                                               if(end.equals(sr.CloudSymbol)) return null;\r
+                                               soa = se.getElementClass().getSingleItem(StaticObjectAdapter.class);\r
+                                               Resource start = soa.adapt(Resource.class);\r
+                                               if(g.isInheritedFrom(start, sr.ModuleSymbol) && !end.equals(sr.InputSymbol)) return null;\r
+                                               if(end.equals(sr.StockSymbol)) return null;\r
+                                       } else if (currentConnection.equals(flow)) {\r
+                                               if(!(end.equals(sr.StockSymbol) || end.equals(sr.ValveSymbol) || end.equals(sr.CloudSymbol))) return null;\r
+                                       } else {\r
+                                               return null;\r
+                                       }\r
+\r
+\r
+                                       if (advisor == null)\r
+                                               return Boolean.TRUE;     \r
+                                       return advisor.canBeConnected(g, se, st, endElement, endTerminal);\r
+                               }\r
+\r
+                       });\r
+               } catch(DatabaseException e) {\r
+                       e.printStackTrace();\r
+                       return null;\r
+               }\r
+\r
+       }\r
+    \r
+    protected boolean processMouseMove(MouseMovedEvent me) {\r
+        mouseHasMoved = true;\r
+\r
+        Point2D mouseControlPos = me.controlPosition;\r
+        Point2D mouseCanvasPos = util.controlToCanvas(mouseControlPos, new Point2D.Double());\r
+\r
+        ISnapAdvisor snapAdvisor = getHint(DiagramHints.SNAP_ADVISOR);\r
+        if (snapAdvisor != null)\r
+            snapAdvisor.snap(mouseCanvasPos);\r
+\r
+        // Record last snapped canvas position of mouse.\r
+        this.lastMouseCanvasPos.setLocation(mouseCanvasPos);\r
+\r
+        if (isEndingInFlag()) {\r
+            endFlagNode.setTransform(AffineTransform.getTranslateInstance(mouseCanvasPos.getX(), mouseCanvasPos.getY()));\r
+        }\r
+\r
+               List<TerminalInfo> tiList = ((org.simantics.sysdyn.ui.editor.participant.PointerInteractor)pi).pickTerminals(me.controlPosition);\r
+               TerminalInfo ti = null;\r
+\r
+               IConnectionAdvisor advisor = diagram.getHint(DiagramHints.CONNECTION_ADVISOR);\r
+               for(TerminalInfo info : tiList) {\r
+                       if(advisor == null || info.e == null || info.t == null)\r
+                               continue;\r
+                       Object canConnect = canConnect(advisor, info.e, info.t);\r
+                       if (canConnect != null) {\r
+                               ti = info;\r
+                               break;\r
+                       }\r
+               }\r
+        \r
+        if (ti != null && !isStartTerminal(ti.e, ti.t)) {\r
+            Object canConnect = canConnect(ti.e, ti.t);\r
+            if (canConnect != null) {\r
+                connectionJudgment = (ConnectionJudgement) canConnect;\r
+\r
+                if (!isEndingInFlag() || !TerminalUtil.isSameTerminal(ti, endTerminal)) {\r
+                    controlPoints.getLast()\r
+                    .setPosition(ti.posDia)\r
+                    .setAttachedToTerminal(ti);\r
+\r
+                    endTerminal = ti;\r
+                    System.out.println("ENDTERMINAL MOUSEMOVESTA: " + ti + ", " + ti.t);\r
+                }\r
+\r
+                // Make sure that we are ending with a flag if ALT is pressed\r
+                // and no end terminal is defined.\r
+                endWithoutTerminal(lastMouseCanvasPos, shouldEndWithFlag(me));\r
+\r
+                updateSG();\r
+                return false;\r
+            }\r
+        }\r
+\r
+        connectionJudgment = null;\r
+        if (isEndTerminalDefined()) {\r
+            // CASE: Mouse was previously on top of a valid terminal to end\r
+            // the connection. Now the mouse has been moved where there is\r
+            // no longer a terminal to connect to.\r
+            //\r
+            // => Disconnect the last edge segment from the previous\r
+            // terminal, mark endElement/endTerminal non-existent\r
+            // and connect the disconnected edge to a new branch point.\r
+\r
+            controlPoints.getLast()\r
+            .setPosition(mouseCanvasPos)\r
+            .setDirection(calculateCurrentBranchPointDirection())\r
+            .setAttachedToTerminal(null);\r
+\r
+            endTerminal = null;\r
+        } else {\r
+            // CASE: Mouse was not previously on top of a valid ending\r
+            // element terminal.\r
+            //\r
+            // => Move and re-orient last branch point.\r
+\r
+            controlPoints.getLast()\r
+            .setPosition(mouseCanvasPos)\r
+            .setDirection(calculateCurrentBranchPointDirection());\r
+        }\r
+\r
+        // Make sure that we are ending with a flag if ALT is pressed and no end\r
+        // terminal is defined.\r
+        endWithoutTerminal(lastMouseCanvasPos, shouldEndWithFlag(me));\r
+\r
+        updateSG();\r
+\r
+        return false;\r
+    }\r
+    \r
+    Point2D mousePosition;\r
+    \r
+    protected boolean processMouseButtonPress(MouseButtonPressedEvent e) {\r
+        MouseButtonEvent me = e;\r
+        mousePosition = me.controlPosition;\r
+        return super.processMouseButtonPress(e);\r
+    }\r
+\r
+    @Override\r
+    protected void createConnection() {\r
+       \r
+        final UndoContext uctx = diagram.getHint(DiagramModelHints.KEY_UNDO_CONTEXT);\r
+        final ConnectionJudgement judgment = this.connectionJudgment;\r
+        // ConnectionBuilder changed to SysdynconnectionBuilder to support overlapping terminals and valve creation\r
+        final ConnectionBuilder builder = new SysdynConnectionBuilder(this.diagram);\r
+        final Deque<ControlPoint> controlPoints = this.controlPoints;\r
+        final TerminalInfo startTerminal = this.startTerminal;\r
+        final TerminalInfo endTerminal = this.endTerminal;\r
+\r
+        SimanticsUI.getSession().asyncRequest(new UndoWriteRequest(uctx, true) {\r
+            @Override\r
+            public void perform(WriteGraph graph) throws DatabaseException {\r
+                builder.create(graph, judgment, controlPoints, startTerminal, endTerminal);\r
+            }\r
+        }, new Callback<DatabaseException>() {\r
+            @Override\r
+            public void run(DatabaseException parameter) {\r
+                if (parameter != null)\r
+                    ExceptionUtils.logAndShowError(parameter);\r
+            }\r
+        });\r
+    }    \r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/SysdynConnectionBuilder.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/SysdynConnectionBuilder.java
new file mode 100644 (file)
index 0000000..ed27b29
--- /dev/null
@@ -0,0 +1,235 @@
+package org.simantics.sysdyn.ui.editor.participant;\r
+\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Point2D;\r
+import java.util.ArrayList;\r
+import java.util.Deque;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.utils.OrderedSetUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.diagram.content.ConnectionUtil;\r
+import org.simantics.diagram.participant.ConnectionBuilder;\r
+import org.simantics.diagram.participant.ControlPoint;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.diagram.stubs.G2DResource;\r
+import org.simantics.diagram.ui.DiagramModelHints;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.diagram.handler.Topology.Terminal;\r
+import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil;\r
+import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil.TerminalInfo;\r
+import org.simantics.g2d.element.ElementClass;\r
+import org.simantics.g2d.element.ElementClasses;\r
+import org.simantics.g2d.element.ElementHints;\r
+import org.simantics.g2d.element.ElementUtils;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd;\r
+import org.simantics.g2d.element.impl.Element;\r
+import org.simantics.g2d.elementclass.FlagClass;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.structural2.modelingRules.ConnectionJudgement;\r
+import org.simantics.structural2.modelingRules.IModelingRules;\r
+import org.simantics.sysdyn.ui.elements2.SysdynElementClasses;\r
+import org.simantics.sysdyn.ui.elements2.ValveFactory;\r
+import org.simantics.sysdyn.ui.elements2.connections.ConnectionClasses;\r
+import org.simantics.utils.datastructures.Pair;\r
+\r
+public class SysdynConnectionBuilder extends ConnectionBuilder{\r
+\r
+       public SysdynConnectionBuilder(IDiagram diagram) {\r
+               super(diagram);\r
+       }\r
+\r
+    /**\r
+     * @param graph\r
+     * @param judgment\r
+     * @param controlPoints\r
+     * @param startTerminal\r
+     * @param endTerminal\r
+     * @throws DatabaseException\r
+     */\r
+    public void create(WriteGraph graph, ConnectionJudgement judgment, Deque<ControlPoint> controlPoints,\r
+            TerminalInfo startTerminal, TerminalInfo endTerminal) throws DatabaseException {\r
+       // If needs a valve, we will create two separate connections\r
+        if(needsValve(startTerminal, endTerminal)) {\r
+               createValveAndConnections(graph, judgment, controlPoints, startTerminal, endTerminal);\r
+        } \r
+        // If no need for valve, just call createConnection with false on createValve parameter\r
+        else {\r
+               createConnection(graph, judgment, controlPoints, startTerminal, endTerminal, false);\r
+        }\r
+    }\r
+    /**\r
+     * @param graph\r
+     * @param judgment\r
+     * @param controlPoints\r
+     * @param startTerminal\r
+     * @param endTerminal\r
+     * @throws DatabaseException\r
+     */\r
+    public TerminalInfo createConnection(WriteGraph graph, ConnectionJudgement judgment, Deque<ControlPoint> controlPoints,\r
+            TerminalInfo startTerminal, TerminalInfo endTerminal, boolean createValve) throws DatabaseException {\r
+        TerminalInfo newValve = null;\r
+\r
+       this.cu = new ConnectionUtil(graph);\r
+\r
+        // 1. Get diagram connection to construct.\r
+        Resource connection = getOrCreateConnection(graph, startTerminal, endTerminal);\r
+\r
+        // 2. Add branch points\r
+        List<Pair<ControlPoint, Resource>> bps = createBranchPoints(graph, connection, controlPoints);\r
+        \r
+        // 3. Create edges between branch points.\r
+        Resource firstBranchPoint = null;\r
+        Resource lastBranchPoint = null;\r
+        if (!bps.isEmpty()) {\r
+            Iterator<Pair<ControlPoint, Resource>> it = bps.iterator();\r
+            Pair<ControlPoint, Resource> prev = it.next();\r
+            firstBranchPoint = prev.second;\r
+            while (it.hasNext()) {\r
+                Pair<ControlPoint, Resource> next = it.next();\r
+                cu.connect(prev.second, next.second);\r
+                prev = next;\r
+            }\r
+            lastBranchPoint = prev.second;\r
+        }\r
+\r
+        // 4. Connect start/end terminals if those exist.\r
+        // If first/lastBranchPoint != null, connect to those.\r
+        // Otherwise connect the start/end terminals together.\r
+        Resource startConnector = null;\r
+        Resource endConnector = null;\r
+        IElement startFlag = null;\r
+        IElement endFlag = null;\r
+\r
+        if (startTerminal != null) {\r
+            startConnector = createConnectorForNode(graph, connection, startTerminal, EdgeEnd.Begin, judgment);\r
+        } else if (createFlags) {\r
+            startFlag = createFlag(graph, connection, EdgeEnd.Begin, controlPoints.getFirst(), FlagClass.Type.In);\r
+                       ArrayList<Terminal> terminals = new ArrayList<Terminal>();\r
+                       ElementUtils.getTerminals(startFlag, terminals, false);\r
+                       Terminal st = terminals.get(1);\r
+            startConnector = createConnectorForNode(graph, connection, (Resource) ElementUtils.getObject(startFlag),\r
+                    st, EdgeEnd.Begin, judgment);\r
+        }\r
+\r
+        if (endTerminal != null) {\r
+            endConnector = createConnectorForNode(graph, connection, endTerminal, EdgeEnd.End, judgment);\r
+        } else if (createFlags) {\r
+               if(createValve)\r
+                endFlag = createValveElement(graph, connection, EdgeEnd.End, controlPoints.getLast());\r
+               else\r
+                       endFlag = createFlag(graph, connection, EdgeEnd.End, controlPoints.getLast(), FlagClass.Type.Out);\r
+                       ArrayList<Terminal> terminals = new ArrayList<Terminal>();\r
+                       ElementUtils.getTerminals(endFlag, terminals, false);\r
+                       Terminal et = terminals.get(0);\r
+            endConnector = createConnectorForNode(graph, connection, (Resource) ElementUtils.getObject(endFlag),\r
+                    et, EdgeEnd.End, judgment);\r
+            \r
+            if(createValve) {\r
+               newValve = new TerminalInfo();\r
+               newValve.e = endFlag;\r
+               newValve.t = terminals.get(1);\r
+               newValve.posElem = TerminalUtil.getTerminalPosOnElement(endFlag, newValve.t);\r
+               newValve.posDia = TerminalUtil.getTerminalPosOnDiagram(endFlag, newValve.t);\r
+            }\r
+        }\r
+\r
+        if (firstBranchPoint == null || lastBranchPoint == null) {\r
+            cu.connect(startConnector, endConnector);\r
+        } else {\r
+            cu.connect(startConnector, firstBranchPoint);\r
+            cu.connect(lastBranchPoint, endConnector);\r
+        }\r
+\r
+        // 5. Finally, set connection type according to modelling rules\r
+        IModelingRules modelingRules = diagram.getHint(DiagramModelHints.KEY_MODELING_RULES);\r
+        if (judgment.connectionType != null && modelingRules != null) {\r
+            modelingRules.setConnectionType(graph, connection, judgment.connectionType);\r
+        }\r
+\r
+        this.cu = null;\r
+        return newValve;\r
+    }\r
+    \r
+    \r
+    /**\r
+     * @param graph\r
+     * @param connection\r
+     * @param end\r
+     * @param cp\r
+     * @param type\r
+     * @return an element describing the new created flag resource\r
+     * @throws DatabaseException\r
+     */\r
+    public IElement createValveElement(WriteGraph graph, Resource connection, EdgeEnd end, ControlPoint cp) throws DatabaseException {\r
+        ElementClass valveClass = elementClassProvider.get(SysdynElementClasses.VALVE);\r
+        IElement valveElement = Element.spawnNew(valveClass);\r
+        Resource valveClassResource = ElementUtils.checkedAdapt(valveClass, Resource.class);\r
+\r
+        Layer0 L0 = Layer0.getInstance(graph);\r
+        G2DResource G2D = G2DResource.getInstance(graph);\r
+        DiagramResource DIA = DiagramResource.getInstance(graph);\r
+\r
+        Resource valve = graph.newResource();\r
+        graph.claim(valve, L0.InstanceOf, null, valveClassResource);\r
+        valveElement.setHint(ElementHints.KEY_OBJECT, valve);\r
+\r
+        OrderedSetUtils.add(graph, diagramResource, valve);\r
+\r
+        AffineTransform at = AffineTransform.getTranslateInstance(cp.getPosition().getX(), cp.getPosition().getY());\r
+        valveElement.setHint(ElementHints.KEY_TRANSFORM, at);\r
+        double[] matrix = new double[6];\r
+        at.getMatrix(matrix);\r
+        graph.claimLiteral(valve, DIA.HasTransform, G2D.Transform, matrix);\r
+\r
+        // Put the element on all the currently active layers if possible.\r
+        if (layerManager != null) {\r
+            layerManager.removeFromAllLayers(graph, valve);\r
+            layerManager.putElementOnVisibleLayers(diagram, graph, valve);\r
+        }\r
+\r
+        return valveElement;\r
+    }\r
+    \r
+    private boolean needsValve(TerminalInfo startTerminal, TerminalInfo endTerminal) {\r
+               if (!elementClassProvider.get(ElementClasses.CONNECTION)\r
+                               .equals(elementClassProvider.get(ConnectionClasses.FLOW))) \r
+                       return false;\r
+               if(startTerminal != null && startTerminal.e != null && startTerminal.e.getElementClass().getId().equals(ValveFactory.class.getSimpleName())) {\r
+                       return false;\r
+               } else if(endTerminal != null && endTerminal.e != null && endTerminal.e.getElementClass().getId().equals(ValveFactory.class.getSimpleName())) {\r
+                       return false;\r
+               }\r
+               return true;\r
+    }\r
+    \r
+    private void createValveAndConnections(WriteGraph graph, ConnectionJudgement judgment, Deque<ControlPoint> controlPoints,\r
+            TerminalInfo startTerminal, TerminalInfo endTerminal) throws DatabaseException {\r
+       \r
+               ControlPoint cpfirst = controlPoints.getFirst();\r
+               ControlPoint cplast = controlPoints.getLast();\r
+\r
+               // Set the position in the middle of the route\r
+               double startX = cpfirst.getPosition().getX();\r
+               double startY = cpfirst.getPosition().getY();\r
+               double x = cplast.getPosition().getX();\r
+               double y = cplast.getPosition().getY();\r
+               Point2D pos = new Point2D.Double(startX - (startX - x) / 2, startY - (startY - y) / 2);\r
+               \r
+               // Replace the last control point with the control point in the middle\r
+        controlPoints.getLast().setPosition(pos);\r
+\r
+        // Create a connection to a new valve and get the new valve\r
+        TerminalInfo newValve = createConnection(graph, judgment, controlPoints, startTerminal, null, true);\r
+        \r
+               // Replace the last control point with the original control point\r
+        controlPoints.getLast().setPosition(x, y);\r
+        \r
+        // Create a connection starting from the new valve\r
+               createConnection(graph, judgment, controlPoints, newValve, endTerminal, false);\r
+    }\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/SysdynElementClassProviders.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/SysdynElementClassProviders.java
new file mode 100644 (file)
index 0000000..93c5675
--- /dev/null
@@ -0,0 +1,69 @@
+package org.simantics.sysdyn.ui.editor.participant;\r
+\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.simantics.g2d.element.ElementClass;\r
+import org.simantics.g2d.element.ElementClassProviders;\r
+import org.simantics.g2d.element.IElementClassProvider;\r
+\r
+public class SysdynElementClassProviders extends ElementClassProviders {\r
+       \r
+    /**\r
+     * Create an element class provider that based on the specified map. The\r
+     * provider will directly access the map with the received keys. The\r
+     * argument map will be copied.\r
+     * \r
+     * @param map the map to use for element class provision\r
+     * @return <code>null</code> if there is no provider for the specified key\r
+     */\r
+    public static IElementClassProvider mappedProvider(Map<Object, ElementClass> map) {\r
+        // Copy the map as a safety measure\r
+        final Map<Object, ElementClass> copy = new HashMap<Object, ElementClass>(map);\r
+        return new ISysdynElementClassProvider() {\r
+            @Override\r
+            public ElementClass get(Object key) {\r
+                return copy.get(key);\r
+            }\r
+\r
+                       @Override\r
+                       public void put(Object key, ElementClass value) {\r
+                               copy.put(key, value);\r
+                       }\r
+\r
+        };\r
+    }\r
+    \r
+    /**\r
+     * Does the same as {@link #mappedProvider(Map)}, the map is simply provided\r
+     * differently. The specified array must contain\r
+     * <code>[key, ElementClass, key, ElementClass, ...]</code>.\r
+     * \r
+     * @param map the map to use for element class provision\r
+     * @return <code>null</code> if there is no provider for the specified key\r
+     */\r
+    public static IElementClassProvider mappedProvider(Object... keyClassPairs) {\r
+        if (keyClassPairs.length % 2 != 0)\r
+            throw new IllegalArgumentException();\r
+        Map<Object, ElementClass> map = new HashMap<Object, ElementClass>();\r
+        int n = keyClassPairs.length / 2;\r
+        for (int i = 0; i < n; ++i) {\r
+            Object key = keyClassPairs[i * 2];\r
+            Object elementClass = keyClassPairs[i*2+1];\r
+            if (!(elementClass instanceof ElementClass))\r
+                throw new IllegalArgumentException("not an ElementClass instance: "  + elementClass);\r
+            map.put(key, (ElementClass) elementClass);\r
+        }\r
+        return mappedProvider(map);\r
+    }\r
+\r
+\r
+       public interface ISysdynElementClassProvider extends IElementClassProvider {\r
+               \r
+               /**\r
+                * Update a value in an IElementClassProvider\r
+                */\r
+           void put(Object key, ElementClass value);\r
+           \r
+       }\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/routing/DependencyRouter.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/routing/DependencyRouter.java
new file mode 100644 (file)
index 0000000..24e527a
--- /dev/null
@@ -0,0 +1,34 @@
+package org.simantics.sysdyn.ui.editor.routing;\r
+\r
+import java.awt.geom.Arc2D;\r
+import java.awt.geom.Path2D;\r
+\r
+import org.simantics.g2d.routing.IConnection;\r
+import org.simantics.g2d.routing.IConnection.Connector;\r
+import org.simantics.g2d.routing.IRouter2;\r
+import org.simantics.sysdyn.ui.elements2.connections.Dependencies;\r
+import org.simantics.utils.datastructures.Pair;\r
+\r
+public class DependencyRouter implements IRouter2 {\r
+\r
+       @Override\r
+       public void route(IConnection connection) {\r
+               if(connection.getSegments().isEmpty())\r
+                       return;\r
+               Object seg = connection.getSegments().iterator().next();\r
+        Connector begin = connection.getBegin(seg);\r
+        Connector end = connection.getEnd(seg);\r
+        \r
+        Pair<Arc2D, Path2D> shapes = new Pair<Arc2D, Path2D>(new Arc2D.Double(), new Path2D.Double());\r
+        Dependencies.createArrowShape(shapes,\r
+                       begin.parentObstacle,\r
+                       end.parentObstacle,\r
+                       0.1);\r
+        \r
+        Path2D path = new Path2D.Double();\r
+        path.append(shapes.first, false);\r
+        path.append(shapes.second, false);\r
+        connection.setPath(seg, path);\r
+       }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynElementClasses.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynElementClasses.java
new file mode 100644 (file)
index 0000000..6dc0364
--- /dev/null
@@ -0,0 +1,8 @@
+package org.simantics.sysdyn.ui.elements2;\r
+\r
+public class SysdynElementClasses {\r
+\r
+    public static final Object VALVE = new Object() {\r
+        public String toString() { return "VALVE"; }\r
+    };\r
+}\r
index f52455bb21476435c74338d36f8bf47950bc658b..097ff3cba8df4500f9f50e12ec5eb6331d3f8f2d 100644 (file)
@@ -80,9 +80,6 @@ public class ExpressionUtils {
         */\r
        static public void validateExpressionFields(final Resource variable, IExpression expression, Table variableTable) {\r
 \r
-               TableItem[] connectedVariables = variableTable.getItems();\r
-\r
-\r
                Resource configuration = null;\r
                try {\r
                        configuration = SimanticsUI.getSession().syncRequest(new Read<Resource>() {\r
@@ -188,12 +185,16 @@ public class ExpressionUtils {
 \r
                // Check that the variables that exist have connections and the connected variables have references in the expressions\r
                if(!(expression instanceof StockExpression)) { \r
-                       for(TableItem ti : connectedVariables) {\r
-                               if(!variables.contains(ti.getText())) {\r
-                                       ti.setForeground(new Color(ti.getDisplay(), 255, 0, 0));\r
-                               } else {\r
-                                       ti.setForeground(new Color(ti.getDisplay(), 0, 0, 0));\r
-                                       variables.remove(ti.getText());\r
+                       \r
+                       if(variableTable != null && !variableTable.isDisposed()) {\r
+                               TableItem[] connectedVariables = variableTable.getItems();\r
+                               for(TableItem ti : connectedVariables) {\r
+                                       if(!variables.contains(ti.getText())) {\r
+                                               ti.setForeground(new Color(ti.getDisplay(), 255, 0, 0));\r
+                                       } else {\r
+                                               ti.setForeground(new Color(ti.getDisplay(), 0, 0, 0));\r
+                                               variables.remove(ti.getText());\r
+                                       }\r
                                }\r
                        }\r
                        \r