]> gerrit.simantics Code Review - simantics/sysdyn.git/commitdiff
All this stuff to make sysdyn connections partially working
authorlempinen <lempinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Thu, 24 Jun 2010 09:08:35 +0000 (09:08 +0000)
committerlempinen <lempinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Thu, 24 Jun 2010 09:08:35 +0000 (09:08 +0000)
git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@16326 ac1ea38d-2e2b-0410-8846-a27921b304fc

18 files changed:
org.simantics.sysdyn.ui/adapters.xml
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/LibraryViewpointContributor.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/DiagramToCompositeMapping3.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/DiagramViewer.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/ConnectTool.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/PointerInteractor.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/ConnectionClasses.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/DependencyConnectionFactory.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/DependencyEdgeClass.java [moved from org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynEdgeClass.java with 91% similarity]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/DependencyEdgeFactory.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/DependencyNode.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/FlowConnectionFactory.java [moved from org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynConnectionFactory.java with 88% similarity]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/FlowEdgeClass.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/FlowEdgeFactory.java [moved from org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynConnectionEdgeFactory.java with 85% similarity]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/FlowNode.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/FlowStroke.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/SysdynResource.java
sysdyn_ontologies/sysdyn.graph

index 8fb25f46a3c93c3effbc5d3871225dcce660013d..dce8a8e705ffe6c9b427a5a8cbdd2fd4159b8632 100644 (file)
@@ -25,5 +25,5 @@
                        <graph />\r
                        <this />\r
                </type>\r
-       </target>\r      \r       <target\r                interface="org.simantics.sysdyn.ui.browser.nodes.AbstractNode">\r                <type\r                  uri="http://www.simantics.org/Sysdyn-1.0/SysdynModel"\r                  class="org.simantics.sysdyn.ui.browser.nodes.ModelNode">\r                       <this />\r               </type>\r                \r               <type\r                  uri="http://www.simantics.org/Sysdyn-1.0/IndependentVariable"\r                  class="org.simantics.sysdyn.ui.browser.nodes.VariableNode">\r                    <this />\r               </type>\r                \r               <type\r                  uri="http://www.simantics.org/Simulation-1.0/Types/Experiment"\r                 class="org.simantics.sysdyn.ui.browser.nodes.ExperimentNode">\r                  <this />\r               </type>\r                \r               <type\r                  uri="http://www.simantics.org/Sysdyn-1.0/Result"\r                       class="org.simantics.sysdyn.ui.browser.nodes.SimulationResultNode">\r                    <this />\r               </type>\r        </target>\r\r     <!-- Inject default connection routing algorithm for sysdyn diagrams -->\r       <target interface="org.simantics.g2d.diagram.DiagramClass">\r            <adapter uri="http://www.simantics.org/Sysdyn-1.0/ConfigurationDiagram"\r                        adapterClass="org.simantics.sysdyn.ui.elements2.ConfigurationDiagramClassAdapter" />\r   </target>\r\r     <!-- Sysdyn symbols -->\r        <target interface="org.simantics.diagram.adapter.ElementFactory">\r              <resource uri="http://www.simantics.org/Sysdyn-1.0/StockSymbol"\r                        class="org.simantics.sysdyn.ui.elements2.StockFactory" />\r              <resource uri="http://www.simantics.org/Sysdyn-1.0/ValveSymbol"\r                        class="org.simantics.sysdyn.ui.elements2.ValveFactory" />\r              <resource uri="http://www.simantics.org/Sysdyn-1.0/AuxiliarySymbol"\r                    class="org.simantics.sysdyn.ui.elements2.AuxiliaryFactory" />\r          <resource uri="http://www.simantics.org/Sysdyn-1.0/CloudSymbol"\r                        class="org.simantics.sysdyn.ui.elements2.CloudFactory" />\r\r             <type uri="http://www.simantics.org/Sysdyn-1.0/StockSymbol"\r                    class="org.simantics.sysdyn.ui.elements2.StockFactory" />\r              <type uri="http://www.simantics.org/Sysdyn-1.0/ValveSymbol"\r                    class="org.simantics.sysdyn.ui.elements2.ValveFactory" />\r              <type uri="http://www.simantics.org/Sysdyn-1.0/AuxiliarySymbol"\r                        class="org.simantics.sysdyn.ui.elements2.AuxiliaryFactory" />\r          <type uri="http://www.simantics.org/Sysdyn-1.0/CloudSymbol"\r                    class="org.simantics.sysdyn.ui.elements2.CloudFactory" />\r      </target>\r      \r       <!-- Sysdyn connections -->\r    <target interface="org.simantics.diagram.adapter.ElementFactory">\r              <!-- Edges -->\r         <resource uri="http://www.simantics.org/Sysdyn-1.0/Connection"\r                 class="org.simantics.sysdyn.ui.elements2.SysdynConnectionEdgeFactory" />\r               <!-- : SYSDYN.Connection-->\r            <type uri="http://www.simantics.org/Sysdyn-1.0/Connection"\r                     class="org.simantics.sysdyn.ui.elements2.SysdynConnectionFactory" />\r   </target>\r      \r       \r
+       </target>\r      \r       <target\r                interface="org.simantics.sysdyn.ui.browser.nodes.AbstractNode">\r                <type\r                  uri="http://www.simantics.org/Sysdyn-1.0/SysdynModel"\r                  class="org.simantics.sysdyn.ui.browser.nodes.ModelNode">\r                       <this />\r               </type>\r                \r               <type\r                  uri="http://www.simantics.org/Sysdyn-1.0/IndependentVariable"\r                  class="org.simantics.sysdyn.ui.browser.nodes.VariableNode">\r                    <this />\r               </type>\r                \r               <type\r                  uri="http://www.simantics.org/Simulation-1.0/Types/Experiment"\r                 class="org.simantics.sysdyn.ui.browser.nodes.ExperimentNode">\r                  <this />\r               </type>\r                \r               <type\r                  uri="http://www.simantics.org/Sysdyn-1.0/Result"\r                       class="org.simantics.sysdyn.ui.browser.nodes.SimulationResultNode">\r                    <this />\r               </type>\r        </target>\r\r     <!-- Inject default connection routing algorithm for sysdyn diagrams -->\r       <target interface="org.simantics.g2d.diagram.DiagramClass">\r            <adapter uri="http://www.simantics.org/Sysdyn-1.0/ConfigurationDiagram"\r                        adapterClass="org.simantics.sysdyn.ui.elements2.ConfigurationDiagramClassAdapter" />\r   </target>\r\r     <!-- Sysdyn symbols -->\r        <target interface="org.simantics.diagram.adapter.ElementFactory">\r              <resource uri="http://www.simantics.org/Sysdyn-1.0/StockSymbol"\r                        class="org.simantics.sysdyn.ui.elements2.StockFactory" />\r              <resource uri="http://www.simantics.org/Sysdyn-1.0/ValveSymbol"\r                        class="org.simantics.sysdyn.ui.elements2.ValveFactory" />\r              <resource uri="http://www.simantics.org/Sysdyn-1.0/AuxiliarySymbol"\r                    class="org.simantics.sysdyn.ui.elements2.AuxiliaryFactory" />\r          <resource uri="http://www.simantics.org/Sysdyn-1.0/CloudSymbol"\r                        class="org.simantics.sysdyn.ui.elements2.CloudFactory" />\r\r             <type uri="http://www.simantics.org/Sysdyn-1.0/StockSymbol"\r                    class="org.simantics.sysdyn.ui.elements2.StockFactory" />\r              <type uri="http://www.simantics.org/Sysdyn-1.0/ValveSymbol"\r                    class="org.simantics.sysdyn.ui.elements2.ValveFactory" />\r              <type uri="http://www.simantics.org/Sysdyn-1.0/AuxiliarySymbol"\r                        class="org.simantics.sysdyn.ui.elements2.AuxiliaryFactory" />\r          <type uri="http://www.simantics.org/Sysdyn-1.0/CloudSymbol"\r                    class="org.simantics.sysdyn.ui.elements2.CloudFactory" />\r      </target>\r      \r       <!-- Sysdyn connections -->\r    <target interface="org.simantics.diagram.adapter.ElementFactory">\r              <!-- Edges -->\r         <resource uri="http://www.simantics.org/Sysdyn-1.0/FlowConnection"\r                     class="org.simantics.sysdyn.ui.elements2.FlowEdgeFactory" />\r           <resource uri="http://www.simantics.org/Sysdyn-1.0/DependencyConnection"\r                       class="org.simantics.sysdyn.ui.elements2.DependencyEdgeFactory" />\r             <!-- : SYSDYN.Connection-->\r            <type uri="http://www.simantics.org/Sysdyn-1.0/FlowConnection"\r                 class="org.simantics.sysdyn.ui.elements2.FlowConnectionFactory" />\r             <type uri="http://www.simantics.org/Sysdyn-1.0/DependencyConnection"\r                   class="org.simantics.sysdyn.ui.elements2.DependencyConnectionFactory" />\r       </target>\r      \r       \r
 </adapters>
