4
|
1 /*******************************************************************************
|
|
2 * Copyright (c) 2004, 2006 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.jface.util.Geometry;
|
|
14
|
|
15 import dwt.DWT;
|
|
16 import dwt.graphics.Point;
|
|
17 import dwt.graphics.Rectangle;
|
|
18 import dwt.widgets.Control;
|
|
19
|
|
20 import dwt.dwthelper.utils;
|
|
21
|
|
22 /**
|
|
23 * Contains static methods for performing simple geometric operations
|
|
24 * on the DWT geometry classes.
|
|
25 *
|
|
26 * @since 3.0
|
|
27 */
|
|
28 public class Geometry {
|
|
29
|
|
30 /**
|
|
31 * Prevent this class from being instantiated.
|
|
32 *
|
|
33 * @since 3.0
|
|
34 */
|
|
35 private this() {
|
|
36 //This is not instantiated
|
|
37 }
|
|
38
|
|
39 /**
|
|
40 * Returns the square of the distance between two points.
|
|
41 * <p>This is preferred over the real distance when searching
|
|
42 * for the closest point, since it avoids square roots.</p>
|
|
43 *
|
|
44 * @param p1 first endpoint
|
|
45 * @param p2 second endpoint
|
|
46 * @return the square of the distance between the two points
|
|
47 *
|
|
48 * @since 3.0
|
|
49 */
|
|
50 public static int distanceSquared(Point p1, Point p2) {
|
|
51 int term1 = p1.x - p2.x;
|
|
52 int term2 = p1.y - p2.y;
|
|
53 return term1 * term1 + term2 * term2;
|
|
54 }
|
|
55
|
|
56 /**
|
|
57 * Returns the magnitude of the given 2d vector (represented as a Point)
|
|
58 *
|
|
59 * @param p point representing the 2d vector whose magnitude is being computed
|
|
60 * @return the magnitude of the given 2d vector
|
|
61 * @since 3.0
|
|
62 */
|
|
63 public static double magnitude(Point p) {
|
|
64 return Math.sqrt( cast(real) magnitudeSquared(p));
|
|
65 }
|
|
66
|
|
67 /**
|
|
68 * Returns the square of the magnitude of the given 2-space vector (represented
|
|
69 * using a point)
|
|
70 *
|
|
71 * @param p the point whose magnitude is being computed
|
|
72 * @return the square of the magnitude of the given vector
|
|
73 * @since 3.0
|
|
74 */
|
|
75 public static int magnitudeSquared(Point p) {
|
|
76 return p.x * p.x + p.y * p.y;
|
|
77 }
|
|
78
|
|
79 /**
|
|
80 * Returns the dot product of the given vectors (expressed as Points)
|
|
81 *
|
|
82 * @param p1 the first vector
|
|
83 * @param p2 the second vector
|
|
84 * @return the dot product of the two vectors
|
|
85 * @since 3.0
|
|
86 */
|
|
87 public static int dotProduct(Point p1, Point p2) {
|
|
88 return p1.x * p2.x + p1.y * p2.y;
|
|
89 }
|
|
90
|
|
91 /**
|
|
92 * Returns a new point whose coordinates are the minimum of the coordinates of the
|
|
93 * given points
|
|
94 *
|
|
95 * @param p1 a Point
|
|
96 * @param p2 a Point
|
|
97 * @return a new point whose coordinates are the minimum of the coordinates of the
|
|
98 * given points
|
|
99 * @since 3.0
|
|
100 */
|
|
101 public static Point min(Point p1, Point p2) {
|
|
102 return new Point(Math.min(p1.x, p2.x), Math.min(p1.y, p2.y));
|
|
103 }
|
|
104
|
|
105 /**
|
|
106 * Returns a new point whose coordinates are the maximum of the coordinates
|
|
107 * of the given points
|
|
108 * @param p1 a Point
|
|
109 * @param p2 a Point
|
|
110 * @return point a new point whose coordinates are the maximum of the coordinates
|
|
111 * @since 3.0
|
|
112 */
|
|
113 public static Point max(Point p1, Point p2) {
|
|
114 return new Point(Math.max(p1.x, p2.x), Math.max(p1.y, p2.y));
|
|
115 }
|
|
116
|
|
117 /**
|
|
118 * Returns a vector in the given direction with the given
|
|
119 * magnitude. Directions are given using DWT direction constants, and
|
|
120 * the resulting vector is in the screen's coordinate system. That is,
|
|
121 * the vector (0, 1) is down and the vector (1, 0) is right.
|
|
122 *
|
|
123 * @param distance magnitude of the vector
|
|
124 * @param direction one of DWT.TOP, DWT.BOTTOM, DWT.LEFT, or DWT.RIGHT
|
|
125 * @return a point representing a vector in the given direction with the given magnitude
|
|
126 * @since 3.0
|
|
127 */
|
|
128 public static Point getDirectionVector(int distance, int direction) {
|
|
129 switch (direction) {
|
|
130 case DWT.TOP:
|
|
131 return new Point(0, -distance);
|
|
132 case DWT.BOTTOM:
|
|
133 return new Point(0, distance);
|
|
134 case DWT.LEFT:
|
|
135 return new Point(-distance, 0);
|
|
136 case DWT.RIGHT:
|
|
137 return new Point(distance, 0);
|
|
138 }
|
|
139
|
|
140 return new Point(0, 0);
|
|
141 }
|
|
142
|
|
143 /**
|
|
144 * Returns the point in the center of the given rectangle.
|
|
145 *
|
|
146 * @param rect rectangle being computed
|
|
147 * @return a Point at the center of the given rectangle.
|
|
148 * @since 3.0
|
|
149 */
|
|
150 public static Point centerPoint(Rectangle rect) {
|
|
151 return new Point(rect.x + rect.width / 2, rect.y + rect.height / 2);
|
|
152 }
|
|
153
|
|
154 /**
|
|
155 * Returns a copy of the given point
|
|
156 *
|
|
157 * @param toCopy point to copy
|
|
158 * @return a copy of the given point
|
|
159 */
|
|
160 public static Point copy(Point toCopy) {
|
|
161 return new Point(toCopy.x, toCopy.y);
|
|
162 }
|
|
163
|
|
164 /**
|
|
165 * Sets result equal to toCopy
|
|
166 *
|
|
167 * @param result object that will be modified
|
|
168 * @param toCopy object that will be copied
|
|
169 * @since 3.1
|
|
170 */
|
|
171 public static void set(Point result, Point toCopy) {
|
|
172 result.x = toCopy.x;
|
|
173 result.y = toCopy.y;
|
|
174 }
|
|
175
|
|
176 /**
|
|
177 * Sets result equal to toCopy
|
|
178 *
|
|
179 * @param result object that will be modified
|
|
180 * @param toCopy object that will be copied
|
|
181 * @since 3.1
|
|
182 */
|
|
183 public static void set(Rectangle result, Rectangle toCopy) {
|
|
184 result.x = toCopy.x;
|
|
185 result.y = toCopy.y;
|
|
186 result.width = toCopy.width;
|
|
187 result.height = toCopy.height;
|
|
188 }
|
|
189
|
|
190 /**
|
|
191 * <p>Returns a new difference Rectangle whose x, y, width, and height are equal to the difference of the corresponding
|
|
192 * attributes from the given rectangles</p>
|
|
193 *
|
|
194 * <p></p>
|
|
195 * <b>Example: Compute the margins for a given Composite, and apply those same margins to a new GridLayout</b>
|
|
196 *
|
|
197 * <code><pre>
|
|
198 * // Compute the client area, in the coordinate system of the input composite's parent
|
|
199 * Rectangle clientArea = Display.getCurrent().map(inputComposite,
|
|
200 * inputComposite.getParent(), inputComposite.getClientArea());
|
|
201 *
|
|
202 * // Compute the margins for a given Composite by subtracting the client area from the composite's bounds
|
|
203 * Rectangle margins = Geometry.subtract(inputComposite.getBounds(), clientArea);
|
|
204 *
|
|
205 * // Now apply these margins to a new GridLayout
|
|
206 * GridLayout layout = GridLayoutFactory.fillDefaults().margins(margins).create();
|
|
207 * </pre></code>
|
|
208 *
|
|
209 * @param rect1 first rectangle
|
|
210 * @param rect2 rectangle to subtract
|
|
211 * @return the difference between the two rectangles (computed as rect1 - rect2)
|
|
212 * @since 3.3
|
|
213 */
|
|
214 public static Rectangle subtract(Rectangle rect1, Rectangle rect2) {
|
|
215 return new Rectangle(rect1.x - rect2.x, rect1.y - rect2.y, rect1.width - rect2.width, rect1.height - rect2.height);
|
|
216 }
|
|
217
|
|
218 /**
|
|
219 * <p>Returns a new Rectangle whose x, y, width, and height is the sum of the x, y, width, and height values of
|
|
220 * both rectangles respectively.</p>
|
|
221 *
|
|
222 * @param rect1 first rectangle to add
|
|
223 * @param rect2 second rectangle to add
|
|
224 * @return a new rectangle whose x, y, height, and width attributes are the sum of the corresponding attributes from
|
|
225 * the arguments.
|
|
226 * @since 3.3
|
|
227 */
|
|
228 public static Rectangle add(Rectangle rect1, Rectangle rect2) {
|
|
229 return new Rectangle(rect1.x + rect2.x, rect1.y + rect2.y,
|
|
230 rect1.width + rect2.width, rect1.height + rect2.height);
|
|
231 }
|
|
232
|
|
233 /**
|
|
234 * Adds two points as 2d vectors. Returns a new point whose coordinates are
|
|
235 * the sum of the original two points.
|
|
236 *
|
|
237 * @param point1 the first point (not null)
|
|
238 * @param point2 the second point (not null)
|
|
239 * @return a new point whose coordinates are the sum of the given points
|
|
240 * @since 3.0
|
|
241 */
|
|
242 public static Point add(Point point1, Point point2) {
|
|
243 return new Point(point1.x + point2.x, point1.y + point2.y);
|
|
244 }
|
|
245
|
|
246 /**
|
|
247 * Divides both coordinates of the given point by the given scalar.
|
|
248 *
|
|
249 * @since 3.1
|
|
250 *
|
|
251 * @param toDivide point to divide
|
|
252 * @param scalar denominator
|
|
253 * @return a new Point whose coordinates are equal to the original point divided by the scalar
|
|
254 */
|
|
255 public static Point divide(Point toDivide, int scalar) {
|
|
256 return new Point(toDivide.x / scalar, toDivide.y / scalar);
|
|
257 }
|
|
258
|
|
259
|
|
260 /**
|
|
261 * Performs vector subtraction on two points. Returns a new point equal to
|
|
262 * (point1 - point2).
|
|
263 *
|
|
264 * @param point1 initial point
|
|
265 * @param point2 vector to subtract
|
|
266 * @return the difference (point1 - point2)
|
|
267 * @since 3.0
|
|
268 */
|
|
269 public static Point subtract(Point point1, Point point2) {
|
|
270 return new Point(point1.x - point2.x, point1.y - point2.y);
|
|
271 }
|
|
272
|
|
273 /**
|
|
274 * Swaps the X and Y coordinates of the given point.
|
|
275 *
|
|
276 * @param toFlip modifies this point
|
|
277 * @since 3.1
|
|
278 */
|
|
279 public static void flipXY(Point toFlip) {
|
|
280 int temp = toFlip.x;
|
|
281 toFlip.x = toFlip.y;
|
|
282 toFlip.y = temp;
|
|
283 }
|
|
284
|
|
285 /**
|
|
286 * Swaps the X and Y coordinates of the given rectangle, along with the height and width.
|
|
287 *
|
|
288 * @param toFlip modifies this rectangle
|
|
289 * @since 3.1
|
|
290 */
|
|
291 public static void flipXY(Rectangle toFlip) {
|
|
292 int temp = toFlip.x;
|
|
293 toFlip.x = toFlip.y;
|
|
294 toFlip.y = temp;
|
|
295
|
|
296 temp = toFlip.width;
|
|
297 toFlip.width = toFlip.height;
|
|
298 toFlip.height = temp;
|
|
299 }
|
|
300
|
|
301 /**
|
|
302 * Returns the height or width of the given rectangle.
|
|
303 *
|
|
304 * @param toMeasure rectangle to measure
|
|
305 * @param width returns the width if true, and the height if false
|
|
306 * @return the width or height of the given rectangle
|
|
307 * @since 3.0
|
|
308 */
|
|
309 public static int getDimension(Rectangle toMeasure, bool width) {
|
|
310 if (width) {
|
|
311 return toMeasure.width;
|
|
312 }
|
|
313 return toMeasure.height;
|
|
314 }
|
|
315
|
|
316 /**
|
|
317 * Returns the x or y coordinates of the given point.
|
|
318 *
|
|
319 * @param toMeasure point being measured
|
|
320 * @param width if true, returns x. Otherwise, returns y.
|
|
321 * @return the x or y coordinate
|
|
322 * @since 3.1
|
|
323 */
|
|
324 public static int getCoordinate(Point toMeasure, bool width) {
|
|
325 return width ? toMeasure.x : toMeasure.y;
|
|
326 }
|
|
327
|
|
328 /**
|
|
329 * Returns the x or y coordinates of the given rectangle.
|
|
330 *
|
|
331 * @param toMeasure rectangle being measured
|
|
332 * @param width if true, returns x. Otherwise, returns y.
|
|
333 * @return the x or y coordinate
|
|
334 * @since 3.1
|
|
335 */
|
|
336 public static int getCoordinate(Rectangle toMeasure, bool width) {
|
|
337 return width ? toMeasure.x : toMeasure.y;
|
|
338 }
|
|
339
|
|
340 /**
|
|
341 * Sets one dimension of the given rectangle. Modifies the given rectangle.
|
|
342 *
|
|
343 * @param toSet rectangle to modify
|
|
344 * @param width if true, the width is modified. If false, the height is modified.
|
|
345 * @param newCoordinate new value of the width or height
|
|
346 * @since 3.1
|
|
347 */
|
|
348 public static void setDimension(Rectangle toSet, bool width, int newCoordinate) {
|
|
349 if (width) {
|
|
350 toSet.width = newCoordinate;
|
|
351 } else {
|
|
352 toSet.height = newCoordinate;
|
|
353 }
|
|
354 }
|
|
355
|
|
356 /**
|
|
357 * Sets one coordinate of the given rectangle. Modifies the given rectangle.
|
|
358 *
|
|
359 * @param toSet rectangle to modify
|
|
360 * @param width if true, the x coordinate is modified. If false, the y coordinate is modified.
|
|
361 * @param newCoordinate new value of the x or y coordinates
|
|
362 * @since 3.1
|
|
363 */
|
|
364 public static void setCoordinate(Rectangle toSet, bool width, int newCoordinate) {
|
|
365 if (width) {
|
|
366 toSet.x = newCoordinate;
|
|
367 } else {
|
|
368 toSet.y = newCoordinate;
|
|
369 }
|
|
370 }
|
|
371
|
|
372 /**
|
|
373 * Sets one coordinate of the given point. Modifies the given point.
|
|
374 *
|
|
375 * @param toSet point to modify
|
|
376 * @param width if true, the x coordinate is modified. If false, the y coordinate is modified.
|
|
377 * @param newCoordinate new value of the x or y coordinates
|
|
378 * @since 3.1
|
|
379 */
|
|
380 public static void setCoordinate(Point toSet, bool width, int newCoordinate) {
|
|
381 if (width) {
|
|
382 toSet.x = newCoordinate;
|
|
383 } else {
|
|
384 toSet.y = newCoordinate;
|
|
385 }
|
|
386 }
|
|
387
|
|
388 /**
|
|
389 * Returns the distance of the given point from a particular side of the given rectangle.
|
|
390 * Returns negative values for points outside the rectangle.
|
|
391 *
|
|
392 * @param rectangle a bounding rectangle
|
|
393 * @param testPoint a point to test
|
|
394 * @param edgeOfInterest side of the rectangle to test against
|
|
395 * @return the distance of the given point from the given edge of the rectangle
|
|
396 * @since 3.0
|
|
397 */
|
|
398 public static int getDistanceFromEdge(Rectangle rectangle, Point testPoint,
|
|
399 int edgeOfInterest) {
|
|
400 switch (edgeOfInterest) {
|
|
401 case DWT.TOP:
|
|
402 return testPoint.y - rectangle.y;
|
|
403 case DWT.BOTTOM:
|
|
404 return rectangle.y + rectangle.height - testPoint.y;
|
|
405 case DWT.LEFT:
|
|
406 return testPoint.x - rectangle.x;
|
|
407 case DWT.RIGHT:
|
|
408 return rectangle.x + rectangle.width - testPoint.x;
|
|
409 }
|
|
410
|
|
411 return 0;
|
|
412 }
|
|
413
|
|
414 /**
|
|
415 * Extrudes the given edge inward by the given distance. That is, if one side of the rectangle
|
|
416 * was sliced off with a given thickness, this returns the rectangle that forms the slice. Note
|
|
417 * that the returned rectangle will be inside the given rectangle if size > 0.
|
|
418 *
|
|
419 * @param toExtrude the rectangle to extrude. The resulting rectangle will share three sides
|
|
420 * with this rectangle.
|
|
421 * @param size distance to extrude. A negative size will extrude outwards (that is, the resulting
|
|
422 * rectangle will overlap the original iff this is positive).
|
|
423 * @param orientation the side to extrude. One of DWT.LEFT, DWT.RIGHT, DWT.TOP, or DWT.BOTTOM. The
|
|
424 * resulting rectangle will always share this side with the original rectangle.
|
|
425 * @return a rectangle formed by extruding the given side of the rectangle by the given distance.
|
|
426 * @since 3.0
|
|
427 */
|
|
428 public static Rectangle getExtrudedEdge(Rectangle toExtrude, int size,
|
|
429 int orientation) {
|
|
430 Rectangle bounds = new Rectangle(toExtrude.x, toExtrude.y,
|
|
431 toExtrude.width, toExtrude.height);
|
|
432
|
|
433 if (!isHorizontal(orientation)) {
|
|
434 bounds.width = size;
|
|
435 } else {
|
|
436 bounds.height = size;
|
|
437 }
|
|
438
|
|
439 switch (orientation) {
|
|
440 case DWT.RIGHT:
|
|
441 bounds.x = toExtrude.x + toExtrude.width - bounds.width;
|
|
442 break;
|
|
443 case DWT.BOTTOM:
|
|
444 bounds.y = toExtrude.y + toExtrude.height - bounds.height;
|
|
445 break;
|
|
446 }
|
|
447
|
|
448 normalize(bounds);
|
|
449
|
|
450 return bounds;
|
|
451 }
|
|
452
|
|
453 /**
|
|
454 * Returns the opposite of the given direction. That is, returns DWT.LEFT if
|
|
455 * given DWT.RIGHT and visa-versa.
|
|
456 *
|
|
457 * @param swtDirectionConstant one of DWT.LEFT, DWT.RIGHT, DWT.TOP, or DWT.BOTTOM
|
|
458 * @return one of DWT.LEFT, DWT.RIGHT, DWT.TOP, or DWT.BOTTOM
|
|
459 * @since 3.0
|
|
460 */
|
|
461 public static int getOppositeSide(int swtDirectionConstant) {
|
|
462 switch (swtDirectionConstant) {
|
|
463 case DWT.TOP:
|
|
464 return DWT.BOTTOM;
|
|
465 case DWT.BOTTOM:
|
|
466 return DWT.TOP;
|
|
467 case DWT.LEFT:
|
|
468 return DWT.RIGHT;
|
|
469 case DWT.RIGHT:
|
|
470 return DWT.LEFT;
|
|
471 }
|
|
472
|
|
473 return swtDirectionConstant;
|
|
474 }
|
|
475
|
|
476 /**
|
|
477 * Converts the given bool into an DWT orientation constant.
|
|
478 *
|
|
479 * @param horizontal if true, returns DWT.HORIZONTAL. If false, returns DWT.VERTICAL
|
|
480 * @return DWT.HORIZONTAL or DWT.VERTICAL.
|
|
481 * @since 3.0
|
|
482 */
|
|
483 public static int getSwtHorizontalOrVerticalConstant(bool horizontal) {
|
|
484 if (horizontal) {
|
|
485 return DWT.HORIZONTAL;
|
|
486 }
|
|
487 return DWT.VERTICAL;
|
|
488 }
|
|
489
|
|
490 /**
|
|
491 * Returns true iff the given DWT side constant corresponds to a horizontal side
|
|
492 * of a rectangle. That is, returns true for the top and bottom but false for the
|
|
493 * left and right.
|
|
494 *
|
|
495 * @param swtSideConstant one of DWT.TOP, DWT.BOTTOM, DWT.LEFT, or DWT.RIGHT
|
|
496 * @return true iff the given side is horizontal.
|
|
497 * @since 3.0
|
|
498 */
|
|
499 public static bool isHorizontal(int swtSideConstant) {
|
|
500 return !(swtSideConstant is DWT.LEFT || swtSideConstant is DWT.RIGHT);
|
|
501 }
|
|
502
|
|
503 /**
|
|
504 * Moves the given rectangle by the given delta.
|
|
505 *
|
|
506 * @param rect rectangle to move (will be modified)
|
|
507 * @param delta direction vector to move the rectangle by
|
|
508 * @since 3.0
|
|
509 */
|
|
510 public static void moveRectangle(Rectangle rect, Point delta) {
|
|
511 rect.x += delta.x;
|
|
512 rect.y += delta.y;
|
|
513 }
|
|
514
|
|
515 /**
|
|
516 * Moves each edge of the given rectangle outward by the given amount. Negative values
|
|
517 * cause the rectangle to contract. Does not allow the rectangle's width or height to be
|
|
518 * reduced below zero.
|
|
519 *
|
|
520 * @param rect normalized rectangle to modify
|
|
521 * @param differenceRect difference rectangle to be added to rect
|
|
522 * @since 3.3
|
|
523 */
|
|
524 public static void expand(Rectangle rect, Rectangle differenceRect) {
|
|
525 rect.x += differenceRect.x;
|
|
526 rect.y += differenceRect.y;
|
|
527 rect.height = Math.max(0, rect.height + differenceRect.height);
|
|
528 rect.width = Math.max(0, rect.width + differenceRect.width);
|
|
529 }
|
|
530
|
|
531 /**
|
|
532 * <p>Returns a rectangle which, when added to another rectangle, will expand each side
|
|
533 * by the given number of units.</p>
|
|
534 *
|
|
535 * <p>This is commonly used to store margin sizes. For example:</p>
|
|
536 *
|
|
537 * <code><pre>
|
|
538 * // Expands the left, right, top, and bottom
|
|
539 * // of the given control by 10, 5, 1, and 15 units respectively
|
|
540 *
|
|
541 * Rectangle margins = Geometry.createDifferenceRect(10,5,1,15);
|
|
542 * Rectangle bounds = someControl.getBounds();
|
|
543 * someControl.setBounds(Geometry.add(bounds, margins));
|
|
544 * </pre></code>
|
|
545 *
|
|
546 * @param left distance to expand the left side (negative values move the edge inward)
|
|
547 * @param right distance to expand the right side (negative values move the edge inward)
|
|
548 * @param top distance to expand the top (negative values move the edge inward)
|
|
549 * @param bottom distance to expand the bottom (negative values move the edge inward)
|
|
550 *
|
|
551 * @return a difference rectangle that, when added to another rectangle, will cause each
|
|
552 * side to expand by the given number of units
|
|
553 * @since 3.3
|
|
554 */
|
|
555 public static Rectangle createDiffRectangle(int left, int right, int top, int bottom) {
|
|
556 return new Rectangle(-left, -top, left + right, top + bottom);
|
|
557 }
|
|
558
|
|
559 /**
|
|
560 * Moves each edge of the given rectangle outward by the given amount. Negative values
|
|
561 * cause the rectangle to contract. Does not allow the rectangle's width or height to be
|
|
562 * reduced below zero.
|
|
563 *
|
|
564 * @param rect normalized rectangle to modify
|
|
565 * @param left distance to move the left edge outward (negative values move the edge inward)
|
|
566 * @param right distance to move the right edge outward (negative values move the edge inward)
|
|
567 * @param top distance to move the top edge outward (negative values move the edge inward)
|
|
568 * @param bottom distance to move the bottom edge outward (negative values move the edge inward)
|
|
569 * @since 3.1
|
|
570 */
|
|
571 public static void expand(Rectangle rect, int left, int right, int top, int bottom) {
|
|
572 rect.x -= left;
|
|
573 rect.width = Math.max(0, rect.width + left + right);
|
|
574 rect.y -= top;
|
|
575 rect.height = Math.max(0, rect.height + top + bottom);
|
|
576 }
|
|
577
|
|
578 /**
|
|
579 * Normalizes the given rectangle. That is, any rectangle with
|
|
580 * negative width or height becomes a rectangle with positive
|
|
581 * width or height that extends to the upper-left of the original
|
|
582 * rectangle.
|
|
583 *
|
|
584 * @param rect rectangle to modify
|
|
585 * @since 3.0
|
|
586 */
|
|
587 public static void normalize(Rectangle rect) {
|
|
588 if (rect.width < 0) {
|
|
589 rect.width = -rect.width;
|
|
590 rect.x -= rect.width;
|
|
591 }
|
|
592
|
|
593 if (rect.height < 0) {
|
|
594 rect.height = -rect.height;
|
|
595 rect.y -= rect.height;
|
|
596 }
|
|
597 }
|
|
598
|
|
599 /**
|
|
600 * Converts the given rectangle from display coordinates to the local coordinate system
|
|
601 * of the given object into display coordinates.
|
|
602 *
|
|
603 * @param coordinateSystem local coordinate system being converted to
|
|
604 * @param toConvert rectangle to convert
|
|
605 * @return a rectangle in control coordinates
|
|
606 * @since 3.0
|
|
607 */
|
|
608 public static Rectangle toControl(Control coordinateSystem,
|
|
609 Rectangle toConvert) {
|
|
610 return(coordinateSystem.getDisplay().map
|
|
611 (null,coordinateSystem,toConvert));
|
|
612 }
|
|
613
|
|
614 /**
|
|
615 * Converts the given rectangle from the local coordinate system of the given object
|
|
616 * into display coordinates.
|
|
617 *
|
|
618 * @param coordinateSystem local coordinate system being converted from
|
|
619 * @param toConvert rectangle to convert
|
|
620 * @return a rectangle in display coordinates
|
|
621 * @since 3.0
|
|
622 */
|
|
623 public static Rectangle toDisplay(Control coordinateSystem,
|
|
624 Rectangle toConvert) {
|
|
625 return(coordinateSystem.getDisplay().map
|
|
626 (coordinateSystem,null,toConvert));
|
|
627
|
|
628 }
|
|
629
|
|
630 /**
|
|
631 * Determines where the given point lies with respect to the given rectangle.
|
|
632 * Returns a combination of DWT.LEFT, DWT.RIGHT, DWT.TOP, and DWT.BOTTOM, combined
|
|
633 * with bitwise or (for example, returns DWT.TOP | DWT.LEFT if the point is to the
|
|
634 * upper-left of the rectangle). Returns 0 if the point lies within the rectangle.
|
|
635 * Positions are in screen coordinates (ie: a point is to the upper-left of the
|
|
636 * rectangle if its x and y coordinates are smaller than any point in the rectangle)
|
|
637 *
|
|
638 * @param boundary normalized boundary rectangle
|
|
639 * @param toTest point whose relative position to the rectangle is being computed
|
|
640 * @return one of DWT.LEFT | DWT.TOP, DWT.TOP, DWT.RIGHT | DWT.TOP, DWT.LEFT, 0,
|
|
641 * DWT.RIGHT, DWT.LEFT | DWT.BOTTOM, DWT.BOTTOM, DWT.RIGHT | DWT.BOTTOM
|
|
642 * @since 3.0
|
|
643 */
|
|
644 public static int getRelativePosition(Rectangle boundary, Point toTest) {
|
|
645 int result = 0;
|
|
646
|
|
647 if (toTest.x < boundary.x) {
|
|
648 result |= DWT.LEFT;
|
|
649 } else if (toTest.x >= boundary.x + boundary.width) {
|
|
650 result |= DWT.RIGHT;
|
|
651 }
|
|
652
|
|
653 if (toTest.y < boundary.y) {
|
|
654 result |= DWT.TOP;
|
|
655 } else if (toTest.y >= boundary.y + boundary.height) {
|
|
656 result |= DWT.BOTTOM;
|
|
657 }
|
|
658
|
|
659 return result;
|
|
660 }
|
|
661
|
|
662 /**
|
|
663 * Returns the distance from the point to the nearest edge of the given
|
|
664 * rectangle. Returns negative values if the point lies outside the rectangle.
|
|
665 *
|
|
666 * @param boundary rectangle to test
|
|
667 * @param toTest point to test
|
|
668 * @return the distance between the given point and the nearest edge of the rectangle.
|
|
669 * Returns positive values for points inside the rectangle and negative values for points
|
|
670 * outside the rectangle.
|
|
671 * @since 3.1
|
|
672 */
|
|
673 public static int getDistanceFrom(Rectangle boundary, Point toTest) {
|
|
674 int side = getClosestSide(boundary, toTest);
|
|
675 return getDistanceFromEdge(boundary, toTest, side);
|
|
676 }
|
|
677
|
|
678 /**
|
|
679 * Returns the edge of the given rectangle is closest to the given
|
|
680 * point.
|
|
681 *
|
|
682 * @param boundary rectangle to test
|
|
683 * @param toTest point to compare
|
|
684 * @return one of DWT.LEFT, DWT.RIGHT, DWT.TOP, or DWT.BOTTOM
|
|
685 *
|
|
686 * @since 3.0
|
|
687 */
|
|
688 public static int getClosestSide(Rectangle boundary, Point toTest) {
|
|
689 int[] sides = [ DWT.LEFT, DWT.RIGHT, DWT.TOP, DWT.BOTTOM ];
|
|
690
|
|
691 int closestSide = DWT.LEFT;
|
|
692 int closestDistance = Integer.MAX_VALUE;
|
|
693
|
|
694 for (int idx = 0; idx < sides.length; idx++) {
|
|
695 int side = sides[idx];
|
|
696
|
|
697 int distance = getDistanceFromEdge(boundary, toTest, side);
|
|
698
|
|
699 if (distance < closestDistance) {
|
|
700 closestDistance = distance;
|
|
701 closestSide = side;
|
|
702 }
|
|
703 }
|
|
704
|
|
705 return closestSide;
|
|
706 }
|
|
707
|
|
708 /**
|
|
709 * Returns a copy of the given rectangle
|
|
710 *
|
|
711 * @param toCopy rectangle to copy
|
|
712 * @return a copy of the given rectangle
|
|
713 * @since 3.0
|
|
714 */
|
|
715 public static Rectangle copy(Rectangle toCopy) {
|
|
716 return new Rectangle(toCopy.x, toCopy.y, toCopy.width, toCopy.height);
|
|
717 }
|
|
718
|
|
719 /**
|
|
720 * Returns the size of the rectangle, as a Point
|
|
721 *
|
|
722 * @param rectangle rectangle whose size is being computed
|
|
723 * @return the size of the given rectangle
|
|
724 * @since 3.0
|
|
725 */
|
|
726 public static Point getSize(Rectangle rectangle) {
|
|
727 return new Point(rectangle.width, rectangle.height);
|
|
728 }
|
|
729
|
|
730 /**
|
|
731 * Sets the size of the given rectangle to the given size
|
|
732 *
|
|
733 * @param rectangle rectangle to modify
|
|
734 * @param newSize new size of the rectangle
|
|
735 * @since 3.0
|
|
736 */
|
|
737 public static void setSize(Rectangle rectangle, Point newSize) {
|
|
738 rectangle.width = newSize.x;
|
|
739 rectangle.height = newSize.y;
|
|
740 }
|
|
741
|
|
742 /**
|
|
743 * Sets the x,y position of the given rectangle. For a normalized
|
|
744 * rectangle (a rectangle with positive width and height), this will
|
|
745 * be the upper-left corner of the rectangle.
|
|
746 *
|
|
747 * @param rectangle rectangle to modify
|
|
748 * @param newSize new size of the rectangle
|
|
749 *
|
|
750 * @since 3.0
|
|
751 */
|
|
752 public static void setLocation(Rectangle rectangle, Point newSize) {
|
|
753 rectangle.width = newSize.x;
|
|
754 rectangle.height = newSize.y;
|
|
755 }
|
|
756
|
|
757 /**
|
|
758 * Returns the x,y position of the given rectangle. For normalized rectangles
|
|
759 * (rectangles with positive width and height), this is the upper-left
|
|
760 * corner of the rectangle.
|
|
761 *
|
|
762 * @param toQuery rectangle to query
|
|
763 * @return a Point containing the x,y position of the rectangle
|
|
764 *
|
|
765 * @since 3.0
|
|
766 */
|
|
767 public static Point getLocation(Rectangle toQuery) {
|
|
768 return new Point(toQuery.x, toQuery.y);
|
|
769 }
|
|
770
|
|
771 /**
|
|
772 * Returns a new rectangle with the given position and dimensions, expressed
|
|
773 * as points.
|
|
774 *
|
|
775 * @param position the (x,y) position of the rectangle
|
|
776 * @param size the size of the new rectangle, where (x,y) -> (width, height)
|
|
777 * @return a new Rectangle with the given position and size
|
|
778 *
|
|
779 * @since 3.0
|
|
780 */
|
|
781 public static Rectangle createRectangle(Point position, Point size) {
|
|
782 return new Rectangle(position.x, position.y, size.x, size.y);
|
|
783 }
|
|
784
|
|
785 /**
|
|
786 * Repositions the 'inner' rectangle to lie completely within the bounds of the 'outer'
|
|
787 * rectangle if possible. One use for this is to ensure that, when setting a control's bounds,
|
|
788 * that they will always lie within its parent's client area (to avoid clipping).
|
|
789 *
|
|
790 * @param inner The 'inner' rectangle to be repositioned (should be smaller than the 'outer' rectangle)
|
|
791 * @param outer The 'outer' rectangle
|
|
792 */
|
|
793 public static void moveInside(Rectangle inner, Rectangle outer) {
|
|
794 // adjust X
|
|
795 if (inner.x < outer.x) {
|
|
796 inner.x = outer.x;
|
|
797 }
|
|
798 if ((inner.x + inner.width) > (outer.x + outer.width)) {
|
|
799 inner.x -= (inner.x + inner.width) - (outer.x + outer.width);
|
|
800 }
|
|
801
|
|
802 // Adjust Y
|
|
803 if (inner.y < outer.y) {
|
|
804 inner.y = outer.y;
|
|
805 }
|
|
806 if ((inner.y + inner.height) > (outer.y + outer.height)) {
|
|
807 inner.y -= (inner.y + inner.height) - (outer.y + outer.height);
|
|
808 }
|
|
809 }
|
|
810
|
|
811 }
|