1 module des.gui.shape; 2 3 import des.gui.base; 4 5 /// 6 interface DiShape 7 { 8 @property 9 { 10 /// bounding box of area 11 DiRect rect() const; 12 13 /// 14 DiRect rect( in DiRect ); 15 } 16 17 /// 18 bool contains( in DiVec ) const; 19 /// 20 bool contains( in DiRect ) const; 21 22 /// 23 bool intersect( in DiRect ) const; 24 25 final @property 26 { 27 DiVec pos() const { return rect.pos; } 28 DiVec size() const { return rect.size; } 29 } 30 } 31 32 /// 33 class DiRectShape : DiShape 34 { 35 protected: 36 37 DiRect bbox; 38 DiVec min_size, max_size; 39 40 public: 41 42 invariant() 43 { 44 enforce( min_size.w <= max_size.w ); 45 enforce( min_size.h <= max_size.h ); 46 } 47 48 @property 49 { 50 /// 51 DiRect rect() const { return bbox; } 52 53 /// 54 DiRect rect( in DiRect r ) 55 { 56 reshape(r); 57 return bbox; 58 } 59 60 /// 61 DiVec minSize() const { return min_size; } 62 /// 63 DiVec minSize( in DiVec ms ) { min_size = ms; return ms; } 64 65 /// 66 DiVec maxSize() const { return max_size; } 67 /// 68 DiVec maxSize( in DiVec ms ) { max_size = ms; return ms; } 69 } 70 71 /// 72 bool contains( in DiVec v ) const 73 { return v in bbox; } 74 75 /// 76 bool contains( in DiRect r ) const 77 { return contains( r.pos ) && contains( r.lim ); } 78 79 /// 80 bool intersect( in DiRect r ) const 81 { return bbox.overlap(r).volume > 0; } 82 83 /// 84 bool reshape( in DiRect nr ) 85 { 86 auto nb = calcAllowRect( nr ); 87 bool ret = bbox != nb; 88 bbox = nb; 89 return ret; 90 } 91 92 protected: 93 94 /// use min_size and max_size for calc new rect 95 DiRect calcAllowRect( in DiRect r ) const 96 { 97 auto sz = DiVec( r.size ); 98 99 if( sz != r.size ) 100 { 101 if( sz.w > max_size.w ) sz.w = max_size.w; 102 if( sz.w < min_size.w ) sz.w = min_size.w; 103 104 if( sz.h > max_size.h ) sz.h = max_size.h; 105 if( sz.h < min_size.h ) sz.h = min_size.h; 106 } 107 108 return DiRect( r.pos, sz ); 109 } 110 }