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.gridpanel; 10 11 import std.algorithm; 12 import dgui.core.interfaces.idisposable; 13 import dgui.layout.layoutcontrol; 14 15 class ColumnPart: IDisposable 16 { 17 private Control _control; 18 private GridPanel _gridPanel; 19 private int _width = 0; 20 private int _marginLeft = 0; 21 private int _marginRight = 0; 22 23 package this(GridPanel gp, Control c) 24 { 25 this._gridPanel = gp; 26 this._control = c; 27 } 28 29 public ~this() 30 { 31 this.dispose(); 32 } 33 34 public void dispose() 35 { 36 if(this._control) 37 { 38 this._control.dispose(); 39 this._control = null; 40 } 41 } 42 43 @property public int marginLeft() 44 { 45 return this._marginLeft; 46 } 47 48 @property public void marginLeft(int m) 49 { 50 this._marginLeft = m; 51 } 52 53 @property public int marginRight() 54 { 55 return this._marginRight; 56 } 57 58 @property public void marginRight(int m) 59 { 60 this._marginRight= m; 61 } 62 63 @property public int width() 64 { 65 return this._width; 66 } 67 68 @property public void width(int w) 69 { 70 this._width = w; 71 72 if(this._gridPanel && this._gridPanel.created) 73 { 74 this._gridPanel.updateLayout(); 75 } 76 } 77 78 @property public GridPanel gridPanel() 79 { 80 return this._gridPanel; 81 } 82 83 @property public Control control() 84 { 85 return this._control; 86 } 87 } 88 89 class RowPart: IDisposable 90 { 91 private Collection!(ColumnPart) _columns; 92 private GridPanel _gridPanel; 93 private int _height = 0; 94 private int _marginTop = 0; 95 private int _marginBottom = 0; 96 97 package this(GridPanel gp) 98 { 99 this._gridPanel = gp; 100 } 101 102 public ~this() 103 { 104 this.dispose(); 105 } 106 107 public void dispose() 108 { 109 if(this._columns) 110 { 111 foreach(ColumnPart cp; this._columns) 112 { 113 cp.dispose(); 114 } 115 116 this._columns.clear(); 117 } 118 } 119 120 @property public int marginTop() 121 { 122 return this._marginTop; 123 } 124 125 @property public void marginTop(int m) 126 { 127 this._marginTop = m; 128 } 129 130 @property public int marginBottom() 131 { 132 return this._marginBottom; 133 } 134 135 @property public void marginBottom(int m) 136 { 137 this._marginBottom = m; 138 } 139 140 @property public int height() 141 { 142 return this._height; 143 } 144 145 @property public void height(int h) 146 { 147 this._height = h; 148 149 if(this._gridPanel && this._gridPanel.created) 150 { 151 this._gridPanel.updateLayout(); 152 } 153 } 154 155 @property public GridPanel gridPanel() 156 { 157 return this._gridPanel; 158 } 159 160 public ColumnPart addColumn() 161 { 162 return this.addColumn(null); 163 } 164 165 public ColumnPart addColumn(Control c) 166 { 167 if(!this._columns) 168 { 169 this._columns = new Collection!(ColumnPart)(); 170 } 171 172 if(c) 173 { 174 this._gridPanel.canAddChild = true; // Unlock Add Child 175 c.parent = this._gridPanel; // Set the parent 176 this._gridPanel.canAddChild = false; // Lock Add Child 177 } 178 179 ColumnPart cp = new ColumnPart(this._gridPanel, c); 180 this._columns.add(cp); 181 182 if(c && this._gridPanel && this._gridPanel.created) 183 { 184 c.show(); // Layout is done by LayoutControl 185 } 186 187 return cp; 188 } 189 190 public void removeColumn(int idx) 191 { 192 ColumnPart c = this._columns[idx]; 193 194 this._columns.removeAt(idx); 195 c.dispose(); 196 197 this._gridPanel.updateLayout(); //Recalculate layout 198 } 199 200 @property public ColumnPart[] columns() 201 { 202 if(this._columns) 203 { 204 return this._columns.get(); 205 } 206 207 return null; 208 } 209 } 210 211 class GridPanel: LayoutControl 212 { 213 private Collection!(RowPart) _rows; 214 private bool _canAddChild = false; 215 216 @property package void canAddChild(bool b) 217 { 218 this._canAddChild = b; 219 } 220 221 public RowPart addRow() 222 { 223 if(!this._rows) 224 { 225 this._rows = new Collection!(RowPart)(); 226 } 227 228 RowPart rp = new RowPart(this); 229 this._rows.add(rp); 230 231 return rp; 232 } 233 234 public void removeRow(int idx) 235 { 236 if(this._rows) 237 { 238 RowPart c = this._rows[idx]; 239 240 this._rows.removeAt(idx); 241 c.dispose(); 242 } 243 } 244 245 @property public RowPart[] rows() 246 { 247 if(this._rows) 248 { 249 return this._rows.get(); 250 } 251 252 return null; 253 } 254 255 protected override void createControlParams(ref CreateControlParams ccp) 256 { 257 ccp.className = WC_DGRIDPANEL; 258 ccp.defaultCursor = SystemCursors.arrow; 259 260 super.createControlParams(ccp); 261 } 262 263 protected override void onDGuiMessage(ref Message m) 264 { 265 switch(m.msg) 266 { 267 case DGUI_ADDCHILDCONTROL: 268 { 269 if(this._canAddChild) 270 { 271 super.onDGuiMessage(m); 272 } 273 else 274 { 275 throwException!(DGuiException)("GridPanel doesn't accept child controls"); 276 } 277 } 278 break; 279 280 default: 281 super.onDGuiMessage(m); 282 break; 283 } 284 } 285 286 287 public override void updateLayout() 288 { 289 if(this._rows) 290 { 291 int x = 0, y = 0, ctrlCount = 0; 292 293 foreach(RowPart rp; this._rows) 294 { 295 if(rp.columns) 296 { 297 ctrlCount += rp.columns.length; 298 } 299 } 300 301 scope ResizeManager rm = new ResizeManager(ctrlCount); 302 303 foreach(RowPart rp; this._rows) 304 { 305 x = 0; // This is a new Row 306 int maxCtrlHeight = rp.height; 307 308 if(rp.columns) 309 { 310 if(!maxCtrlHeight) 311 { 312 // Find the max height of Controls 313 foreach(ColumnPart cp; rp.columns) 314 { 315 if(cp.control) 316 { 317 maxCtrlHeight = max(maxCtrlHeight, cp.control.height); 318 } 319 } 320 } 321 322 foreach(ColumnPart cp; rp.columns) 323 { 324 int w = cp.width; 325 326 if(cp.control) 327 { 328 if(!w) 329 { 330 w = cp.control.width; 331 } 332 333 //cp.control.bounds = Rect(cp.marginLeft + x, rp.marginTop + y, w, maxCtrlHeight); 334 rm.resizeControl(cp.control, cp.marginLeft + x, rp.marginTop + y, w, maxCtrlHeight); 335 } 336 337 x += cp.marginLeft + w + cp.marginRight; 338 } 339 } 340 341 y += rp.marginTop + maxCtrlHeight + rp.marginBottom; 342 } 343 } 344 } 345 }