Mercurial > projects > mde
diff mde/gui/widget/layout.d @ 46:03fa79a48c48
Fixed resizing bugs in previous commit and made code cleaner and more efficient.
setSize replaced by setWidth & setHeight.
setPosition must be called after setWidth/Height.
committer: Diggory Hardy <diggory.hardy@gmail.com>
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Thu, 22 May 2008 12:51:47 +0100 |
parents | 0fd51d2c6c8a |
children | d43523ed4b62 |
line wrap: on
line diff
--- a/mde/gui/widget/layout.d Thu May 22 11:34:09 2008 +0100 +++ b/mde/gui/widget/layout.d Thu May 22 12:51:47 2008 +0100 @@ -37,6 +37,7 @@ * The grid has no border but has spacing between widgets. */ class GridLayoutWidget : Widget { + //BEGIN Creation & saving this (IWindow wind, int[] data) { // Get grid size and check data // Check sufficient data for rows, cols, and at least one widget: @@ -62,6 +63,10 @@ genCachedConstructionData; } + /* This does two things: + * 1. Pass adjust data on to sub-widgets + * 2. Set the size, from the adjust data if possible + */ int[] adjust (int[] data) { // Give all sub-widgets their data: foreach (widget; subWidgets) @@ -89,9 +94,11 @@ h = row.genPositions; // Tell subwidgets their new sizes. Positions are given by a later call to setPosition. - foreach (i,widget; subWidgets) - // Resizing direction is arbitrarily set to "high direction": - widget.setSize (col.width[i % cols], row.width[i / cols], true, true); + foreach (i,widget; subWidgets) { + // Resizing direction is arbitrarily set to negative: + widget.setWidth (col.width[i % cols], -1); + widget.setHeight (row.width[i / cols], -1); + } return data[lenUsed..$]; } @@ -115,7 +122,9 @@ ret ~= col.width ~ row.width; return ret; } + //END Creation & saving + //BEGIN Size & position bool isWSizable () { return col.firstSizable >= 0; } @@ -129,28 +138,19 @@ mh = this.mh; } - void setSize (int nw, int nh, bool wHigh, bool hHigh) { - debug scope (failure) { - char[128] tmp; - logger.trace ("setSize failed: hHigh = " ~ (hHigh ? "true" : "false")); - logger.trace (logger.format (tmp, "rows to resize: {}, {}", row.firstSizable, row.lastSizable)); - } - // Optimisation (could easily be called with same sizes if a parent layout widget is - // resized, since many columns/rows may not be resized). - if (nw == w && nh == h) return; + void setWidth (int nw, int dir) { + if (nw == w) return; + + w += col.adjustCellSizes (nw - w, (dir == -1 ? col.lastSizable : col.firstSizable), dir); - // calculate the row/column sizes (and new positions) - if (wHigh) - w += col.adjustCellSizes (nw - w, col.lastSizable, -1); - else - w += col.adjustCellSizes (nw - w, col.firstSizable, 1); - if (hHigh) - h += row.adjustCellSizes (nh - h, row.lastSizable, -1); - else - h += row.adjustCellSizes (nh - h, row.firstSizable, 1); + // Note: setPosition must be called after! + } + void setHeight (int nh, int dir) { + if (nh == h) return; - // set the sub-widget's sizes & positions - setSubWidgetSP (wHigh, hHigh); + h += row.adjustCellSizes (nh - h, (dir == -1 ? row.lastSizable : row.firstSizable), dir); + + // Note: setPosition must be called after! } void setPosition (int x, int y) { @@ -160,6 +160,7 @@ foreach (i,widget; subWidgets) widget.setPosition (x + col.pos[i % cols], y + row.pos[i / cols]); } + //END Size & position // Find the relevant widget. @@ -210,6 +211,8 @@ * (i.e. to produce cached data calculated from construction data). */ void genCachedConstructionData () { col.spacing = row.spacing = window.renderer.layoutSpacing; + col.setColWidth = &setColWidth; + row.setColWidth = &setRowHeight; // Calculate the minimal column and row sizes: // set length, making sure the arrays are initialised to zero: @@ -269,21 +272,22 @@ row.firstSizable = row.lastSizable; } } - - // set sub-widgets size & position (done after resizing widget or rows/columns) - void setSubWidgetSP (bool wH, bool hH) { - for (myIt i = 0; i < cols; ++i) - for (myIt j = 0; j < rows; ++j) - { - IWidget widget = subWidgets[i + cols*j]; - widget.setSize (col.width[i], row.width[j], wH, hH); - widget.setPosition (x + col.pos[i], y + row.pos[j]); - } - } //END Cache calculation functions - //BEGIN Col/row resizing + void setColWidth (myIt i, int w, int dir) { + for (myIt j = 0; j < rows; ++j) { + subWidgets[i + cols*j].setWidth (w, dir); + } + } + void setRowHeight (myIt j, int h, int dir) { + for (myIt i = 0; i < cols; ++i) { + subWidgets[i + cols*j].setHeight (h, dir); + } + } + + + //BEGIN Col/row resizing callback void resizeCallback (ushort cx, ushort cy) { col.resize (cx - dragX); row.resize (cy - dragY); @@ -292,10 +296,9 @@ dragX = cx; dragY = cy; - // NOTE: Resizing direction is set to "high direction" which isn't always going to be - // correct. A more accurate but more complex approach might be to get - // adjustCellSizes to do the work. - setSubWidgetSP (true, true); + foreach (i,widget; subWidgets) + widget.setPosition (x + col.pos[i % cols], + y + row.pos[i / cols]); window.requestRedraw; } bool endCallback (ushort cx, ushort cy, ubyte b, bool state) { @@ -309,7 +312,7 @@ protected: // Data for resizing cols/rows: int dragX, dragY; // coords where drag starts - //END Col/row resizing + //END Col/row resizing callback myIt cols, rows; // number of cells in grid @@ -334,6 +337,10 @@ myDiff resizeD, // resize down from this index (<0 if not resizing) resizeU; // and up from this index int spacing; // used by genPositions (which cannot access the layout class's data) + /* This is a delegate to a enclosing class's function, since: + * a different implementation is needed for cols or rows + * we're unable to access enclosing class members directly */ + void delegate (myIt,int,int) setColWidth; // set width of a column, with resize direction void dupMin () { width = minWidth.dup; @@ -407,20 +414,25 @@ * * Returns: * The amount adjusted. This may be larger than diff, since cellD is clamped by cellDMin. + * + * Note: Check variable used for start is valid before calling! If a non-sizable column's + * index is passed, this should get increased (if diff > 0) but not decreased. */ - int adjustCellSizes (int diff, myDiff start, myDiff incr) - in {// Could occur if adjust isn't called first, but this would be a code error: - char[128] tmp; - logger.trace (logger.format (tmp, "start is {}", start)); + int adjustCellSizes (int diff, myDiff start, int incr) + in { + // Could occur if adjust isn't called first, but this would be a code error: assert (width !is null, "adjustCellSizes: width is null"); + // Most likely if passed negative when sizing is disabled: assert (start >= 0 && start < minWidth.length, "adjustCellSizes: invalid start"); assert (incr == 1 || incr == -1, "adjustCellSizes: invalid incr"); + assert (setColWidth !is null, "adjustCellSizes: setColWidth is null"); } body { debug scope(failure) logger.trace ("adjustCellSizes: failure"); myDiff i = start; if (diff > 0) { // increase size of first resizable cell width[i] += diff; + setColWidth (i, width[i], incr); } else if (diff < 0) { // decrease int rd = diff; // running diff @@ -428,13 +440,17 @@ while (true) { width[i] += rd; // decrease this cell's size (but may be too much) rd = width[i] - minWidth[i]; - if (rd >= 0) // OK; we're done + if (rd >= 0) { // OK; we're done + setColWidth (i, width[i], incr); // set new width break; // we hit the mark exactly: diff is correct + } // else we decreased it too much! width[i] = minWidth[i]; + setColWidth (i, width[i], incr); // rd is remainder to decrease by + bool it = true; // iterate (force first time) while (it) { i += incr; @@ -468,6 +484,8 @@ CellDimensions col, row; // Index types. Note that in some cases they need to hold negative values. + // Int is used for resizing direction (although ptrdiff_t would be more appropriate), + // since the value must always be -1 or +1 and int is smaller on X86_64. alias size_t myIt; alias ptrdiff_t myDiff; }