]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/DefinedElementTerminals.java
Dynamic positioning of terminals in G2D
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / adapter / DefinedElementTerminals.java
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