1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 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 org.eclipse.swt.graphics.Rectangle;
14 
15 import java.lang.all;
16 
17 public import org.eclipse.swt.graphics.Point;
18 public import org.eclipse.swt.internal.SerializableCompatibility;
19 
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.SWTError;
22 
23 /**
24  * Instances of this class represent rectangular areas in an
25  * (x, y) coordinate system. The top left corner of the rectangle
26  * is specified by its x and y values, and the extent of the
27  * rectangle is specified by its width and height.
28  * <p>
29  * The coordinate space for rectangles and points is considered
30  * to have increasing values downward and to the right from its
31  * origin making this the normal, computer graphics oriented notion
32  * of (x, y) coordinates rather than the strict mathematical one.
33  * </p>
34  * <p>
35  * The hashCode() method in this class uses the values of the public
36  * fields to compute the hash value. When storing instances of the
37  * class in hashed collections, do not modify these fields after the
38  * object has been inserted.
39  * </p>
40  * <p>
41  * Application code does <em>not</em> need to explicitly release the
42  * resources managed by each instance when those instances are no longer
43  * required, and thus no <code>dispose()</code> method is provided.
44  * </p>
45  *
46  * @see Point
47  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
48  */
49 
50 public final class Rectangle : SerializableCompatibility {
51 
52     /**
53      * the x coordinate of the rectangle
54      */
55     public int x;
56 
57     /**
58      * the y coordinate of the rectangle
59      */
60     public int y;
61 
62     /**
63      * the width of the rectangle
64      */
65     public int width;
66 
67     /**
68      * the height of the rectangle
69      */
70     public int height;
71 
72     //static final long serialVersionUID = 3256439218279428914L;
73 
74 /**
75  * Construct a new instance of this class given the
76  * x, y, width and height values.
77  *
78  * @param x the x coordinate of the origin of the rectangle
79  * @param y the y coordinate of the origin of the rectangle
80  * @param width the width of the rectangle
81  * @param height the height of the rectangle
82  */
83 public this (int x, int y, int width, int height) {
84     this.x = x;
85     this.y = y;
86     this.width = width;
87     this.height = height;
88 }
89 
90 /**
91  * Destructively replaces the x, y, width and height values
92  * in the receiver with ones which represent the union of the
93  * rectangles specified by the receiver and the given rectangle.
94  * <p>
95  * The union of two rectangles is the smallest single rectangle
96  * that completely covers both of the areas covered by the two
97  * given rectangles.
98  * </p>
99  *
100  * @param rect the rectangle to merge with the receiver
101  *
102  * @exception IllegalArgumentException <ul>
103  *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
104  * </ul>
105  */
106 public void add (Rectangle rect) {
107     if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
108     int left = x < rect.x ? x : rect.x;
109     int top = y < rect.y ? y : rect.y;
110     int lhs = x + width;
111     int rhs = rect.x + rect.width;
112     int right = lhs > rhs ? lhs : rhs;
113     lhs = y + height;
114     rhs = rect.y + rect.height;
115     int bottom = lhs > rhs ? lhs : rhs;
116     x = left;  y = top;  width = right - left;  height = bottom - top;
117 }
118 
119 /**
120  * Returns <code>true</code> if the point specified by the
121  * arguments is inside the area specified by the receiver,
122  * and <code>false</code> otherwise.
123  *
124  * @param x the x coordinate of the point to test for containment
125  * @param y the y coordinate of the point to test for containment
126  * @return <code>true</code> if the rectangle contains the point and <code>false</code> otherwise
127  */
128 public bool contains (int x, int y) {
129     return (x >= this.x) && (y >= this.y) && ((x - this.x) < width) && ((y - this.y) < height);
130 }
131 
132 /**
133  * Returns <code>true</code> if the given point is inside the
134  * area specified by the receiver, and <code>false</code>
135  * otherwise.
136  *
137  * @param pt the point to test for containment
138  * @return <code>true</code> if the rectangle contains the point and <code>false</code> otherwise
139  *
140  * @exception IllegalArgumentException <ul>
141  *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
142  * </ul>
143  */
144 public bool contains (Point pt) {
145     if (pt is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
146     return contains(pt.x, pt.y);
147 }
148 
149 /**
150  * Compares the argument to the receiver, and returns true
151  * if they represent the <em>same</em> object using a class
152  * specific comparison.
153  *
154  * @param object the object to compare with this object
155  * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
156  *
157  * @see #hashCode()
158  */
159 public override equals_t opEquals (Object object) {
160     if (object is this) return true;
161     if( auto r = cast(Rectangle) object ){
162         return (r.x is this.x) && (r.y is this.y) && (r.width is this.width) && (r.height is this.height);
163     }
164     return false;
165 }
166 
167 /**
168  * Returns an integer hash code for the receiver. Any two
169  * objects that return <code>true</code> when passed to
170  * <code>equals</code> must return the same value for this
171  * method.
172  *
173  * @return the receiver's hash
174  *
175  * @see #equals(Object)
176  */
177 public override hash_t toHash () {
178     return x ^ y ^ width ^ height;
179 }
180 
181 /**
182  * Destructively replaces the x, y, width and height values
183  * in the receiver with ones which represent the intersection of the
184  * rectangles specified by the receiver and the given rectangle.
185  *
186  * @param rect the rectangle to intersect with the receiver
187  *
188  * @exception IllegalArgumentException <ul>
189  *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
190  * </ul>
191  *
192  * since 3.0
193  */
194 public void intersect (Rectangle rect) {
195     if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
196     if (this is rect) return;
197     int left = x > rect.x ? x : rect.x;
198     int top = y > rect.y ? y : rect.y;
199     int lhs = x + width;
200     int rhs = rect.x + rect.width;
201     int right = lhs < rhs ? lhs : rhs;
202     lhs = y + height;
203     rhs = rect.y + rect.height;
204     int bottom = lhs < rhs ? lhs : rhs;
205     x = right < left ? 0 : left;
206     y = bottom < top ? 0 : top;
207     width = right < left ? 0 : right - left;
208     height = bottom < top ? 0 : bottom - top;
209 }
210 
211 /**
212  * Returns a new rectangle which represents the intersection
213  * of the receiver and the given rectangle.
214  * <p>
215  * The intersection of two rectangles is the rectangle that
216  * covers the area which is contained within both rectangles.
217  * </p>
218  *
219  * @param rect the rectangle to intersect with the receiver
220  * @return the intersection of the receiver and the argument
221  *
222  * @exception IllegalArgumentException <ul>
223  *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
224  * </ul>
225  */
226 public Rectangle intersection (Rectangle rect) {
227     if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
228     if (this is rect) return new Rectangle (x, y, width, height);
229     int left = x > rect.x ? x : rect.x;
230     int top = y > rect.y ? y : rect.y;
231     int lhs = x + width;
232     int rhs = rect.x + rect.width;
233     int right = lhs < rhs ? lhs : rhs;
234     lhs = y + height;
235     rhs = rect.y + rect.height;
236     int bottom = lhs < rhs ? lhs : rhs;
237     return new Rectangle (
238         right < left ? 0 : left,
239         bottom < top ? 0 : top,
240         right < left ? 0 : right - left,
241         bottom < top ? 0 : bottom - top);
242 }
243 
244 /**
245  * Returns <code>true</code> if the rectangle described by the
246  * arguments intersects with the receiver and <code>false</code>
247  * otherwise.
248  * <p>
249  * Two rectangles intersect if the area of the rectangle
250  * representing their intersection is not empty.
251  * </p>
252  *
253  * @param x the x coordinate of the origin of the rectangle
254  * @param y the y coordinate of the origin of the rectangle
255  * @param width the width of the rectangle
256  * @param height the height of the rectangle
257  * @return <code>true</code> if the rectangle intersects with the receiver, and <code>false</code> otherwise
258  *
259  * @exception IllegalArgumentException <ul>
260  *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
261  * </ul>
262  *
263  * @see #intersection(Rectangle)
264  * @see #isEmpty()
265  *
266  * @since 3.0
267  */
268 public bool intersects (int x, int y, int width, int height) {
269     return (x < this.x + this.width) && (y < this.y + this.height) &&
270         (x + width > this.x) && (y + height > this.y);
271 }
272 
273 /**
274  * Returns <code>true</code> if the given rectangle intersects
275  * with the receiver and <code>false</code> otherwise.
276  * <p>
277  * Two rectangles intersect if the area of the rectangle
278  * representing their intersection is not empty.
279  * </p>
280  *
281  * @param rect the rectangle to test for intersection
282  * @return <code>true</code> if the rectangle intersects with the receiver, and <code>false</code> otherwise
283  *
284  * @exception IllegalArgumentException <ul>
285  *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
286  * </ul>
287  *
288  * @see #intersection(Rectangle)
289  * @see #isEmpty()
290  */
291 public bool intersects (Rectangle rect) {
292     if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
293     return rect is this || intersects (rect.x, rect.y, rect.width, rect.height);
294 }
295 
296 /**
297  * Returns <code>true</code> if the receiver does not cover any
298  * area in the (x, y) coordinate plane, and <code>false</code> if
299  * the receiver does cover some area in the plane.
300  * <p>
301  * A rectangle is considered to <em>cover area</em> in the
302  * (x, y) coordinate plane if both its width and height are
303  * non-zero.
304  * </p>
305  *
306  * @return <code>true</code> if the receiver is empty, and <code>false</code> otherwise
307  */
308 public bool isEmpty () {
309     return (width <= 0) || (height <= 0);
310 }
311 
312 /**
313  * Returns a string containing a concise, human-readable
314  * description of the receiver.
315  *
316  * @return a string representation of the rectangle
317  */
318 public override String toString () {
319     return Format( "Rectangle {{{}, {}, {}, {}}", x, y, width, height ); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
320 }
321 
322 /**
323  * Returns a new rectangle which represents the union of
324  * the receiver and the given rectangle.
325  * <p>
326  * The union of two rectangles is the smallest single rectangle
327  * that completely covers both of the areas covered by the two
328  * given rectangles.
329  * </p>
330  *
331  * @param rect the rectangle to perform union with
332  * @return the union of the receiver and the argument
333  *
334  * @exception IllegalArgumentException <ul>
335  *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
336  * </ul>
337  *
338  * @see #add(Rectangle)
339  */
340 public Rectangle makeUnion (Rectangle rect) {
341     if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
342     int left = x < rect.x ? x : rect.x;
343     int top = y < rect.y ? y : rect.y;
344     int lhs = x + width;
345     int rhs = rect.x + rect.width;
346     int right = lhs > rhs ? lhs : rhs;
347     lhs = y + height;
348     rhs = rect.y + rect.height;
349     int bottom = lhs > rhs ? lhs : rhs;
350     return new Rectangle (left, top, right - left, bottom - top);
351 }
352 
353 }