1 /** DGui project file.
2 
3 Copyright: Trogu Antonio Davide 2011-2013
4 
5 License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
6 
7 Authors: Trogu Antonio Davide
8 */
9 module dguihub.layout.layoutcontrol;
10 
11 import dguihub.core.interfaces.ilayoutcontrol;
12 public import dguihub.core.controls.containercontrol;
13 
14 class ResizeManager : Handle!(HDWP), IDisposable {
15    public this(int c) {
16       if (c > 1) {
17          this._handle = BeginDeferWindowPos(c);
18       }
19    }
20 
21    public ~this() {
22       this.dispose();
23    }
24 
25    public void dispose() {
26       if (this._handle) {
27          EndDeferWindowPos(this._handle);
28       }
29    }
30 
31    public void setPosition(Control ctrl, Point pt) {
32       this.setPosition(ctrl, pt.x, pt.y);
33    }
34 
35    public void setPosition(Control ctrl, int x, int y) {
36       this.resizeControl(ctrl, x, y, 0, 0, PositionSpecified.position);
37    }
38 
39    public void setSize(Control ctrl, Size sz) {
40       this.setSize(ctrl, sz.width, sz.height);
41    }
42 
43    public void setSize(Control ctrl, int w, int h) {
44       this.resizeControl(ctrl, 0, 0, w, h, PositionSpecified.size);
45    }
46 
47    public void resizeControl(Control ctrl, Rect r, PositionSpecified ps = PositionSpecified.all) {
48       this.resizeControl(ctrl, r.x, r.y, r.width, r.height, ps);
49    }
50 
51    public void resizeControl(Control ctrl, int x, int y, int w, int h,
52          PositionSpecified ps = PositionSpecified.all) {
53       uint wpf = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE;
54 
55       if (ps !is PositionSpecified.all) {
56          if (ps is PositionSpecified.position) {
57             wpf &= ~SWP_NOMOVE;
58          } else //if(ps is PositionSpecified.size)
59          {
60             wpf &= ~SWP_NOSIZE;
61          }
62       } else {
63          wpf &= ~(SWP_NOMOVE | SWP_NOSIZE);
64       }
65 
66       if (this._handle) {
67          this._handle = DeferWindowPos(this._handle, ctrl.handle, null, x, y, w, h, wpf);
68       } else {
69          SetWindowPos(ctrl.handle, null, x, y, w, h, wpf); //Bounds updated in WM_WINDOWPOSCHANGED
70       }
71    }
72 }
73 
74 abstract class LayoutControl : ContainerControl, ILayoutControl {
75    public override void show() {
76       super.show();
77       this.updateLayout();
78    }
79 
80    public void updateLayout() {
81       if (this._childControls && this.created && this.visible) {
82          scope ResizeManager rm = new ResizeManager(this._childControls.length);
83          Rect da = Rect(nullPoint, this.clientSize);
84 
85          foreach (Control c; this._childControls) {
86             if (da.empty) {
87                rm.dispose();
88                break;
89             }
90 
91             if (c.dock !is DockStyle.none && c.visible && c.created) {
92                switch (c.dock) {
93                case DockStyle.left:
94                   //c.bounds = Rect(da.left, da.top, c.width, da.height);
95                   rm.resizeControl(c, da.left, da.top, c.width, da.height);
96                   da.left += c.width;
97                   break;
98 
99                case DockStyle.top:
100                   //c.bounds = Rect(da.left, da.top, da.width, c.height);
101                   rm.resizeControl(c, da.left, da.top, da.width, c.height);
102                   da.top += c.height;
103                   break;
104 
105                case DockStyle.right:
106                   //c.bounds = Rect(da.right - c.width, da.top, c.width, da.height);
107                   rm.resizeControl(c, da.right - c.width,
108                         da.top, c.width, da.height);
109                   da.right -= c.width;
110                   break;
111 
112                case DockStyle.bottom:
113                   //c.bounds = Rect(c, da.left, da.bottom - c.height, da.width, c.height);
114                   rm.resizeControl(c, da.left,
115                         da.bottom - c.height, da.width, c.height);
116                   da.bottom -= c.height;
117                   break;
118 
119                case DockStyle.fill:
120                   //c.bounds = da;
121                   rm.resizeControl(c, da);
122                   da.size = nullSize;
123                   break;
124 
125                default:
126                   rm.dispose();
127                   assert(false, "Unknown DockStyle");
128                   //break;
129                }
130             }
131          }
132       }
133    }
134 
135    protected override void onDGuiMessage(ref Message m) {
136       switch (m.msg) {
137       case DGUI_DOLAYOUT:
138          this.updateLayout();
139          break;
140 
141       case DGUI_CHILDCONTROLCREATED: {
142             Control c = winCast!(Control)(m.wParam);
143 
144             if (c.dock !is DockStyle.none && c.visible) {
145                this.updateLayout();
146             }
147          }
148          break;
149 
150       default:
151          break;
152       }
153 
154       super.onDGuiMessage(m);
155    }
156 
157    protected override void onHandleCreated(EventArgs e) {
158       super.onHandleCreated(e);
159 
160       this.updateLayout();
161    }
162 
163    protected override void onResize(EventArgs e) {
164       this.updateLayout();
165 
166       InvalidateRect(this._handle, null, true);
167       UpdateWindow(this._handle);
168       super.onResize(e);
169    }
170 }