\ No newline at end of file
index 50ab222a626c1e6920376b8cfb86e9dd4992651a..fd43e11f999e0ce267da53a859f29751cae2bbc6 100644 (file)
@@ -19,6 +19,7 @@ import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;\r
 import org.simantics.db.exception.DatabaseException;\r
 import org.simantics.db.request.Read;\r
+import org.simantics.sysdyn.SysdynResource;\r
 import org.simantics.sysdyn.ui.browser.nodes.AbstractNode;\r
 \r
 /**\r
@@ -35,6 +36,7 @@ public abstract class LibraryViewpointContributor<T extends AbstractNode> extend
         ArrayList<AbstractNode> result = new ArrayList<AbstractNode>();\r
         for (Resource r : graph.syncRequest(getChildRequest(graph, lib))) {\r
             try {\r
+                System.out.println("Is Flow? " + graph.isInstanceOf(r, SysdynResource.getInstance(graph).Flow));\r
                 AbstractNode n = graph.adapt(r, AbstractNode.class);\r
                 result.add(n);\r
             } catch (DatabaseException e) {\r
index 2eed79eee667834dbc462b16fe1b70a5e96736a0..27bfbfab634e6cbe753209090669c01154be4032 100644 (file)
@@ -17,75 +17,113 @@ import org.simantics.db.exception.DatabaseException;
 import org.simantics.layer0.utils.binaryPredicates.InversePredicate;\r
 import org.simantics.layer0.utils.binaryPredicates.OrderedSetElementsPredicate;\r
 import org.simantics.mapping.constraint.instructions.IInstruction;\r
+import org.simantics.mapping.constraint.instructions.PrintStateInstruction;\r
 import org.simantics.mapping.constraint.instructions.TypedBracketInstruction.CreationInstruction;\r
 import org.simantics.mapping.rule.instructions.IRuleInstruction;\r
-import org.simantics.modeling.mapping.NamingCreationInstruction;\r
 import org.simantics.sysdyn.SysdynResource;\r
 \r
 public class DiagramToCompositeMapping3 extends org.simantics.modeling.mapping.DiagramToCompositeMapping3 {\r
 \r
-       private SysdynResource sdr;\r
+    private SysdynResource sdr;\r
 \r
-       public DiagramToCompositeMapping3(ReadGraph g, Resource mapping)\r
-       throws DatabaseException {\r
-               super(g, mapping);\r
-       }\r
+    public DiagramToCompositeMapping3(ReadGraph g, Resource mapping)\r
+    throws DatabaseException {\r
+        super(g, mapping);\r
+    }\r
 \r
-       @Override\r
-       protected void setup(ReadGraph graph) {\r
-               sdr = SysdynResource.getInstance(graph);\r
-       }\r
+    @Override\r
+    protected void setup(ReadGraph graph) {\r
+        sdr = SysdynResource.getInstance(graph);\r
+    }\r
 \r
-       @Override\r
-       protected Resource getConfigurationConnectionType() {\r
-               return sdr.Flow;\r
-       }\r
+    @Override\r
+    protected Resource getConfigurationConnectionType() {\r
+        return sdr.DependencyConnection;\r
+    }\r
 \r
-       public CreationInstruction componentCreationInstruction(int component, int componentType, int configuration) {\r
-               return new SysdynCreationInstruction(project, configurationRoot, component, componentType, configuration);\r
-       }\r
-       \r
-       @Override\r
-       protected IRuleInstruction destructiveRule() {\r
-               return\r
-               if_(and(bf(b.ConsistsOf, Configuration, Component),\r
+    @Override\r
+    public CreationInstruction componentCreationInstruction(int component, int componentType, int configuration) {\r
+        return new SysdynCreationInstruction(project, configurationRoot, component, componentType, configuration);\r
+    }\r
+\r
+    @Override\r
+    protected IRuleInstruction additiveRule() {\r
+        return \r
+        \r
+        if_(bf(OrderedSetElementsPredicate.INSTANCE, Diagram, Element),\r
+                query(\r
+                    if_(and(bf(b.InstanceOf, Element, ElementType),\r
+                               bf(mr.SymbolToComponentType, ElementType, ComponentType)\r
+                        ),\r
+                        // If element type of the element has a corresponding component type\r
+                        createComponentRule(),\r
+                    \r
+                        if_(and(b(dr.Connection, Element), bf(b.InstanceOf, Element, ElementType), bf(mr.DiagramConnectionTypeToConnectionType, ElementType, ComponentType)),\r
+                                createNormalConnectionRule(),\r
+\r
+                                if_(b(dr.Flag, Element),\r
+                                        createFlagRule()\r
+                                )\r
+                        )\r
+                    )\r
+                )\r
+            );\r
+    }\r
+\r
+    @Override\r
+    protected IRuleInstruction destructiveRule() {\r
+        return\r
+        if_(and(bf(b.ConsistsOf, Configuration, Component),\r
                 b(mapped, Component) // handle only mapped components\r
-            ),\r
-            query(\r
+        ),\r
+        query(\r
                 if_(and(bf(mr.ComponentToElement, Component, Element),\r
                         bf(new InversePredicate(OrderedSetElementsPredicate.INSTANCE), Element, Diagram)\r
-                    ),\r
-                    // If component has a corresponding element in the diagram\r
-                    if_(and(statement_bff(Component, ConnectionRelation, Connection, sr.IsConnectedTo),\r
-                            b(mapped, Connection)\r
-                        ),\r
-                        // If component has a mapped connection\r
-                        unless(\r
-                            bf(mr.ConnectionToDiagramConnection, Connection, DiagramConnectionRelation),\r
-                            // If the configuration connection does not have a correspondence in the diagram remove it\r
-                            and(deny(exists(Connection)))\r
-                        )\r
-                    ),\r
+                ),\r
+                // If component has a corresponding element in the diagram\r
+                if_(and(statement_bff(Component, ConnectionRelation, Connection, sr.IsConnectedTo),\r
+                        b(mapped, Connection)\r
+                ),\r
+                // If component has a mapped connection\r
+                unless(\r
+                        bf(mr.ConnectionToDiagramConnection, Connection, DiagramConnectionRelation),\r
+                        // If the configuration connection does not have a correspondence in the diagram remove it\r
+                        and(deny(exists(Connection)))\r
+                )\r
+                ),\r
+\r
+                unless(\r
+                        bf(mr.ConnectionToDiagramConnection, Component, Element),\r
+                        // If the configuration connection does not have a correspondence in the diagram remove it\r
+                        and(deny(exists(Component)))\r
+                )\r
 \r
-                    unless(\r
-                               bf(mr.ConnectionToDiagramConnection, Component, Element),\r
-                            // If the configuration connection does not have a correspondence in the diagram remove it\r
-                               and(deny(exists(Component)))\r
-                        )\r
-                    \r
                 )\r
-            )\r
+        )\r
         );\r
-       }\r
-       \r
-       protected IInstruction claimBasicConnection() {\r
-               return and(exists(\r
+    }\r
+\r
+    @Override\r
+    protected IInstruction claimBasicConnection() {\r
+        return and(exists(\r
                 bf(mr.DiagramConnectionToConnection, Element, Connection),\r
                 Connection\r
-            ),\r
-            bb(b.InstanceOf, Connection, ConnectionType),\r
-            bb(b.PartOf, Connection, Configuration)\r
-        );\r
-       }\r
+        ),\r
+        bb(b.InstanceOf, Connection, ComponentType),\r
+        b(mapped, Connection)\r
 \r
+        );\r
+    }\r
+    \r
+//    @Override\r
+//    protected IInstruction claimBasicConnection() {\r
+//        return and(exists(\r
+//                bf(mr.DiagramConnectionToConnection, Element, Connection),\r
+//                Connection\r
+//        ),\r
+//        bb(b.InstanceOf, Connection, ComponentType),\r
+//        b(mapped, Connection),\r
+//        bb(b.PartOf, Connection, Configuration)\r
+//        );\r
+//    }\r
 }\r
index e223b1931b5c512e279103cfee592d22f79b6315..a130c3a893b545274754e1244c3ae7479b26c4f2 100644 (file)
@@ -14,6 +14,7 @@ import org.simantics.g2d.canvas.ICanvasContext;
 import org.simantics.g2d.canvas.impl.CanvasContext;\r
 import org.simantics.g2d.diagram.DiagramHints;\r
 import org.simantics.g2d.diagram.participant.DeleteHandler;\r
+import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor;\r
 import org.simantics.g2d.element.ElementClassProviders;\r
 import org.simantics.g2d.element.ElementClasses;\r
 import org.simantics.g2d.element.IElementClassProvider;\r
@@ -21,6 +22,8 @@ import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;
 import org.simantics.g2d.elementclass.connection.ConnectionClass;\r
 import org.simantics.modeling.ui.diagramEditor.handlers.WorkbenchStructuralSelectionProvider2;\r
 import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.sysdyn.ui.elements2.ConnectionClasses;\r
+import org.simantics.sysdyn.ui.elements2.SysdynConnectionClass;\r
 import org.simantics.sysdyn.ui.properties.SysdynPropertyPage;\r
 \r
 /**\r
@@ -42,10 +45,15 @@ public class DiagramViewer extends org.simantics.modeling.ui.diagramEditor.Diagr
     protected IElementClassProvider createElementClassProvider(ReadGraph graph) {\r
         DiagramResource dr = DiagramResource.getInstance(graph);\r
         SysdynResource sr = SysdynResource.getInstance(graph);\r
+\r
         return ElementClassProviders.mappedProvider(\r
-                ElementClasses.CONNECTION, ConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.Connection)),\r
-                ElementClasses.FLAG, FlagClassFactory.createFlagClass(dr.Flag)\r
+                ElementClasses.CONNECTION, SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.FlowConnection)),\r
+                ElementClasses.FLAG, FlagClassFactory.createFlagClass(dr.Flag),\r
+                ConnectionClasses.FLOW, SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.FlowConnection)),\r
+                ConnectionClasses.DEPENDENCY, SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.DependencyConnection))\r
         );\r
+        \r
+        \r
     }\r
 \r
     @Override\r
@@ -73,4 +81,13 @@ public class DiagramViewer extends org.simantics.modeling.ui.diagramEditor.Diagr
         ctx.add(new WorkbenchStructuralSelectionProvider2(swt, getSite(), structuralPath));\r
     }\r
 \r
+    @Override\r
+    protected void addOtherParticipants(CanvasContext ctx) {\r
+    }\r
+    \r
+    @Override \r
+    protected PointerInteractor getPointerInteractor() {\r
+        return new org.simantics.sysdyn.ui.editor.participant.PointerInteractor(true, true, true, false, true, false, synchronizer.getElementClassProvider());\r
+    }\r
+\r
 }\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
new file mode 100644 (file)
index 0000000..6bb112b
--- /dev/null
@@ -0,0 +1,502 @@
+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.Resource;\r
+import org.simantics.diagram.content.ResourceTerminal;\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.IElementClassProvider;\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.elementclass.BranchPoint;\r
+import org.simantics.g2d.elementclass.FlagClass;\r
+import org.simantics.g2d.elementclass.FlagHandler;\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.ui.elements2.ConnectionClasses;\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
+            firstTerminal = ElementUtils.getSingleTerminal(firstElement);\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
+    @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
+                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
+                    commitDiagram();\r
+                    update();\r
+                    remove(); // Remove ConnectTool participant\r
+                    return true;\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
+    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
+    /**\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(IConnectionAdvisor advisor, IElement endElement, Terminal endTerminal) {\r
+        // Making sure that tail (head) terminal doesn't connect to another tail (head) terminal\r
+        Resource t1 = ((ResourceTerminal) startTerminal).getResource();\r
+        Resource t2 = ((ResourceTerminal) endTerminal).getResource();\r
+        if (startElement.equals(endElement) || t1.equals(t2))\r
+            return null;\r
+        \r
+        if (advisor == null)\r
+            return Boolean.TRUE;     \r
+        return advisor.canBeConnected(null, startElement, startTerminal, endElement, endTerminal);\r
+    }\r
+\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/PointerInteractor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/PointerInteractor.java
new file mode 100644 (file)
index 0000000..17f7879
--- /dev/null
@@ -0,0 +1,185 @@
+package org.simantics.sysdyn.ui.editor.participant;\r
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in 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
+\r
+import java.awt.Shape;\r
+import java.awt.geom.Point2D;\r
+import java.awt.geom.Rectangle2D;\r
+import java.util.List;\r
+\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
+import org.simantics.g2d.connection.IConnectionAdvisor;\r
+import org.simantics.g2d.diagram.DiagramHints;\r
+import org.simantics.g2d.diagram.handler.PickContext;\r
+import org.simantics.g2d.diagram.participant.Selection;\r
+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.IElementClassProvider;\r
+import org.simantics.g2d.event.MouseEvent;\r
+import org.simantics.g2d.event.EventHandlerReflection.EventHandler;\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.snap.ISnapAdvisor;\r
+import org.simantics.g2d.utils.GeometryUtils;\r
+import org.simantics.sysdyn.ui.elements2.ConnectionClasses;\r
+\r
+/**\r
+ * Pointer tool does the following operations with mouse:\r
+ *   - Selections\r
+ *   - Scale\r
+ *   - Rotate\r
+ *   - Translate\r
+ *   - Draws connections\r
+ *\r
+ *\r
+ * Pointer tool is active only when KEY_TOOLMODE is PointerToolMode\r
+ *\r
+ * TODO Pick rectangle not a point\r
+ *\r
+ * @author Toni Kalajainen\r
+ */\r
+public class PointerInteractor extends org.simantics.g2d.diagram.participant.pointertool.PointerInteractor {\r
+\r
+    @Dependency Selection selection;\r
+    @Dependency KeyUtil keys;\r
+    @Dependency TransformUtil util;\r
+    @Dependency PickContext pickContext;\r
+    @Dependency MouseUtil mice;\r
+    @Reference TerminalPainter terminalPainter;\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
+\r
+    @EventHandler(priority = TOOL_PRIORITY)\r
+    public boolean handlePress(MouseButtonPressedEvent me) {\r
+        if (!connects()) return false;\r
+//        if (me.button != MouseEvent.LEFT_BUTTON) return false;\r
+        if (getHint(Hints.KEY_TOOL) != Hints.POINTERTOOL) return false;\r
+        assertDependencies();\r
+        Point2D         curCanvasPos    = util.controlToCanvas(me.controlPosition, null);\r
+        \r
+        // Pick Terminal\r
+        TerminalInfo ti = pickTerminal(me.controlPosition);\r
+        \r
+        if(elementClassProvider != null) {\r
+            \r
+            ElementClass connectionClass = null;\r
+            \r
+            if( me.button == MouseEvent.LEFT_BUTTON && (me.stateMask & MouseEvent.ALT_MASK) != 0) {\r
+                diagram.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(false, false));\r
+                connectionClass = elementClassProvider.get(ConnectionClasses.DEPENDENCY);\r
+                \r
+            } else if (me.button == MouseEvent.RIGHT_BUTTON && (me.stateMask & MouseEvent.ALT_MASK) != 0) {\r
+                diagram.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(true, true));\r
+                connectionClass = elementClassProvider.get(ConnectionClasses.FLOW);\r
+            } else {\r
+                return false;\r
+            }\r
+            \r
+            ConnectTool bsi = null;\r
+            if (ti != null) {\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
+                }\r
+            } else {\r
+                ISnapAdvisor snapAdvisor = getHint(DiagramHints.SNAP_ADVISOR);\r
+                if(snapAdvisor != null) \r
+                    snapAdvisor.snap(curCanvasPos);\r
+\r
+                // Start connection out of thin air, without a terminal.\r
+                bsi = new ConnectTool(diagram, elementClassProvider.get(ConnectionClasses.DEPENDENCY), null, null, me.mouseId, curCanvasPos);\r
+            }\r
+            if (bsi != null) {\r
+                getContext().add(bsi);\r
+                return true;\r
+            }\r
+            \r
+        }\r
+        return false;\r
+    }\r
+    \r
+    public List<TerminalInfo> pickTerminals(Point2D controlPos)\r
+    {\r
+        Rectangle2D     controlPickRect     = new Rectangle2D.Double(controlPos.getX()-PointerInteractor.PICK_DIST, controlPos.getY()-PointerInteractor.PICK_DIST, PointerInteractor.PICK_DIST*2+1, PointerInteractor.PICK_DIST*2+1);\r
+        Shape           canvasPickRect      = GeometryUtils.transformShape(controlPickRect, util.getInverseTransform());\r
+        List<TerminalInfo> ti = TerminalUtil.pickTerminals(diagram, canvasPickRect, false, true);\r
+        return ti;\r
+    }\r
+\r
+    /**\r
+     * Paint bend handles. Handle is a selectable and draggable object.\r
+     *\r
+     * @param gc\r
+     */\r
+//    @Painter(priority = TerminalPainter.PAINT_PRIORITY + 10)\r
+//    public void paintBendHandles(GraphicsContext gc) {\r
+//        if (!connects()) return;\r
+//      double controlScale = GeometryUtils.getScale(gc.getGraphics2D().getTransform());\r
+//        // TODO: use another key for setting the bend point stroke color\r
+//      //Color bgColor = getHint(Hints.KEY_BACKGROUND_COLOR);\r
+//      Color bgColor = null;\r
+//      if (bgColor==null) bgColor = Color.GRAY;\r
+//      Graphics2D g = gc.createClone();\r
+//      util.controlToCanvas(g);\r
+//      if (!connects()) return;\r
+//      ArrayList<Bend> bends = new ArrayList<Bend>();\r
+//      AffineTransform _at = g.getTransform();\r
+//      Point2D bendPos = new Point2D.Double();\r
+//      for (IElement e : selection.getAllSelections())\r
+//      {\r
+//          BendsHandler bh = e.getElementClass().getAtMostOneItemOfClass(BendsHandler.class);\r
+//          if (bh==null) continue;\r
+//          bends.clear(); bh.getBends(e, bends);\r
+//          if (bends.isEmpty()) continue;\r
+//          g.setTransform(_at);\r
+//          g.transform( ElementUtils.getTransform(e) );\r
+//          double scale = GeometryUtils.getScale( g.getTransform() );\r
+//          for (Bend b : bends) {\r
+//              bh.getBendPosition(e, b, bendPos);\r
+//              g.translate(bendPos.getX(), bendPos.getY());\r
+//              g.setColor(Color.WHITE);\r
+//              g.scale(controlScale / scale, controlScale / scale);\r
+//              g.fill(BENDS);\r
+//              g.setColor(bgColor);\r
+//              g.draw(BENDS);\r
+//              g.scale(scale / controlScale, scale / controlScale);\r
+//              g.translate(-bendPos.getX(), -bendPos.getY());\r
+//          }\r
+//      }\r
+//    }\r
+//    static final Shape BENDS = new Rectangle2D.Double(-5, -5, 11, 11);\r
+\r
+\r
+\r
+    // <SCALING>\r
+    /*\r
+    @EventHandler(priority = -1)\r
+    public boolean scaleKey(KeyEvent ke) {\r
+        boolean alt = (ke.stateMask & java.awt.event.MouseEvent.ALT_DOWN_MASK) != 0;\r
+        if (alt && ke.keyCode == java.awt.event.KeyEvent.VK_S) {\r
+            //ScaleMode sm = new ScaleMode(me.startCanvasPos, curCanvasPos, me.mouseId, elementsToScale);\r
+            //getContext().add(sm);\r
+        }\r
+        return false;\r
+    }\r
+    // </SCALING>\r
+     */\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/ConnectionClasses.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/ConnectionClasses.java
new file mode 100644 (file)
index 0000000..7d10288
--- /dev/null
@@ -0,0 +1,20 @@
+package org.simantics.sysdyn.ui.elements2;\r
+\r
+public class ConnectionClasses {\r
+\r
+    public static final Object CONNECTION = new Object() {\r
+        public String toString() { return "CONNECTION"; }\r
+    };\r
+\r
+    public static final Object FLAG = new Object() {\r
+        public String toString() { return "FLAG"; }\r
+    };\r
+\r
+    public static final Object FLOW = new Object() {\r
+        public String toString() { return "CONNECTION"; }\r
+    };\r
+\r
+    public static final Object DEPENDENCY = new Object() {\r
+        public String toString() { return "DEPENDENCY"; }\r
+    };\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/DependencyConnectionFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/DependencyConnectionFactory.java
new file mode 100644 (file)
index 0000000..8f69965
--- /dev/null
@@ -0,0 +1,60 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in 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.elements2;\r
+\r
+import org.simantics.db.AsyncReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.procedure.AsyncProcedure;\r
+import org.simantics.diagram.adapter.ElementFactoryAdapter;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.g2d.diagram.DiagramHints;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.element.ElementClass;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
+import org.simantics.g2d.elementclass.connection.ConnectionClass;\r
+import org.simantics.g2d.routing.RouterFactory;\r
+\r
+/**\r
+ * An element class for single connection entity elements. A connection entity\r
+ * consists of connection edge segments and branch points as its children.\r
+ * \r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class DependencyConnectionFactory extends ElementFactoryAdapter {\r
+\r
+    public static final ElementClass CLASS = SysdynConnectionClass.CLASS;\r
+\r
+    @Override\r
+    public void create(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementType, final AsyncProcedure<ElementClass> procedure) {\r
+        DiagramResource dr = graph.getService(DiagramResource.class);\r
+        graph.forSingleType(elementType, dr.Connection, new AsyncProcedure<Resource>() {\r
+            @Override\r
+            public void exception(AsyncReadGraph graph, Throwable throwable) {\r
+                procedure.exception(graph, throwable);\r
+            }\r
+            @Override\r
+            public void execute(AsyncReadGraph graph, Resource connectionType) {\r
+                procedure.execute(graph, ConnectionClass.CLASS.newClassWith(false, new StaticObjectAdapter(connectionType)));\r
+            }\r
+        });\r
+    }\r
+\r
+    @Override\r
+    public void load(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementResource,\r
+            final IElement element, final AsyncProcedure<IElement> procedure) {\r
+        element.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(false, false));\r
+        procedure.execute(graph, element);\r
+    }\r
+\r
+}\r
similarity index 91%
rename from org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynEdgeClass.java
rename to org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/DependencyEdgeClass.java
index 95ace23054ee8a08d491bd165b72e3cc33bf9bcd..5a2d9a41b35716ad5b2c61c00f7dbb5848d32c3a 100644 (file)
@@ -49,13 +49,12 @@ import org.simantics.g2d.elementclass.connection.EdgeClass.EdgeHandler;
 import org.simantics.g2d.elementclass.connection.EdgeClass.FixedTransform;\r
 import org.simantics.g2d.utils.PathUtils;\r
 import org.simantics.scenegraph.g2d.G2DParentNode;\r
-import org.simantics.scenegraph.g2d.nodes.EdgeNode;\r
 import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
 \r
 /**\r
  * @author Toni Kalajainen\r
  */\r
-public class SysdynEdgeClass {\r
+public class DependencyEdgeClass {\r
 \r
     // TODO scale, rotate, move, transform\r
     public static final ElementClass CLASS =\r
@@ -79,11 +78,11 @@ public class SysdynEdgeClass {
 \r
         public static final Stroke ARROW_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER);\r
 \r
-        public static final Key KEY_SG_NODE = new SceneGraphNodeKey(EdgeNode.class, "EDGE_NODE");\r
+        public static final Key KEY_SG_NODE = new SceneGraphNodeKey(DependencyNode.class, "EDGE_NODE");\r
 \r
         @Override\r
         public void init(IElement e, G2DParentNode parent) {\r
-            ElementUtils.getOrCreateNode(e, parent, KEY_SG_NODE, "edge_" + e.hashCode(), EdgeNode.class);\r
+            ElementUtils.getOrCreateNode(e, parent, KEY_SG_NODE, "edge_" + e.hashCode(), DependencyNode.class);\r
             update(e);\r
         }\r
 \r
@@ -93,7 +92,7 @@ public class SysdynEdgeClass {
         }\r
 \r
         public void update(final IElement e) {\r
-            EdgeNode node = e.getHint(KEY_SG_NODE);\r
+            DependencyNode node = e.getHint(KEY_SG_NODE);\r
             if(node == null) return;\r
 \r
             EdgeVisuals vh = e.getElementClass().getSingleItem(EdgeVisuals.class);\r
@@ -131,7 +130,7 @@ public class SysdynEdgeClass {
             // Read bends\r
             BendsHandler bh = e.getElementClass().getSingleItem(BendsHandler.class);\r
             Path2D line = bh.getPath(e);\r
-\r
+            \r
             boolean drawArrows = at1 != ArrowType.None || at2 != ArrowType.None;\r
             //line = clipLineEnds(line, beginTerminalShape, endTerminalShape);\r
 \r
@@ -142,17 +141,17 @@ public class SysdynEdgeClass {
             PathIterator pi     = line.getPathIterator(null);\r
             drawArrows &= PathUtils.getPathArrows(pi, first, dir1, last, dir2);\r
 \r
-            EdgeNode.ArrowType pat1 = convert(at1);\r
-            EdgeNode.ArrowType pat2 = convert(at2);\r
+            DependencyNode.ArrowType pat1 = convert(at1);\r
+            DependencyNode.ArrowType pat2 = convert(at2);\r
 \r
             node.init(new GeneralPath(line), stroke, c, dir1, dir2, first, last, as1, as2, pat1, pat2, null, null);\r
         }\r
 \r
-        private static EdgeNode.ArrowType convert(ArrowType at) {\r
+        private static DependencyNode.ArrowType convert(ArrowType at) {\r
             switch (at) {\r
-                case None: return EdgeNode.ArrowType.None;\r
-                case Stroke: return EdgeNode.ArrowType.Stroke;\r
-                case Fill: return EdgeNode.ArrowType.Fill;\r
+                case None: return DependencyNode.ArrowType.None;\r
+                case Stroke: return DependencyNode.ArrowType.Stroke;\r
+                case Fill: return DependencyNode.ArrowType.Fill;\r
                 default:\r
                     throw new IllegalArgumentException("unsupported arrow type: " + at);\r
             }\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/DependencyEdgeFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/DependencyEdgeFactory.java
new file mode 100644 (file)
index 0000000..7443d02
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in 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.elements2;\r
+\r
+import org.simantics.db.AsyncReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.procedure.AsyncProcedure;\r
+import org.simantics.diagram.adapter.ElementFactoryAdapter;\r
+import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.element.ElementClass;\r
+\r
+/**\r
+ * An element class factory for sysdyn dependency connection edge segments.\r
+ * \r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class DependencyEdgeFactory extends ElementFactoryAdapter {\r
+\r
+    private static final ElementClass CLASS = DependencyEdgeClass.CLASS;\r
+\r
+    @Override\r
+    public void create(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementType,\r
+            AsyncProcedure<ElementClass> procedure) {\r
+        procedure.execute(graph, CLASS);\r
+    }\r
+\r
+    @Override\r
+    public void getClass(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementResource,\r
+            AsyncProcedure<ElementClass> procedure) {\r
+        throw new UnsupportedOperationException();\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/DependencyNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/DependencyNode.java
new file mode 100644 (file)
index 0000000..3584f16
--- /dev/null
@@ -0,0 +1,182 @@
+package org.simantics.sysdyn.ui.elements2;\r
+\r
+import java.awt.AlphaComposite;\r
+import java.awt.BasicStroke;\r
+import java.awt.Color;\r
+import java.awt.Composite;\r
+import java.awt.Graphics2D;\r
+import java.awt.RenderingHints;\r
+import java.awt.Shape;\r
+import java.awt.Stroke;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.GeneralPath;\r
+import java.awt.geom.Point2D;\r
+import java.awt.geom.Rectangle2D;\r
+import org.simantics.scenegraph.g2d.G2DNode;\r
+\r
+public class DependencyNode extends G2DNode {\r
+\r
+    private static final long serialVersionUID = 1294351381209071074L;\r
+\r
+    public static enum ArrowType { None, Stroke, Fill, Both }\r
+\r
+    protected Color color = null;\r
+    protected Stroke stroke = null;\r
+    protected Shape shape = null;\r
+    protected Point2D firstdir = null;\r
+    protected Point2D lastdir = null;\r
+    protected Point2D first = null;\r
+    protected Point2D last = null;\r
+    protected double firstsize = 0;\r
+    protected double lastsize = 0;\r
+    protected ArrowType first_at = null;\r
+    protected ArrowType last_at = null;\r
+    protected Shape firstShape = null;\r
+    protected Shape lastShape = null;\r
+\r
+    private transient Rectangle2D bounds;\r
+\r
+    @SyncField({"color", "stroke", "shape", "firstdir", "lastdir", "first", "last", "firstsize", "lastsize", "first_at", "last_at"})\r
+    public void init(Shape shape, Stroke stroke, Color color, Point2D firstdir, Point2D lastdir, Point2D first, Point2D last, double firstsize, double lastsize, ArrowType first_at, ArrowType last_at, Shape firstShape, Shape lastShape) {\r
+        this.color = color;\r
+        this.stroke = stroke;\r
+        this.shape = shape;\r
+        this.firstdir = firstdir;\r
+        this.lastdir = lastdir;\r
+        this.first = first;\r
+        this.last = last;\r
+        this.firstsize = firstsize;\r
+        this.lastsize = lastsize;\r
+        this.first_at = first_at;\r
+        this.last_at = last_at;\r
+        this.firstShape = firstShape;\r
+        this.lastShape = lastShape;\r
+\r
+        if (shape != null) {\r
+            this.bounds = shape.getBounds2D();\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void render(Graphics2D g) {\r
+        if(color != null) g.setColor(color);\r
+        if(stroke == null || shape == null)  return;\r
+\r
+        if(alphaComposite != null) {\r
+            g.setComposite(alphaComposite);\r
+        }\r
+        \r
+        Stroke effectiveStroke = stroke;\r
+        if(dynamicStroke != null) {\r
+            effectiveStroke = dynamicStroke;\r
+        }\r
+\r
+        Color effectiveColor = color;\r
+        if(dynamicColor != null) {\r
+            effectiveColor = dynamicColor;\r
+        }\r
+\r
+        g.setStroke(effectiveStroke);\r
+\r
+        // NICENESS\r
+        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
+\r
+        //g.draw(shape);\r
+\r
+        // Draw line "halo"\r
+        float f = 0.1f * 3f;\r
+        Color background = Color.WHITE; // FIXME\r
+        g.setColor(background);\r
+        g.setStroke(new BasicStroke(f));\r
+        g.draw(shape);\r
+\r
+        // Draw line\r
+        g.setColor(effectiveColor);\r
+        g.setStroke(effectiveStroke);\r
+        g.draw(shape);\r
+\r
+        // Draw line ends if necessary.\r
+        boolean drawArrows = first_at != ArrowType.None || last_at != ArrowType.None;\r
+        if (!drawArrows)\r
+            return;\r
+\r
+        g.setStroke(ARROW_STROKE);\r
+        AffineTransform at = g.getTransform();\r
+\r
+        double theta = Math.atan2(firstdir.getY(), firstdir.getX()) - Math.PI/2;\r
+        g.translate(first.getX(), first.getY());\r
+        g.rotate(theta);\r
+        g.scale(firstsize, firstsize);\r
+\r
+        if (first_at == ArrowType.Fill)\r
+            g.fill(FILLED_ARROW);\r
+        else if (first_at == ArrowType.Stroke)\r
+            g.draw(NORMAL_ARROW);\r
+\r
+        g.setTransform(at);\r
+\r
+        theta = Math.atan2(lastdir.getY(), lastdir.getX()) - Math.PI/2;\r
+\r
+        g.translate(last.getX(), last.getY());\r
+        g.rotate(theta);\r
+        g.scale(lastsize, lastsize);\r
+\r
+        if (last_at == ArrowType.Fill)\r
+            g.fill(FILLED_ARROW);\r
+        else if (last_at == ArrowType.Stroke)\r
+            g.draw(NORMAL_ARROW);\r
+    }\r
+\r
+\r
+    public transient final static GeneralPath NORMAL_ARROW;\r
+    public transient final static GeneralPath FILLED_ARROW;\r
+    public transient static final Stroke ARROW_STROKE = new BasicStroke(1.0f);\r
+\r
+    static {\r
+        FILLED_ARROW = new GeneralPath();\r
+        FILLED_ARROW.moveTo(-0.5f, 1f);\r
+        FILLED_ARROW.lineTo(   0f, 0f);\r
+        FILLED_ARROW.lineTo( 0.5f, 1f);\r
+        FILLED_ARROW.closePath();\r
+\r
+        NORMAL_ARROW = new GeneralPath();\r
+        NORMAL_ARROW.moveTo(-0.5f, 1f);\r
+        NORMAL_ARROW.lineTo(   0f, 0f);\r
+        NORMAL_ARROW.lineTo( 0.5f, 1f);\r
+    }\r
+\r
+    @Override\r
+    public Rectangle2D getBoundsInLocal() {\r
+        return bounds;\r
+    }\r
+\r
+    protected Composite alphaComposite = null;\r
+    protected Stroke dynamicStroke = null;\r
+    protected Color dynamicColor = null;\r
+\r
+    @Override\r
+    public void setValue(String key, Object value) {\r
+\r
+        if ("alpha".equals(key)) {\r
+            Float val = Float.parseFloat((String)value);\r
+            alphaComposite = AlphaComposite.getInstance(AlphaComposite. SRC_OVER, val);\r
+        } else if ("width".equals(key)) {\r
+            dynamicStroke = new BasicStroke(((Double)value).floatValue());\r
+        } else if ("color".equals(key)) {\r
+            try {\r
+                dynamicColor = new Color(Integer.parseInt(value.toString(), 16));\r
+            } catch (Throwable t) {\r
+                t.printStackTrace();\r
+            }\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void initValues() {\r
+        dynamicStroke = null;\r
+        dynamicColor = null;\r
+        alphaComposite = null;\r
+    }\r
+\r
+\r
+}\r
similarity index 88%
rename from org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynConnectionFactory.java
rename to org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/FlowConnectionFactory.java
index 3023e54460a76e96ea7cfcae72ae90f206b4f8a9..691cf55e684a3143ce114bc9d3e2b875af53171c 100644 (file)
@@ -17,11 +17,13 @@ import org.simantics.db.procedure.AsyncProcedure;
 import org.simantics.diagram.adapter.ElementFactoryAdapter;\r
 import org.simantics.diagram.stubs.DiagramResource;\r
 import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.g2d.diagram.DiagramHints;\r
 import org.simantics.g2d.diagram.IDiagram;\r
 import org.simantics.g2d.element.ElementClass;\r
 import org.simantics.g2d.element.IElement;\r
 import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
 import org.simantics.g2d.elementclass.connection.ConnectionClass;\r
+import org.simantics.g2d.routing.RouterFactory;\r
 \r
 /**\r
  * An element class for single connection entity elements. A connection entity\r
@@ -29,7 +31,7 @@ import org.simantics.g2d.elementclass.connection.ConnectionClass;
  * \r
  * @author Tuukka Lehtonen\r
  */\r
-public class SysdynConnectionFactory extends ElementFactoryAdapter {\r
+public class FlowConnectionFactory extends ElementFactoryAdapter {\r
 \r
     public static final ElementClass CLASS = SysdynConnectionClass.CLASS;\r
 \r
@@ -51,6 +53,7 @@ public class SysdynConnectionFactory extends ElementFactoryAdapter {
     @Override\r
     public void load(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementResource,\r
             final IElement element, final AsyncProcedure<IElement> procedure) {\r
+        element.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(true, true));\r
         procedure.execute(graph, element);\r
     }\r
 \r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/FlowEdgeClass.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/FlowEdgeClass.java
new file mode 100644 (file)
index 0000000..9e6f477
--- /dev/null
@@ -0,0 +1,198 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in 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.elements2;\r
+\r
+import java.awt.BasicStroke;\r
+import java.awt.Color;\r
+import java.awt.Shape;\r
+import java.awt.Stroke;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.GeneralPath;\r
+import java.awt.geom.Path2D;\r
+import java.awt.geom.PathIterator;\r
+import java.awt.geom.Point2D;\r
+import java.awt.geom.Rectangle2D;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.diagram.handler.Topology;\r
+import org.simantics.g2d.diagram.handler.Topology.Connection;\r
+import org.simantics.g2d.element.ElementClass;\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.BendsHandler;\r
+import org.simantics.g2d.element.handler.EdgeVisuals;\r
+import org.simantics.g2d.element.handler.EdgeVisuals.ArrowType;\r
+import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd;\r
+import org.simantics.g2d.element.handler.Rotate;\r
+import org.simantics.g2d.element.handler.SceneGraph;\r
+import org.simantics.g2d.element.handler.TerminalLayout;\r
+import org.simantics.g2d.element.handler.impl.ConfigurableEdgeVisuals;\r
+import org.simantics.g2d.element.handler.impl.ConnectionSelectionOutline;\r
+import org.simantics.g2d.element.handler.impl.FillColorImpl;\r
+import org.simantics.g2d.element.handler.impl.ParentImpl;\r
+import org.simantics.g2d.element.handler.impl.ShapePick;\r
+import org.simantics.g2d.element.handler.impl.SimpleElementLayers;\r
+import org.simantics.g2d.elementclass.BranchPoint;\r
+import org.simantics.g2d.elementclass.connection.EdgeClass.EdgeHandler;\r
+import org.simantics.g2d.elementclass.connection.EdgeClass.FixedTransform;\r
+import org.simantics.g2d.utils.PathUtils;\r
+import org.simantics.scenegraph.g2d.G2DParentNode;\r
+import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
+\r
+/**\r
+ * @author Toni Kalajainen\r
+ */\r
+public class FlowEdgeClass {\r
+\r
+    // TODO scale, rotate, move, transform\r
+    public static final ElementClass CLASS =\r
+        ElementClass.compile(\r
+                SysdynEdgeSceneGraph.INSTANCE,\r
+                EdgeHandler.INSTANCE,\r
+                ConfigurableEdgeVisuals.DEFAULT,\r
+                FillColorImpl.BLACK,\r
+                FixedTransform.INSTANCE,\r
+                ShapePick.INSTANCE,\r
+                ConnectionSelectionOutline.INSTANCE,\r
+                SimpleElementLayers.INSTANCE,\r
+                ParentImpl.INSTANCE\r
+        ).setId("EdgeClass.STRAIGHT");\r
+\r
+    public static class SysdynEdgeSceneGraph implements SceneGraph {\r
+\r
+        private static final long serialVersionUID = 2914383071126238996L;\r
+\r
+        public static final SysdynEdgeSceneGraph INSTANCE = new SysdynEdgeSceneGraph();\r
+\r
+        public static final Stroke ARROW_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER);\r
+\r
+        public static final Key KEY_SG_NODE = new SceneGraphNodeKey(FlowNode.class, "EDGE_NODE");\r
+\r
+        @Override\r
+        public void init(IElement e, G2DParentNode parent) {\r
+            ElementUtils.getOrCreateNode(e, parent, KEY_SG_NODE, "edge_" + e.hashCode(), FlowNode.class);\r
+            update(e);\r
+        }\r
+\r
+        @Override\r
+        public void cleanup(IElement e) {\r
+            ElementUtils.removePossibleNode(e, KEY_SG_NODE);\r
+        }\r
+\r
+        public void update(final IElement e) {\r
+            FlowNode node = e.getHint(KEY_SG_NODE);\r
+            if(node == null) return;\r
+\r
+            EdgeVisuals vh = e.getElementClass().getSingleItem(EdgeVisuals.class);\r
+            ArrowType at1 = vh.getArrowType(e, EdgeEnd.Begin);\r
+            ArrowType at2 = vh.getArrowType(e, EdgeEnd.End);\r
+            Stroke stroke = new FlowStroke(\r
+                    new BasicStroke(0.4f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER), \r
+                    new BasicStroke(0.1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));\r
+//            Stroke stroke = vh.getStroke(e);\r
+            //StrokeType strokeType = vh.getStrokeType(e);\r
+            double as1 = vh.getArrowSize(e, EdgeEnd.Begin);\r
+            double as2 = vh.getArrowSize(e, EdgeEnd.End);\r
+\r
+            Color c = ElementUtils.getFillColor(e, Color.BLACK);\r
+\r
+            // Get terminal shape for clipping the painted edge to its bounds.\r
+            IDiagram diagram = ElementUtils.peekDiagram(e);\r
+            Shape beginTerminalShape = null;\r
+            Shape endTerminalShape = null;\r
+            if (diagram != null) {\r
+                Topology topology = diagram.getDiagramClass().getAtMostOneItemOfClass(Topology.class);\r
+                if (topology != null) {\r
+                    Connection beginConnection = topology.getConnection(e, EdgeEnd.Begin);\r
+                    Connection endConnection = topology.getConnection(e, EdgeEnd.End);\r
+                    beginTerminalShape = getTerminalShape(beginConnection);\r
+                    endTerminalShape = getTerminalShape(endConnection);\r
+                    int beginBranchDegree = getBranchPointDegree(beginConnection, topology);\r
+                    int endBranchDegree = getBranchPointDegree(endConnection, topology);\r
+                    if (beginBranchDegree > 0 && beginBranchDegree < 3) {\r
+                        at1 = ArrowType.None;\r
+                    }\r
+                    if (endBranchDegree > 0 && endBranchDegree < 3) {\r
+                        at2 = ArrowType.None;\r
+                    }\r
+                }\r
+            }\r
+\r
+            // Read bends\r
+            BendsHandler bh = e.getElementClass().getSingleItem(BendsHandler.class);\r
+            Path2D line = bh.getPath(e);\r
+            \r
+            boolean drawArrows = at1 != ArrowType.None || at2 != ArrowType.None;\r
+            //line = clipLineEnds(line, beginTerminalShape, endTerminalShape);\r
+\r
+            Point2D first       = new Point2D.Double();\r
+            Point2D dir1        = new Point2D.Double();\r
+            Point2D last        = new Point2D.Double();\r
+            Point2D dir2        = new Point2D.Double();\r
+            PathIterator pi     = line.getPathIterator(null);\r
+            drawArrows &= PathUtils.getPathArrows(pi, first, dir1, last, dir2);\r
+\r
+            FlowNode.ArrowType pat1 = convert(at1);\r
+            FlowNode.ArrowType pat2 = convert(at2);\r
+\r
+            node.init(new GeneralPath(line), stroke, c, dir1, dir2, first, last, as1, as2, pat1, pat2, null, null);\r
+        }\r
+\r
+        private static FlowNode.ArrowType convert(ArrowType at) {\r
+            switch (at) {\r
+                case None: return FlowNode.ArrowType.None;\r
+                case Stroke: return FlowNode.ArrowType.Stroke;\r
+                case Fill: return FlowNode.ArrowType.Fill;\r
+                default:\r
+                    throw new IllegalArgumentException("unsupported arrow type: " + at);\r
+            }\r
+        }\r
+\r
+        private static final Rectangle2D EMPTY = new Rectangle2D.Double();\r
+\r
+        private static Shape getTerminalShape(Connection connection) {\r
+            if (connection != null && connection.node != null && connection.terminal != null) {\r
+                TerminalLayout layout = connection.node.getElementClass().getAtMostOneItemOfClass(TerminalLayout.class);\r
+                if (layout != null) {\r
+                    //return layout.getTerminalShape(connection.node, connection.terminal);\r
+                    Shape shp = layout.getTerminalShape(connection.node, connection.terminal);\r
+                    Rotate rotate = connection.node.getElementClass().getAtMostOneItemOfClass(Rotate.class);\r
+                    if (rotate == null)\r
+                        return shp;\r
+\r
+                    double theta = rotate.getAngle(connection.node);\r
+                    return AffineTransform.getRotateInstance(theta).createTransformedShape(shp);\r
+                }\r
+            }\r
+            return null;\r
+        }\r
+\r
+        private final Collection<Connection> connectionsTemp = new ArrayList<Connection>();\r
+        private int getBranchPointDegree(Connection connection, Topology topology) {\r
+            if (connection != null && connection.node != null) {\r
+                if (connection.node.getElementClass().containsClass(BranchPoint.class)) {\r
+                    connectionsTemp.clear();\r
+                    topology.getConnections(connection.node, connection.terminal, connectionsTemp);\r
+                    int degree = connectionsTemp.size();\r
+                    connectionsTemp.clear();\r
+                    return degree;\r
+                }\r
+            }\r
+            return -1;\r
+        }\r
+\r
+    }\r
+\r
+}\r
similarity index 85%
rename from org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynConnectionEdgeFactory.java
rename to org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/FlowEdgeFactory.java
index 180a2349244ec20bc86e0273debf9b968836d50b..7d428da972ba1257d600f8043dba64a815d530d4 100644 (file)
@@ -20,13 +20,13 @@ import org.simantics.g2d.diagram.IDiagram;
 import org.simantics.g2d.element.ElementClass;\r
 \r
 /**\r
- * An element class factory for sysdyn connection edge segments.\r
+ * An element class factory for sysdyn flow connection edge segments.\r
  * \r
  * @author Tuukka Lehtonen\r
  */\r
-public class SysdynConnectionEdgeFactory extends ElementFactoryAdapter {\r
+public class FlowEdgeFactory extends ElementFactoryAdapter {\r
 \r
-    private static final ElementClass CLASS = SysdynEdgeClass.CLASS;\r
+    private static final ElementClass CLASS = FlowEdgeClass.CLASS;\r
 \r
     @Override\r
     public void create(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementType,\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/FlowNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/FlowNode.java
new file mode 100644 (file)
index 0000000..5bfb68d
--- /dev/null
@@ -0,0 +1,182 @@
+package org.simantics.sysdyn.ui.elements2;\r
+\r
+import java.awt.AlphaComposite;\r
+import java.awt.BasicStroke;\r
+import java.awt.Color;\r
+import java.awt.Composite;\r
+import java.awt.Graphics2D;\r
+import java.awt.RenderingHints;\r
+import java.awt.Shape;\r
+import java.awt.Stroke;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.GeneralPath;\r
+import java.awt.geom.Point2D;\r
+import java.awt.geom.Rectangle2D;\r
+import org.simantics.scenegraph.g2d.G2DNode;\r
+\r
+public class FlowNode extends G2DNode {\r
+\r
+    private static final long serialVersionUID = 1294351381209071074L;\r
+\r
+    public static enum ArrowType { None, Stroke, Fill, Both }\r
+\r
+    protected Color color = null;\r
+    protected Stroke stroke = null;\r
+    protected Shape shape = null;\r
+    protected Point2D firstdir = null;\r
+    protected Point2D lastdir = null;\r
+    protected Point2D first = null;\r
+    protected Point2D last = null;\r
+    protected double firstsize = 0;\r
+    protected double lastsize = 0;\r
+    protected ArrowType first_at = null;\r
+    protected ArrowType last_at = null;\r
+    protected Shape firstShape = null;\r
+    protected Shape lastShape = null;\r
+\r
+    private transient Rectangle2D bounds;\r
+\r
+    @SyncField({"color", "stroke", "shape", "firstdir", "lastdir", "first", "last", "firstsize", "lastsize", "first_at", "last_at"})\r
+    public void init(Shape shape, Stroke stroke, Color color, Point2D firstdir, Point2D lastdir, Point2D first, Point2D last, double firstsize, double lastsize, ArrowType first_at, ArrowType last_at, Shape firstShape, Shape lastShape) {\r
+        this.color = color;\r
+        this.stroke = stroke;\r
+        this.shape = shape;\r
+        this.firstdir = firstdir;\r
+        this.lastdir = lastdir;\r
+        this.first = first;\r
+        this.last = last;\r
+        this.firstsize = firstsize;\r
+        this.lastsize = lastsize;\r
+        this.first_at = first_at;\r
+        this.last_at = last_at;\r
+        this.firstShape = firstShape;\r
+        this.lastShape = lastShape;\r
+\r
+        if (shape != null) {\r
+            this.bounds = shape.getBounds2D();\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void render(Graphics2D g) {\r
+        if(color != null) g.setColor(color);\r
+        if(stroke == null || shape == null)  return;\r
+\r
+        if(alphaComposite != null) {\r
+            g.setComposite(alphaComposite);\r
+        }\r
+        \r
+        Stroke effectiveStroke = stroke;\r
+        if(dynamicStroke != null) {\r
+            effectiveStroke = dynamicStroke;\r
+        }\r
+\r
+        Color effectiveColor = color;\r
+        if(dynamicColor != null) {\r
+            effectiveColor = dynamicColor;\r
+        }\r
+\r
+        g.setStroke(effectiveStroke);\r
+\r
+        // NICENESS\r
+        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
+\r
+        //g.draw(shape);\r
+\r
+        // Draw line "halo"\r
+        float f = 0.1f * 3f;\r
+        Color background = Color.WHITE; // FIXME\r
+        g.setColor(background);\r
+        g.setStroke(new BasicStroke(f));\r
+        g.draw(shape);\r
+\r
+        // Draw line\r
+        g.setColor(effectiveColor);\r
+        g.setStroke(effectiveStroke);\r
+        g.draw(shape);\r
+\r
+        // Draw line ends if necessary.\r
+        boolean drawArrows = first_at != ArrowType.None || last_at != ArrowType.None;\r
+        if (!drawArrows)\r
+            return;\r
+\r
+        g.setStroke(ARROW_STROKE);\r
+        AffineTransform at = g.getTransform();\r
+\r
+        double theta = Math.atan2(firstdir.getY(), firstdir.getX()) - Math.PI/2;\r
+        g.translate(first.getX(), first.getY());\r
+        g.rotate(theta);\r
+        g.scale(firstsize, firstsize);\r
+\r
+        if (first_at == ArrowType.Fill)\r
+            g.fill(FILLED_ARROW);\r
+        else if (first_at == ArrowType.Stroke)\r
+            g.draw(NORMAL_ARROW);\r
+\r
+        g.setTransform(at);\r
+\r
+        theta = Math.atan2(lastdir.getY(), lastdir.getX()) - Math.PI/2;\r
+\r
+        g.translate(last.getX(), last.getY());\r
+        g.rotate(theta);\r
+        g.scale(lastsize, lastsize);\r
+\r
+        if (last_at == ArrowType.Fill)\r
+            g.fill(FILLED_ARROW);\r
+        else if (last_at == ArrowType.Stroke)\r
+            g.draw(NORMAL_ARROW);\r
+    }\r
+\r
+\r
+    public transient final static GeneralPath NORMAL_ARROW;\r
+    public transient final static GeneralPath FILLED_ARROW;\r
+    public transient static final Stroke ARROW_STROKE = new BasicStroke(1.0f);\r
+\r
+    static {\r
+        FILLED_ARROW = new GeneralPath();\r
+        FILLED_ARROW.moveTo(-0.5f, 1f);\r
+        FILLED_ARROW.lineTo(   0f, 0f);\r
+        FILLED_ARROW.lineTo( 0.5f, 1f);\r
+        FILLED_ARROW.closePath();\r
+\r
+        NORMAL_ARROW = new GeneralPath();\r
+        NORMAL_ARROW.moveTo(-0.5f, 1f);\r
+        NORMAL_ARROW.lineTo(   0f, 0f);\r
+        NORMAL_ARROW.lineTo( 0.5f, 1f);\r
+    }\r
+\r
+    @Override\r
+    public Rectangle2D getBoundsInLocal() {\r
+        return bounds;\r
+    }\r
+\r
+    protected Composite alphaComposite = null;\r
+    protected Stroke dynamicStroke = null;\r
+    protected Color dynamicColor = null;\r
+\r
+    @Override\r
+    public void setValue(String key, Object value) {\r
+\r
+        if ("alpha".equals(key)) {\r
+            Float val = Float.parseFloat((String)value);\r
+            alphaComposite = AlphaComposite.getInstance(AlphaComposite. SRC_OVER, val);\r
+        } else if ("width".equals(key)) {\r
+            dynamicStroke = new BasicStroke(((Double)value).floatValue());\r
+        } else if ("color".equals(key)) {\r
+            try {\r
+                dynamicColor = new Color(Integer.parseInt(value.toString(), 16));\r
+            } catch (Throwable t) {\r
+                t.printStackTrace();\r
+            }\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void initValues() {\r
+        dynamicStroke = null;\r
+        dynamicColor = null;\r
+        alphaComposite = null;\r
+    }\r
+\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/FlowStroke.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/FlowStroke.java
new file mode 100644 (file)
index 0000000..76e7d4d
--- /dev/null
@@ -0,0 +1,18 @@
+package org.simantics.sysdyn.ui.elements2;\r
+\r
+import java.awt.Shape;\r
+import java.awt.Stroke;\r
+\r
+public class FlowStroke implements Stroke {\r
+    private Stroke stroke1, stroke2;\r
+\r
+    public FlowStroke( Stroke stroke1, Stroke stroke2 ) {\r
+        this.stroke1 = stroke1;\r
+        this.stroke2 = stroke2;\r
+    }\r
+\r
+    public Shape createStrokedShape( Shape shape ) {\r
+        return stroke2.createStrokedShape( stroke1.createStrokedShape( shape ) );\r
+    }\r
+   \r
+}\r
index c58bc2309d89e00addcadea1d4546c082ab549b5..723dc2348dd00048c23c6cca932fba4f2d7afb88 100644 (file)
@@ -27,14 +27,15 @@ public class SysdynResource {
     public final Resource CloudSymbol;\r
     public final Resource Configuration;\r
     public final Resource ConfigurationDiagram;\r
-    public final Resource Connection;\r
     public final Resource ConstantExpression;\r
     public final Resource DelayExpression;\r
     public final Resource Dependency;\r
+    public final Resource DependencyConnection;\r
     public final Resource DiagramToCompositeMapping;\r
     public final Resource Experiment;\r
     public final Resource Expression;\r
     public final Resource Flow;\r
+    public final Resource FlowConnection;\r
     public final Resource GameExperiment;\r
     public final Resource HasAngle;\r
     public final Resource HasEquation;\r
@@ -94,14 +95,15 @@ public class SysdynResource {
         public static final String CloudSymbol = "http://www.simantics.org/Sysdyn-1.0/CloudSymbol";\r
         public static final String Configuration = "http://www.simantics.org/Sysdyn-1.0/Configuration";\r
         public static final String ConfigurationDiagram = "http://www.simantics.org/Sysdyn-1.0/ConfigurationDiagram";\r
-        public static final String Connection = "http://www.simantics.org/Sysdyn-1.0/Connection";\r
         public static final String ConstantExpression = "http://www.simantics.org/Sysdyn-1.0/ConstantExpression";\r
         public static final String DelayExpression = "http://www.simantics.org/Sysdyn-1.0/DelayExpression";\r
         public static final String Dependency = "http://www.simantics.org/Sysdyn-1.0/Dependency";\r
+        public static final String DependencyConnection = "http://www.simantics.org/Sysdyn-1.0/DependencyConnection";\r
         public static final String DiagramToCompositeMapping = "http://www.simantics.org/Sysdyn-1.0/DiagramToCompositeMapping";\r
         public static final String Experiment = "http://www.simantics.org/Sysdyn-1.0/Experiment";\r
         public static final String Expression = "http://www.simantics.org/Sysdyn-1.0/Expression";\r
         public static final String Flow = "http://www.simantics.org/Sysdyn-1.0/Flow";\r
+        public static final String FlowConnection = "http://www.simantics.org/Sysdyn-1.0/FlowConnection";\r
         public static final String GameExperiment = "http://www.simantics.org/Sysdyn-1.0/GameExperiment";\r
         public static final String HasAngle = "http://www.simantics.org/Sysdyn-1.0/HasAngle";\r
         public static final String HasEquation = "http://www.simantics.org/Sysdyn-1.0/HasEquation";\r
@@ -171,14 +173,15 @@ public class SysdynResource {
         CloudSymbol = getResourceOrNull(graph, URIs.CloudSymbol);\r
         Configuration = getResourceOrNull(graph, URIs.Configuration);\r
         ConfigurationDiagram = getResourceOrNull(graph, URIs.ConfigurationDiagram);\r
-        Connection = getResourceOrNull(graph, URIs.Connection);\r
         ConstantExpression = getResourceOrNull(graph, URIs.ConstantExpression);\r
         DelayExpression = getResourceOrNull(graph, URIs.DelayExpression);\r
         Dependency = getResourceOrNull(graph, URIs.Dependency);\r
+        DependencyConnection = getResourceOrNull(graph, URIs.DependencyConnection);\r
         DiagramToCompositeMapping = getResourceOrNull(graph, URIs.DiagramToCompositeMapping);\r
         Experiment = getResourceOrNull(graph, URIs.Experiment);\r
         Expression = getResourceOrNull(graph, URIs.Expression);\r
         Flow = getResourceOrNull(graph, URIs.Flow);\r
+        FlowConnection = getResourceOrNull(graph, URIs.FlowConnection);\r
         GameExperiment = getResourceOrNull(graph, URIs.GameExperiment);\r
         HasAngle = getResourceOrNull(graph, URIs.HasAngle);\r
         HasEquation = getResourceOrNull(graph, URIs.HasEquation);\r
index afbd29a88ea589762cb3d8a9df2658bc4e370988..d2a16833a289a3dae37c7dd83e3c9f847f70be0c 100644 (file)
@@ -164,8 +164,6 @@ Terminal <T Variable
 # Connections and Relations\r
 ######################################################################\r
 \r
-HasAngle <R L0.HasProperty\r
-    L0.HasRange L0.Double\r
 IsTailOf <R ST.IsConnectedTo\r
     L0.HasDomain Variable\r
     L0.HasRange Dependency\r
@@ -391,4 +389,15 @@ CloudSymbol <T DIA.FontProvider <T DIA.ColorProvider
 # Diagram connection types\r
 ######################################################################\r
 \r
-Connection <T DIA.Connection\r
+HasAngle <R L0.HasProperty\r
+  L0.HasRange L0.Double\r
+\r
+FlowConnection <T DIA.Connection\r
+  MOD.DiagramConnectionTypeToConnectionType\r
+    Flow  \r
+    \r
+DependencyConnection <T DIA.Connection\r
+  [HasAngle card "1"]  \r
+  MOD.DiagramConnectionTypeToConnectionType\r
+    Dependency\r
+    \r