comparison mde/gui/WidgetManager.d @ 111:1655693702fc

Resolved ticket #4, allowing widgets to reload strings and recalculate sizes mid-run. Removed prefinalize and finalize and added setup as the new second initialization phase, which can be re-run.
author Diggory Hardy <diggory.hardy@gmail.com>
date Sat, 06 Dec 2008 17:41:42 +0000
parents 6acd96f8685f
children fe061009029d
comparison
equal deleted inserted replaced
110:6acd96f8685f 111:1655693702fc
171 IRenderer renderer () { 171 IRenderer renderer () {
172 assert (rend !is null, "WidgetManager.renderer: rend is null"); 172 assert (rend !is null, "WidgetManager.renderer: rend is null");
173 return rend; 173 return rend;
174 } 174 }
175 175
176 /** Place a pop-up widget near px,py.
177 *
178 * WidgetManager sets its position, draws it, passes it click events and removes it; other
179 * functionality should be handled by the widget's parent. */
176 void addPopup (wdabs px, wdabs py, IChildWidget widg) { 180 void addPopup (wdabs px, wdabs py, IChildWidget widg) {
177 ActivePopup popup; 181 ActivePopup popup;
178 with (popup) { 182 with (popup) {
179 widget = widg; 183 widget = widg;
180 w = widg.width; 184 w = widg.width;
212 if (rend is null) 216 if (rend is null)
213 rend = createRenderer (rendName); 217 rend = createRenderer (rendName);
214 popups = new CircularList!(ActivePopup); 218 popups = new CircularList!(ActivePopup);
215 219
216 child = makeWidget ("root"); 220 child = makeWidget ("root");
217 finalize; 221 child.setup (0, 3);
218 222
219 mw = child.minWidth; 223 mw = child.minWidth;
220 mh = child.minHeight; 224 mh = child.minHeight;
221 225
222 if (w < mw || h < mh) 226 if (w < mw || h < mh)
442 } 446 }
443 447
444 /** Called when translation strings have been reloaded. */ 448 /** Called when translation strings have been reloaded. */
445 void reloadStrings (AContent c) { 449 void reloadStrings (AContent c) {
446 Items.loadTranslation; 450 Items.loadTranslation;
447 child.reloadStrings; //FIXME : all widgets, resize 451 child.setup (++setupN, 2);
452 child.setPosition (0,0);
448 requestRedraw; 453 requestRedraw;
449 } 454 }
450 455
451 protected: 456 protected:
452 /** Second stage of loading the widgets. 457 /** Second stage of loading the widgets.
453 * 458 *
454 * loadDesign handles the data; this method needs to: 459 * loadDesign handles the data; this method needs to:
455 * --- 460 * ---
456 * // 1. Create the root widget: 461 * // 1. Create the root widget:
457 * child = makeWidget ("root"); 462 * child = makeWidget ("root");
458 * finalize; 463 * child.setup (0, 3);
459 * // 2. Set the setSize, e.g.: 464 * // 2. Set the size:
460 * child.setWidth (child.minWidth, 1); 465 * child.setWidth (child.minWidth, 1);
461 * child.setHeight (child.minHeight, 1); 466 * child.setHeight (child.minHeight, 1);
467 * // 3. Set the position (necessary part of initialization):
468 * child.setPosition (0,0);
462 * --- 469 * ---
463 */ 470 */
464 void createRootWidget(); 471 void createRootWidget();
465
466 /** Runs finalize for all descendants, in a deepest first order. */
467 /* NOTE: The way this function works may seem a little odd, but it's designed to allow
468 * shared alignments to be initialized properly:
469 * 1. all sharing members need to know their children's min size
470 * 2. all sharing members need to add their children's min size to the alignment
471 * 3. all sharing members can only then get their min size
472 * This method will fail if alignment members are not all of the same generation. An alternate
473 * method without this drawback would be to have shared alignments created with a list of
474 * pointers to their members, and once all members have been created the alignment could
475 * initialize itself, first making sure each members' children have been initialized. */
476 void finalize () {
477 IChildWidget[][] descendants; // first index: depth; is a list of widgets at each depth
478
479 void recurseChildren (size_t depth, IChildWidget widget) {
480 foreach (child; widget.children)
481 recurseChildren (depth+1, child);
482
483 if (descendants.length <= depth)
484 descendants.length = depth * 2 + 1;
485 descendants[depth] ~= widget;
486 }
487
488 recurseChildren (0, child);
489 foreach_reverse (generation; descendants) {
490 foreach (widget; generation)
491 widget.prefinalize;
492 foreach (widget; generation)
493 widget.finalize;
494 }
495 }
496 472
497 /** Called before saving (usually when the GUI is about to be destroyed, although not 473 /** Called before saving (usually when the GUI is about to be destroyed, although not
498 * necessarily). */ 474 * necessarily). */
499 void preSave (); 475 void preSave ();
500 476
532 WidgetDataChanges changes; // Changes for the current design. 508 WidgetDataChanges changes; // Changes for the current design.
533 scope mt.DataSet changesDS; // changes and sections from user file (used for saving) 509 scope mt.DataSet changesDS; // changes and sections from user file (used for saving)
534 bool loadUserFile = true; // still need to load user file for saving? 510 bool loadUserFile = true; // still need to load user file for saving?
535 511
536 scope IChildWidget child; // The primary widget. 512 scope IChildWidget child; // The primary widget.
513 uint setupN; // n to pass to IChildWidget.setup
537 514
538 Mutex mutex; // lock on methods for use outside the package. 515 Mutex mutex; // lock on methods for use outside the package.
539 } 516 }