OSDN Git Service

2003-06-05 Michael Koch <konqueror@gmx.de>
[pf3gnuchains/gcc-fork.git] / libjava / java / awt / Rectangle.java
1 /* Rectangle.java -- represents a graphics rectangle
2    Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package java.awt;
40
41 import java.awt.geom.Rectangle2D;
42 import java.io.Serializable;
43
44 /**
45  * This class represents a rectangle and all the interesting things you
46  * might want to do with it.  Note that the coordinate system uses
47  * the origin (0,0) as the top left of the screen, with the x and y
48  * values increasing as they move to the right and down respectively.
49  *
50  * <p>It is valid for a rectangle to have negative width or height; but it
51  * is considered to have no area or internal points. Therefore, the behavior
52  * in methods like <code>contains</code> or <code>intersects</code> is
53  * undefined unless the rectangle has positive width and height.
54  *
55  * <p>There are some public fields; if you mess with them in an inconsistent
56  * manner, it is your own fault when you get NullPointerException,
57  * ArrayIndexOutOfBoundsException, or invalid results. Also, this class is
58  * not threadsafe.
59  *
60  * @author Warren Levy  <warrenl@cygnus.com>
61  * @author Aaron M. Renn <arenn@urbanophile.com>
62  * @author Eric Blake <ebb9@email.byu.edu>
63  * @since 1.0
64  * @status updated to 1.4
65  */
66 public class Rectangle extends Rectangle2D implements Shape, Serializable
67 {
68   /**
69    * Compatible with JDK 1.0+.
70    */
71   private static final long serialVersionUID = -4345857070255674764L;
72
73   /**
74    * The X coordinate of the top-left corner of the rectangle.
75    *
76    * @see #setLocation(int, int)
77    * @see #getLocation()
78    * @serial the x coordinate
79    */
80   public int x;
81
82   /**
83    * The Y coordinate of the top-left corner of the rectangle.
84    *
85    * @see #setLocation(int, int)
86    * @see #getLocation()
87    * @serial the y coordinate
88    */
89   public int y;
90
91   /**
92    * The width of the rectangle.
93    *
94    * @see #setSize(int, int)
95    * @see #getSize()
96    * @serial
97    */
98   public int width;
99
100   /**
101    * The height of the rectangle.
102    *
103    * @see #setSize(int, int)
104    * @see #getSize()
105    * @serial
106    */
107   public int height;
108
109   /**
110    * Initializes a new instance of <code>Rectangle</code> with a top
111    * left corner at (0,0) and a width and height of 0.
112    */
113   public Rectangle()
114   {
115   }
116
117   /**
118    * Initializes a new instance of <code>Rectangle</code> from the
119    * coordinates of the specified rectangle.
120    *
121    * @param r the rectangle to copy from
122    * @throws NullPointerException if r is null
123    * @since 1.1
124    */
125   public Rectangle(Rectangle r)
126   {
127     x = r.x;
128     y = r.y;
129     width = r.width;
130     height = r.height;
131   }
132
133   /**
134    * Initializes a new instance of <code>Rectangle</code> from the specified
135    * inputs.
136    *
137    * @param x the X coordinate of the top left corner
138    * @param y the Y coordinate of the top left corner
139    * @param width the width of the rectangle
140    * @param height the height of the rectangle
141    */
142   public Rectangle(int x, int y, int width, int height)
143   {
144     this.x = x;
145     this.y = y;
146     this.width = width;
147     this.height = height;
148   }
149
150   /**
151    * Initializes a new instance of <code>Rectangle</code> with the specified
152    * width and height. The upper left corner of the rectangle will be at
153    * the origin (0,0).
154    *
155    * @param width the width of the rectangle
156    * @param height the height of the rectange
157    */
158   public Rectangle(int width, int height)
159   {
160     this.width = width;
161     this.height = height;
162   }
163
164   /**
165    * Initializes a new instance of <code>Rectangle</code> with a top-left
166    * corner represented by the specified point and the width and height
167    * represented by the specified dimension.
168    *
169    * @param p the upper left corner of the rectangle
170    * @param d the width and height of the rectangle
171    * @throws NullPointerException if p or d is null
172    */
173   public Rectangle(Point p, Dimension d)
174   {
175     x = p.x;
176     y = p.y;
177     width = d.width;
178     height = d.height;
179   }
180
181   /**
182    * Initializes a new instance of <code>Rectangle</code> with a top left
183    * corner at the specified point and a width and height of zero.
184    *
185    * @param p the upper left corner of the rectangle
186    */
187   public Rectangle(Point p)
188   {
189     x = p.x;
190     y = p.y;
191   }
192
193   /**
194    * Initializes a new instance of <code>Rectangle</code> with an
195    * upper left corner at the origin (0,0) and a width and height represented
196    * by the specified dimension.
197    *
198    * @param d the width and height of the rectangle
199    */
200   public Rectangle(Dimension d)
201   {
202     width = d.width;
203     height = d.height;
204   }
205
206   /**
207    * Get the X coordinate of the upper-left corner.
208    *
209    * @return the value of x, as a double
210    */
211   public double getX()
212   {
213     return x;
214   }
215
216   /**
217    * Get the Y coordinate of the upper-left corner.
218    *
219    * @return the value of y, as a double
220    */
221   public double getY()
222   {
223     return y;
224   }
225
226   /**
227    * Get the width of the rectangle.
228    *
229    * @return the value of width, as a double
230    */
231   public double getWidth()
232   {
233     return width;
234   }
235
236   /**
237    * Get the height of the rectangle.
238    *
239    * @return the value of height, as a double
240    */
241   public double getHeight()
242   {
243     return height;
244   }
245
246   /**
247    * Returns the bounds of this rectangle. A pretty useless method, as this
248    * is already a rectangle; it is included to mimic the
249    * <code>getBounds</code> method in Component.
250    *
251    * @return a copy of this rectangle
252    * @see #setBounds(Rectangle)
253    * @since 1.1
254    */
255   public Rectangle getBounds()
256   {
257     return new Rectangle(this);
258   }
259
260   /**
261    * Returns the high-precision bounds of this rectangle. A pretty useless
262    * method, as this is already a rectangle.
263    *
264    * @return a copy of this rectangle
265    * @see #setBounds(Rectangle)
266    * @since 1.2
267    */
268   public Rectangle2D getBounds2D()
269   {
270     return new Rectangle(x, y, width, height);
271   }
272
273   /**
274    * Updates this rectangle to match the dimensions of the specified
275    * rectangle.
276    *
277    * @param r the rectangle to update from
278    * @throws NullPointerException if r is null
279    * @see #setBounds(int, int, int, int)
280    * @since 1.1
281    */
282   public void setBounds(Rectangle r)
283   {
284     x = r.x;
285     y = r.y;
286     width = r.width;
287     height = r.height;
288   }
289
290   /**
291    * Updates this rectangle to have the specified dimensions.
292    *
293    * @param x the new X coordinate of the upper left hand corner
294    * @param y the new Y coordinate of the upper left hand corner
295    * @param width the new width of this rectangle
296    * @param height the new height of this rectangle
297    * @since 1.1
298    */
299   public void setBounds(int x, int y, int width, int height)
300   {
301     this.x = x;
302     this.y = y;
303     this.width = width;
304     this.height = height;
305   }
306
307   /**
308    * Updates this rectangle to have the specified dimensions, as rounded to
309    * integers.
310    *
311    * @param x the new X coordinate of the upper left hand corner
312    * @param y the new Y coordinate of the upper left hand corner
313    * @param width the new width of this rectangle
314    * @param height the new height of this rectangle
315    * @since 1.2
316    */
317   public void setRect(double x, double y, double width, double height)
318   {
319     this.x = (int) x;
320     this.y = (int) y;
321     this.width = (int) width;
322     this.height = (int) height;
323   }
324
325   /**
326    * Updates this rectangle to have the specified dimensions.
327    *
328    * @param x the new X coordinate of the upper left hand corner
329    * @param y the new Y coordinate of the upper left hand corner
330    * @param width the new width of this rectangle
331    * @param height the new height of this rectangle
332    * @deprecated use {@link #setBounds(int, int, int, int)} instead
333    */
334   public void reshape(int x, int y, int width, int height)
335   {
336     setBounds(x, y, width, height);
337   }
338
339   /**
340    * Returns the location of this rectangle, which is the coordinates of
341    * its upper left corner.
342    *
343    * @return the point where this rectangle is located
344    * @see setLocation(Point)
345    * @since 1.1
346    */
347   public Point getLocation()
348   {
349     return new Point(x,y);
350   }
351
352   /**
353    * Moves the location of this rectangle by setting its upper left
354    * corner to the specified point.
355    *
356    * @param p the point to move the rectangle to
357    * @throws NullPointerException if p is null
358    * @see #getLocation()
359    * @since 1.1
360    */
361   public void setLocation(Point p)
362   {
363     this.x = p.x;
364     this.y = p.y;
365   }
366
367   /**
368    * Moves the location of this rectangle by setting its upper left
369    * corner to the specified coordinates.
370    *
371    * @param x the new X coordinate for this rectangle
372    * @param y the new Y coordinate for this rectangle
373    * @since 1.1
374    */
375   public void setLocation(int x, int y)
376   {
377     this.x = x;
378     this.y = y;
379   }
380
381   /**
382    * Moves the location of this rectangle by setting its upper left
383    * corner to the specified coordinates.
384    *
385    * @param x the new X coordinate for this rectangle
386    * @param y the new Y coordinate for this rectangle
387    * @deprecated use {@link #setLocation(int, int)} instead
388    */
389   public void move(int x, int y)
390   {
391     setLocation(x, y);
392   }
393
394   /**
395    * Translate the location of this rectangle by the given amounts.
396    *
397    * @param dx the x distance to move by
398    * @param dy the y distance to move by
399    * @see #setLocation(int, int)
400    */
401   public void translate(int dx, int dy)
402   {
403     x += dx;
404     y += dy;
405   }
406
407   /**
408    * Returns the size of this rectangle.
409    *
410    * @return the size of this rectangle
411    * @see #setSize(Dimension)
412    * @since 1.1
413    */
414   public Dimension getSize()
415   {
416     return new Dimension(width, height);
417   }
418
419   /**
420    * Sets the size of this rectangle based on the specified dimensions.
421    *
422    * @param d the new dimensions of the rectangle
423    * @throws NullPointerException if d is null
424    * @see #getSize()
425    * @since 1.1
426    */
427   public void setSize(Dimension d)
428   {
429     width = d.width;
430     height = d.height;
431   }
432
433   /**
434    * Sets the size of this rectangle based on the specified dimensions.
435    *
436    * @param width the new width of the rectangle
437    * @param height the new height of the rectangle
438    * @since 1.1
439    */
440   public void setSize(int width, int height)
441   {
442     this.width = width;
443     this.height = height;
444   }
445
446   /**
447    * Sets the size of this rectangle based on the specified dimensions.
448    *
449    * @param width the new width of the rectangle
450    * @param height the new height of the rectangle
451    * @deprecated use {@link #setSize(int, int)} instead
452    */
453   public void resize(int width, int height)
454   {
455     setSize(width, height);
456   }
457
458   /**
459    * Tests whether or not the specified point is inside this rectangle.
460    * According to the contract of Shape, a point on the border is in only if
461    * it has an adjacent point inside the rectangle in either the increasing
462    * x or y direction.
463    *
464    * @param p the point to test
465    * @return true if the point is inside the rectangle
466    * @throws NullPointerException if p is null
467    * @see #contains(int, int)
468    * @since 1.1
469    */
470   public boolean contains(Point p)
471   {
472     return width > 0 && height > 0
473       && p.x >= x && p.x < x + width
474       && p.y >= y && p.y < y + height;
475   }
476
477   /**
478    * Tests whether or not the specified point is inside this rectangle.
479    * According to the contract of Shape, a point on the border is in only if
480    * it has an adjacent point inside the rectangle in either the increasing
481    * x or y direction.
482    *
483    * @param x the X coordinate of the point to test
484    * @param y the Y coordinate of the point to test
485    * @return true if the point is inside the rectangle
486    * @since 1.1
487    */
488   public boolean contains(int x, int y)
489   {
490     return width > 0 && height > 0
491       && x >= this.x && x < this.x + width
492       && y >= this.y && y < this.y + height;
493   }
494
495   /**
496    * Checks whether all points in the given rectangle are contained in this
497    * rectangle.
498    *
499    * @param r the rectangle to check
500    * @return true if r is contained in this rectangle
501    * @throws NullPointerException if r is null
502    * @see #contains(int, int, int, int)
503    * @since 1.1
504    */
505   public boolean contains(Rectangle r)
506   {
507     return width > 0 && height > 0 && r.width > 0 && r.height > 0
508       && r.x >= x && r.x + r.width <= x + width
509       && r.y >= y && r.y + r.height <= y + height;
510   }
511
512   /**
513    * Checks whether all points in the given rectangle are contained in this
514    * rectangle.
515    *
516    * @param x the x coordinate of the rectangle to check
517    * @param y the y coordinate of the rectangle to check
518    * @param w the width of the rectangle to check
519    * @param h the height of the rectangle to check
520    * @return true if the parameters are contained in this rectangle
521    * @since 1.1
522    */
523   public boolean contains(int x, int y, int w, int h)
524   {
525     return width > 0 && height > 0 && w > 0 && h > 0
526       && x >= this.x && x + w <= this.x + this.width
527       && y >= this.y && y + h <= this.y + this.height;
528   }
529
530   /**
531    * Tests whether or not the specified point is inside this rectangle.
532    *
533    * @param x the X coordinate of the point to test
534    * @param y the Y coordinate of the point to test
535    * @return true if the point is inside the rectangle
536    * @deprecated use {@link #contains(int, int)} instead
537    */
538   public boolean inside(int x, int y)
539   {
540     return contains(x, y);
541   }
542
543   /**
544    * Tests whether or not the specified rectangle intersects this rectangle.
545    * This means the two rectangles share at least one internal point.
546    *
547    * @param r the rectangle to test against
548    * @return true if the specified rectangle intersects this one
549    * @throws NullPointerException if r is null
550    * @since 1.2
551    */
552   public boolean intersects(Rectangle r)
553   {
554     return width > 0 && height > 0 && r.width > 0 && r.height > 0
555       && r.x < x + width && r.x + r.width > x
556       && r.y < y + height && r.y + r.height > y;
557   }
558
559   /**
560    * Determines the rectangle which is formed by the intersection of this
561    * rectangle with the specified rectangle. If the two do not intersect,
562    * an empty rectangle will be returned (meaning the width and/or height
563    * will be non-positive).
564    *
565    * @param r the rectange to calculate the intersection with
566    * @return a new rectangle bounding the intersection
567    * @throws NullPointerException if r is null
568    */
569   public Rectangle intersection(Rectangle r)
570   {
571     Rectangle res = new Rectangle();
572     intersect(this, r, res);
573     return res;
574   }
575
576   /**
577    * Returns the smallest rectangle that contains both this rectangle
578    * and the specified rectangle.
579    *
580    * @param r the rectangle to compute the union with
581    * @return the smallest rectangle containing both rectangles
582    * @throws NullPointerException if r is null
583    */
584   public Rectangle union(Rectangle r)
585   {
586     Rectangle res = new Rectangle();
587     union(this, r, res);
588     return res;
589   }
590
591   /**
592    * Modifies this rectangle so that it represents the smallest rectangle
593    * that contains both the existing rectangle and the specified point.
594    * However, if the point falls on one of the two borders which are not
595    * inside the rectangle, a subsequent call to <code>contains</code> may
596    * return false.
597    *
598    * @param x the X coordinate of the point to add to this rectangle
599    * @param y the Y coordinate of the point to add to this rectangle
600    */
601   public void add(int x, int y)
602   {
603     add((double) x, (double) y);
604   }
605
606   /**
607    * Modifies this rectangle so that it represents the smallest rectangle
608    * that contains both the existing rectangle and the specified point.
609    * However, if the point falls on one of the two borders which are not
610    * inside the rectangle, a subsequent call to <code>contains</code> may
611    * return false.
612    *
613    * @param p the point to add to this rectangle
614    * @throws NullPointerException if p is null
615    */
616   public void add(Point p)
617   {
618     add((double) p.x, (double) p.y);
619   }
620
621   /**
622    * Modifies this rectangle so that it represents the smallest rectangle
623    * that contains both the existing rectangle and the specified rectangle.
624    *
625    * @param r the rectangle to add to this rectangle
626    * @throws NullPointerException if r is null
627    * @see #union(Rectangle)
628    */
629   public void add(Rectangle r)
630   {
631     union(this, r, this);
632   }
633
634   /**
635    * Expands the rectangle by the specified amount.  The horizontal
636    * and vertical expansion values are applied both to the X,Y coordinate
637    * of this rectangle, and its width and height.  Thus the width and
638    * height will increase by 2h and 2v accordingly.
639    *
640    * @param h the horizontal expansion value
641    * @param v the vertical expansion value
642    */
643   public void grow(int h, int v)
644   {
645     x -= h;
646     y -= v;
647     width += h + h;
648     height += v + v;
649   }
650
651   /**
652    * Tests whether or not this rectangle is empty.  An empty rectangle
653    * has a non-positive width or height.
654    *
655    * @return true if the rectangle is empty
656    */
657   public boolean isEmpty()
658   {
659     return width <= 0 || height <= 0;
660   }
661
662   /**
663    * Determine where the point lies with respect to this rectangle. The
664    * result will be the binary OR of the appropriate bit masks.
665    *
666    * @param x the x coordinate to check
667    * @param y the y coordinate to check
668    * @return the binary OR of the result
669    * @see #OUT_LEFT
670    * @see #OUT_TOP
671    * @see #OUT_RIGHT
672    * @see #OUT_BOTTOM
673    * @since 1.2
674    */
675   public int outcode(double x, double y)
676   {
677     int result = 0;
678     if (width <= 0)
679       result |= OUT_LEFT | OUT_RIGHT;
680     else if (x < this.x)
681       result |= OUT_LEFT;
682     else if (x > this.x + width)
683       result |= OUT_RIGHT;
684     if (height <= 0)
685       result |= OUT_BOTTOM | OUT_TOP;
686     else if (y < this.y) // Remember that +y heads top-to-bottom.
687       result |= OUT_TOP;
688     else if (y > this.y + height)
689       result |= OUT_BOTTOM;
690     return result;
691   }
692
693   /**
694    * Determines the rectangle which is formed by the intersection of this
695    * rectangle with the specified rectangle. If the two do not intersect,
696    * an empty rectangle will be returned (meaning the width and/or height
697    * will be non-positive).
698    *
699    * @param r the rectange to calculate the intersection with
700    * @return a new rectangle bounding the intersection
701    * @throws NullPointerException if r is null
702    * @since 1.2
703    */
704   public Rectangle2D createIntersection(Rectangle2D r)
705   {
706     // Favor runtime type of other rectangle.
707     Rectangle2D res = r.getBounds2D();
708     intersect(this, r, res);
709     return res;
710   }
711
712   /**
713    * Returns the smallest rectangle that contains both this rectangle
714    * and the specified rectangle.
715    *
716    * @param r the rectangle to compute the union with
717    * @return the smallest rectangle containing both rectangles
718    * @throws NullPointerException if r is null
719    * @since 1.2
720    */
721   public Rectangle2D createUnion(Rectangle2D r)
722   {
723     // Favor runtime type of other rectangle.
724     Rectangle2D res = r.getBounds2D();
725     union(this, r, res);
726     return res;
727   }
728
729   /**
730    * Tests this rectangle for equality against the specified object.  This
731    * will be true if an only if the specified object is an instance of
732    * Rectangle2D with the same coordinates and dimensions.
733    *
734    * @param obj the object to test against for equality
735    * @return true if the specified object is equal to this one
736    */
737   public boolean equals(Object obj)
738   {
739     if (! (obj instanceof Rectangle2D))
740       return false;
741     Rectangle2D r = (Rectangle2D) obj;
742     return r.getX() == x && r.getY() == y
743       && r.getWidth() == width && r.getHeight() == height;
744   }
745
746   /**
747    * Returns a string representation of this rectangle. This is in the form
748    * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width
749    * + ",height=" + height + ']'</code>.
750    *
751    * @return a string representation of this rectangle
752    */
753   public String toString()
754   {
755     return getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width
756       + ",height=" + height + ']';
757   }
758 } // class Rectangle