]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Dynamic positioning of terminals in G2D 91/391/2
authorAntti Villberg <antti.villberg@semantum.fi>
Mon, 3 Apr 2017 07:21:16 +0000 (10:21 +0300)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Mon, 3 Apr 2017 22:14:13 +0000 (01:14 +0300)
refs #7119

Change-Id: Ib0585c71c94ddca77ce41311cdce4916d033afba

bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/DefinedElementFactory.java
bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/DefinedElementTerminals.java [new file with mode: 0644]
bundles/org.simantics.g2d/src/org/simantics/g2d/element/handler/impl/Terminals.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/NodeUtil.java

index 6d5b30237870d2ad9c556197c6c8b88e5d45103b..e7bb472e4ed610450bdbb19a62df5be9f30d67de 100644 (file)
@@ -231,7 +231,7 @@ public class DefinedElementFactory extends ElementFactoryAdapter {
                                             StaticSymbolImageInitializer.INSTANCE,
                                             new StaticSymbolImpl(img),
                                             DefinedElementHandler.INSTANCE,
-                                            new Terminals(terminals),
+                                            new DefinedElementTerminals(terminals),
                                             SimpleElementLayers.INSTANCE,
                                             PlainElementPropertySetter.INSTANCE
                                             ).setId(id));
diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/DefinedElementTerminals.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/DefinedElementTerminals.java
new file mode 100644 (file)
index 0000000..6f83954
--- /dev/null
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Semantum Oy - #7119 initial API and implementation
+ *******************************************************************************/
+package org.simantics.diagram.adapter;
+
+import java.awt.geom.AffineTransform;
+import java.util.Collection;
+
+import org.simantics.diagram.content.ResourceTerminal;
+import org.simantics.g2d.diagram.handler.Topology.Terminal;
+import org.simantics.g2d.element.IElement;
+import org.simantics.g2d.element.handler.TerminalLayout;
+import org.simantics.g2d.element.handler.TerminalTopology;
+import org.simantics.g2d.element.handler.impl.ObjectTerminal;
+import org.simantics.g2d.element.handler.impl.Terminals;
+import org.simantics.scenegraph.INode;
+import org.simantics.scenegraph.g2d.IG2DNode;
+import org.simantics.scenegraph.g2d.nodes.SingleElementNode;
+import org.simantics.scenegraph.utils.NodeUtil;
+
+/**
+ * A {@link TerminalTopology} and more specifically a {@link TerminalLayout}
+ * implementation that relies primarily on the scene graph and only secondarily
+ * on its internal datastructures to resolve terminal locations. This implementation
+ * is used to support dynamic terminals.
+ * 
+ * @author Antti Villberg
+ * @since 1.29.0
+ */
+public class DefinedElementTerminals extends Terminals {
+
+    private static final long serialVersionUID = -726490868093887444L;
+
+    public DefinedElementTerminals(Collection<ObjectTerminal> ts) {
+        super(ts);
+    }
+
+    private IG2DNode findResourceTerminalNode(IG2DNode node, ResourceTerminal rt) {
+        return (IG2DNode) NodeUtil.forChildrenDeep(node, SingleElementNode.class, n -> {
+            Object key = n.getKey();
+            if (rt.getResource().equals(key)) {
+                IG2DNode[] children = n.getSortedNodes();
+                if (children.length > 0)
+                    return children[0];
+                return n;
+            }
+            return null;
+        });
+    }
+
+    @Override
+    public AffineTransform getTerminalPosition(IElement e, Terminal t) {
+        if (t instanceof ResourceTerminal) {
+            ResourceTerminal rt = (ResourceTerminal) t;
+            IG2DNode node = e.getHint(DefinedElementHandler.KEY_SG_NODE);
+            if (node != null) {
+                IG2DNode n = findResourceTerminalNode(node, rt);
+                if (n != null) {
+                    return n.getTransform();
+                }
+            }
+        }
+
+        ObjectTerminal ti = terminalMap.get(t);
+        if (ti == null)
+            return null;
+        return new AffineTransform(ti.getTransform());
+    }
+
+}
\ No newline at end of file
index ca8518e6c38a5863267edb63b4f5336a01fdfe1b..f38e0a6c5910d08555783168e777b2f574bc224b 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * Copyright (c) 2007, 2017 Association for Decentralized Information Management
  * in Industry THTH ry.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,7 @@
  *
  * Contributors:
  *     VTT Technical Research Centre of Finland - initial API and implementation
+ *     Semantum Oy - #7119 refactoring
  *******************************************************************************/
 package org.simantics.g2d.element.handler.impl;
 
@@ -30,10 +31,10 @@ import org.simantics.g2d.utils.geom.DirectionSet;
  */
 public class Terminals implements TerminalLayout, TerminalTopology {
 
-    private static final long             serialVersionUID = -6532093690907028016L;
+    private static final long serialVersionUID = -6532093690907028016L;
 
-    private final Map<Terminal, ObjectTerminal> terminalMap      = new THashMap<Terminal, ObjectTerminal>();
-    private final ArrayList<Terminal>           terminals        = new ArrayList<Terminal>();
+    protected final Map<Terminal, ObjectTerminal> terminalMap = new THashMap<>();
+    protected final ArrayList<Terminal>           terminals   = new ArrayList<>();
 
     public Terminals(Collection<ObjectTerminal> ts) {
         for (ObjectTerminal ti : ts) {
index c3bb2144108256319a21368469d2385216db658e..615899a59eef25676ff17b0cbdcb69ca0d62d1b8 100644 (file)
@@ -32,6 +32,7 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Function;
 
 import org.simantics.scenegraph.IDynamicSelectionPainterNode;
 import org.simantics.scenegraph.ILookupService;
@@ -276,6 +277,7 @@ public final class NodeUtil {
         printSceneGraph(System.out, 0, node);
     }
 
+    @FunctionalInterface
     public static interface NodeProcedure<T> {
         T execute(INode node, String id);
     }
@@ -324,6 +326,47 @@ public final class NodeUtil {
         return result;
     }
 
+    /**
+     * Recursively iterates through all child nodes of the specified node and
+     * for those nodes that are of class <code>ofClass</code>, invokes
+     * <code>consumer</code>.
+     * 
+     * @param node
+     * @param ofClass
+     * @param consumer
+     */
+    @SuppressWarnings("unchecked")
+    public static <T extends INode> INode forChildrenDeep(INode node, Class<T> ofClass, Function<T, INode> func) {
+        return forChildrenDeep(node, n -> ofClass.isInstance(n) ? func.apply((T) n) : null);
+    }
+
+    public static <T extends INode> INode forChildrenDeep(INode node, Function<INode, INode> func) {
+        INode ret = func.apply(node);
+        if (ret != null)
+            return ret;
+
+        if (node instanceof ParentNode<?>) {
+            if (node instanceof G2DParentNode) {
+                G2DParentNode g2dpn = (G2DParentNode) node;
+                for (IG2DNode n : g2dpn.getSortedNodes()) {
+                    INode r = forChildrenDeep(n, func);
+                    if (r != null) {
+                        return r;
+                    }
+                }
+            } else {
+                for (INode n : ((ParentNode<?>) node).getNodes()) {
+                    INode r = forChildrenDeep(n, func);
+                    if (r != null) {
+                        return r;
+                    }
+                }
+            }
+        }
+
+        return null;
+    }
+
     public static final int countTreeNodes(INode node) {
         int result = 1;
         if (node instanceof ParentNode<?>) {