]> gerrit.simantics Code Review - simantics/sysdyn.git/commitdiff
Desperately working towards a g2d version of the sysdyn diagram editor. True crap...
authorlehtonen <lehtonen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Mon, 21 Jun 2010 15:19:41 +0000 (15:19 +0000)
committerlehtonen <lehtonen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Mon, 21 Jun 2010 15:19:41 +0000 (15:19 +0000)
Connections are not created properly on the configuration side.
PointerInteractor/ConnectTool needs to be replaced by something that works better for
sysdyn models. Not quite sure how to model the connections.

git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@16266 ac1ea38d-2e2b-0410-8846-a27921b304fc

org.simantics.sysdyn.ui/adapters.xml
org.simantics.sysdyn.ui/plugin.xml
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/DiagramViewer.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/AuxiliaryFactory.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/ConfigurationDiagramClassAdapter.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynConnectionClass.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynConnectionEdgeFactory.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynConnectionFactory.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynEdgeClass.java [new file with mode: 0644]
org.simantics.sysdyn/src/org/simantics/sysdyn/SysdynResource.java
sysdyn_ontologies/sysdyn.graph

index 863bfe886212bcda32571264dc9989f785dda049..8fb25f46a3c93c3effbc5d3871225dcce660013d 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     <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
+       </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
 </adapters>
\ No newline at end of file
index 2b48bcc7aba7acd850695cddc233685065a03508..4d1fce63ee5a3c41515d38a1d3c065eee6cb4d62 100644 (file)
@@ -37,8 +37,9 @@
    <extension\r
          point="org.simantics.ui.resourceEditorAdapter">\r
          <adapterClass\r
-            class="org.simantics.sysdyn.ui.editor.OpenDiagramFromConfigurationAdapter"\r
-            priority="100">\r
+         class="org.simantics.sysdyn.ui.editor.OpenDiagramFromConfigurationAdapter"\r
+         groupId="org.simantics.diagramEditor.group"\r
+         priority="100">\r
       </adapterClass>\r
       <adapter\r
             editorId="org.simantics.sysdyn.ui.diagramEditor"\r
index 72a5f8e66334da419d74b4d023534626cbf0e641..e223b1931b5c512e279103cfee592d22f79b6315 100644 (file)
@@ -6,12 +6,19 @@ import java.util.Set;
 import org.eclipse.ui.IWorkbenchPartSite;\r
 import org.simantics.browsing.ui.swt.IPropertyPage;\r
 import org.simantics.db.ReadGraph;\r
-import org.simantics.diagram.handler.ConnectionCommandHandler;\r
+import org.simantics.diagram.adapter.FlagClassFactory;\r
 import org.simantics.diagram.handler.CopyPasteHandler;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
 import org.simantics.diagram.synchronization.IModifiableSynchronizationContext;\r
 import org.simantics.g2d.canvas.ICanvasContext;\r
 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.element.ElementClassProviders;\r
+import org.simantics.g2d.element.ElementClasses;\r
+import org.simantics.g2d.element.IElementClassProvider;\r
+import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
+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.properties.SysdynPropertyPage;\r
@@ -31,12 +38,25 @@ public class DiagramViewer extends org.simantics.modeling.ui.diagramEditor.Diagr
         return new SysdynPropertyPage(site, contexts);\r
     }\r
 \r
+    @Override\r
+    protected IElementClassProvider createElementClassProvider(ReadGraph graph) {\r
+        DiagramResource dr = DiagramResource.getInstance(graph);\r
+        SysdynResource sr = SysdynResource.getInstance(graph);\r
+        return ElementClassProviders.mappedProvider(\r
+                ElementClasses.CONNECTION, ConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.Connection)),\r
+                ElementClasses.FLAG, FlagClassFactory.createFlagClass(dr.Flag)\r
+        );\r
+    }\r
+\r
+    @Override\r
+    protected void onCreated() {\r
+        sourceDiagram.setHint(DiagramHints.KEY_ALLOW_ROUTE_POINTS, Boolean.FALSE);\r
+    }\r
+\r
     @Override\r
     protected void addKeyBindingParticipants(CanvasContext ctx) {\r
-//        ctx.add(new KeyToCommand(AprosKeyBindings.BINDINGS));\r
         ctx.add(new DeleteHandler(getEditorSite().getActionBars().getStatusLineManager()));\r
         ctx.add(new CopyPasteHandler(getEditorSite().getActionBars().getStatusLineManager()));\r
-        ctx.add(new ConnectionCommandHandler());\r
     }\r
 \r
     @Override\r
