Mercurial > projects > mde
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 + }