Mercurial > projects > dwt-addons
comparison dwtx/draw2d/ConnectionEndpointLocator.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.ConnectionEndpointLocator; | |
14 | |
15 import dwt.dwthelper.utils; | |
16 import dwtx.draw2d.geometry.Dimension; | |
17 import dwtx.draw2d.geometry.Point; | |
18 import dwtx.draw2d.geometry.Rectangle; | |
19 import dwtx.draw2d.geometry.Transposer; | |
20 import dwtx.draw2d.Locator; | |
21 import dwtx.draw2d.Connection; | |
22 import dwtx.draw2d.IFigure; | |
23 | |
24 /** | |
25 * Used to place IFigures along the endpoint or starting point of a {@link Connection}. | |
26 * <code>uDistance</code> represents the distance from the Connection's owner to the | |
27 * IFigure. <code>vDistance</code> represents the distance from the IFigure to the | |
28 * Connection itself. | |
29 */ | |
30 public class ConnectionEndpointLocator | |
31 : Locator | |
32 { | |
33 | |
34 private bool end; | |
35 private Connection conn; | |
36 private int uDistance; | |
37 private int vDistance; | |
38 private static Rectangle figureBounds; | |
39 | |
40 /** | |
41 * Transposes the location if the connection point is along the top or bottom of its owner | |
42 * figure. | |
43 */ | |
44 protected Transposer transposer; | |
45 | |
46 /** | |
47 * Constructs a ConnectionEndpointLocator using the given {@link Connection}. If | |
48 * <i>isEnd</i> is <code>true</code>, the location is relative to the Connection's end (or | |
49 * target) point. If <i>isEnd</i> is <code>false</code>, the location is relative to the | |
50 * Connection's start (or source) point. | |
51 * | |
52 * @param c The Connection | |
53 * @param isEnd <code>true</code> is location is relative to end point | |
54 * @since 2.0 | |
55 */ | |
56 public this(Connection c, bool isEnd) { | |
57 transposer = new Transposer(); | |
58 end = isEnd; | |
59 conn = c; | |
60 uDistance = 14; | |
61 vDistance = 4; | |
62 figureBounds = new Rectangle(); | |
63 } | |
64 | |
65 /* | |
66 * Returns an integer representing the side of the passed Rectangle that a point lies on. | |
67 * 1 is Top | |
68 * 2 is Right | |
69 * 3 is Bottom | |
70 * 4 is Left | |
71 * | |
72 * @param loc The point that is to be located | |
73 */ | |
74 private int calculateConnectionLocation(Point loc, Point topLeft, Point center) { | |
75 double m1, m2 = 0; | |
76 m1 = cast(double)(topLeft.y - center.y) / cast(double)(topLeft.x - center.x); | |
77 | |
78 if (loc.x - center.x !is 0) | |
79 m2 = cast(double)(loc.y - center.y) / cast(double)(loc.x - center.x); | |
80 | |
81 if (loc.x is center.x) { | |
82 // Case where m2 is vertical | |
83 if (loc.y < center.y) | |
84 return 3; | |
85 else | |
86 return 1; | |
87 } else if (Math.abs(m2) <= Math.abs(m1)) { | |
88 // Connection start point along left or right side | |
89 if (loc.x < center.x) | |
90 return 4; | |
91 else | |
92 return 2; | |
93 } else { | |
94 // Connection start point along top or bottom | |
95 if (loc.y < center.y) | |
96 return 3; | |
97 else | |
98 return 1; | |
99 } | |
100 } | |
101 | |
102 /* | |
103 * This method is used to calculate the "quadrant" value of a connection that does not | |
104 * have an owner on its starting point. | |
105 * | |
106 * 1 is Top | |
107 * 2 is Right | |
108 * 3 is Bottom | |
109 * 4 is Left | |
110 * | |
111 * @param startPoint The starting point of the connection. | |
112 * @param endPoint The end point of the connection. | |
113 */ | |
114 private int calculateConnectionLocation(Point startPoint, Point endPoint) { | |
115 if (Math.abs(endPoint.x - startPoint.x) > Math.abs(endPoint.y - startPoint.y)) { | |
116 if (endPoint.x > startPoint.x) | |
117 return 2; | |
118 else | |
119 return 4; | |
120 } else { | |
121 if (endPoint.y > startPoint.y) | |
122 return 1; | |
123 else | |
124 return 3; | |
125 } | |
126 } | |
127 | |
128 /* | |
129 * Calculates 'tan' which is used as a factor for y adjustment when placing the connection | |
130 * label. 'tan' is capped at 1.0 in the positive direction and -1.0 in the negative | |
131 * direction. | |
132 * | |
133 * @param startPoint The starting point of the connection. | |
134 * @param endPoint The end point of the connection. | |
135 * @since 2.0 | |
136 */ | |
137 private double calculateTan(Point startPoint, Point endPoint) { | |
138 double tan = 0; | |
139 if (endPoint.x is startPoint.x) | |
140 tan = 1.0; | |
141 else | |
142 tan = cast(double)(endPoint.y - startPoint.y) | |
143 / cast(double)(endPoint.x - startPoint.x); | |
144 if (tan > 1) | |
145 tan = 1.0; | |
146 else if (tan < -1) | |
147 tan = -1.0; | |
148 | |
149 return tan; | |
150 } | |
151 | |
152 private int calculateYShift(int figureWidth, int figureHeight) { | |
153 int yShift = 0; | |
154 if (vDistance < 0) | |
155 yShift = -figureHeight; | |
156 else if (vDistance is 0) | |
157 yShift = -figureHeight / 2; | |
158 return yShift; | |
159 } | |
160 | |
161 private Connection getConnection() { | |
162 return conn; | |
163 } | |
164 | |
165 private IFigure getConnectionOwner() { | |
166 IFigure connOwner; | |
167 if (isEnd()) | |
168 connOwner = conn.getTargetAnchor().getOwner(); | |
169 else | |
170 connOwner = conn.getSourceAnchor().getOwner(); | |
171 | |
172 return connOwner; | |
173 } | |
174 | |
175 /** | |
176 * Returns the distance in pixels from the anchor's owner. | |
177 * @return the offset distance from the endpoint figure | |
178 */ | |
179 public int getUDistance() { | |
180 return uDistance; | |
181 } | |
182 | |
183 /** | |
184 * Returns the distance in pixels from the connection | |
185 * @return the offset from the connection itself | |
186 */ | |
187 public int getVDistance() { | |
188 return vDistance; | |
189 } | |
190 | |
191 private bool isEnd() { | |
192 return end; | |
193 } | |
194 | |
195 /** | |
196 * Relocates the given IFigure at either the source or target end of the Connection, | |
197 * based on the <code>bool</code> given in the constructor | |
198 * {@link #ConnectionEndpointLocator(Connection, bool)}. | |
199 * | |
200 * @param figure The figure to relocate | |
201 */ | |
202 public void relocate(IFigure figure) { | |
203 Connection conn = getConnection(); | |
204 Point startPoint = Point.SINGLETON; | |
205 Point endPoint = new Point(); | |
206 | |
207 int startPointPosition = 0; | |
208 int endPointPosition = 1; | |
209 if (isEnd()) { | |
210 startPointPosition = conn.getPoints().size() - 1; | |
211 endPointPosition = startPointPosition - 1; | |
212 } | |
213 | |
214 conn.getPoints().getPoint(startPoint, startPointPosition); | |
215 conn.getPoints().getPoint(endPoint, endPointPosition); | |
216 | |
217 IFigure connOwner = getConnectionOwner(); | |
218 | |
219 int quadrant; | |
220 if (connOwner !is null) { | |
221 Rectangle connOwnerBounds = connOwner.getBounds(); | |
222 Point connOwnerCenter = connOwnerBounds.getCenter(); | |
223 Point connOwnerTL = connOwnerBounds.getTopLeft(); | |
224 quadrant = calculateConnectionLocation(startPoint, connOwnerTL, connOwnerCenter); | |
225 } else | |
226 quadrant = calculateConnectionLocation(startPoint, endPoint); | |
227 | |
228 int cos = 1; | |
229 transposer.setEnabled(false); | |
230 | |
231 /* | |
232 * Label placement calculations are done as if the connection point is along the left | |
233 * or right side of the figure. If the connection point is along the top or bottom, | |
234 * values are transposed. | |
235 */ | |
236 if (quadrant is 1 || quadrant is 3) | |
237 transposer.setEnabled(true); | |
238 | |
239 if (quadrant is 3 || quadrant is 4) | |
240 cos = -1; | |
241 | |
242 Dimension figureSize = transposer.t(figure.getPreferredSize()); | |
243 startPoint = transposer.t(startPoint); | |
244 endPoint = transposer.t(endPoint); | |
245 | |
246 double tan = calculateTan(startPoint, endPoint); | |
247 | |
248 int figureWidth = figureSize.width; | |
249 int figureHeight = figureSize.height; | |
250 int yShift = calculateYShift(figureWidth, figureHeight); | |
251 | |
252 Point figurePoint = | |
253 new Point(startPoint.x + (uDistance * cos) + figureWidth * ((cos - 1) / 2), | |
254 cast(int)(startPoint.y + cos * uDistance * tan + vDistance + yShift)); | |
255 | |
256 figureBounds.setSize(transposer.t(figureSize)); | |
257 figureBounds.setLocation(transposer.t(figurePoint)); | |
258 figure.setBounds(figureBounds); | |
259 } | |
260 | |
261 /** | |
262 * Sets the distance in pixels from the Connection's owner. | |
263 * | |
264 * @param distance Number of pixels to place the ConnectionEndpointLocator from its owner. | |
265 * @since 2.0 | |
266 */ | |
267 public void setUDistance(int distance) { | |
268 uDistance = distance; | |
269 } | |
270 | |
271 /** | |
272 * Sets the distance in pixels from the Connection. | |
273 * | |
274 * @param distance Number of pixels to place the ConnectionEndpointLocator from its | |
275 * Connection. | |
276 * @since 2.0 | |
277 */ | |
278 public void setVDistance(int distance) { | |
279 vDistance = distance; | |
280 } | |
281 | |
282 } |