comparison mde/gui/widget/layout.d @ 58:d43523ed4b62

Included a wdim typedef for all variables to do with window position or size instead of just using int.
author Diggory Hardy <diggory.hardy@gmail.com>
date Sat, 14 Jun 2008 17:15:06 +0100
parents 03fa79a48c48
children 891211f034f2
comparison
equal deleted inserted replaced
57:9e1f05fbbcef 58:d43523ed4b62
81 if (data.length < rows + cols) { // data error; use defaults 81 if (data.length < rows + cols) { // data error; use defaults
82 col.dupMin; 82 col.dupMin;
83 row.dupMin; 83 row.dupMin;
84 } else { // sufficient data 84 } else { // sufficient data
85 lenUsed = rows+cols; 85 lenUsed = rows+cols;
86 col.setCheck (data[0..cols]); 86 col.setCheck (cast(wdim[])data[0..cols]);
87 row.setCheck (data[cols..lenUsed]); 87 row.setCheck (cast(wdim[])data[cols..lenUsed]);
88 } 88 }
89 89
90 90
91 // Generate cached mutable data 91 // Generate cached mutable data
92 // Calculate column and row locations: 92 // Calculate column and row locations:
117 int[] getMutableData () { 117 int[] getMutableData () {
118 int[] ret; 118 int[] ret;
119 foreach (widget; subWidgets) 119 foreach (widget; subWidgets)
120 ret ~= widget.getMutableData; 120 ret ~= widget.getMutableData;
121 121
122 ret ~= col.width ~ row.width; 122 return ret ~ cast(int[])col.width ~ cast(int[])row.width;
123 return ret;
124 } 123 }
125 //END Creation & saving 124 //END Creation & saving
126 125
127 //BEGIN Size & position 126 //BEGIN Size & position
128 bool isWSizable () { 127 bool isWSizable () {
131 bool isHSizable () { 130 bool isHSizable () {
132 return row.firstSizable >= 0; 131 return row.firstSizable >= 0;
133 } 132 }
134 133
135 /* Calculates the minimal size from all rows and columns of widgets. */ 134 /* Calculates the minimal size from all rows and columns of widgets. */
136 void getMinimalSize (out int mw, out int mh) { 135 void getMinimalSize (out wdim mw, out wdim mh) {
137 mw = this.mw; 136 mw = this.mw;
138 mh = this.mh; 137 mh = this.mh;
139 } 138 }
140 139
141 void setWidth (int nw, int dir) { 140 void setWidth (wdim nw, int dir) {
142 if (nw == w) return; 141 if (nw == w) return;
143 142
144 w += col.adjustCellSizes (nw - w, (dir == -1 ? col.lastSizable : col.firstSizable), dir); 143 w += col.adjustCellSizes (nw - w, (dir == -1 ? col.lastSizable : col.firstSizable), dir);
145 144
146 // Note: setPosition must be called after! 145 // Note: setPosition must be called after!
147 } 146 }
148 void setHeight (int nh, int dir) { 147 void setHeight (wdim nh, int dir) {
149 if (nh == h) return; 148 if (nh == h) return;
150 149
151 h += row.adjustCellSizes (nh - h, (dir == -1 ? row.lastSizable : row.firstSizable), dir); 150 h += row.adjustCellSizes (nh - h, (dir == -1 ? row.lastSizable : row.firstSizable), dir);
152 151
153 // Note: setPosition must be called after! 152 // Note: setPosition must be called after!
154 } 153 }
155 154
156 void setPosition (int x, int y) { 155 void setPosition (wdim x, wdim y) {
157 this.x = x; 156 this.x = x;
158 this.y = y; 157 this.y = y;
159 158
160 foreach (i,widget; subWidgets) 159 foreach (i,widget; subWidgets)
161 widget.setPosition (x + col.pos[i % cols], y + row.pos[i / cols]); 160 widget.setPosition (x + col.pos[i % cols], y + row.pos[i / cols]);
162 } 161 }
163 //END Size & position 162 //END Size & position
164 163
165 164
166 // Find the relevant widget. 165 // Find the relevant widget.
167 IWidget getWidget (int cx, int cy) { 166 IWidget getWidget (wdim cx, wdim cy) {
168 debug scope (failure) 167 debug scope (failure)
169 logger.warn ("getWidget: failure"); 168 logger.warn ("getWidget: failure");
170 // Find row/column: 169 // Find row/column:
171 myDiff i = col.getCell (cx - x); 170 myDiff i = col.getCell (cx - x);
172 myDiff j = row.getCell (cy - y); 171 myDiff j = row.getCell (cy - y);
176 // On a subwidget; recurse call: 175 // On a subwidget; recurse call:
177 return subWidgets[i + j*cols].getWidget (cx, cy); 176 return subWidgets[i + j*cols].getWidget (cx, cy);
178 } 177 }
179 178
180 // Resizing columns & rows 179 // Resizing columns & rows
181 void clickEvent (ushort cx, ushort cy, ubyte b, bool state) { 180 void clickEvent (wdabs cx, wdabs cy, ubyte b, bool state) {
182 debug scope (failure) 181 debug scope (failure)
183 logger.warn ("clickEvent: failure"); 182 logger.warn ("clickEvent: failure");
184 if (b == 1 && state == true) { 183 if (b == 1 && state == true) {
185 /* Note: Because of getWidget, this function is only called if the click is not on a 184 /* Note: Because of getWidget, this function is only called if the click is not on a
186 * sub-widget, so we know it's on some divisor (so at least one of resizeCol and 185 * sub-widget, so we know it's on some divisor (so at least one of resizeCol and
214 col.setColWidth = &setColWidth; 213 col.setColWidth = &setColWidth;
215 row.setColWidth = &setRowHeight; 214 row.setColWidth = &setRowHeight;
216 215
217 // Calculate the minimal column and row sizes: 216 // Calculate the minimal column and row sizes:
218 // set length, making sure the arrays are initialised to zero: 217 // set length, making sure the arrays are initialised to zero:
219 col.minWidth = new int[cols]; 218 col.minWidth = new wdim[cols];
220 row.minWidth = new int[rows]; 219 row.minWidth = new wdim[rows];
221 int ww, wh; // sub-widget minimal sizes 220 wdim ww, wh; // sub-widget minimal sizes
222 foreach (i,widget; subWidgets) { 221 foreach (i,widget; subWidgets) {
223 widget.getMinimalSize (ww, wh); 222 widget.getMinimalSize (ww, wh);
224 223
225 // Increase dimensions if current minimal size is larger: 224 // Increase dimensions if current minimal size is larger:
226 myIt n = i % cols; // column 225 myIt n = i % cols; // column
230 } 229 }
231 230
232 231
233 // Calculate the overall minimal size, starting with the spacing: 232 // Calculate the overall minimal size, starting with the spacing:
234 mh = window.renderer.layoutSpacing; // use mh temporarily 233 mh = window.renderer.layoutSpacing; // use mh temporarily
235 mw = mh * (cols - 1); 234 mw = mh * cast(wdim)(cols - 1);
236 mh *= (rows - 1); 235 mh *= cast(wdim)(rows - 1);
237 236
238 foreach (x; col.minWidth) // add the column/row's dimensions 237 foreach (x; col.minWidth) // add the column/row's dimensions
239 mw += x; 238 mw += x;
240 foreach (x; row.minWidth) 239 foreach (x; row.minWidth)
241 mh += x; 240 mh += x;
273 } 272 }
274 } 273 }
275 //END Cache calculation functions 274 //END Cache calculation functions
276 275
277 276
278 void setColWidth (myIt i, int w, int dir) { 277 void setColWidth (myIt i, wdim w, int dir) {
279 for (myIt j = 0; j < rows; ++j) { 278 for (myIt j = 0; j < rows; ++j) {
280 subWidgets[i + cols*j].setWidth (w, dir); 279 subWidgets[i + cols*j].setWidth (w, dir);
281 } 280 }
282 } 281 }
283 void setRowHeight (myIt j, int h, int dir) { 282 void setRowHeight (myIt j, wdim h, int dir) {
284 for (myIt i = 0; i < cols; ++i) { 283 for (myIt i = 0; i < cols; ++i) {
285 subWidgets[i + cols*j].setHeight (h, dir); 284 subWidgets[i + cols*j].setHeight (h, dir);
286 } 285 }
287 } 286 }
288 287
289 288
290 //BEGIN Col/row resizing callback 289 //BEGIN Col/row resizing callback
291 void resizeCallback (ushort cx, ushort cy) { 290 void resizeCallback (wdim cx, wdim cy) {
292 col.resize (cx - dragX); 291 col.resize (cx - dragX);
293 row.resize (cy - dragY); 292 row.resize (cy - dragY);
294 293
295 // NOTE: all adjustments are relative; might be better if they were absolute? 294 // NOTE: all adjustments are relative; might be better if they were absolute?
296 dragX = cx; 295 dragX = cx;
299 foreach (i,widget; subWidgets) 298 foreach (i,widget; subWidgets)
300 widget.setPosition (x + col.pos[i % cols], 299 widget.setPosition (x + col.pos[i % cols],
301 y + row.pos[i / cols]); 300 y + row.pos[i / cols]);
302 window.requestRedraw; 301 window.requestRedraw;
303 } 302 }
304 bool endCallback (ushort cx, ushort cy, ubyte b, bool state) { 303 bool endCallback (wdabs cx, wdabs cy, ubyte b, bool state) {
305 if (b == 1 && state == false) { 304 if (b == 1 && state == false) {
306 window.gui.removeCallbacks (cast(void*) this); 305 window.gui.removeCallbacks (cast(void*) this);
307 return true; // we've handled the up-click 306 return true; // we've handled the up-click
308 } 307 }
309 return false; // we haven't handled it 308 return false; // we haven't handled it
310 } 309 }
311 310
312 protected: 311 protected:
313 // Data for resizing cols/rows: 312 // Data for resizing cols/rows:
314 int dragX, dragY; // coords where drag starts 313 wdim dragX, dragY; // coords where drag starts
315 //END Col/row resizing callback 314 //END Col/row resizing callback
316 315
317 316
318 myIt cols, rows; // number of cells in grid 317 myIt cols, rows; // number of cells in grid
319 318
326 * The purpose of this struct is mostly to unify functionality which must work the same on both 325 * The purpose of this struct is mostly to unify functionality which must work the same on both
327 * horizontal and vertical cell placement. 326 * horizontal and vertical cell placement.
328 * 327 *
329 * Most notation corresponds to horizontal layout (columns), simply for easy of naming. */ 328 * Most notation corresponds to horizontal layout (columns), simply for easy of naming. */
330 struct CellDimensions { 329 struct CellDimensions {
331 int[] pos, // relative position (cumulative width[i-1] plus spacing) 330 wdim[] pos, // relative position (cumulative width[i-1] plus spacing)
332 width, // current widths 331 width, // current widths
333 minWidth; // minimal widths (set by genCachedConstructionData) 332 minWidth; // minimal widths (set by genCachedConstructionData)
334 bool[] sizable; // true if col is resizable (set by genCachedConstructionData) 333 bool[] sizable; // true if col is resizable (set by genCachedConstructionData)
335 myDiff firstSizable, // first col which is resizable, negative if none 334 myDiff firstSizable, // first col which is resizable, negative if none
336 lastSizable; // as above, but last (set by genCachedConstructionData) 335 lastSizable; // as above, but last (set by genCachedConstructionData)
337 myDiff resizeD, // resize down from this index (<0 if not resizing) 336 myDiff resizeD, // resize down from this index (<0 if not resizing)
338 resizeU; // and up from this index 337 resizeU; // and up from this index
339 int spacing; // used by genPositions (which cannot access the layout class's data) 338 wdim spacing; // used by genPositions (which cannot access the layout class's data)
340 /* This is a delegate to a enclosing class's function, since: 339 /* This is a delegate to a enclosing class's function, since:
341 * a different implementation is needed for cols or rows 340 * a different implementation is needed for cols or rows
342 * we're unable to access enclosing class members directly */ 341 * we're unable to access enclosing class members directly */
343 void delegate (myIt,int,int) setColWidth; // set width of a column, with resize direction 342 void delegate (myIt,wdim,int) setColWidth; // set width of a column, with resize direction
344 343
345 void dupMin () { 344 void dupMin () {
346 width = minWidth.dup; 345 width = minWidth.dup;
347 } 346 }
348 void setCheck (int[] data) { 347 void setCheck (wdim[] data) {
349 // Set to provided data: 348 // Set to provided data:
350 width = data; 349 width = data;
351 // And check sizes are valid: 350 // And check sizes are valid:
352 foreach (i, m; minWidth) 351 foreach (i, m; minWidth)
353 // if fixed width or width is less than minimum: 352 // if fixed width or width is less than minimum:
354 if (!sizable[i] || width[i] < m) 353 if (!sizable[i] || width[i] < m)
355 width[i] = m; 354 width[i] = m;
356 } 355 }
357 356
358 // Generate position infomation and return total width (i.e. widget width/height) 357 // Generate position infomation and return total width (i.e. widget width/height)
359 int genPositions () { 358 wdim genPositions () {
360 pos.length = minWidth.length; 359 pos.length = minWidth.length;
361 360
362 int x = 0; 361 wdim x = 0;
363 foreach (i, w; width) { 362 foreach (i, w; width) {
364 pos[i] = x; 363 pos[i] = x;
365 x += w + spacing; 364 x += w + spacing;
366 } 365 }
367 return x - spacing; 366 return x - spacing;
368 } 367 }
369 368
370 // Get the row/column a click occured in 369 // Get the row/column a click occured in
371 // Returns -i if in space to left of col i, or i if on col i 370 // Returns -i if in space to left of col i, or i if on col i
372 myDiff getCell (int l) { 371 myDiff getCell (wdim l) {
373 myDiff i = minWidth.length - 1; // starting from right... 372 myDiff i = minWidth.length - 1; // starting from right...
374 while (l < pos[i]) { // decrement while left of this column 373 while (l < pos[i]) { // decrement while left of this column
375 debug assert (i > 0, "getCell: l < pos[0] (code error)"); 374 debug assert (i > 0, "getCell: l < pos[0] (code error)");
376 --i; 375 --i;
377 } // now (l >= pos[i]) 376 } // now (l >= pos[i])
379 return -i - 1; // note: i might be 0 so cannot just return -i 378 return -i - 1; // note: i might be 0 so cannot just return -i
380 return i; 379 return i;
381 } 380 }
382 381
383 // Calculate resizeU/resizeD, and return true if unable to resize. 382 // Calculate resizeU/resizeD, and return true if unable to resize.
384 bool findResize (int l) { 383 bool findResize (wdim l) {
385 resizeU = -getCell (l); // potential start for upward-resizes 384 resizeU = -getCell (l); // potential start for upward-resizes
386 if (resizeU <= 0) return true; // not on a space between cells 385 if (resizeU <= 0) return true; // not on a space between cells
387 resizeD = resizeU - 1; // potential start for downward-resizes 386 resizeD = resizeU - 1; // potential start for downward-resizes
388 387
389 while (!sizable[resizeU]) { // find first actually resizable column (upwards) 388 while (!sizable[resizeU]) { // find first actually resizable column (upwards)
416 * The amount adjusted. This may be larger than diff, since cellD is clamped by cellDMin. 415 * The amount adjusted. This may be larger than diff, since cellD is clamped by cellDMin.
417 * 416 *
418 * Note: Check variable used for start is valid before calling! If a non-sizable column's 417 * Note: Check variable used for start is valid before calling! If a non-sizable column's
419 * index is passed, this should get increased (if diff > 0) but not decreased. 418 * index is passed, this should get increased (if diff > 0) but not decreased.
420 */ 419 */
421 int adjustCellSizes (int diff, myDiff start, int incr) 420 wdim adjustCellSizes (wdim diff, myDiff start, int incr)
422 in { 421 in {
423 // Could occur if adjust isn't called first, but this would be a code error: 422 // Could occur if adjust isn't called first, but this would be a code error:
424 assert (width !is null, "adjustCellSizes: width is null"); 423 assert (width !is null, "adjustCellSizes: width is null");
425 // Most likely if passed negative when sizing is disabled: 424 // Most likely if passed negative when sizing is disabled:
426 assert (start >= 0 && start < minWidth.length, "adjustCellSizes: invalid start"); 425 assert (start >= 0 && start < minWidth.length, "adjustCellSizes: invalid start");
433 if (diff > 0) { // increase size of first resizable cell 432 if (diff > 0) { // increase size of first resizable cell
434 width[i] += diff; 433 width[i] += diff;
435 setColWidth (i, width[i], incr); 434 setColWidth (i, width[i], incr);
436 } 435 }
437 else if (diff < 0) { // decrease 436 else if (diff < 0) { // decrease
438 int rd = diff; // running diff 437 wdim rd = diff; // running diff
439 aCSwhile: 438 aCSwhile:
440 while (true) { 439 while (true) {
441 width[i] += rd; // decrease this cell's size (but may be too much) 440 width[i] += rd; // decrease this cell's size (but may be too much)
442 rd = width[i] - minWidth[i]; 441 rd = width[i] - minWidth[i];
443 if (rd >= 0) { // OK; we're done 442 if (rd >= 0) { // OK; we're done
466 465
467 genPositions; 466 genPositions;
468 return diff; 467 return diff;
469 } 468 }
470 469
471 void resize (int diff) { 470 void resize (wdim diff) {
472 if (resizeU <= 0) return; 471 if (resizeU <= 0) return;
473 472
474 // do shrinking first (in case we hit the minimum) 473 // do shrinking first (in case we hit the minimum)
475 if (diff >= 0) { 474 if (diff >= 0) {
476 diff = -adjustCellSizes (-diff, resizeU, 1); 475 diff = -adjustCellSizes (-diff, resizeU, 1);
482 } 481 }
483 } 482 }
484 CellDimensions col, row; 483 CellDimensions col, row;
485 484
486 // Index types. Note that in some cases they need to hold negative values. 485 // Index types. Note that in some cases they need to hold negative values.
487 // Int is used for resizing direction (although ptrdiff_t would be more appropriate), 486 // int is used for resizing direction (although ptrdiff_t would be more appropriate),
488 // since the value must always be -1 or +1 and int is smaller on X86_64. 487 // since the value must always be -1 or +1 and int is smaller on X86_64.
489 alias size_t myIt; 488 alias size_t myIt;
490 alias ptrdiff_t myDiff; 489 alias ptrdiff_t myDiff;
491 } 490 }