Mercurial > projects > mde
comparison mde/gui/widget/layout.d @ 126:c9843fbaac88
Dynamic minimal size changing improved; works over layouts sharing alignment.
EnumContent sub-contents use EnumValueContent instead of BoolContent; fixes a few small bugs.
EnumContent substrings get translated (bug fixed).
The widget manager no longer attempts to set widget sizes smaller than their minimals, even though some will not be shown.
SwitchWidget: has fixed sizableness now.
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Thu, 08 Jan 2009 13:05:44 +0000 |
parents | a2ef6b549101 |
children | ad91de8867a0 |
comparison
equal
deleted
inserted
replaced
125:3e648bc53bde | 126:c9843fbaac88 |
---|---|
159 // Create cell aligners with appropriate col/row adjustment function | 159 // Create cell aligners with appropriate col/row adjustment function |
160 if (data.ints[1] & 1) | 160 if (data.ints[1] & 1) |
161 col = AlignColumns.getInstance (id, cols); | 161 col = AlignColumns.getInstance (id, cols); |
162 else | 162 else |
163 col = (new AlignColumns (cols)); | 163 col = (new AlignColumns (cols)); |
164 col.addCallbacks (&setColWidth, &setupAlignDimData); | |
165 if (data.ints[1] & 2) | 164 if (data.ints[1] & 2) |
166 row = AlignColumns.getInstance (id~"R", rows); // id must be unique to that for cols! | 165 row = AlignColumns.getInstance (id~"R", rows); // id must be unique to that for cols! |
167 else | 166 else |
168 row = (new AlignColumns (rows)); | 167 row = (new AlignColumns (rows)); |
169 row.addCallbacks (&setRowHeight, &setupAlignDimData); | 168 |
169 AlignColumns.CallbackStruct cbS; | |
170 cbS.setWidth = &setColWidth; | |
171 cbS.sADD = &setupAlignDimData; | |
172 cbS.newMW = &colNewMW; | |
173 col.cbs ~= cbS; | |
174 cbS.setWidth = &setRowHeight; | |
175 cbS.newMW = &rowNewMW; | |
176 row.cbs ~= cbS; | |
177 | |
170 useSpacing = (data.ints[1] & 4) != 0; | 178 useSpacing = (data.ints[1] & 4) != 0; |
171 } | 179 } |
172 | 180 |
173 /** Responsible for calculating the minimal size and initializing some stuff. | 181 /** Responsible for calculating the minimal size and initializing some stuff. |
174 * | 182 * |
238 debug assert (col.pos && row.pos, "setPosition: col/row.pos not set (code error)"); | 246 debug assert (col.pos && row.pos, "setPosition: col/row.pos not set (code error)"); |
239 foreach (i,widget; subWidgets) | 247 foreach (i,widget; subWidgets) |
240 widget.setPosition (x + col.pos[i % cols], y + row.pos[i / cols]); | 248 widget.setPosition (x + col.pos[i % cols], y + row.pos[i / cols]); |
241 } | 249 } |
242 | 250 |
243 override void minSizeChange (IChildWidget widg, wdim nmw, wdim nmh) { | 251 // Unlike for most widgets, these actually resize self and sub-widgets, since the parent |
244 size_t c = 0; | 252 // simply calling setWidth/setHeight wouldn't work. |
245 while (c < subWidgets.length) { | 253 override void minWChange (IChildWidget widg, wdim nmw) { |
246 if (subWidgets[c] is widg) | 254 size_t i = getWidgetIndex(widg); |
247 goto gotCell; | 255 col.newMinWidth (i%cols, i/cols + colR, nmw); |
248 ++c; | 256 // callbacks to all sharing layouts do the rest |
249 } | 257 } |
250 debug logger.error ("minSizeChange: widget is not my child (code error)"); | 258 override void minHChange (IChildWidget widg, wdim nmh) { |
251 return; | 259 size_t i = getWidgetIndex(widg); |
252 | 260 row.newMinWidth (i/cols, i%cols + rowR, nmh); |
253 gotCell: | |
254 size_t r = c / cols; | |
255 c = c % cols; | |
256 bool sizeChange = col.newMinWidth (c, r+colR, nmw); | |
257 sizeChange = row.newMinWidth (r, c+rowR, nmh) || sizeChange; | |
258 if (sizeChange) { | |
259 w = col.w; | |
260 h = row.w; | |
261 parent.minSizeChange (this, col.mw, row.mw); | |
262 } | |
263 mgr.requestRedraw; | |
264 } | 261 } |
265 //END Size & position | 262 //END Size & position |
266 | 263 |
267 | 264 |
268 // Find the relevant widget. | 265 // Find the relevant widget. |
269 override IChildWidget getWidget (wdim cx, wdim cy) { | 266 override IChildWidget getWidget (wdim cx, wdim cy) { |
270 debug scope (failure) | 267 debug scope (failure) |
271 logger.warn ("getWidget: failure; values: click; pos; width: {},{}; {},{}; {},{}", cx, cy, x, y, w, h); | 268 logger.warn ("getWidget: failure; values: click; pos; width: {},{}; {},{}; {},{}", cx, cy, x, y, w, h); |
383 for (size_t i = 0; i < cols; ++i) { | 380 for (size_t i = 0; i < cols; ++i) { |
384 subWidgets[i + cols*j].setHeight (h, dir); | 381 subWidgets[i + cols*j].setHeight (h, dir); |
385 } | 382 } |
386 } | 383 } |
387 | 384 |
385 void colNewMW (bool mwChange) { | |
386 if (mwChange) { | |
387 w = col.w; | |
388 parent.minWChange (this, col.mw); | |
389 } else { // don't propegate call to parent | |
390 setPosition (x,y); | |
391 mgr.requestRedraw; | |
392 } | |
393 } | |
394 void rowNewMW (bool mwChange) { | |
395 if (mwChange) { | |
396 h = row.w; | |
397 parent.minHChange (this, row.mw); | |
398 } else { // don't propegate call to parent | |
399 setPosition (x,y); | |
400 mgr.requestRedraw; | |
401 } | |
402 } | |
403 | |
388 | 404 |
389 //BEGIN Col/row resizing callback | 405 //BEGIN Col/row resizing callback |
390 override void resizeCallback (wdim cx, wdim cy) { | 406 override void resizeCallback (wdim cx, wdim cy) { |
391 col.resizeCols (cx - dragX); | 407 col.resizeCols (cx - dragX); |
392 row.resizeCols (cy - dragY); | 408 row.resizeCols (cy - dragY); |
477 if (n != setup_n) { | 493 if (n != setup_n) { |
478 setup_n = n; | 494 setup_n = n; |
479 setupWidths = false; | 495 setupWidths = false; |
480 reset (cols); | 496 reset (cols); |
481 | 497 |
482 foreach (dg; sADD) | 498 foreach (cb; cbs) |
483 dg (n, flags); // set flag 1 | 499 cb.sADD (n, flags); // set flag 1 |
484 } | 500 } |
485 } | 501 } |
486 | 502 |
487 /** Reset all column information (only keep set callbacks). | 503 /** Reset all column information (only keep set callbacks). |
488 * | 504 * |
557 } | 573 } |
558 } | 574 } |
559 } | 575 } |
560 } | 576 } |
561 | 577 |
562 /** Add a callback to be called to notify changes in a column's width, and the sADD callback. | |
563 */ | |
564 typeof(this) addCallbacks (void delegate (size_t,wdim,int) setCW, void delegate (uint,uint) sDg) { | |
565 assert (setCW && sDg, "AlignColumns.addCallbacks: null callback (code error)"); | |
566 setWidthCb ~= setCW; | |
567 sADD ~= sDg; | |
568 return this; | |
569 } | |
570 | |
571 /** Get the row/column of relative position l. | 578 /** Get the row/column of relative position l. |
572 * | 579 * |
573 * returns: | 580 * returns: |
574 * -i if in space to left of col i, or i if on col i. */ | 581 * -i if in space to left of col i, or i if on col i. */ |
575 ptrdiff_t getCell (wdim l) { | 582 ptrdiff_t getCell (wdim l) { |
657 genPositions; | 664 genPositions; |
658 } | 665 } |
659 | 666 |
660 /** Called when one of the cells in column col now has minimal width nmw. | 667 /** Called when one of the cells in column col now has minimal width nmw. |
661 * | 668 * |
662 * Enlarges column minimal width if necessary; tries to keep total width the same but returns | 669 * Enlarges column minimal width if necessary; tries to keep total width the same. */ |
663 * true if it cannot. */ | 670 void newMinWidth (size_t col, size_t row, wdim nmw) { |
664 bool newMinWidth (size_t col, size_t row, wdim nmw) { | |
665 minCellWidths[col + row*cols] = nmw; | 671 minCellWidths[col + row*cols] = nmw; |
666 wdim nd = 0; // negative diff to keep overall size constant if possible | 672 wdim nd = 0; // negative diff to keep overall size constant if possible |
667 if (minWidth[col] < nmw) { // increase minimal | 673 wdim omw = minWidth[col]; // to check if mw actually changes |
674 if (minWidth[col] < nmw) { // increase minimal | |
668 minWidth[col] = nmw; | 675 minWidth[col] = nmw; |
669 nd = width[col] - nmw; // negative diff | 676 nd = width[col] - nmw; // negative diff |
670 } else if (minWidth[col] > nmw) { // potentially decrease minimal | 677 } else if (minWidth[col] > nmw) { // potentially decrease minimal |
671 nmw = 0; | 678 nmw = 0; |
672 for (size_t r = 0; r < rows; ++r) { | 679 for (size_t r = 0; r < rows; ++r) { |
673 wdim mcw = minCellWidths[col+r*cols]; | 680 wdim mcw = minCellWidths[col+r*cols]; |
674 if (nmw < mcw) | 681 if (nmw < mcw) |
682 | 689 |
683 mw = spacing * cast(wdim)(cols - 1); | 690 mw = spacing * cast(wdim)(cols - 1); |
684 foreach (imw; minWidth) | 691 foreach (imw; minWidth) |
685 mw += imw; | 692 mw += imw; |
686 | 693 |
687 if (nd != 0) { // needs enlarging | 694 if (nd < 0 || (nd > 0 && !sizable[col])) { // needs enlarging or shrinking |
688 width[col] = nmw; | 695 width[col] = nmw; |
689 foreach (dg; setWidthCb) | 696 foreach (cb; cbs) |
690 dg(col, nmw, -1); | 697 cb.setWidth (col, nmw, -1); |
691 if (lastSizable >= 0) | 698 if (lastSizable >= 0) |
692 adjustCellSizes (nd, lastSizable, -1); // doesn't necessarily resize exactly | 699 adjustCellSizes (nd, lastSizable, -1); // doesn't necessarily resize exactly |
693 genPositions; | 700 genPositions; |
694 } | 701 } |
695 | 702 |
696 return true; | 703 bool mwChange = nmw != omw; // size only changes if true, presuming old size is valid |
704 foreach (cb; cbs) | |
705 cb.newMW (mwChange); | |
697 } | 706 } |
698 | 707 |
699 /* Generate position infomation for each column and set w. */ | 708 /* Generate position infomation for each column and set w. */ |
700 private void genPositions () { | 709 private void genPositions () { |
701 pos.length = cols; | 710 pos.length = cols; |
732 } body { | 741 } body { |
733 debug scope(failure) logger.trace ("adjustCellSizes: failure"); | 742 debug scope(failure) logger.trace ("adjustCellSizes: failure"); |
734 ptrdiff_t i = start; | 743 ptrdiff_t i = start; |
735 if (diff > 0) { // increase size of first resizable cell | 744 if (diff > 0) { // increase size of first resizable cell |
736 width[i] += diff; | 745 width[i] += diff; |
737 foreach (dg; setWidthCb) | 746 foreach (cb; cbs) |
738 dg(i, width[i], incr); | 747 cb.setWidth (i, width[i], incr); |
739 } | 748 } |
740 else if (diff < 0) { // decrease | 749 else if (diff < 0) { // decrease |
741 wdim rd = diff; // running diff | 750 wdim rd = diff; // running diff |
742 aCSwhile: | 751 aCSwhile: |
743 while (true) { | 752 while (true) { |
744 width[i] += rd; // decrease this cell's size (but may be too much) | 753 width[i] += rd; // decrease this cell's size (but may be too much) |
745 rd = width[i] - minWidth[i]; | 754 rd = width[i] - minWidth[i]; |
746 if (rd >= 0) { // OK; we're done | 755 if (rd >= 0) { // OK; we're done |
747 foreach (dg; setWidthCb) | 756 foreach (cb; cbs) |
748 dg(i, width[i], incr); | 757 cb.setWidth (i, width[i], incr); |
749 break; // we hit the mark exactly: diff is correct | 758 break; // we hit the mark exactly: diff is correct |
750 } | 759 } |
751 | 760 |
752 // else we decreased it too much! | 761 // else we decreased it too much! |
753 width[i] = minWidth[i]; | 762 width[i] = minWidth[i]; |
754 foreach (dg; setWidthCb) | 763 foreach (cb; cbs) |
755 dg(i, width[i], incr); | 764 cb.setWidth (i, width[i], incr); |
756 // rd is remainder to decrease by | 765 // rd is remainder to decrease by |
757 | 766 |
758 do { | 767 do { |
759 i += incr; | 768 i += incr; |
760 if (i < 0 || i >= cols) { // run out of next cells | 769 if (i < 0 || i >= cols) { // run out of next cells |
788 * Treat as READ ONLY outside this class! */ | 797 * Treat as READ ONLY outside this class! */ |
789 wdim[] width; // only adjusted within the class | 798 wdim[] width; // only adjusted within the class |
790 wdim[] pos; /// ditto | 799 wdim[] pos; /// ditto |
791 wdim spacing; // used by genPositions (which cannot access the layout class's data) | 800 wdim spacing; // used by genPositions (which cannot access the layout class's data) |
792 wdim w,mw; // current & minimal widths | 801 wdim w,mw; // current & minimal widths |
802 | |
803 package struct CallbackStruct { | |
804 void delegate (size_t,wdim,int) setWidth; // set width of a column, with resize direction | |
805 void delegate (uint,uint) sADD; // setupAlignDimData dlgs | |
806 void delegate (bool) newMW; // propegate or finalize minimal width change | |
807 } | |
808 CallbackStruct cbs[]; | |
809 | |
793 protected: | 810 protected: |
794 /* Minimal width for each column. | 811 /* Minimal width for each column. |
795 * | 812 * |
796 * Set by setWidths. */ | 813 * Set by setWidths. */ |
797 wdim[] minWidth; | 814 wdim[] minWidth; |
801 ptrdiff_t resizeD, // resizeCols works down from this index (<0 if not resizing) | 818 ptrdiff_t resizeD, // resizeCols works down from this index (<0 if not resizing) |
802 resizeU; // and up from this index | 819 resizeU; // and up from this index |
803 /* indicies of the first/last resizable column (negative if none are resizable). */ | 820 /* indicies of the first/last resizable column (negative if none are resizable). */ |
804 ptrdiff_t firstSizable = -1, lastSizable = -1; // set by calcFLSbl | 821 ptrdiff_t firstSizable = -1, lastSizable = -1; // set by calcFLSbl |
805 // Callbacks used to actually adjust a column's width: | 822 // Callbacks used to actually adjust a column's width: |
806 void delegate (size_t,wdim,int) setWidthCb[]; // set width of a column, with resize direction | |
807 void delegate (uint,uint) sADD[]; // setupAlignDimData dlgs | |
808 | 823 |
809 uint setup_n = uint.max; // param n of last setup call | 824 uint setup_n = uint.max; // param n of last setup call |
810 bool setupWidths; // setWidths has been run | 825 bool setupWidths; // setWidths has been run |
811 | 826 |
812 static HashMap!(widgetID,AlignColumns) instances; | 827 static HashMap!(widgetID,AlignColumns) instances; |