d67f9f547f9c5a27a2ad552849f5842e0746bdd8
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / adapter / DefinedElementTerminals.java
1 /*******************************************************************************
2  * Copyright (c) 2017 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     Semantum Oy - #7119 initial API and implementation
11  *******************************************************************************/
12 package org.simantics.diagram.adapter;
13
14 import java.awt.geom.AffineTransform;
15 import java.util.Collection;
16
17 import org.simantics.diagram.content.ResourceTerminal;
18 import org.simantics.g2d.diagram.handler.Topology.Terminal;
19 import org.simantics.g2d.element.IElement;
20 import org.simantics.g2d.element.handler.TerminalLayout;
21 import org.simantics.g2d.element.handler.TerminalTopology;
22 import org.simantics.g2d.element.handler.impl.ObjectTerminal;
23 import org.simantics.g2d.element.handler.impl.Terminals;
24 import org.simantics.scenegraph.g2d.IG2DNode;
25 import org.simantics.scenegraph.g2d.nodes.SingleElementNode;
26 import org.simantics.scenegraph.utils.NodeUtil;
27
28 /**
29  * A {@link TerminalTopology} and more specifically a {@link TerminalLayout}
30  * implementation that relies primarily on the scene graph and only secondarily
31  * on its internal datastructures to resolve terminal locations. This implementation
32  * is used to support dynamic terminals.
33  * 
34  * @author Antti Villberg
35  * @since 1.29.0
36  */
37 public class DefinedElementTerminals extends Terminals {
38
39     private static final long serialVersionUID = -726490868093887444L;
40
41     public DefinedElementTerminals(Collection<ObjectTerminal> ts) {
42         super(ts);
43     }
44
45     private IG2DNode findResourceTerminalNode(IG2DNode node, ResourceTerminal rt) {
46         return (IG2DNode) NodeUtil.forChildrenDeep(node, SingleElementNode.class, n -> {
47             Object key = n.getKey();
48             if (rt.getResource().equals(key)) {
49                 IG2DNode[] children = n.getSortedNodes();
50                 if (children.length > 0)
51                     return children[0];
52                 return n;
53             }
54             return null;
55         });
56     }
57
58     @Override
59     public AffineTransform getTerminalPosition(IElement e, Terminal t) {
60         if (t instanceof ResourceTerminal) {
61             ResourceTerminal rt = (ResourceTerminal) t;
62             IG2DNode node = e.getHint(DefinedElementHandler.KEY_SG_NODE);
63             if (node != null) {
64                 IG2DNode n = findResourceTerminalNode(node, rt);
65                 if (n != null) {
66                     return n.getTransform();
67                 }
68             }
69         }
70
71         ObjectTerminal ti = terminalMap.get(t);
72         if (ti == null)
73             return null;
74         return ti.getTransform();
75     }
76
77 }