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