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;