Rect.java revision 3db9393ba06bbf70fa7b4a6db1ef60396979a1d4
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Eclipse Public License, Version 1.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.eclipse.org/org/documents/epl-v10.php
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.ide.common.api;
18
19import com.google.common.annotations.Beta;
20
21
22
23/**
24 * Mutable rectangle bounds.
25 * <p/>
26 * To be valid, w >= 1 and h >= 1.
27 * By definition:
28 * - right side = x + w - 1.
29 * - bottom side = y + h - 1.
30 * <p>
31 * <b>NOTE: This is not a public or final API; if you rely on this be prepared
32 * to adjust your code for the next tools release.</b>
33 * </p>
34 */
35@Beta
36public class Rect {
37    public int x, y, w, h;
38
39    /** Initialize an invalid rectangle. */
40    public Rect() {
41    }
42
43    /** Initialize rectangle to the given values. They can be invalid. */
44    public Rect(int x, int y, int w, int h) {
45        set(x, y, w, h);
46    }
47
48    /** Initialize rectangle to the given values. They can be invalid. */
49    public Rect(Rect r) {
50        set(r);
51    }
52
53    /** Initialize rectangle to the given values. They can be invalid. */
54    public Rect set(int x, int y, int w, int h) {
55        this.x = x;
56        this.y = y;
57        this.w = w;
58        this.h = h;
59        return this;
60    }
61
62    /** Initialize rectangle to match the given one. */
63    public Rect set(Rect r) {
64        set(r.x, r.y, r.w, r.h);
65        return this;
66    }
67
68    /** Returns a new instance of a rectangle with the same values. */
69    public Rect copy() {
70        return new Rect(x, y, w, h);
71    }
72
73    /** Returns true if the rectangle has valid bounds, i.e. w>0 and h>0. */
74    public boolean isValid() {
75        return w > 0 && h > 0;
76    }
77
78    /** Returns true if the rectangle contains the x,y coordinates, borders included. */
79    public boolean contains(int x, int y) {
80        return isValid() &&
81            x >= this.x &&
82            y >= this.y &&
83            x < (this.x + this.w) &&
84            y < (this.y + this.h);
85    }
86
87    /** Returns true if the rectangle contains the x,y coordinates, borders included. */
88    public boolean contains(Point p) {
89        return p != null && contains(p.x, p.y);
90    }
91
92    /**
93     * Moves this rectangle by setting it's x,y coordinates to the new values.
94     * @return Returns self, for chaining.
95     */
96    public Rect moveTo(int x, int y) {
97        this.x = x;
98        this.y = y;
99        return this;
100    }
101
102    /**
103     * Offsets this rectangle by adding the given x,y deltas to the x,y coordinates.
104     * @return Returns self, for chaining.
105     */
106    public Rect offsetBy(int x, int y) {
107        this.x += x;
108        this.y += y;
109        return this;
110    }
111
112    public Point getCenter() {
113        return new Point(x + (w > 0 ? w / 2 : 0),
114                         y + (h > 0 ? h / 2 : 0));
115    }
116
117    public Point getTopLeft() {
118        return new Point(x, y);
119    }
120
121    public Point getBottomLeft() {
122        return new Point(x,
123                         y + (h > 0 ? h : 0));
124    }
125
126    public Point getTopRight() {
127        return new Point(x + (w > 0 ? w : 0),
128                         y);
129    }
130
131    public Point getBottomRight() {
132        return new Point(x + (w > 0 ? w : 0),
133                         y + (h > 0 ? h : 0));
134    }
135
136    /**
137     * Returns the X coordinate of the right hand side of the rectangle
138     *
139     * @return the X coordinate of the right hand side of the rectangle
140     */
141    public int x2() {
142        return x + w;
143    }
144
145    /**
146     * Returns the Y coordinate of the bottom of the rectangle
147     *
148     * @return the Y coordinate of the bottom of the rectangle
149     */
150    public int y2() {
151        return y + h;
152    }
153
154    /**
155     * Returns the X coordinate of the center of the rectangle
156     *
157     * @return the X coordinate of the center of the rectangle
158     */
159    public int centerX() {
160        return x + w / 2;
161    }
162
163    /**
164     * Returns the Y coordinate of the center of the rectangle
165     *
166     * @return the Y coordinate of the center of the rectangle
167     */
168    public int centerY() {
169        return y + h / 2;
170    }
171
172    @Override
173    public String toString() {
174        return String.format("Rect [(%d,%d)-(%d,%d): %dx%d]", x, y, x + w, y + h, w, h);
175    }
176
177    @Override
178    public boolean equals(Object obj) {
179        if (obj instanceof Rect) {
180            Rect rhs = (Rect) obj;
181            // validity must be equal on both sides.
182            if (isValid() != rhs.isValid()) {
183                return false;
184            }
185            // an invalid rect is equal to any other invalid rect regardless of coordinates
186            if (!isValid() && !rhs.isValid()) {
187                return true;
188            }
189
190            return this.x == rhs.x && this.y == rhs.y && this.w == rhs.w && this.h == rhs.h;
191        }
192
193        return false;
194    }
195
196    @Override
197    public int hashCode() {
198        int hc = x;
199        hc ^= ((y >>  8) & 0x0FFFFFF) | ((y & 0x00000FF) << 24);
200        hc ^= ((w >> 16) & 0x000FFFF) | ((w & 0x000FFFF) << 16);
201        hc ^= ((h >> 24) & 0x00000FF) | ((h & 0x0FFFFFF) <<  8);
202        return hc;
203    }
204
205    /**
206     * Returns the center point in the rectangle
207     *
208     * @return the center point in the rectangle
209     */
210    public Point center() {
211        return new Point(x + w / 2, y + h / 2);
212    }
213}
214