Mercurial > projects > dwt-addons
comparison dwtx/draw2d/AutomaticRouter.d @ 98:95307ad235d9
Added Draw2d code, still work in progress
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sun, 03 Aug 2008 00:52:14 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
96:b492ba44e44d | 98:95307ad235d9 |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2000, 2005 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
12 *******************************************************************************/ | |
13 module dwtx.draw2d.AutomaticRouter; | |
14 | |
15 import dwt.dwthelper.utils; | |
16 import dwtx.dwtxhelper.Collection; | |
17 | |
18 import dwtx.draw2d.geometry.Point; | |
19 import dwtx.draw2d.geometry.PointList; | |
20 import dwtx.draw2d.internal.MultiValueMap; | |
21 import dwtx.draw2d.AbstractRouter; | |
22 import dwtx.draw2d.ConnectionRouter; | |
23 import dwtx.draw2d.ConnectionAnchor; | |
24 import dwtx.draw2d.Connection; | |
25 | |
26 /** | |
27 * An abstract router implementation which detects when multiple connections are | |
28 * overlapping. Two connections overlap if the combination of source and target | |
29 * anchors are equal. Subclasses must implement {@link #handleCollision(PointList, int)} | |
30 * to determine how to avoid the overlap. | |
31 * <p> | |
32 * This router can delegate to another connection router. The wrappered router will route | |
33 * the connections first, after which overlapping will be determined. | |
34 */ | |
35 public abstract class AutomaticRouter | |
36 : AbstractRouter | |
37 { | |
38 | |
39 private ConnectionRouter nextRouter; | |
40 private MultiValueMap connections; | |
41 | |
42 public this(){ | |
43 connections = new MultiValueMap(); | |
44 } | |
45 | |
46 private class HashKey { | |
47 | |
48 private ConnectionAnchor anchor1, anchor2; | |
49 | |
50 this(Connection conn) { | |
51 anchor1 = conn.getSourceAnchor(); | |
52 anchor2 = conn.getTargetAnchor(); | |
53 } | |
54 | |
55 public override int opEquals(Object object) { | |
56 bool isEqual = false; | |
57 HashKey hashKey; | |
58 | |
59 if (auto hashKey = cast(HashKey)object ) { | |
60 ConnectionAnchor hkA1 = hashKey.getFirstAnchor(); | |
61 ConnectionAnchor hkA2 = hashKey.getSecondAnchor(); | |
62 | |
63 isEqual = ((cast(Object)hkA1).opEquals(cast(Object)anchor1) && (cast(Object)hkA2).opEquals(cast(Object)anchor2)) | |
64 || ((cast(Object)hkA1).opEquals(cast(Object)anchor2) && (cast(Object)hkA2).opEquals(cast(Object)anchor1)); | |
65 } | |
66 return isEqual; | |
67 } | |
68 | |
69 public ConnectionAnchor getFirstAnchor() { | |
70 return anchor1; | |
71 } | |
72 | |
73 public ConnectionAnchor getSecondAnchor() { | |
74 return anchor2; | |
75 } | |
76 | |
77 public override hash_t toHash() { | |
78 return (cast(Object)anchor1).toHash() ^ (cast(Object)anchor2).toHash(); | |
79 } | |
80 } | |
81 | |
82 /** | |
83 * @see dwtx.draw2d.ConnectionRouter#getConstraint(Connection) | |
84 */ | |
85 public Object getConstraint(Connection connection) { | |
86 if (next() !is null) | |
87 return next().getConstraint(connection); | |
88 return null; | |
89 } | |
90 | |
91 /** | |
92 * Handles collisions between 2 or more Connections. Collisions are currently defined as 2 | |
93 * connections with no bendpoints and whose start and end points coincide. In other | |
94 * words, the 2 connections are the exact same line. | |
95 * | |
96 * @param list The PointList of a connection that collides with another connection | |
97 * @param index The index of the current connection in the list of colliding connections | |
98 */ | |
99 protected abstract void handleCollision(PointList list, int index); | |
100 | |
101 /** | |
102 * @see dwtx.draw2d.ConnectionRouter#invalidate(Connection) | |
103 */ | |
104 public void invalidate(Connection conn) { | |
105 if (next() !is null) | |
106 next().invalidate(conn); | |
107 if (conn.getSourceAnchor() is null || conn.getTargetAnchor() is null) | |
108 return; | |
109 HashKey connectionKey = new HashKey(conn); | |
110 ArrayList connectionList = connections.get(connectionKey); | |
111 int affected = connections.remove(connectionKey, cast(Object)conn); | |
112 if (affected !is -1) { | |
113 for (int i = affected; i < connectionList.size(); i++) | |
114 (cast(Connection)connectionList.get(i)).revalidate(); | |
115 } else | |
116 connections.removeValue(cast(Object)conn); | |
117 | |
118 } | |
119 | |
120 /** | |
121 * Returns the next router in the chain. | |
122 * @return The next router | |
123 * @since 2.0 | |
124 */ | |
125 protected ConnectionRouter next() { | |
126 return nextRouter; | |
127 } | |
128 | |
129 | |
130 | |
131 /** | |
132 * @see dwtx.draw2d.ConnectionRouter#remove(Connection) | |
133 */ | |
134 public void remove(Connection conn) { | |
135 if (conn.getSourceAnchor() is null || conn.getTargetAnchor() is null) | |
136 return; | |
137 HashKey connectionKey = new HashKey(conn); | |
138 ArrayList connectionList = connections.get(connectionKey); | |
139 if (connectionList !is null) { | |
140 int index = connections.remove(connectionKey,cast(Object) conn); | |
141 for (int i = index + 1; i < connectionList.size(); i++) | |
142 (cast(Connection)connectionList.get(i)).revalidate(); | |
143 } | |
144 if (next() !is null) | |
145 next().remove(conn); | |
146 } | |
147 | |
148 /** | |
149 * Routes the given connection. Calls the 'next' router first (if one exists) and if no | |
150 * bendpoints were added by the next router, collisions are dealt with by calling | |
151 * {@link #handleCollision(PointList, int)}. | |
152 * @param conn The connection to route | |
153 */ | |
154 public void route(Connection conn) { | |
155 if (next() !is null) | |
156 next().route(conn); | |
157 else { | |
158 conn.getPoints().removeAllPoints(); | |
159 setEndPoints(conn); | |
160 } | |
161 | |
162 if (conn.getPoints().size() is 2) { | |
163 PointList points = conn.getPoints(); | |
164 HashKey connectionKey = new HashKey(conn); | |
165 ArrayList connectionList = connections.get(connectionKey); | |
166 | |
167 if (connectionList !is null) { | |
168 | |
169 int index; | |
170 | |
171 if (connectionList.contains(cast(Object)conn)) { | |
172 index = connectionList.indexOf(cast(Object)conn) + 1; | |
173 } else { | |
174 index = connectionList.size() + 1; | |
175 connections.put(connectionKey, cast(Object)conn); | |
176 } | |
177 | |
178 handleCollision(points, index); | |
179 conn.setPoints(points); | |
180 } else { | |
181 connections.put(connectionKey, cast(Object)conn); | |
182 } | |
183 } | |
184 } | |
185 | |
186 /** | |
187 * An AutomaticRouter needs no constraints for the connections it routes. This method | |
188 * invalidates the connections and calls {@link #setConstraint(Connection, Object)} on the | |
189 * {@link #next()} router. | |
190 * @see dwtx.draw2d.ConnectionRouter#setConstraint(Connection, Object) | |
191 */ | |
192 public void setConstraint(Connection connection, Object constraint) { | |
193 invalidate(connection); | |
194 if (next() !is null) | |
195 next().setConstraint(connection, constraint); | |
196 } | |
197 | |
198 /** | |
199 * Sets the start and end points for the given connection. | |
200 * @param conn The connection | |
201 */ | |
202 protected void setEndPoints(Connection conn) { | |
203 PointList points = conn.getPoints(); | |
204 points.removeAllPoints(); | |
205 Point start = getStartPoint(conn); | |
206 Point end = getEndPoint(conn); | |
207 conn.translateToRelative(start); | |
208 conn.translateToRelative(end); | |
209 points.addPoint(start); | |
210 points.addPoint(end); | |
211 conn.setPoints(points); | |
212 } | |
213 | |
214 /** | |
215 * Sets the next router. | |
216 * @param router The ConnectionRouter | |
217 * @since 2.0 | |
218 */ | |
219 public void setNextRouter(ConnectionRouter router) { | |
220 nextRouter = router; | |
221 } | |
222 | |
223 } |