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 }