StaticSymbolImageInitializer.INSTANCE,
new StaticSymbolImpl(img),
DefinedElementHandler.INSTANCE,
- new Terminals(terminals),
+ new DefinedElementTerminals(terminals),
SimpleElementLayers.INSTANCE,
PlainElementPropertySetter.INSTANCE
).setId(id));
--- /dev/null
+/*******************************************************************************
+ * 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
/*******************************************************************************
- * 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
*
* Contributors:
* VTT Technical Research Centre of Finland - initial API and implementation
+ * Semantum Oy - #7119 refactoring
*******************************************************************************/
package org.simantics.g2d.element.handler.impl;
*/
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) {
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;
printSceneGraph(System.out, 0, node);
}
+ @FunctionalInterface
public static interface NodeProcedure<T> {
T execute(INode node, String id);
}
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<?>) {