diff mde/gui/gui.d @ 30:467c74d4804d

Major changes to the scheduler, previously only used by the main loop. Revamped Scheduler. Functions can be removed, have multiple schedules, have their scheduling changed, etc. Scheduler has a unittest. Checked all pass. Main loop scheduler moved to mde. Draw-on-demand currently disabled, simplifying this. Made mtunitest.d remove the temporary file it uses afterwards. committer: Diggory Hardy <diggory.hardy@gmail.com>
author Diggory Hardy <diggory.hardy@gmail.com>
date Mon, 28 Apr 2008 10:59:47 +0100
parents f985c28c0ec9
children baa87e68d7dc
line wrap: on
line diff
--- a/mde/gui/gui.d	Sat Apr 12 14:10:13 2008 +0100
+++ b/mde/gui/gui.d	Mon Apr 28 10:59:47 2008 +0100
@@ -30,17 +30,27 @@
 import tango.scrapple.text.convert.parseTo : parseTo;
 import tango.scrapple.text.convert.parseFrom : parseFrom;
 
+import tango.util.log.Log : Log, Logger;
+
 private Logger logger;
 static this () {
     logger = Log.getLogger ("mde.gui.gui");
     
-    init.addFunc (&GUI.load, "GUI.load");
+    init.addFunc (&loadGUI, "loadGUI");
 }
 
+GUI gui;    // Currently just one instance; handle differently later.
+// Wrap gui.load, since init doesn't handle delegates
+// (do it this way since GUI handling will eventually be changed)
+void loadGUI () {
+    gui.load();
+}
+
+/** A GUI handles a bunch of windows, all to be drawn to the same device. */
 struct GUI {
-static:
-    private const fileName = "gui";
+    /** Load all windows from the file gui. */
     void load() {
+        static const fileName = "gui";
         if (!confDir.exists (fileName)) {
             logger.error ("Unable to load GUI: no config file!");
             return; // not a fatal error (so long as the game can run without a GUI!)
@@ -65,20 +75,32 @@
         windows.length = 0;
         foreach (sec; reader.dataset.sec) {
             Window w = cast(Window) sec;
-            if (w !is null) {                       // extra safety
-                windows ~= w;
-                try {
-                    w.finalise();
-                    
-                    gl.addDrawCallback (&w.draw);
-                } catch (WindowLoadException e) {
-                    logger.error ("Window failed to load: " ~ e.msg);
-                }
+            debug if (w is null) {
+                logger.error (__FILE__ ~ "(GUI.load): code error (w is null)");
+                continue;
+            }
+            try {
+                //logger.trace ("1");
+                int x;
+                w.finalise();
+                x = 6;
+                windows ~= w;       // only add if load successful
+            } catch (WindowLoadException e) {
+                logger.error ("Window failed to load: " ~ e.msg);
             }
         }
     }
     
-private:
+    /** Draw each window.
+    *
+    * Currently no concept of how to draw overlapping windows, or how to not bother drawing windows
+    * which don't need redrawing. */
+    void draw() {
+        foreach (w; windows)
+            w.draw();
+    }
+    
+    private:
     Window[] windows;
 }
 
@@ -95,40 +117,50 @@
 class Window : mt.IDataSection, IWindow
 {
     alias int widgetID;     // Widget ID type. Each ID is unique under this window. Type is int since this is the widget data type.
-    private int[][widgetID] widgetData;     // Data for all widgets under this window.
-    private Widget[widgetID] widgets;       // List of all widgets under this window (created on demand).
     
-    Widget widget;                  // The primary widget in this window.
-    int x,y;                        // Window position
-    int w,h;                        // Window size (calculated from Widgets)
-    
-    const BORDER_WIDTH = 8;         // Temporary way to handle window decorations
-    
-    
-    // Call after loading is finished to setup the window and confirm that it's valid.
+    /** Call after loading is finished to setup the window and confirm that it's valid.
+    *
+    * Throws: WindowLoadException. Do not use the instance in this case! */
     void finalise () {
-        // Create the widget, throwing on error:
+        // Check data was loaded:
+        if (widgetData is null) throw new WindowLoadException ("No widget data");
+        
+        // Create the primary widget (and indirectly all sub-widgets), throwing on error:
         widget = getWidget (0);     // primary widget always has ID 0.
-        widget.getSize (w,h);       // Find the initial size
+        
+        widgetData = null;          // data is no longer needed: allow GC to collect (cannot safely delete)
+        
+        widget.getCurrentSize (w,h);// Find the initial size
         w += BORDER_WIDTH * 2;      // Adjust for border
         h += BORDER_WIDTH * 2;
     }
     
-    Widget getWidget (widgetID i) {
+    /** Get/create a widget by ID.
+    *
+    * Should $(I only) be called internally and by sub-widgets! */
+    IWidget getWidget (widgetID i)
+    in {
+        // widgetData is normally left to be garbage collected after widgets have been created:
+        assert (widgetData !is null, "getWidget: widgetData is null");
+    } body {
         // See if it's already been created:
-        Widget* p = i in widgets;
+        IWidget* p = i in widgets;
         if (p !is null) return *p;  // yes
         else {                      // no
             int[]* d = i in widgetData;
             if (d is null) throw new WindowLoadException ("Widget not found");
             
             // Throws WidgetDataException (a WindowLoadException) if bad data:
-            Widget w = createWidget (this, *d);
+            IWidget w = createWidget (this, *d);
             widgets[i] = w;
             return w;
         }
     }
     
+    void requestRedraw () {
+    //FIXME
+    }
+    
     void draw () {
         //BEGIN Window border/back
         gl.setColor (0.0f, 0.0f, 0.5f);
@@ -156,4 +188,15 @@
     void writeAll (ItemDelg dlg) {
     }
     //END Mergetag code
+    
+    private:
+    int[][widgetID] widgetData;     // Data for all widgets under this window (deleted after loading)
+    IWidget[widgetID] widgets;      // List of all widgets under this window (created on demand).
+    
+    IWidget widget;                 // The primary widget in this window.
+    int x,y;                        // Window position
+    int w,h;                        // Window size (calculated from Widgets)
+    
+    const BORDER_WIDTH = 8;         // Temporary way to handle window decorations
+
 }