]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteLine.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.diagram.connection / src / org / simantics / diagram / connection / RouteLine.java
1 /*******************************************************************************
2  * Copyright (c) 2011 Association for Decentralized Information Management in
3  * 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.diagram.connection;
13
14 import gnu.trove.map.hash.THashMap;
15
16 import java.io.PrintStream;
17 import java.io.Serializable;
18 import java.util.ArrayList;
19 import java.util.Collection;
20 import java.util.Collections;
21 import java.util.List;
22
23 import org.simantics.diagram.connection.segments.Segment;
24
25 public class RouteLine implements RouteNode, Serializable {
26     private static final long serialVersionUID = -7256429294500809465L;
27
28     Object data;
29     boolean isHorizontal;
30     double  position;
31     boolean hidden;
32     
33     ArrayList<RoutePoint> points = new ArrayList<RoutePoint>(4);
34     RouteLine nextTransient;
35     RouteTerminal terminal;
36     
37     public RouteLine(boolean isHorizontal, double position) {
38         this.isHorizontal = isHorizontal;
39         this.position = position;
40     }
41     
42     @Override
43     public void setData(Object data) {
44         this.data = data;
45     }
46     
47     @Override
48     public Object getData() {
49         return data;
50     }
51
52     public boolean isHorizontal() {
53         return isHorizontal;
54     }
55     
56     public boolean isHidden() {
57                 return hidden;
58         }
59     
60     public void setHidden(boolean hidden) {
61                 this.hidden = hidden;
62         }
63     
64     public double getPosition() {
65         return position;
66     }
67     
68     public List<RoutePoint> getPoints() {
69         if(RouteGraph.RETURN_UNMODIFIABLE_COLLECTIONS)
70                 return Collections.unmodifiableList(points);
71         else
72                 return points;
73     }
74     
75     public void addPoint(RoutePoint link) {
76         points.add(link);        
77     }
78
79     void remove() {
80         for(RoutePoint point : points)
81             point.removeFromOther(this);
82     }
83     
84     public void setPointPositions() {        
85         if(isHorizontal) {
86             for(RoutePoint point : points)
87                 point.y = position;
88         }
89         else {
90             for(RoutePoint point : points)
91                 point.x = position;
92         }
93     }
94
95     public void sortPoints() {
96         Collections.sort(points, isHorizontal 
97                 ? RoutePoint.X_COMPARATOR 
98                 : RoutePoint.Y_COMPARATOR);
99     }
100     
101     public boolean isNear(double x2, double y2, double tolerance) {
102         return isHorizontal 
103                 ? Math.abs(y2-position) <= tolerance 
104                     && points.get(0).x - tolerance <= x2
105                     && x2 <= points.get(points.size()-1).x + tolerance
106                 : Math.abs(x2-position) <= tolerance 
107                     && points.get(0).y - tolerance <= y2
108                     && y2 <= points.get(points.size()-1).y + tolerance;
109     }
110
111     public void print(PrintStream out) {
112         if(isHorizontal)
113             out.print("    HOR");
114         else
115             out.print("    VER");
116         if (hidden)
117             out.print(" HIDDEN");
118         out.print(" @ " + position);
119         for(RoutePoint point : points) {
120             out.print(" ("+point.x+","+point.y+")");
121         }
122         out.print(" (data=" + data + ")");
123         if (nextTransient != null)
124             out.print(" (next transient line=" + nextTransient.getData() + ")");
125         if (terminal != null)
126             out.print(" (terminal=" + terminal.getData() + ")");
127         out.println();
128     }
129
130     void setLocation(double x, double y) {
131         if(isHorizontal)
132             position = y;
133         else
134             position = x;
135     }
136
137     public double getLength() {
138         if(isHorizontal)
139             return points.get(points.size()-1).x - points.get(0).x;
140         else
141             return points.get(points.size()-1).y - points.get(0).y;
142     }
143
144     boolean isConnectedToPeristentLine() {
145         for(RoutePoint point : points)
146             if(point instanceof RouteLink) {
147                 RouteLink link = (RouteLink)point;
148                 if(link.a == this) {
149                     if(!link.b.isTransient())
150                         return true;
151                 }
152                 else {
153                     if(!link.a.isTransient())
154                         return true;
155                 }
156             }
157         return false;
158     }
159     
160     public RoutePoint getBegin() {
161         return points.get(0);
162     }
163     
164     public RoutePoint getEnd() {
165         return points.get(points.size()-1);
166     }
167
168     public boolean isTransient() {
169         return terminal != null;
170     }
171
172     public RouteLine copy(THashMap<Object, Object> map) {       
173         RouteLine copy = (RouteLine)map.get(this);
174         if(copy == null) {
175                 copy = new RouteLine(isHorizontal, position);
176                 map.put(this, copy);
177                 copy.data = data;
178                 copy.nextTransient = nextTransient == null ? null : nextTransient.copy(map);
179                 copy.terminal = terminal == null ? null : terminal.copy(map);
180                 for(RoutePoint point : points)
181                         copy.points.add(point.copy(map));
182         }
183         return copy;
184     }
185     
186     public Collection<RouteLine> getPersistentNeighbors() {
187         ArrayList<RouteLine> lines = new ArrayList<RouteLine>();
188         for(RoutePoint point : points)
189                 if(point instanceof RouteLink) {
190                         RouteLink link = (RouteLink)point;
191                         RouteLine line = link.getOther(this);
192                         if(!line.isTransient())
193                                 lines.add(line);
194                 }
195         return lines;
196     }
197
198     public void removeRouteTerminals() {
199         points.removeIf(p -> p instanceof RouteTerminal);
200     }
201
202     public RouteTerminal getTerminal() {
203         return terminal;
204     }
205     
206     public void setTerminal(RouteTerminal terminal) {
207                 this.terminal = terminal;
208         }
209
210     public RouteLine getNextTransient() {
211         return nextTransient;
212     }
213
214     public boolean beginsWithTerminal() {
215         RoutePoint begin = points.get(0);
216         if(begin == terminal)
217             return true;
218         else if(begin instanceof RouteLink) {
219             RouteLink link = (RouteLink)begin;
220             if(link.a == this)
221                 return link.b.hasTerminal(link, terminal);
222             else
223                 return link.a.hasTerminal(link, terminal);
224         }
225         else
226             return false;
227     }
228
229     private boolean hasTerminal(RouteLink oldLink, RouteTerminal terminal) {
230         RoutePoint begin = points.get(0);
231         RoutePoint end = points.get(1);
232         if(begin == terminal || end == terminal)
233             return true;
234         if(begin instanceof RouteLink && begin != oldLink) {
235             RouteLink link = (RouteLink)begin;
236             if(link.a == this)
237                 return link.b.hasTerminal(link, terminal);
238             else
239                 return link.a.hasTerminal(link, terminal);
240         }
241         else if(end instanceof RouteLink && end != oldLink) {
242             RouteLink link = (RouteLink)end;
243             if(link.a == this)
244                 return link.b.hasTerminal(link, terminal);
245             else
246                 return link.a.hasTerminal(link, terminal);
247         }
248         else
249             return false;
250     }
251
252     public boolean isDegenerated() {
253         if(points.size() <= 1)
254             return true;
255         if(isHorizontal)
256             return points.get(0).x == points.get(points.size()-1).x;
257         else
258             return points.get(0).y == points.get(points.size()-1).y;
259     }
260
261     public void collectSegments(ArrayList<Segment> segments) {
262         RoutePoint p0 = points.get(0);
263         for(int i=1;i<points.size();++i) {
264             RoutePoint p1 = points.get(i);
265             segments.add(new Segment(p0, p1));            
266             p0 = p1;
267         }
268     }
269 }