Project

General

Profile

Download (29.8 KB) Statistics
| Branch: | Tag: | Revision:
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2010 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
 *     Mariot Chauvin <mariot.chauvin@obeo.fr> - bug 260740
11
 *******************************************************************************/
12
package org.eclipse.draw2d.geometry;
13

    
14
import org.eclipse.draw2d.PositionConstants;
15

    
16
/**
17
 * Represents a Rectangle(x, y, width, height). This class provides various
18
 * methods for manipulating this Rectangle or creating new derived geometrical
19
 * Objects.
20
 */
21
public class Rectangle implements Cloneable, java.io.Serializable, Translatable {
22

    
23
	static final long serialVersionUID = 1;
24

    
25
	/**
26
	 * A singleton for use in short calculations. Use to avoid newing
27
	 * unnecessary objects.
28
	 */
29
	public static final Rectangle SINGLETON = new Rectangle();
30

    
31
	/**
32
	 * The height
33
	 */
34
	public int height;
35

    
36
	/**
37
	 * The width
38
	 */
39
	public int width;
40

    
41
	/**
42
	 * The x value
43
	 */
44
	public int x;
45

    
46
	/**
47
	 * The y value
48
	 */
49
	public int y;
50

    
51
	/**
52
	 * Constructs a Rectangle at the origin with zero width and height.
53
	 * 
54
	 * @since 2.0
55
	 */
56
	public Rectangle() {
57
	}
58

    
59
	/**
60
	 * Constructs a Rectangle with the provided values.
61
	 * 
62
	 * @param x
63
	 *            X location
64
	 * @param y
65
	 *            Y location
66
	 * @param width
67
	 *            Width of the rectangle
68
	 * @param height
69
	 *            Height of the rectangle
70
	 * @since 2.0
71
	 */
72
	public Rectangle(int x, int y, int width, int height) {
73
		this.x = x;
74
		this.y = y;
75
		this.width = width;
76
		this.height = height;
77
	}
78

    
79
	/**
80
	 * Constructs a copy of the provided SWT
81
	 * {@link org.eclipse.swt.graphics.Rectangle}.
82
	 * 
83
	 * @param rect
84
	 *            The SWT Rectangle being copied
85
	 * @since 2.0
86
	 */
87
	public Rectangle(org.eclipse.swt.graphics.Rectangle rect) {
88
		this(rect.x, rect.y, rect.width, rect.height);
89
	}
90

    
91
	/**
92
	 * Constructs a Rectangle given a location and size.
93
	 * 
94
	 * @param p
95
	 *            the location
96
	 * @param size
97
	 *            the size
98
	 * @since 2.0
99
	 */
100
	public Rectangle(Point p, Dimension size) {
101
		this(p.x(), p.y(), size.width(), size.height());
102
	}
103

    
104
	/**
105
	 * Constructs the smallest Rectangle that contains the specified Points.
106
	 * 
107
	 * @param p1
108
	 *            Upper left hand corner
109
	 * @param p2
110
	 *            Lower right hand corner
111
	 * @since 2.0
112
	 */
113
	public Rectangle(Point p1, Point p2) {
114
		this.x = Math.min(p1.x(), p2.x());
115
		this.y = Math.min(p1.y(), p2.y());
116
		this.width = Math.abs(p2.x() - p1.x()) + 1;
117
		this.height = Math.abs(p2.y() - p1.y()) + 1;
118
	}
119

    
120
	/**
121
	 * Constructs a copy of the provided Rectangle.
122
	 * 
123
	 * @param rect
124
	 *            Rectangle supplying the initial values
125
	 * @since 2.0
126
	 */
127
	public Rectangle(Rectangle rect) {
128
		this(rect.x(), rect.y(), rect.width(), rect.height());
129
	}
130

    
131
	/**
132
	 * Returns the y-coordinate of the bottom of this Rectangle.
133
	 * 
134
	 * @return The Y coordinate of the bottom
135
	 * @since 2.0
136
	 */
137
	public int bottom() {
138
		return y + height;
139
	}
140

    
141
	/**
142
	 * Returns whether the given coordinates are within the boundaries of this
143
	 * Rectangle. The boundaries are inclusive of the top and left edges, but
144
	 * exclusive of the bottom and right edges.
145
	 * 
146
	 * @param x
147
	 *            X value
148
	 * @param y
149
	 *            Y value
150
	 * @return true if the coordinates are within this Rectangle
151
	 * @since 2.0
152
	 */
153
	public boolean contains(int x, int y) {
154
		return y >= this.y && y < this.y + this.height && x >= this.x
155
				&& x < this.x + this.width;
156
	}
157

    
158
	/**
159
	 * Returns whether the given point is within the boundaries of this
160
	 * Rectangle. The boundaries are inclusive of the top and left edges, but
161
	 * exclusive of the bottom and right edges.
162
	 * 
163
	 * @param p
164
	 *            Point being tested for containment
165
	 * @return true if the Point is within this Rectangle
166
	 * @since 2.0
167
	 */
168
	public boolean contains(Point p) {
169
		return contains(p.x(), p.y());
170
	}
171

    
172
	/**
173
	 * Returns <code>true</code> if the given rectangle is contained within the
174
	 * boundaries of this Rectangle.
175
	 * 
176
	 * @param rect
177
	 *            the Rectangle to test
178
	 * @return true if the Rectangle is within this Rectangle
179
	 */
180
	public boolean contains(Rectangle rect) {
181
		return x <= rect.x() && y <= rect.y() && right() >= rect.right()
182
				&& bottom() >= rect.bottom();
183
	}
184

    
185
	/**
186
	 * Crops this rectangle by the amount specified in <code>insets</code>.
187
	 * 
188
	 * @param insets
189
	 *            Insets to be removed from the Rectangle
190
	 * @return <code>this</code> for convenience
191
	 * @since 2.0
192
	 * @deprecated Use {@link #shrink(Insets)} instead.
193
	 */
194
	public Rectangle crop(Insets insets) {
195
		return shrink(insets);
196
	}
197

    
198
	/**
199
	 * Returns <code>true</code> if this Rectangle's x, y, width, and height
200
	 * values are identical to the provided ones.
201
	 * 
202
	 * @param x
203
	 *            The x value to test
204
	 * @param y
205
	 *            The y value to test
206
	 * @param width
207
	 *            The width value to test
208
	 * @param height
209
	 *            The height value to test
210
	 * @return <code>true</code> if this Rectangle's x, y, width, and height
211
	 *         values are identical to the provided ones, <code>false</code>
212
	 *         otherwise
213
	 * @since 3.7
214
	 */
215
	public boolean equals(int x, int y, int width, int height) {
216
		return this.x == x && this.y == y && this.width == width
217
				&& this.height == height;
218
	}
219

    
220
	/**
221
	 * Returns whether the input object is equal to this Rectangle or not.
222
	 * Rectangles are equivalent if their x, y, height, and width values are the
223
	 * same.
224
	 * 
225
	 * @param o
226
	 *            Object being tested for equality
227
	 * @return Returns the result of the equality test
228
	 * @since 2.0
229
	 */
230
	public boolean equals(Object o) {
231
		if (this == o)
232
			return true;
233
		if (o instanceof Rectangle) {
234
			Rectangle r = (Rectangle) o;
235
			return (x == r.x()) && (y == r.y()) && (width == r.width())
236
					&& (height == r.height());
237
		}
238
		return false;
239
	}
240

    
241
	/**
242
	 * Expands the horizontal and vertical sides of this Rectangle by the width
243
	 * and height of the given Insets, and returns this for convenience.
244
	 * 
245
	 * @param insets
246
	 *            contains the amounts to expand on each side
247
	 * @return <code>this</code> for convenience
248
	 * @since 2.0
249
	 */
250
	public Rectangle expand(Insets insets) {
251
		x -= insets.left;
252
		y -= insets.top;
253
		width += insets.getWidth();
254
		height += insets.getHeight();
255
		return this;
256
	}
257

    
258
	/**
259
	 * Expands the horizontal and vertical sides of this Rectangle with the
260
	 * values provided as input, and returns this for convenience. The location
261
	 * of its center is kept constant.
262
	 * 
263
	 * @param h
264
	 *            Horizontal increment
265
	 * @param v
266
	 *            Vertical increment
267
	 * @return <code>this</code> for convenience
268
	 * @since 2.0
269
	 */
270
	public Rectangle expand(int h, int v) {
271
		return shrink(-h, -v);
272
	}
273

    
274
	/**
275
	 * Returns a new Point representing the middle point of the bottom side of
276
	 * this Rectangle.
277
	 * 
278
	 * @return Point at the bottom of the Rectangle
279
	 * @since 2.0
280
	 */
281
	public Point getBottom() {
282
		return new Point(x + width / 2, bottom());
283
	}
284

    
285
	/**
286
	 * Returns a new Point representing the bottom left point of this Rectangle.
287
	 * 
288
	 * @return Point at the bottom left of the rectangle
289
	 * @since 2.0
290
	 */
291
	public Point getBottomLeft() {
292
		return new Point(x, y + height);
293
	}
294

    
295
	/**
296
	 * Returns a new Point representing the bottom right point of this
297
	 * Rectangle.
298
	 * 
299
	 * @return Point at the bottom right of the rectangle
300
	 * @since 2.0
301
	 */
302
	public Point getBottomRight() {
303
		return new Point(x + width, y + height);
304
	}
305

    
306
	/**
307
	 * Returns a new point representing the center of this Rectangle.
308
	 * 
309
	 * @return Point at the center of the rectangle
310
	 */
311
	public Point getCenter() {
312
		return new Point(x + width / 2, y + height / 2);
313
	}
314

    
315
	/**
316
	 * Returns a new Rectangle which has the exact same parameters as this
317
	 * Rectangle.
318
	 * 
319
	 * @return Copy of this Rectangle
320
	 * @since 2.0
321
	 */
322
	public Rectangle getCopy() {
323
		// FIXME: This is inconsistent with the behavior of getCopy() within
324
		// Point and Dimension and should only return a new Rectangle, leaving
325
		// the property copying of others to subclasses. Clients should
326
		// not relay on this method performing a clone()
327
		if (getClass() == Rectangle.class) {
328
			/* avoid clone() call cost see bug #260740 */
329
			return new Rectangle(this);
330
		} else {
331
			try {
332
				return (Rectangle) clone();
333
			} catch (CloneNotSupportedException exc) {
334
				return new Rectangle(this);
335
			}
336
		}
337
	}
338

    
339
	/**
340
	 * Returns a new Rectangle with the specified insets cropped.
341
	 * 
342
	 * @param insets
343
	 *            Insets being cropped from the Rectangle
344
	 * @return Cropped new Rectangle
345
	 * @deprecated Use {@link #getShrinked(Insets)} instead.
346
	 */
347
	public Rectangle getCropped(Insets insets) {
348
		return getShrinked(insets);
349
	}
350

    
351
	/**
352
	 * Creates and returns a new Rectangle with the bounds of <code>this</code>
353
	 * Rectangle, expanded by the given Insets.
354
	 * 
355
	 * @param insets
356
	 *            The insets used to expand this rectangle
357
	 * @return A new expanded Rectangle
358
	 * @since 2.0
359
	 */
360
	public Rectangle getExpanded(Insets insets) {
361
		return getCopy().expand(insets);
362
	}
363

    
364
	/**
365
	 * Returns a new incremented Rectangle, where the sides are expanded by the
366
	 * horizontal and vertical values provided. The center of the Rectangle is
367
	 * maintained constant.
368
	 * 
369
	 * @param h
370
	 *            Horizontal increment
371
	 * @param v
372
	 *            Vertical increment
373
	 * @return A new expanded Rectangle
374
	 * @since 2.0
375
	 */
376
	public Rectangle getExpanded(int h, int v) {
377
		return getCopy().expand(h, v);
378
	}
379

    
380
	/**
381
	 * Returns a new Rectangle which has the intersection of this Rectangle and
382
	 * the rectangle provided as input. Returns an empty Rectangle if there is
383
	 * no intersection.
384
	 * 
385
	 * @param rect
386
	 *            Rectangle provided to test for intersection
387
	 * @return A new Rectangle representing the intersection
388
	 * @since 2.0
389
	 */
390
	public Rectangle getIntersection(Rectangle rect) {
391
		return getCopy().intersect(rect);
392
	}
393

    
394
	/**
395
	 * Returns a new Point representing the middle point of the left hand side
396
	 * of this Rectangle.
397
	 * 
398
	 * @return Point at the left of the Rectangle
399
	 */
400
	public Point getLeft() {
401
		return new Point(x, y + height / 2);
402
	}
403

    
404
	/**
405
	 * Returns the upper left hand corner of the rectangle.
406
	 * 
407
	 * @return Location of the rectangle
408
	 * @see #setLocation(Point)
409
	 */
410
	public Point getLocation() {
411
		return new Point(x, y);
412
	}
413

    
414
	/**
415
	 * <P>
416
	 * Returns an integer which represents the position of the given point with
417
	 * respect to this rectangle. Possible return values are bitwise ORs of the
418
	 * constants WEST, EAST, NORTH, and SOUTH as found in
419
	 * {@link org.eclipse.draw2d.PositionConstants}.
420
	 * 
421
	 * <P>
422
	 * Returns PositionConstant.NONE if the given point is inside this
423
	 * Rectangle.
424
	 * 
425
	 * @param p
426
	 *            The Point whose position has to be determined
427
	 * @return An <code>int</code> which is a PositionConstant
428
	 * @see org.eclipse.draw2d.PositionConstants
429
	 * @since 2.0
430
	 */
431
	public int getPosition(Point p) {
432
		int result = PositionConstants.NONE;
433

    
434
		if (contains(p))
435
			return result;
436

    
437
		if (p.x() < x)
438
			result = PositionConstants.WEST;
439
		else if (p.x() >= (x + width))
440
			result = PositionConstants.EAST;
441

    
442
		if (p.y() < y)
443
			result = result | PositionConstants.NORTH;
444
		else if (p.y() >= (y + height))
445
			result = result | PositionConstants.SOUTH;
446

    
447
		return result;
448
	}
449

    
450
	/**
451
	 * Returns a new Rectangle which is equivalent to this Rectangle with its
452
	 * dimensions modified by the passed Dimension <i>d</i>.
453
	 * 
454
	 * @param d
455
	 *            Dimensions by which the rectangle's size should be modified
456
	 * @return The new rectangle with the modified dimensions
457
	 * @since 2.0
458
	 */
459
	public Rectangle getResized(Dimension d) {
460
		return getCopy().resize(d);
461
	}
462

    
463
	/**
464
	 * Returns a new Rectangle which is equivalent to this Rectangle with its
465
	 * dimensions modified by the passed width <i>w</i> and height <i>h</i>.
466
	 * 
467
	 * @param w
468
	 *            Amount by which width is to be resized
469
	 * @param h
470
	 *            Amount by which height is to be resized
471
	 * @return a new rectangle with its width and height modified
472
	 */
473
	public Rectangle getResized(int w, int h) {
474
		return getCopy().resize(w, h);
475
	}
476

    
477
	/**
478
	 * Returns a new Point which represents the middle point of the right hand
479
	 * side of this Rectangle.
480
	 * 
481
	 * @return Point at the right of the Rectangle
482
	 * @since 2.0
483
	 */
484
	public Point getRight() {
485
		return new Point(right(), y + height / 2);
486
	}
487

    
488
	/**
489
	 * Returns a new Rectangle shrinked by the specified insets.
490
	 * 
491
	 * @param insets
492
	 *            Insets being cropped from the Rectangle
493
	 * @return Shrinked new Rectangle
494
	 * @since 3.7
495
	 */
496
	public Rectangle getShrinked(Insets insets) {
497
		return getCopy().shrink(insets);
498
	}
499

    
500
	/**
501
	 * Returns a new Rectangle, where the sides are shrinked by the horizontal
502
	 * and vertical values supplied. The center of this Rectangle is kept
503
	 * constant.
504
	 * 
505
	 * @param h
506
	 *            Horizontal reduction amount
507
	 * @param v
508
	 *            Vertical reduction amount
509
	 * @return <code>this</code> for convenience
510
	 * @since 3.7
511
	 */
512
	public Rectangle getShrinked(int h, int v) {
513
		return getCopy().shrink(h, v);
514
	}
515

    
516
	/**
517
	 * Retuns the dimensions of this Rectangle.
518
	 * 
519
	 * @return Size of this Rectangle as a Dimension
520
	 * @since 2.0
521
	 */
522
	public Dimension getSize() {
523
		return new Dimension(width, height);
524
	}
525

    
526
	/**
527
	 * Returns a new Point which represents the middle point of the top side of
528
	 * this Rectangle.
529
	 * 
530
	 * @return Point at the top of the Rectangle
531
	 * @since 2.0
532
	 */
533
	public Point getTop() {
534
		return new Point(x + width / 2, y);
535
	}
536

    
537
	/**
538
	 * Returns a new Point which represents the top left hand corner of this
539
	 * Rectangle.
540
	 * 
541
	 * @return Point at the top left of the rectangle
542
	 * @since 2.0
543
	 */
544
	public Point getTopLeft() {
545
		return new Point(x, y);
546
	}
547

    
548
	/**
549
	 * Returns a new Point which represents the top right hand corner of this
550
	 * Rectangle.
551
	 * 
552
	 * @return Point at the top right of the rectangle
553
	 * @since 2.0
554
	 */
555
	public Point getTopRight() {
556
		return new Point(x + width, y);
557
	}
558

    
559
	/**
560
	 * Returns a new Rectangle which is shifted along each axis by the passed
561
	 * values.
562
	 * 
563
	 * @param dx
564
	 *            Displacement along X axis
565
	 * @param dy
566
	 *            Displacement along Y axis
567
	 * @return The new translated rectangle
568
	 * @since 2.0
569
	 */
570
	public Rectangle getTranslated(int dx, int dy) {
571
		return getCopy().translate(dx, dy);
572
	}
573

    
574
	/**
575
	 * Returns a new Rectangle which is shifted by the position of the given
576
	 * Point.
577
	 * 
578
	 * @param pt
579
	 *            Point providing the amount of shift along each axis
580
	 * @return The new translated Rectangle
581
	 * @since 2.0
582
	 */
583
	public Rectangle getTranslated(Point pt) {
584
		return getCopy().translate(pt);
585
	}
586

    
587
	/**
588
	 * Returns a new rectangle whose width and height have been interchanged, as
589
	 * well as its x and y values. This can be useful in orientation changes.
590
	 * 
591
	 * @return The transposed rectangle
592
	 * @since 2.0
593
	 */
594
	public Rectangle getTransposed() {
595
		return getCopy().transpose();
596
	}
597

    
598
	/**
599
	 * Returns a new Rectangle which contains both this Rectangle and the Point
600
	 * supplied as input.
601
	 * 
602
	 * @param p
603
	 *            Point for calculating union
604
	 * @return A new unioned Rectangle
605
	 * @since 3.7
606
	 */
607
	public Rectangle getUnion(Point p) {
608
		Rectangle copy = getCopy();
609
		copy.union(p);
610
		return copy;
611
	}
612

    
613
	/**
614
	 * Returns a new Rectangle which contains both this Rectangle and the
615
	 * Rectangle supplied as input.
616
	 * 
617
	 * @param rect
618
	 *            Rectangle for calculating union
619
	 * @return A new unioned Rectangle
620
	 * @since 2.0
621
	 */
622
	public Rectangle getUnion(Rectangle rect) {
623
		return getCopy().union(rect);
624
	}
625

    
626
	/**
627
	 * @see java.lang.Object#hashCode()
628
	 */
629
	public int hashCode() {
630
		return (x + height + 1) * (y + width + 1) ^ x ^ y;
631
	}
632

    
633
	/**
634
	 * Returns the current height of this Rectangle
635
	 * 
636
	 * @return The current height
637
	 * @since 3.7
638
	 */
639
	public int height() {
640
		return height;
641
	}
642

    
643
	/**
644
	 * Sets the size of this Rectangle to the intersection region with the
645
	 * Rectangle supplied as input, and returns this for convenience. The
646
	 * location and dimensions are set to zero if there is no intersection with
647
	 * the input Rectangle.
648
	 * 
649
	 * @param rect
650
	 *            Rectangle for the calculating intersection.
651
	 * @return <code>this</code> for convenience
652
	 * @since 2.0
653
	 */
654
	public Rectangle intersect(Rectangle rect) {
655
		int x1 = Math.max(x, rect.x());
656
		int x2 = Math.min(x + width, rect.x() + rect.width());
657
		int y1 = Math.max(y, rect.y());
658
		int y2 = Math.min(y + height, rect.y() + rect.height());
659
		if (((x2 - x1) < 0) || ((y2 - y1) < 0))
660
			return setBounds(0, 0, 0, 0); // no intersection
661
		else {
662
			return setBounds(x1, y1, x2 - x1, y2 - y1);
663
		}
664
	}
665

    
666
	/**
667
	 * Returns <code>true</code> if the input Rectangle intersects this
668
	 * Rectangle.
669
	 * 
670
	 * @param rect
671
	 *            Rectangle for the intersection test
672
	 * @return <code>true</code> if the input Rectangle intersects this
673
	 *         Rectangle
674
	 * @since 2.0
675
	 */
676
	public boolean intersects(Rectangle rect) {
677
		return !getIntersection(rect).isEmpty();
678
	}
679

    
680
	/**
681
	 * Returns <code>true</code> if this Rectangle's width or height is less
682
	 * than or equal to 0.
683
	 * 
684
	 * @return <code>true</code> if this Rectangle is empty
685
	 * @since 2.0
686
	 */
687
	public boolean isEmpty() {
688
		return width <= 0 || height <= 0;
689
	}
690

    
691
	/**
692
	 * @see Translatable#performScale(double)
693
	 */
694
	public void performScale(double factor) {
695
		scale(factor);
696
	}
697

    
698
	/**
699
	 * @see Translatable#performTranslate(int, int)
700
	 */
701
	public void performTranslate(int dx, int dy) {
702
		translate(dx, dy);
703
	}
704

    
705
	/**
706
	 * Returns <code>double</code> height
707
	 * 
708
	 * @return <code>double</code> height
709
	 * @since 3.4
710
	 */
711
	public double preciseHeight() {
712
		return height;
713
	}
714

    
715
	/**
716
	 * Returns <code>double</code> width
717
	 * 
718
	 * @return <code>double</code> width
719
	 * @since 3.4
720
	 */
721
	public double preciseWidth() {
722
		return width;
723
	}
724

    
725
	/**
726
	 * Returns <code>double</code> x coordinate
727
	 * 
728
	 * @return <code>double</code> x coordinate
729
	 * @since 3.4
730
	 */
731
	public double preciseX() {
732
		return x;
733
	}
734

    
735
	/**
736
	 * Returns <code>double</code> y coordinate
737
	 * 
738
	 * @return <code>double</code> y coordinate
739
	 * @since 3.4
740
	 */
741
	public double preciseY() {
742
		return y;
743
	}
744

    
745
	/**
746
	 * Resizes this Rectangle by the Dimension provided as input and returns
747
	 * this for convenience. This Rectange's width will become this.width +
748
	 * sizeDelta.width. Likewise for height.
749
	 * 
750
	 * @param d
751
	 *            Resize data as a Dimension
752
	 * @return <code>this</code> for convenience
753
	 * @since 2.0
754
	 */
755
	public Rectangle resize(Dimension d) {
756
		width += d.width();
757
		height += d.height();
758
		return this;
759
	}
760

    
761
	/**
762
	 * Resizes this Rectangle by the values supplied as input and returns this
763
	 * for convenience. This Rectangle's width will become this.width + dw. This
764
	 * Rectangle's height will become this.height + dh.
765
	 * 
766
	 * @param w
767
	 *            Amount by which width is to be resized
768
	 * @param h
769
	 *            Amount by which height is to be resized
770
	 * @return <code>this</code> for convenience
771
	 * @since 2.0
772
	 */
773
	public Rectangle resize(int w, int h) {
774
		width += w;
775
		height += h;
776
		return this;
777
	}
778

    
779
	/**
780
	 * Returns the x-coordinate of the right side of this Rectangle.
781
	 * 
782
	 * @return The X coordinate of the right side
783
	 * @since 2.0
784
	 */
785
	public int right() {
786
		return x + width;
787
	}
788

    
789
	/**
790
	 * Scales the location and size of this Rectangle by the given scale and
791
	 * returns this for convenience.
792
	 * 
793
	 * @param scaleFactor
794
	 *            The factor by which this rectangle will be scaled
795
	 * @return <code>this</code> for convenience
796
	 * @since 2.0
797
	 */
798
	public final Rectangle scale(double scaleFactor) {
799
		return scale(scaleFactor, scaleFactor);
800
	}
801

    
802
	/**
803
	 * Scales the location and size of this Rectangle by the given scales and
804
	 * returns this for convenience.
805
	 * 
806
	 * @param scaleX
807
	 *            the factor by which the X dimension has to be scaled
808
	 * @param scaleY
809
	 *            the factor by which the Y dimension has to be scaled
810
	 * @return <code>this</code> for convenience
811
	 * @since 2.0
812
	 */
813
	public Rectangle scale(double scaleX, double scaleY) {
814
		int oldX = x;
815
		int oldY = y;
816
		x = (int) (Math.floor(x * scaleX));
817
		y = (int) (Math.floor(y * scaleY));
818
		width = (int) (Math.ceil((oldX + width) * scaleX)) - x;
819
		height = (int) (Math.ceil((oldY + height) * scaleY)) - y;
820
		return this;
821
	}
822

    
823
	/**
824
	 * Sets the x, y, width, and height values of this Rectangle to the provided
825
	 * values.
826
	 * 
827
	 * @param x
828
	 *            The new x
829
	 * @param y
830
	 *            The new y
831
	 * @param width
832
	 *            The new width
833
	 * @param height
834
	 *            The new height
835
	 * @return this for convenience
836
	 * @since 3.7
837
	 */
838
	public Rectangle setBounds(int x, int y, int width, int height) {
839
		this.x = x;
840
		this.y = y;
841
		this.width = width;
842
		this.height = height;
843
		return this;
844
	}
845

    
846
	/**
847
	 * Sets the location and size of this rectangle to the provided ones.
848
	 * 
849
	 * @param location
850
	 *            The new location
851
	 * @param size
852
	 *            The new size
853
	 * @return this for convenience
854
	 * @since 3.7
855
	 */
856
	public Rectangle setBounds(Point location, Dimension size) {
857
		return setBounds(location.x(), location.y(), size.width(),
858
				size.height());
859
	}
860

    
861
	/**
862
	 * Sets the parameters of this Rectangle from the Rectangle passed in and
863
	 * returns this for convenience.
864
	 * 
865
	 * @return <code>this</code> for convenience
866
	 * @param rect
867
	 *            Rectangle providing the bounding values
868
	 * @since 2.0
869
	 */
870
	public Rectangle setBounds(Rectangle rect) {
871
		return setBounds(rect.x(), rect.y(), rect.width(), rect.height());
872
	}
873

    
874
	/**
875
	 * Sets the height of this Rectangle to the specified one.
876
	 * 
877
	 * @param height
878
	 *            The new height
879
	 * @return this for convenience.
880
	 * @since 3.7
881
	 */
882
	public Rectangle setHeight(int height) {
883
		this.height = height;
884
		return this;
885
	}
886

    
887
	/**
888
	 * Sets the location of this Rectangle to the coordinates given as input and
889
	 * returns this for convenience.
890
	 * 
891
	 * @param x
892
	 *            The new X coordinate
893
	 * @param y
894
	 *            The new Y coordinate
895
	 * @return <code>this</code> for convenience
896
	 * @since 2.0
897
	 */
898
	public Rectangle setLocation(int x, int y) {
899
		this.x = x;
900
		this.y = y;
901
		return this;
902
	}
903

    
904
	/**
905
	 * Sets the location of this Rectangle to the point given as input and
906
	 * returns this for convenience.
907
	 * 
908
	 * @return <code>this</code> for convenience
909
	 * @param p
910
	 *            New position of this Rectangle
911
	 * @since 2.0
912
	 */
913
	public Rectangle setLocation(Point p) {
914
		return setLocation(p.x(), p.y());
915
	}
916

    
917
	/**
918
	 * Sets the width and height of this Rectangle to the width and height of
919
	 * the given Dimension and returns this for convenience.
920
	 * 
921
	 * @param d
922
	 *            The new Dimension
923
	 * @return <code>this</code> for convenience
924
	 * @since 2.0
925
	 */
926
	public Rectangle setSize(Dimension d) {
927
		return setSize(d.width(), d.height());
928
	}
929

    
930
	/**
931
	 * Sets the width of this Rectangle to <i>w</i> and the height of this
932
	 * Rectangle to <i>h</i> and returns this for convenience.
933
	 * 
934
	 * @return <code>this</code> for convenience
935
	 * @param w
936
	 *            The new width
937
	 * @param h
938
	 *            The new height
939
	 * @since 2.0
940
	 */
941
	public Rectangle setSize(int w, int h) {
942
		width = w;
943
		height = h;
944
		return this;
945
	}
946

    
947
	/**
948
	 * Sets the width of this Rectangle to the specified one.
949
	 * 
950
	 * @param width
951
	 *            The new width
952
	 * @return this for convenience.
953
	 * @since 3.7
954
	 */
955
	public Rectangle setWidth(int width) {
956
		this.width = width;
957
		return this;
958
	}
959

    
960
	/**
961
	 * Sets the x value of the Rectangle and returns this for convenience.
962
	 * 
963
	 * @return <code>this</code> for convenience
964
	 * @param x
965
	 *            The new x value
966
	 * @since 3.7
967
	 */
968
	public Rectangle setX(int x) {
969
		this.x = x;
970
		return this;
971
	}
972

    
973
	/**
974
	 * Sets the y value of the Rectangle and returns this for convenience.
975
	 * 
976
	 * @return <code>this</code> for convenience
977
	 * @param y
978
	 *            The new y value
979
	 * @since 3.7
980
	 */
981
	public Rectangle setY(int y) {
982
		this.y = y;
983
		return this;
984
	}
985

    
986
	/**
987
	 * Shrinks this rectangle by the amount specified in <code>insets</code>.
988
	 * 
989
	 * @param insets
990
	 *            Insets to be removed from the Rectangle
991
	 * @return <code>this</code> for convenience
992
	 * @since 3.7
993
	 */
994
	public Rectangle shrink(Insets insets) {
995
		if (insets == null)
996
			return this;
997
		x += insets.left;
998
		y += insets.top;
999
		width -= (insets.getWidth());
1000
		height -= (insets.getHeight());
1001
		return this;
1002
	}
1003

    
1004
	/**
1005
	 * Shrinks the sides of this Rectangle by the horizontal and vertical values
1006
	 * provided as input, and returns this Rectangle for convenience. The center
1007
	 * of this Rectangle is kept constant.
1008
	 * 
1009
	 * @param h
1010
	 *            Horizontal reduction amount
1011
	 * @param v
1012
	 *            Vertical reduction amount
1013
	 * @return <code>this</code> for convenience
1014
	 * @since 2.0
1015
	 */
1016
	public Rectangle shrink(int h, int v) {
1017
		x += h;
1018
		width -= (h + h);
1019
		y += v;
1020
		height -= (v + v);
1021
		return this;
1022
	}
1023

    
1024
	/**
1025
	 * Returns the description of this Rectangle.
1026
	 * 
1027
	 * @return String containing the description
1028
	 * @since 2.0
1029
	 */
1030
	public String toString() {
1031
		return "Rectangle(" + x + ", " + y + ", " + //$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
1032
				width + ", " + height + ")";//$NON-NLS-2$//$NON-NLS-1$
1033
	}
1034

    
1035
	/**
1036
	 * Returns <code>true</code> if the input Rectangle touches this Rectangle.
1037
	 * 
1038
	 * @param rect
1039
	 *            Rectangle being checked for contact
1040
	 * @return <code>true</code> if rect touches this Rectangle
1041
	 * @since 2.0
1042
	 */
1043
	public boolean touches(Rectangle rect) {
1044
		return rect.x() <= x + width && rect.y() <= y + height
1045
				&& rect.x() + rect.width() >= x
1046
				&& rect.y() + rect.height() >= y;
1047
	}
1048

    
1049
	/**
1050
	 * Moves this Rectangle horizontally by dx and vertically by dy, then
1051
	 * returns this Rectangle for convenience.
1052
	 * 
1053
	 * @param dx
1054
	 *            Shift along X axis
1055
	 * @param dy
1056
	 *            Shift along Y axis
1057
	 * @return <code>this</code> for convenience
1058
	 * @since 2.0
1059
	 */
1060
	public Rectangle translate(int dx, int dy) {
1061
		x += dx;
1062
		y += dy;
1063
		return this;
1064
	}
1065

    
1066
	/**
1067
	 * Moves this Rectangle horizontally by the x value of the given Point and
1068
	 * vertically by the y value of the given Point, then returns this Rectangle
1069
	 * for convenience.
1070
	 * 
1071
	 * @param p
1072
	 *            Point which provides translation information
1073
	 * @return <code>this</code> for convenience
1074
	 */
1075
	public Rectangle translate(Point p) {
1076
		x += p.x;
1077
		y += p.y;
1078
		return this;
1079
	}
1080

    
1081
	/**
1082
	 * Switches the x and y values, as well as the width and height of this
1083
	 * Rectangle. Useful for orientation changes.
1084
	 * 
1085
	 * @return <code>this</code> for convenience
1086
	 * @since 2.0
1087
	 */
1088
	public Rectangle transpose() {
1089
		int temp = x;
1090
		x = y;
1091
		y = temp;
1092
		temp = width;
1093
		width = height;
1094
		height = temp;
1095
		return this;
1096
	}
1097

    
1098
	/**
1099
	 * Unions this Rectangle's width and height with the specified Dimension.
1100
	 * 
1101
	 * @param d
1102
	 *            Dimension being unioned
1103
	 * @return <code>this</code> for convenience
1104
	 * @since 2.0
1105
	 * @deprecated Union with a dimension generally does not make much sense,
1106
	 *             thus deprecating this. Use
1107
	 *             {@link Dimension#max(Dimension, Dimension)} and
1108
	 *             {@link #setSize(Dimension)} to implement the desired behavior
1109
	 *             instead.
1110
	 */
1111
	public Rectangle union(Dimension d) {
1112
		width = Math.max(width, d.width);
1113
		height = Math.max(height, d.height);
1114
		return this;
1115
	}
1116

    
1117
	/**
1118
	 * Updates this Rectangle's bounds to the minimum size which can hold both
1119
	 * this Rectangle and the coordinate (x,y).
1120
	 * 
1121
	 * @return <code>this</code> for convenience
1122
	 * @param x1
1123
	 *            X coordinate
1124
	 * @param y1
1125
	 *            Y coordinate
1126
	 * @since 2.0
1127
	 */
1128
	public Rectangle union(int x1, int y1) {
1129
		if (x1 < x) {
1130
			width += (x - x1);
1131
			x = x1;
1132
		} else {
1133
			int right = x + width;
1134
			if (x1 >= right) {
1135
				right = x1 + 1;
1136
				width = right - x;
1137
			}
1138
		}
1139
		if (y1 < y) {
1140
			height += (y - y1);
1141
			y = y1;
1142
		} else {
1143
			int bottom = y + height;
1144
			if (y1 >= bottom) {
1145
				bottom = y1 + 1;
1146
				height = bottom - y;
1147
			}
1148
		}
1149
		return this;
1150
	}
1151

    
1152
	/**
1153
	 * Updates this Rectangle's dimensions to the minimum size which can hold
1154
	 * both this Rectangle and the rectangle (x, y, w, h).
1155
	 * 
1156
	 * @param x
1157
	 *            X coordinate of desired union.
1158
	 * @param y
1159
	 *            Y coordinate of desired union.
1160
	 * @param w
1161
	 *            Width of desired union.
1162
	 * @param h
1163
	 *            Height of desired union.
1164
	 * @return <code>this</code> for convenience
1165
	 * @since 2.0
1166
	 */
1167
	public Rectangle union(int x, int y, int w, int h) {
1168
		int right = Math.max(this.x + width, x + w);
1169
		int bottom = Math.max(this.y + height, y + h);
1170
		this.x = Math.min(this.x, x);
1171
		this.y = Math.min(this.y, y);
1172
		this.width = right - this.x;
1173
		this.height = bottom - this.y;
1174
		return this;
1175
	}
1176

    
1177
	/**
1178
	 * Updates this Rectangle's bounds to the minimum size which can hold both
1179
	 * this Rectangle and the given Point.
1180
	 * 
1181
	 * @param p
1182
	 *            Point to be unioned with this Rectangle
1183
	 * @since 2.0
1184
	 */
1185
	public void union(Point p) {
1186
		// TODO: This should for the sake of consistency also return this
1187
		// by convenience; however, this is regarded as API break so it
1188
		// may be done not sooner than in 4.0; if this is done, it has
1189
		// to be ensured that the overwritten method in PrecisionRectangle
1190
		// is adjusted as well.
1191
		union(p.x(), p.y());
1192
	}
1193

    
1194
	/**
1195
	 * Updates this Rectangle's dimensions to the minimum size which can hold
1196
	 * both this Rectangle and the given Rectangle.
1197
	 * 
1198
	 * @return <code>this</code> for convenience
1199
	 * @param rect
1200
	 *            Rectangle to be unioned with this Rectangle
1201
	 * @since 2.0
1202
	 */
1203
	public Rectangle union(Rectangle rect) {
1204
		if (rect == null || rect.isEmpty())
1205
			return this;
1206
		return union(rect.x, rect.y, rect.width, rect.height);
1207
	}
1208

    
1209
	/**
1210
	 * Returns the current width of this Rectangle
1211
	 * 
1212
	 * @return The current width
1213
	 * @since 3.7
1214
	 */
1215
	public int width() {
1216
		return width;
1217
	}
1218

    
1219
	/**
1220
	 * Returns the x value of this Rectangle.
1221
	 * 
1222
	 * @return The current x value
1223
	 * @since 3.7
1224
	 */
1225
	public int x() {
1226
		return x;
1227
	}
1228

    
1229
	/**
1230
	 * Returns the y value of the Rectangle
1231
	 * 
1232
	 * @return The current y value
1233
	 * @since 3.7
1234
	 */
1235
	public int y() {
1236
		return y;
1237
	}
1238

    
1239
}
(11-11/17)