comparison org.eclipse.draw2d/src/org/eclipse/draw2d/AutomaticRouter.d @ 12:bc29606a740c

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