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 104 // MGW 105 import std.stdio: writeln; 106 107 108 if(this._childControls && this.created && this.visible) 109 { 110 scope ResizeManager rm = new ResizeManager(this._childControls.length); 111 Rect da = Rect(nullPoint, this.clientSize); 112 // writeln("---> da = ", da); 113 // writeln("---> da.top = ", da.top); 114 // Считаем высоту и ширину всех элементов 115 int allH, allW; 116 foreach(Control c; this._childControls) { 117 if(c.dock == DockStyle.top || c.dock == DockStyle.bottom || c.dock == DockStyle.height) allH += c.height; 118 if(c.dock == DockStyle.left || c.dock == DockStyle.right || c.dock == DockStyle.width) allW += c.width; 119 } 120 121 foreach(Control c; this._childControls) 122 { 123 if(da.empty) 124 { 125 rm.dispose(); 126 break; 127 } 128 129 if(c.dock !is DockStyle.none && c.visible && c.created) 130 { 131 Rect da2 = Rect(nullPoint, this.clientSize); 132 switch(c.dock) 133 { 134 // Добавлено два новых стиля height и width. В наборен элементов может быть 135 // только один элемент этих стилей 136 case DockStyle.height: 137 allH -= c.height; c.height = da2.height - allH; 138 rm.resizeControl(c, da.left, da.top, da.width, c.height); 139 break; 140 141 case DockStyle.width: 142 allW -= c.width; c.width = da2.width - allW; 143 rm.resizeControl(c, da.left, da.top, c.width, da.height); 144 break; 145 146 case DockStyle.left: 147 //c.bounds = Rect(da.left, da.top, c.width, da.height); 148 rm.resizeControl(c, da.left, da.top, c.width, da.height); 149 da.left += c.width; 150 break; 151 152 case DockStyle.top: 153 //c.bounds = Rect(da.left, da.top, da.width, c.height); 154 rm.resizeControl(c, da.left, da.top, da.width, c.height); 155 da.top += c.height; 156 break; 157 158 case DockStyle.right: 159 //c.bounds = Rect(da.right - c.width, da.top, c.width, da.height); 160 rm.resizeControl(c, da.right - c.width, da.top, c.width, da.height); 161 da.right -= c.width; 162 break; 163 164 case DockStyle.bottom: 165 //c.bounds = Rect(c, da.left, da.bottom - c.height, da.width, c.height); 166 rm.resizeControl(c, da.left, da.bottom - c.height, da.width, c.height); 167 da.bottom -= c.height; 168 break; 169 170 case DockStyle.fill: 171 //c.bounds = da; 172 rm.resizeControl(c, da); 173 da.size = nullSize; 174 break; 175 176 default: 177 rm.dispose(); 178 assert(false, "Unknown DockStyle"); 179 //break; 180 } 181 } 182 } 183 } 184 } 185 186 protected override void onDGuiMessage(ref Message m) 187 { 188 switch(m.msg) 189 { 190 case DGUI_DOLAYOUT: 191 this.updateLayout(); 192 break; 193 194 case DGUI_CHILDCONTROLCREATED: 195 { 196 Control c = winCast!(Control)(m.wParam); 197 198 if(c.dock !is DockStyle.none && c.visible) 199 { 200 this.updateLayout(); 201 } 202 } 203 break; 204 205 default: 206 break; 207 } 208 209 super.onDGuiMessage(m); 210 } 211 212 protected override void onHandleCreated(EventArgs e) 213 { 214 super.onHandleCreated(e); 215 216 this.updateLayout(); 217 } 218 219 protected override void onResize(EventArgs e) 220 { 221 this.updateLayout(); 222 223 InvalidateRect(this._handle, null, true); 224 UpdateWindow(this._handle); 225 super.onResize(e); 226 } 227 }