| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * |
| * Licensed under the Eclipse Public License, Version 1.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.eclipse.org/org/documents/epl-v10.php |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.ide.common.api; |
| |
| import com.android.annotations.NonNull; |
| import com.android.annotations.Nullable; |
| import com.google.common.annotations.Beta; |
| |
| |
| /** |
| * Mutable rectangle bounds. |
| * <p/> |
| * To be valid, w >= 1 and h >= 1. |
| * By definition: |
| * - right side = x + w - 1. |
| * - bottom side = y + h - 1. |
| * <p> |
| * <b>NOTE: This is not a public or final API; if you rely on this be prepared |
| * to adjust your code for the next tools release.</b> |
| * </p> |
| */ |
| @Beta |
| public class Rect { |
| public int x, y, w, h; |
| |
| /** Initialize an invalid rectangle. */ |
| public Rect() { |
| } |
| |
| /** Initialize rectangle to the given values. They can be invalid. */ |
| public Rect(int x, int y, int w, int h) { |
| set(x, y, w, h); |
| } |
| |
| /** Initialize rectangle to the given values. They can be invalid. */ |
| public Rect(@NonNull Rect r) { |
| set(r); |
| } |
| |
| /** Initialize rectangle to the given values. They can be invalid. */ |
| @NonNull |
| public Rect set(int x, int y, int w, int h) { |
| this.x = x; |
| this.y = y; |
| this.w = w; |
| this.h = h; |
| return this; |
| } |
| |
| /** Initialize rectangle to match the given one. */ |
| @NonNull |
| public Rect set(@NonNull Rect r) { |
| set(r.x, r.y, r.w, r.h); |
| return this; |
| } |
| |
| /** Returns a new instance of a rectangle with the same values. */ |
| @NonNull |
| public Rect copy() { |
| return new Rect(x, y, w, h); |
| } |
| |
| /** Returns true if the rectangle has valid bounds, i.e. w>0 and h>0. */ |
| public boolean isValid() { |
| return w > 0 && h > 0; |
| } |
| |
| /** Returns true if the rectangle contains the x,y coordinates, borders included. */ |
| public boolean contains(int x, int y) { |
| return isValid() |
| && x >= this.x |
| && y >= this.y |
| && x < (this.x + this.w) |
| && y < (this.y + this.h); |
| } |
| |
| /** |
| * Returns true if this rectangle intersects the given rectangle. |
| * Two rectangles intersect if they overlap. |
| * @param other the other rectangle to test |
| * @return true if the two rectangles overlap |
| */ |
| public boolean intersects(@Nullable Rect other) { |
| if (other == null) { |
| return false; |
| } |
| if (x2() <= other.x |
| || other.x2() <= x |
| || y2() <= other.y |
| || other.y2() <= y) { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /** Returns true if the rectangle fully contains the given rectangle */ |
| public boolean contains(@Nullable Rect rect) { |
| return rect != null && x <= rect.x |
| && y <= rect.y |
| && x2() >= rect.x2() |
| && y2() >= rect.y2(); |
| } |
| |
| /** Returns true if the rectangle contains the x,y coordinates, borders included. */ |
| public boolean contains(@Nullable Point p) { |
| return p != null && contains(p.x, p.y); |
| } |
| |
| /** |
| * Moves this rectangle by setting it's x,y coordinates to the new values. |
| * @return Returns self, for chaining. |
| */ |
| @NonNull |
| public Rect moveTo(int x, int y) { |
| this.x = x; |
| this.y = y; |
| return this; |
| } |
| |
| /** |
| * Offsets this rectangle by adding the given x,y deltas to the x,y coordinates. |
| * @return Returns self, for chaining. |
| */ |
| @NonNull |
| public Rect offsetBy(int x, int y) { |
| this.x += x; |
| this.y += y; |
| return this; |
| } |
| |
| @NonNull |
| public Point getCenter() { |
| return new Point(x + (w > 0 ? w / 2 : 0), |
| y + (h > 0 ? h / 2 : 0)); |
| } |
| |
| @NonNull |
| public Point getTopLeft() { |
| return new Point(x, y); |
| } |
| |
| @NonNull |
| public Point getBottomLeft() { |
| return new Point(x, |
| y + (h > 0 ? h : 0)); |
| } |
| |
| @NonNull |
| public Point getTopRight() { |
| return new Point(x + (w > 0 ? w : 0), |
| y); |
| } |
| |
| @NonNull |
| public Point getBottomRight() { |
| return new Point(x + (w > 0 ? w : 0), |
| y + (h > 0 ? h : 0)); |
| } |
| |
| /** |
| * Returns the X coordinate of the right hand side of the rectangle |
| * |
| * @return the X coordinate of the right hand side of the rectangle |
| */ |
| public int x2() { |
| return x + w; |
| } |
| |
| /** |
| * Returns the Y coordinate of the bottom of the rectangle |
| * |
| * @return the Y coordinate of the bottom of the rectangle |
| */ |
| public int y2() { |
| return y + h; |
| } |
| |
| /** |
| * Returns the X coordinate of the center of the rectangle |
| * |
| * @return the X coordinate of the center of the rectangle |
| */ |
| public int centerX() { |
| return x + w / 2; |
| } |
| |
| /** |
| * Returns the Y coordinate of the center of the rectangle |
| * |
| * @return the Y coordinate of the center of the rectangle |
| */ |
| public int centerY() { |
| return y + h / 2; |
| } |
| |
| @Override |
| public String toString() { |
| return String.format("Rect [(%d,%d)-(%d,%d): %dx%d]", x, y, x + w, y + h, w, h); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (obj instanceof Rect) { |
| Rect rhs = (Rect) obj; |
| // validity must be equal on both sides. |
| if (isValid() != rhs.isValid()) { |
| return false; |
| } |
| // an invalid rect is equal to any other invalid rect regardless of coordinates |
| if (!isValid() && !rhs.isValid()) { |
| return true; |
| } |
| |
| return this.x == rhs.x && this.y == rhs.y && this.w == rhs.w && this.h == rhs.h; |
| } |
| |
| return false; |
| } |
| |
| @Override |
| public int hashCode() { |
| int hc = x; |
| hc ^= ((y >> 8) & 0x0FFFFFF) | ((y & 0x00000FF) << 24); |
| hc ^= ((w >> 16) & 0x000FFFF) | ((w & 0x000FFFF) << 16); |
| hc ^= ((h >> 24) & 0x00000FF) | ((h & 0x0FFFFFF) << 8); |
| return hc; |
| } |
| |
| /** |
| * Returns the center point in the rectangle |
| * |
| * @return the center point in the rectangle |
| */ |
| @NonNull |
| public Point center() { |
| return new Point(x + w / 2, y + h / 2); |
| } |
| } |