1 /** 2 * Module for space and dimension manipulation. 3 * 4 * Authors: 5 * Jacob Jensen 6 * License: 7 * https://github.com/PoisonEngine/poison-ui/blob/master/LICENSE 8 */ 9 module poison.ui.space; 10 11 import poison.core : Point, Size, Edge, Location, EventObserver, ChangeEventArgs; 12 13 /// A wrapper around a space. 14 class Space : EventObserver { 15 private: 16 /// The position. 17 Point _position; 18 19 /// The size. 20 Size _size; 21 22 /// The margin. 23 Edge _margin; 24 25 /// The padding. 26 Edge _padding; 27 28 public: 29 /** 30 * Creates a new space. 31 * Params: 32 * position = The position. 33 * size = The size. 34 */ 35 this(Point position, Size size) { 36 assert(position !is null); 37 assert(size !is null); 38 39 _position = position; 40 _size = size; 41 42 _margin = new Edge(0,0,0,0); 43 _padding = new Edge(0,0,0,0); 44 } 45 46 @property { 47 /// Gets the position of the space. 48 Point position() { return _position; } 49 50 /// Sets the position of the space. 51 void position(Point newPosition) { 52 auto oldPosition = _position; 53 _position = newPosition; 54 55 fireEvent("position", new ChangeEventArgs!Point(oldPosition, _position)); 56 } 57 58 /// Gets the x coordinate of the space. 59 ptrdiff_t x() { return _position.x; } 60 61 /// Gets the y coordinate of the space. 62 ptrdiff_t y() { return _position.y; } 63 64 /// Gets the size of the space. 65 Size size() { return _size; } 66 67 /// Sets the size of the space. 68 void size(Size newSize) { 69 auto oldSize = _size; 70 _size = newSize; 71 72 fireEvent("size", new ChangeEventArgs!Size(oldSize, _size)); 73 } 74 75 /// Gets the width of the space. 76 size_t width() { return _size.width; } 77 78 /// Gets the height of the space. 79 size_t height() { return _size.height; } 80 81 /// Gets the margin of the space. 82 Edge margin() { return _margin; } 83 84 /// Sets the margin of the space. 85 void margin(Edge newMargin) { 86 auto oldMargin = _margin; 87 _margin = newMargin; 88 89 fireEvent("margin", new ChangeEventArgs!Edge(oldMargin, _margin)); 90 } 91 92 /// Gets the top margin of the space. 93 ptrdiff_t marginTop() { return _margin.top; } 94 95 /// Gets the right margin of the space. 96 ptrdiff_t marginRight() { return _margin.right; } 97 98 /// Gets the bottom margin of the space. 99 ptrdiff_t marginBottom() { return _margin.bottom; } 100 101 /// Gets the left margin of the space. 102 ptrdiff_t marginLeft() { return _margin.left; } 103 104 /// Gets the padding of the space. 105 Edge padding() { return _padding; } 106 107 /// Sets the padding of the space. 108 void padding(Edge newPadding) { 109 auto oldPadding = _padding; 110 _padding = newPadding; 111 112 fireEvent("padding", new ChangeEventArgs!Edge(oldPadding, _padding)); 113 } 114 115 /// Gets the top padding of the space. 116 ptrdiff_t paddingTop() { return _padding.top; } 117 118 /// Gets the right padding of the space. 119 ptrdiff_t paddingRight() { return _padding.right; } 120 121 /// Gets the bottom padding of the space. 122 ptrdiff_t paddingBottom() { return _padding.bottom; } 123 124 /// Gets the left padding of the space. 125 ptrdiff_t paddingLeft() { return _padding.left; } 126 } 127 128 /** 129 * Moves the space to another space. 130 * Params: 131 * target = The target of the space. 132 */ 133 void moveTo(Location location)(Space target) { 134 assert(target !is null); 135 136 auto newX = target.x; 137 auto newY = target.y; 138 139 static if (location == Location.northWest) { 140 newX -= width + target.marginLeft; 141 newY -= height + target.marginTop; 142 } 143 else static if (location == Location.north) { 144 newX += (target.width / 2) - (width / 2); 145 newY -= height + target.marginTop; 146 } 147 else static if (location == Location.northEast) { 148 newX += target.width + target.marginRight; 149 newY -= height + target.marginTop; 150 } 151 else static if (location == Location.east) { 152 newX += target.width + target.marginRight; 153 newY += (target.height / 2) - (height / 2); 154 } 155 else static if (location == Location.southEast) { 156 newX += target.width + target.marginRight; 157 newY += target.height + target.marginBottom; 158 } 159 else static if (location == Location.south) { 160 newX += (target.width / 2) - (width / 2); 161 newY += target.height + target.marginBottom; 162 } 163 else static if (location == Location.southWest) { 164 newX -= width + target.marginLeft; 165 newY += target.height + target.marginBottom; 166 } 167 else static if (location == Location.west) { 168 newX -= width + target.marginLeft; 169 newY += (target.height / 2) - (height / 2); 170 } 171 else { 172 static assert(0); 173 } 174 175 position = new Point(newX, newY); 176 } 177 178 /** 179 * Moves the space into another space. 180 * Params: 181 * target = The space to move the space into. 182 */ 183 void moveIn(Location location)(Space target) { 184 assert(target !is null); 185 186 auto newX = target.x; 187 auto newY = target.y; 188 189 static if (location == Location.northWest) { 190 newX += target.paddingLeft; 191 newY += target.paddingTop; 192 } 193 else static if (location == Location.north) { 194 newX += (target.width / 2) - (width / 2); 195 newY += target.paddingTop; 196 } 197 else static if (location == Location.northEast) { 198 newX += target.width - (target.paddingRight + width); 199 newY += target.paddingTop; 200 } 201 else static if (location == Location.east) { 202 newX += target.width - (target.paddingRight + width); 203 newY += (target.height / 2) - (height / 2); 204 } 205 else static if (location == Location.southEast) { 206 newX += target.width - (target.paddingRight + width); 207 newY += target.height - (target.paddingBottom + height); 208 } 209 else static if (location == Location.south) { 210 newX += (target.width / 2) - (width / 2); 211 newY += target.height - (target.paddingBottom + height); 212 } 213 else static if (location == Location.southWest) { 214 newX += target.paddingLeft; 215 newY += target.height - (target.paddingBottom + height); 216 } 217 else static if (location == Location.west) { 218 newX += target.paddingLeft; 219 newY += (target.height / 2) - (height / 2); 220 } 221 else { 222 static assert(0); 223 } 224 225 position = new Point(newX, newY); 226 } 227 228 /** 229 * Centers the x coordinate of the space relative to another space. 230 * Params: 231 * target = The target to be relative to. 232 */ 233 void centerX(Space target) { 234 position = new Point((target.width / 2) - (width / 2), y); 235 } 236 237 /** 238 * Centers the y coordinate of the space relative to another space. 239 * Params: 240 * target = The target to be relative to. 241 */ 242 void centerY(Space target) { 243 position = new Point(x, (target.height / 2) - (height / 2)); 244 } 245 246 /** 247 * Centers the space relative to another space. 248 * Params: 249 * target = The target to be relative to. 250 */ 251 void center(Space target) { 252 position = new Point((target.width / 2) - (width / 2), (target.height / 2) - (height / 2)); 253 } 254 255 void moveX(ptrdiff_t amount) { 256 position = new Point(x + amount, y); 257 } 258 259 void moveY(ptrdiff_t amount) { 260 position = new Point(x, y + amount); 261 } 262 263 /** 264 * Checks whether the space intersects with a point. 265 * Params: 266 * p = The point to check for intersection with. 267 * Returns: 268 * If the space intersects with the point. 269 */ 270 bool intersect(Point p) { 271 return (p.x > this.x) && 272 (p.x < (this.x + cast(ptrdiff_t)this.width)) && 273 (p.y > this.y) && 274 (p.y < (this.y + cast(ptrdiff_t)this.height)); 275 } 276 277 /** 278 * Checks whether the space intersects with another space. 279 * Params: 280 * target = The space to check for intersection with. 281 * Returns: 282 * True if the two spaces intersects. 283 */ 284 bool intersect(Space target) { 285 return(target.x < this.x + cast(ptrdiff_t)this.width) && 286 (this.x < (target.x + cast(ptrdiff_t)target.width)) && 287 (target.y < this.y + cast(ptrdiff_t)this.height) && 288 (this.y < target.y + cast(ptrdiff_t)target.height); 289 } 290 }