diff mde/gui/WidgetManager.d @ 92:085f2ca31914

Shared alignments supported in more complex cases.
author Diggory Hardy <diggory.hardy@gmail.com>
date Tue, 21 Oct 2008 09:57:19 +0100
parents 4d5d53e4f881
children 08a4ae11454b
line wrap: on
line diff
--- a/mde/gui/WidgetManager.d	Thu Oct 16 17:43:48 2008 +0100
+++ b/mde/gui/WidgetManager.d	Tue Oct 21 09:57:19 2008 +0100
@@ -62,8 +62,7 @@
         Screen.addDrawable (this);
     }
     
-    // NOTE - temporarily here to allow CTOR to run safely during static this
-    // called during init
+    // this() runs during static this(), when imde.input doesn't exist. init() runs later.
     void init () {
         // Doesn't need a lock - cannot conflict with other class functions.
         // Events we want to know about:
@@ -170,6 +169,7 @@
             rend = createRenderer (rendName);
         
         child = makeWidget ("root");
+        finalize;
         
         mw = child.minWidth;
         mh = child.minHeight;
@@ -384,7 +384,7 @@
     /** Create a widget by ID.
      *
      * A widget instance is created from data found under ID. Multiple instances may be created.
-     * FIXME - data conflicts when saving?
+     * NOTE - data conflicts when saving?
      *
      * An IContent may be passed. This could contain many things, e.g. some basic data, a widget,
      * multiple sub-IContents. It is only passed to the widget by createWidget if it's enumeration
@@ -394,6 +394,37 @@
         return createWidget (this, id, curData[id], content);
     }
     
+    /** Runs finalize for all descendants, in a deepest first order. */
+    /* NOTE: The way this function works may seem a little odd, but it's designed to allow
+     * shared alignments to be initialized properly:
+     * 1. all sharing members need to know their children's min size
+     * 2. all sharing members need to add their children's min size to the alignment
+     * 3. all sharing members can only then get their min size
+     * This method will fail if alignment members are not all of the same generation. An alternate
+     * method without this drawback would be to have shared alignments created with a list of
+     * pointers to their members, and once all members have been created the alignment could
+     * initialize itself, first making sure each members' children have been initialized. */
+    void finalize () {
+        IChildWidget[][] descendants;   // first index: depth; is a list of widgets at each depth
+        
+        void recurseChildren (size_t depth, IChildWidget widget) {
+            foreach (child; widget.children)
+                recurseChildren (depth+1, child);
+            
+            if (descendants.length <= depth)
+                descendants.length = depth * 2 + 1;
+            descendants[depth] ~= widget;
+        }
+        
+        recurseChildren (0, child);
+        foreach_reverse (generation; descendants) {
+            foreach (widget; generation)
+                widget.prefinalize;
+            foreach (widget; generation)
+                widget.finalize;
+        }
+    }
+    
     /** For making changes. */
     void setData (widgetID id, WidgetData d) {
         changes[id] = d;        // also updates WidgetDataSet in data.
@@ -405,6 +436,7 @@
     * ---
     * // 1. Create the root widget:
     * child = makeWidget ("root");
+    * finalize;
     * // 2. Set the setSize, e.g.:
     * child.setWidth  (child.minWidth,  1);
     * child.setHeight (child.minHeight, 1);