index ef91c80a6cca772645249cdb1fc806f434da3c58..e0f6838fa2df8b7b2c25d0ad1718e7570d7c4559 100644 (file)
@@ -38,7 +38,7 @@ import org.simantics.g2d.image.impl.ShapeImage;
 public class AuxiliaryFactory extends SysdynElementFactory {\r
 \r
     // TODO: make the static symbol image a text "AUX"\r
-    private static final Image AUX_STATIC_IMAGE = new ShapeImage(new Ellipse2D.Double(-5, -2, 10, 4), null, new BasicStroke(0.1f), true);\r
+    private static final Image AUX_STATIC_IMAGE = new ShapeImage(new Ellipse2D.Double(-5, -2, 10, 4), null, new BasicStroke(1), true);\r
 \r
     @Override\r
     protected ElementClass compileElementClass(Resource elementType, Collection<ObjectTerminal> terminals) {\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/ConfigurationDiagramClassAdapter.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/ConfigurationDiagramClassAdapter.java
new file mode 100644 (file)
index 0000000..6e4a945
--- /dev/null
@@ -0,0 +1,46 @@
+/*******************************************************************************\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.adaption.Adapter;\r
+import org.simantics.db.procedure.AsyncProcedure;\r
+import org.simantics.diagram.adapter.DiagramClassAdapter;\r
+import org.simantics.g2d.diagram.DiagramClass;\r
+import org.simantics.g2d.diagram.DiagramHints;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.diagram.handler.LifeCycle;\r
+import org.simantics.g2d.routing.RouterFactory;\r
+\r
+/**\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class ConfigurationDiagramClassAdapter implements Adapter<DiagramClass> {\r
+\r
+    @Override\r
+    public void adapt(AsyncReadGraph g, Resource r, AsyncProcedure<DiagramClass> procedure) {\r
+        procedure.execute(g, DiagramClassAdapter.INSTANCE.newClassWith(\r
+                Initializer.INSTANCE\r
+        ));\r
+    }\r
+\r
+    static class Initializer extends LifeCycle.Stub {\r
+        public static final Initializer INSTANCE = new Initializer();\r
+\r
+        @Override\r
+        public void onDiagramCreated(IDiagram diagram) {\r
+            diagram.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(false, false));\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynConnectionClass.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynConnectionClass.java
new file mode 100644 (file)
index 0000000..0291a89
--- /dev/null
@@ -0,0 +1,545 @@
+/*******************************************************************************\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.Composite;\r
+import java.awt.Shape;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Area;\r
+import java.awt.geom.Rectangle2D;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import org.simantics.g2d.connection.ConnectionEntity;\r
+import org.simantics.g2d.connection.ConnectionEntity.ConnectionEvent;\r
+import org.simantics.g2d.connection.ConnectionEntity.ConnectionListener;\r
+import org.simantics.g2d.connection.handler.ConnectionHandler;\r
+import org.simantics.g2d.diagram.handler.PickRequest.PickPolicy;\r
+import org.simantics.g2d.diagram.handler.Topology.Connection;\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.handler.Children;\r
+import org.simantics.g2d.element.handler.InternalSize;\r
+import org.simantics.g2d.element.handler.Outline;\r
+import org.simantics.g2d.element.handler.Pick;\r
+import org.simantics.g2d.element.handler.Pick2;\r
+import org.simantics.g2d.element.handler.SceneGraph;\r
+import org.simantics.g2d.element.handler.SelectionOutline;\r
+import org.simantics.g2d.element.handler.Transform;\r
+import org.simantics.g2d.element.handler.impl.ConnectionSelectionOutline;\r
+import org.simantics.g2d.element.handler.impl.ParentImpl;\r
+import org.simantics.g2d.element.handler.impl.SimpleElementLayers;\r
+import org.simantics.g2d.element.handler.impl.TextImpl;\r
+import org.simantics.g2d.elementclass.connection.EdgeClass.FixedTransform;\r
+import org.simantics.g2d.utils.GeometryUtils;\r
+import org.simantics.scenegraph.g2d.G2DParentNode;\r
+import org.simantics.scenegraph.g2d.IG2DNode;\r
+import org.simantics.scenegraph.g2d.nodes.SingleElementNode;\r
+import org.simantics.utils.datastructures.ListenerList;\r
+import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
+import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;\r
+\r
+/**\r
+ * An element class for single connection entity elements. A sysdyn connection\r
+ * entity consists of a single edge. Sysdyn connections can't be branched.\r
+ * \r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class SysdynConnectionClass {\r
+\r
+    public static final ElementClass CLASS =\r
+        ElementClass.compile(\r
+                TextImpl.INSTANCE,\r
+                FixedTransform.INSTANCE,\r
+                ConnectionPick.INSTANCE,\r
+                ConnectionBounds.INSTANCE,\r
+                ConnectionSelectionOutline.INSTANCE,\r
+                ConnectionHandlerImpl.INSTANCE,\r
+                ConnectionChildren.INSTANCE,\r
+                ParentImpl.INSTANCE,\r
+                ConnectionSceneGraph.INSTANCE,\r
+                SimpleElementLayers.INSTANCE\r
+        ).setId(SysdynConnectionClass.class.getSimpleName());\r
+\r
+    private static final ThreadLocal<List<IElement>> perThreadElementList = new ThreadLocal<List<IElement>>() {\r
+        @Override\r
+        protected java.util.List<IElement> initialValue() {\r
+            return new ArrayList<IElement>();\r
+        }\r
+    };\r
+\r
+    static class ConnectionHandlerImpl implements ConnectionHandler {\r
+\r
+        public static final ConnectionHandlerImpl INSTANCE = new ConnectionHandlerImpl();\r
+\r
+        private static final long serialVersionUID = 3267139233182458330L;\r
+\r
+        @Override\r
+        public Collection<IElement> getBranchPoints(IElement connection, Collection<IElement> result) {\r
+            ConnectionEntity entity = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY);\r
+            if (entity == null)\r
+                return Collections.emptySet();\r
+            return entity.getBranchPoints(result);\r
+        }\r
+\r
+        @Override\r
+        public Collection<IElement> getChildren(IElement connection, Collection<IElement> result) {\r
+            ConnectionEntity entity = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY);\r
+            if (entity == null)\r
+                return Collections.emptySet();\r
+            result = entity.getSegments(result);\r
+            return entity.getBranchPoints(result);\r
+        }\r
+\r
+        @Override\r
+        public Collection<IElement> getSegments(IElement connection, Collection<IElement> result) {\r
+            ConnectionEntity entity = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY);\r
+            if (entity == null)\r
+                return Collections.emptySet();\r
+            return entity.getSegments(result);\r
+        }\r
+\r
+        @Override\r
+        public Collection<Connection> getTerminalConnections(IElement connection, Collection<Connection> result) {\r
+            ConnectionEntity entity = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY);\r
+            if (entity == null)\r
+                return Collections.emptySet();\r
+            return entity.getTerminalConnections(result);\r
+        }\r
+\r
+        @Override\r
+        public IElement newBranchPoint(IElement connection) {\r
+            ConnectionEntity entity = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY);\r
+            if (entity == null)\r
+                throw new IllegalArgumentException("element '" + connection + "' is not a connection element");\r
+            return entity.newBranchPoint();\r
+        }\r
+\r
+        @Override\r
+        public IElement newEdge(IElement connection) {\r
+            ConnectionEntity entity = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY);\r
+            if (entity == null)\r
+                throw new IllegalArgumentException("element '" + connection + "' is not a connection element");\r
+            return entity.newEdge();\r
+        }\r
+\r
+        @Override\r
+        public void removeBranchPoint(IElement connection, IElement branchPoint) {\r
+            ConnectionEntity entity = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY);\r
+            if (entity == null)\r
+                throw new IllegalArgumentException("element '" + connection + "' is not a connection element");\r
+            entity.removeBranchPoint(branchPoint);\r
+        }\r
+\r
+        @Override\r
+        public void removeEdge(IElement connection, IElement edge) {\r
+            ConnectionEntity entity = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY);\r
+            if (entity == null)\r
+                throw new IllegalArgumentException("element '" + connection + "' is not a connection element");\r
+            entity.removeEdge(edge);\r
+        }\r
+    }\r
+\r
+    static final class ConnectionSceneGraph implements SceneGraph {\r
+\r
+        public static final ConnectionSceneGraph INSTANCE = new ConnectionSceneGraph();\r
+\r
+        private static final long serialVersionUID = 4232871859964883266L;\r
+\r
+        @Override\r
+        public void init(IElement connection, G2DParentNode parent) {\r
+            ConnectionEntity ce = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY);\r
+            if (ce == null)\r
+                return;\r
+\r
+            // Painting is single-threaded, it is OK to use a single thread-local collection here.\r
+            List<IElement> children = perThreadElementList.get();\r
+            children.clear();\r
+            ce.getSegments(children);\r
+            ce.getBranchPoints(children);\r
+            //new Exception("painting connection entity " + ce.hashCode() + " with " + children.size() + " segments and branch points").printStackTrace();\r
+            if (children.isEmpty())\r
+                return;\r
+\r
+            Set<SingleElementNode> tmp = new HashSet<SingleElementNode>();\r
+\r
+            int zIndex = 0;\r
+            for (IElement child : children) {\r
+                ElementClass ec = child.getElementClass();\r
+\r
+                Transform transform = child.getElementClass().getSingleItem(Transform.class);\r
+                assert (transform != null);\r
+                AffineTransform at2 = transform.getTransform(child);\r
+                if (at2 == null)\r
+                    continue;\r
+\r
+                SingleElementNode holder = child.getHint(ElementHints.KEY_SG_NODE);\r
+                if (holder == null) {\r
+                    holder = parent.addNode(ElementUtils.generateNodeId(child), SingleElementNode.class);\r
+                    child.setHint(ElementHints.KEY_SG_NODE, holder);\r
+                }\r
+                holder.setZIndex(++zIndex);\r
+\r
+                Composite composite = child.getHint(ElementHints.KEY_COMPOSITE);\r
+\r
+                holder.setTransform(at2);\r
+                holder.setComposite(composite);\r
+                holder.setVisible(true);\r
+\r
+                // New node handler\r
+                for (SceneGraph n : ec.getItemsByClass(SceneGraph.class)) {\r
+                    n.init(child, holder);\r
+                }\r
+                tmp.add(holder);\r
+            }\r
+\r
+            // Hide unaccessed nodes (but don't remove)\r
+            for (IG2DNode node : parent.getNodes()) {\r
+                if (node instanceof SingleElementNode) {\r
+                    if (!tmp.contains(node)) {\r
+                        ((SingleElementNode)node).setVisible(false);\r
+                    }\r
+                } else {\r
+                    //System.out.println("WHAT IS THIS: ");\r
+                    //NodeDebug.printSceneGraph(((Node) node));\r
+                }\r
+            }\r
+\r
+            // Don't leave dangling references behind.\r
+            children.clear();\r
+        }\r
+\r
+        @Override\r
+        public void cleanup(IElement e) {\r
+        }\r
+    }\r
+\r
+    static final class ConnectionBounds implements InternalSize, Outline {\r
+\r
+        public static final ConnectionBounds INSTANCE = new ConnectionBounds();\r
+\r
+        private static final long serialVersionUID = 4232871859964883266L;\r
+\r
+        @Override\r
+        public Rectangle2D getBounds(IElement e, Rectangle2D size) {\r
+            if (size == null)\r
+                size = new Rectangle2D.Double();\r
+            size.setFrame(0, 0, 0, 0);\r
+\r
+            ConnectionEntity ce = e.getHint(ElementHints.KEY_CONNECTION_ENTITY);\r
+            if (ce == null)\r
+                return size;\r
+\r
+            Collection<IElement> parts = ce.getSegments(null);\r
+            if (parts.isEmpty())\r
+                return size;\r
+            parts = ce.getBranchPoints(parts);\r
+\r
+            Rectangle2D temp = null;\r
+            for (IElement part : parts) {\r
+                // Using on-diagram coordinates because neither connections nor\r
+                // edges have a non-identity transform which means that\r
+                // coordinates are always absolute. Therefore branch point\r
+                // bounds also need to be calculated in absolute coordinates.\r
+                ElementUtils.getElementBoundsOnDiagram(part, size);\r
+                //System.out.println("InternalSize BOUNDS: " + size + " for part " + part);\r
+                if (temp == null) {\r
+                    temp = new Rectangle2D.Double();\r
+                    temp.setRect(size);\r
+                } else\r
+                    Rectangle2D.union(temp, size, temp);\r
+                //System.out.println("InternalSize Combined BOUNDS: " + temp);\r
+            }\r
+            size.setRect(temp);\r
+            return size;\r
+        }\r
+\r
+        private Shape getSelectionShape(IElement forPart) {\r
+            for (SelectionOutline so : forPart.getElementClass().getItemsByClass(SelectionOutline.class)) {\r
+                Shape shape = so.getSelectionShape(forPart);\r
+                if (shape != null)\r
+                    return shape;\r
+            }\r
+            // Using on-diagram coordinates because neither connections nor\r
+            // edges have a non-identity transform which means that\r
+            // coordinates are always absolute. Therefore branch point\r
+            // shape also needs to be calculated in absolute coordinates.\r
+            Shape shape = ElementUtils.getElementShapeOrBoundsOnDiagram(forPart);\r
+            return shape;\r
+            //return shape.getBounds2D();\r
+        }\r
+\r
+        @Override\r
+        public Shape getElementShape(IElement e) {\r
+            ConnectionEntity ce = e.getHint(ElementHints.KEY_CONNECTION_ENTITY);\r
+            if (ce == null)\r
+                return new Rectangle2D.Double();\r
+\r
+            Collection<IElement> parts = ce.getSegments(null);\r
+            if (parts.isEmpty())\r
+                return new Rectangle2D.Double();\r
+            parts = ce.getBranchPoints(parts);\r
+\r
+            if (parts.size() == 1) {\r
+                Shape shape = getSelectionShape(parts.iterator().next());\r
+                //System.out.println("Outline SHAPE: " + shape);\r
+                //System.out.println("Outline BOUNDS: " + shape.getBounds2D());\r
+                return shape;\r
+            }\r
+\r
+            //System.out.println("Outline: " + e);\r
+            Area area = new Area();\r
+            for (IElement part : parts) {\r
+                //System.out.println(part);\r
+\r
+                Shape shape = getSelectionShape(part);\r
+\r
+                Rectangle2D bounds = shape.getBounds2D();\r
+//                System.out.println("    shape: " + shape);\r
+//                System.out.println("    bounds: " + bounds);\r
+\r
+                if (bounds.isEmpty()) {\r
+                    double w = bounds.getWidth();\r
+                    double h = bounds.getHeight();\r
+                    if (w <= 0.0 && h <= 0.0)\r
+                        continue;\r
+\r
+                    // Need to expand shape in either width or height to make it visible.\r
+                    final double exp = 0.1;\r
+                    if (w <= 0.0)\r
+                        shape = GeometryUtils.expandRectangle(bounds, 0, 0, exp, exp);\r
+                    else if (h <= 0.0)\r
+                        shape = GeometryUtils.expandRectangle(bounds, exp, exp, 0, 0);\r
+                }\r
+\r
+                //System.out.println("    final shape: " + shape);\r
+                //shape =  bounds;\r
+\r
+                Area a = null;\r
+                if (shape instanceof Area)\r
+                    a = (Area) shape;\r
+                else\r
+                    a = new Area(shape);\r
+                area.add(a);\r
+            }\r
+\r
+            //System.out.println("    connection area outline: " + area);\r
+            //System.out.println("    connection area outline bounds: " + area.getBounds2D());\r
+            return area;\r
+        }\r
+    }\r
+\r
+    public static class ConnectionPick implements Pick2 {\r
+\r
+        public final static ConnectionPick INSTANCE = new ConnectionPick();\r
+\r
+        private static final long serialVersionUID = 1L;\r
+\r
+        @Override\r
+        public boolean pickTest(IElement e, Shape s, PickPolicy policy) {\r
+            ConnectionEntity ce = e.getHint(ElementHints.KEY_CONNECTION_ENTITY);\r
+            if (ce == null)\r
+                return false;\r
+\r
+            // Primarily pick branch points and then edges.\r
+            Collection<IElement> parts = ce.getBranchPoints(null);\r
+            parts = ce.getSegments(parts);\r
+            if (parts.isEmpty())\r
+                return false;\r
+\r
+            for (IElement part : parts) {\r
+                for (Pick pick : part.getElementClass().getItemsByClass(Pick.class)) {\r
+                    //System.out.println("TESTING: " + part + " : " + s + " : " + policy);\r
+                    if (pick.pickTest(part, s, policy)) {\r
+                        //System.out.println("  HIT!");\r
+                        return true;\r
+                    }\r
+                }\r
+            }\r
+\r
+            return false;\r
+        }\r
+\r
+        @Override\r
+        public int pick(IElement e, Shape s, PickPolicy policy, Collection<IElement> result) {\r
+            int oldResultSize = result.size();\r
+\r
+            ConnectionEntity ce = e.getHint(ElementHints.KEY_CONNECTION_ENTITY);\r
+            if (ce == null)\r
+                return 0;\r
+\r
+            // Primarily pick branch points and then edges.\r
+            List<IElement> parts = perThreadElementList.get();\r
+            parts.clear();\r
+\r
+            ce.getSegments(parts);\r
+            int edges = parts.size();\r
+            ce.getBranchPoints(parts);\r
+            int branchPoints = parts.size() - edges;\r
+\r
+            boolean singleEdge = branchPoints == 0 && edges == 1;\r
+\r
+            if (parts.isEmpty())\r
+                return 0;\r
+\r
+            // See whether the whole connection is to be picked..\r
+            boolean pickConnection = false;\r
+            wholeConnectionPick:\r
+                for (Outline outline : e.getElementClass().getItemsByClass(Outline.class)) {\r
+                    Shape elementShape = outline.getElementShape(e);\r
+                    if (elementShape == null)\r
+                        continue;\r
+\r
+                    switch (policy) {\r
+                        case PICK_CONTAINED_OBJECTS:\r
+                            if (GeometryUtils.contains(s, elementShape)) {\r
+                                pickConnection = true;\r
+                                break wholeConnectionPick;\r
+                            }\r
+                            break;\r
+                        case PICK_INTERSECTING_OBJECTS:\r
+                            if (GeometryUtils.intersects(s, elementShape)) {\r
+                                pickConnection = true;\r
+                                break wholeConnectionPick;\r
+                            }\r
+                            break;\r
+                    }\r
+                }\r
+\r
+            ArrayList<IElement> picks = null;\r
+\r
+            // Pick connection segments\r
+            for (int i = 0; i < edges; ++i) {\r
+                IElement part = parts.get(i);\r
+                for (Pick pick : part.getElementClass().getItemsByClass(Pick.class)) {\r
+                    //System.out.println("TESTING SEGMENT: " + part + " : " + s + " : " + policy);\r
+                    if (pick.pickTest(part, s, policy)) {\r
+                        //System.out.println("  HIT!");\r
+                        if (picks == null)\r
+                            picks = new ArrayList<IElement>(4);\r
+                        picks.add(part);\r
+                        break;\r
+                    }\r
+                }\r
+            }\r
+\r
+            // Pick the whole connection ?\r
+            if (pickConnection) {\r
+                if (picks == null)\r
+                    picks = new ArrayList<IElement>(4);\r
+                picks.add(e);\r
+            }\r
+\r
+            // Pick branch/route points\r
+            for (int i = edges; i < parts.size(); ++i) {\r
+                IElement part = parts.get(i);\r
+                for (Pick pick : part.getElementClass().getItemsByClass(Pick.class)) {\r
+                    //System.out.println("TESTING BRANCHPOINT: " + part + " : " + s + " : " + policy);\r
+                    if (pick.pickTest(part, s, policy)) {\r
+                        //System.out.println("  HIT!");\r
+                        if (picks == null)\r
+                            picks = new ArrayList<IElement>(4);\r
+                        picks.add(part);\r
+                        break;\r
+                    }\r
+                }\r
+            }\r
+\r
+            if (picks != null) {\r
+                // Add the discovered pickable children to the result after the\r
+                // parent to make the parent the primary pickable.\r
+                // Skip the children if there is only one child.\r
+                if (!singleEdge) {\r
+                    result.addAll(picks);\r
+                } else {\r
+                    result.add(e);\r
+                }\r
+            }\r
+\r
+            return result.size() - oldResultSize;\r
+        }\r
+    }\r
+\r
+    private static final Key CHILD_LISTENERS = new KeyOf(ListenerList.class, "CHILD_LISTENERS");\r
+\r
+    public static class ConnectionChildren implements Children, ConnectionListener {\r
+\r
+        public final static ConnectionChildren INSTANCE = new ConnectionChildren();\r
+\r
+        private static final long serialVersionUID = 1L;\r
+\r
+        @Override\r
+        public Collection<IElement> getChildren(IElement element, Collection<IElement> result) {\r
+            ConnectionEntity ce = element.getHint(ElementHints.KEY_CONNECTION_ENTITY);\r
+            if (ce == null) {\r
+                if (result == null)\r
+                    result = new ArrayList<IElement>(0);\r
+                return result;\r
+            }\r
+            result = ce.getSegments(result);\r
+            result = ce.getBranchPoints(result);\r
+            return result;\r
+        }\r
+\r
+        @Override\r
+        public void addChildListener(IElement element, ChildListener listener) {\r
+            ListenerList<ChildListener> ll = null;\r
+            synchronized (element) {\r
+                ll = element.getHint(CHILD_LISTENERS);\r
+                if (ll == null) {\r
+                    ll = new ListenerList<ChildListener>(ChildListener.class);\r
+                    element.setHint(CHILD_LISTENERS, ll);\r
+                    ConnectionEntity entity = element.getHint(ElementHints.KEY_CONNECTION_ENTITY);\r
+                    entity.setListener(this);\r
+                }\r
+            }\r
+            ll.add(listener);\r
+        }\r
+\r
+        @Override\r
+        public void removeChildListener(IElement element, ChildListener listener) {\r
+            synchronized (element) {\r
+                ListenerList<ChildListener> ll = element.getHint(CHILD_LISTENERS);\r
+                if (ll == null)\r
+                    return;\r
+                ll.remove(listener);\r
+                if (ll.isEmpty()) {\r
+                    ConnectionEntity entity = element.getHint(ElementHints.KEY_CONNECTION_ENTITY);\r
+                    entity.setListener(null);\r
+                }\r
+            }\r
+        }\r
+\r
+        @Override\r
+        public void connectionChanged(ConnectionEvent event) {\r
+            fireChildrenChanged(event);\r
+        }\r
+\r
+        private void fireChildrenChanged(ConnectionEvent event) {\r
+            ListenerList<ChildListener> ll = event.connection.getHint(CHILD_LISTENERS);\r
+            if (ll == null)\r
+                return;\r
+            ChildEvent ce = new ChildEvent(event.connection, event.removedParts, event.addedParts);\r
+            for (ChildListener cl : ll.getListeners()) {\r
+                cl.elementChildrenChanged(ce);\r
+            }\r
+        }\r
+\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynConnectionEdgeFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynConnectionEdgeFactory.java
new file mode 100644 (file)
index 0000000..180a234
--- /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 connection edge segments.\r
+ * \r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class SysdynConnectionEdgeFactory extends ElementFactoryAdapter {\r
+\r
+    private static final ElementClass CLASS = SysdynEdgeClass.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/SysdynConnectionFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynConnectionFactory.java
new file mode 100644 (file)
index 0000000..3023e54
--- /dev/null
@@ -0,0 +1,57 @@
+/*******************************************************************************\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.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
+\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 SysdynConnectionFactory 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
+        procedure.execute(graph, element);\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynEdgeClass.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynEdgeClass.java
new file mode 100644 (file)
index 0000000..95ace23
--- /dev/null
@@ -0,0 +1,196 @@
+/*******************************************************************************\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.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
+\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(EdgeNode.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
+            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
+            EdgeNode 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 = 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
+            EdgeNode.ArrowType pat1 = convert(at1);\r
+            EdgeNode.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
+            switch (at) {\r
+                case None: return EdgeNode.ArrowType.None;\r
+                case Stroke: return EdgeNode.ArrowType.Stroke;\r
+                case Fill: return EdgeNode.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
index b745a584d50049ffe84e2d8fb6edca4be3eb7600..c58bc2309d89e00addcadea1d4546c082ab549b5 100644 (file)
@@ -27,6 +27,7 @@ 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
@@ -93,6 +94,7 @@ 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
@@ -169,6 +171,7 @@ 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
index 16f5064066d6c68a57ae5623bf447efeb209b4df..afbd29a88ea589762cb3d8a9df2658bc4e370988 100644 (file)
@@ -390,3 +390,5 @@ CloudSymbol <T DIA.FontProvider <T DIA.ColorProvider
 ######################################################################\r
 # Diagram connection types\r
 ######################################################################\r
+\r
+Connection <T DIA.Connection\r