]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/handler/impl/TopologyImpl.java
Made spatial picking optimization optional for now
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / diagram / handler / impl / TopologyImpl.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 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  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.g2d.diagram.handler.impl;
13
14 import java.util.Collection;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18
19 import org.simantics.g2d.connection.EndKeyOf;
20 import org.simantics.g2d.connection.TerminalKeyOf;
21 import org.simantics.g2d.diagram.IDiagram;
22 import org.simantics.g2d.diagram.handler.ElementListener;
23 import org.simantics.g2d.diagram.handler.SubstituteElement;
24 import org.simantics.g2d.diagram.handler.Topology;
25 import org.simantics.g2d.element.ElementHints;
26 import org.simantics.g2d.element.ElementUtils;
27 import org.simantics.g2d.element.IElement;
28 import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd;
29 import org.simantics.utils.datastructures.hints.IHintContext.Key;
30
31 /**
32  * 
33  * @author Toni Kalajainen
34  */
35 public class TopologyImpl implements Topology, ElementListener {
36
37     @Override
38     public Connection getConnection(IElement edge, EdgeEnd end)
39     {
40         Key key = EndKeyOf.get(end);
41         Connection c = edge.getHint(key);
42         if (c == null)
43             return null;
44         IDiagram d = ElementUtils.getDiagram(edge);
45         c = _updateReferences(d, c);
46         return c;
47     }
48
49     @Override
50     public void getConnections(IElement node, Terminal terminal, Collection<Connection> connections)
51     {
52         // FIXME: only allows single connection / terminal
53         Key key = new TerminalKeyOf(terminal, null, Connection.class);
54         Connection c = node.getHint(key);
55         if (c != null) {
56             connections.add(c);
57         }
58         IDiagram d = ElementUtils.getDiagram(node);
59         _updateReferences(d, c);
60     }
61
62     private Connection _updateReferences(IDiagram d, Connection c)
63     {
64         List<SubstituteElement> list = d.getDiagramClass().getItemsByClass(SubstituteElement.class);
65         if (list.size()==0) return c;
66
67         IElement e = c.edge;
68         IElement n = c.node;
69
70         for (SubstituteElement se : list)
71         {
72             IElement ne = se.substitute(d, e);
73             IElement nn = se.substitute(d, n);
74             if (ne != null)
75                 e = ne;
76             if (nn != null)
77                 n = nn;
78         }
79
80         return new Connection(e, c.end, n, c.terminal);
81     }
82
83     @Override
84     public void connect(IElement edge, EdgeEnd end, IElement node, Terminal terminal) {
85         if (edge == null)
86             throw new NullPointerException("null edge");
87         if (end == null)
88             throw new NullPointerException("null end");
89         if (node == null)
90             throw new NullPointerException("null node");
91         if (terminal == null)
92             throw new NullPointerException("null terminal");
93
94         IDiagram d = ElementUtils.getDiagram(edge);
95         assert( d == ElementUtils.getDiagram(node) );
96
97         Connection c = new Connection(edge, end, node, terminal);
98
99         // It is not the job of this code to check or resolve modelling issues
100         // caused by this connection.
101
102         // This makes it possible to have more than one connection to the same
103         // terminal.
104         Object edgeData = edge.getHint(ElementHints.KEY_OBJECT);
105
106         TerminalKeyOf key = new TerminalKeyOf(terminal, edgeData, Connection.class);
107         node.setHint(key, c);
108         EndKeyOf key2 = EndKeyOf.get(end);
109         edge.setHint(key2, c);
110     }
111
112     @Override
113     public void disconnect(IElement edge, EdgeEnd end, IElement node, Terminal terminal) {
114         if (edge == null)
115             throw new NullPointerException("null edge");
116         if (end == null)
117             throw new NullPointerException("null end");
118         if (node == null)
119             throw new NullPointerException("null node");
120         if (terminal == null)
121             throw new NullPointerException("null terminal");
122
123         IDiagram d = ElementUtils.getDiagram(edge);
124         assert( d == ElementUtils.getDiagram(node) );
125
126         EndKeyOf edgeKey = EndKeyOf.get(end);
127         Connection c = edge.getHint(edgeKey);
128         if (c == null)
129             throw new UnsupportedOperationException("cannot disconnect, no Connection in edge " + edge);
130
131         for (Map.Entry<TerminalKeyOf, Object> entry : node.getHintsOfClass(TerminalKeyOf.class).entrySet()) {
132             Connection cc = (Connection) entry.getValue();
133             if (c == cc) {
134                 node.removeHint(entry.getKey());
135                 edge.removeHint(edgeKey);
136                 return;
137             }
138         }
139
140         throw new UnsupportedOperationException("cannot disconnect, no connection between found between edge "
141                 + edge + " and node " + node);
142     }
143
144     @Override
145     public void onElementAdded(IDiagram d, IElement e) {
146     }
147
148     @Override
149     public void onElementRemoved(IDiagram d, IElement e) {
150         Set<TerminalKeyOf> keys1 = e.getHintsOfClass(TerminalKeyOf.class).keySet();
151         for (TerminalKeyOf key : keys1)
152             e.removeHint(key);
153         for (EndKeyOf key : EndKeyOf.KEYS)
154             e.removeHint(key);
155     }
156
157 }