1Rect { 2 var <>left=0, <>top=0, <>width=0, <>height=0; 3 4 *new { arg left=0, top=0, width=0, height=0; 5 ^super.newCopyArgs(left, top, width, height) 6 } 7 *newSides { arg left=0, top=0, right=0, bottom=0; 8 ^super.newCopyArgs(left, top, right-left, bottom-top) 9 } 10 *fromPoints { arg pt1, pt2; 11 ^super.newCopyArgs( 12 pt1.x min: pt2.x, 13 pt1.y min: pt2.y, 14 absdif(pt1.x, pt2.x), 15 absdif(pt1.y, pt2.y) 16 ) 17 } 18 *fromRect { arg rect; 19 ^this.new(rect.left, rect.top, rect.width, rect.height) 20 } 21 *fromArray {|array| 22 ^this.new(*array) 23 } 24 *aboutPoint { arg point, dx, dy; 25 ^this.new(point.x-dx, point.y-dy, 2*dx, 2*dy) 26 } 27 28 set { arg argLeft=0, argTop=0, argWidth=0, argHeight=0; 29 left = argLeft; 30 top = argTop; 31 width = argWidth; 32 height = argHeight; 33 } 34 setExtent { arg argWidth=0, argHeight=0; 35 width = argWidth; 36 height = argHeight; 37 } 38 39 origin { ^Point.new(left, top) } 40 origin_ { | pt | left = pt.x; top = pt.y } 41 extent { ^Point.new(width, height) } 42 extent_ { | pt | width = pt.x; height = pt.y } 43 center { ^Point.new(left + (width * 0.5), top + (height * 0.5)) } 44 center_ { arg center; ^this.class.aboutPoint(center, width * 0.5, height * 0.5) } 45 46 bottom { ^top + height } 47 bottom_ { |b| top = top - (this.bottom - b) } 48 right { ^left + width } 49 right_ { |r| left = left - (this.right - r) } 50 51 leftTop { ^Point.new(this.left, this.top) } 52 rightTop { ^Point.new(this.right, this.top) } 53 leftBottom { ^Point.new(this.left, this.bottom) } 54 rightBottom { ^Point.new(this.right, this.bottom) } 55 56 size { ^Size(width,height) } 57 size_ { |sz| width = sz.width; height = sz.height } 58 59 moveBy { arg h, v; 60 ^this.class.new(left + h, top + v, width, height) 61 } 62 moveTo { arg h, v; 63 ^this.class.new(h, v, width, height) 64 } 65 moveToPoint { arg aPoint; 66 ^this.class.new(aPoint.x, aPoint.y, width, height) 67 } 68 resizeBy { arg h, v; 69 ^this.class.new(left, top, width + h, height + (v ? h)) 70 } 71 resizeTo { arg h, v; 72 ^this.class.new(left, top, h, v) 73 } 74 insetBy { arg h, v; 75 if(v.isNil){ v = h }; 76 ^this.class.new(left + h, top + v, width - h - h, height - v - v) 77 } 78 insetAll { arg a, b, c, d; 79 ^this.class.new(left + a, top + b, width - a - c, height - b - d) 80 } 81 insetByRect { arg r; 82 ^this.copy.insetAll(r.left, r.top, r.right, r.bottom) 83 } 84 centerSquare { 85 var pos, center; 86 if (width > height, { 87 pos = (width - height) * 0.5 + left; 88 ^Rect(pos, top, height, height) 89 },{ 90 pos = (height - width) * 0.5 + top; 91 ^Rect(left, pos, width, width) 92 }); 93 } 94 centerIn { arg inRect; 95 var pos, spacing; 96 spacing = (inRect.extent - this.extent) * 0.5; 97 ^inRect.origin - this.origin + spacing; 98 } 99 100 contains{ arg anObject; 101 if ( anObject.isKindOf( Point ), 102 { ^this.containsPoint( anObject ) }); 103 if ( anObject.isKindOf( Rect ), 104 { ^this.containsRect( anObject ) }); 105 ^false; 106 } 107 108 containsPoint { arg aPoint; 109 ^(aPoint.x.inclusivelyBetween(left, left + width) 110 and: { aPoint.y.inclusivelyBetween(top, top + height) }) 111 } 112 containsRect { arg aRect; 113 ^(this.containsPoint(aRect.leftTop) and: {this.containsPoint(aRect.rightBottom) }) 114 } 115 intersects { arg aRect; 116 if (aRect.right <= this.left, { ^false }); 117 if (aRect.bottom <= this.top, { ^false }); 118 if (aRect.left >= this.right, { ^false }); 119 if (aRect.top >= this.bottom, { ^false }); 120 ^true 121 } 122 123 & { arg aRect; ^this sect: aRect } 124 | { arg aRect; ^this union: aRect } 125 126 union { arg aRect; 127 ^this.class.newSides( left min: aRect.left, top min: aRect.top, 128 this.right max: aRect.right, this.bottom max: aRect.bottom) 129 } 130 sect { arg aRect; 131 ^this.class.newSides( left max: aRect.left, top max: aRect.top, 132 this.right min: aRect.right, this.bottom min: aRect.bottom) 133 } 134 storeArgs { ^[left,top,width,height] } 135 printOn { arg stream; 136 stream << this.class.name << "(" <<* [left, top, width, height] << ")"; 137 } 138 139 // the drawing routine here use Quickdraw. 140 // If you want CoreGraphics drawing, use methods in Pen. 141 draw { arg color, operation=2; 142 _Rect_Draw 143 ^this.primitiveFailed 144 } 145 146 asRect { ^this } 147 bounds { ^Rect.new(left, top, width, height) } 148 == { arg that; 149 ^this.compareObject(that, #[\left, \top, \width, \height]) 150 } 151 hash { 152 ^this.instVarHash(#[\left, \top, \width, \height]) 153 } 154 155 // deprec 156 layout { arg argBounds; 157 this.set(argBounds.left, argBounds.top, argBounds.width, argBounds.height); 158 } 159 160 asArray { ^[this.left, this.top, this.width, this.height] } 161 162 performBinaryOpOnSomething { |aSelector, thing, adverb| 163 ^thing.asRect.perform(aSelector, this, adverb) 164 } 165 + {|that| 166 var thatRect; 167 thatRect = that.asRect; 168 169 ^Rect( 170 this.left + thatRect.left, 171 this.top + thatRect.top, 172 this.width + thatRect.width, 173 this.height + thatRect.height 174 ) 175 } 176 - {|that| 177 var thatRect; 178 thatRect = that.asRect; 179 180 ^Rect( 181 this.left - thatRect.left, 182 this.top - thatRect.top, 183 this.width - thatRect.width, 184 this.height - thatRect.height 185 ) 186 } 187} 188