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