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 }