changeset 65:891211f034f2

Changes to widgets: widgets may now get strings as creation data. Strings for TextWidgets can be set in files (in a temporary mannor).
author Diggory Hardy <diggory.hardy@gmail.com>
date Sun, 29 Jun 2008 15:40:37 +0100
parents cc3763817b8a
children f54ae4fc2b2f 108d123238c0
files mde/gui/Gui.d mde/gui/content/Content.d mde/gui/widget/Ifaces.d mde/gui/widget/TextWidget.d mde/gui/widget/Widget.d mde/gui/widget/Window.d mde/gui/widget/layout.d
diffstat 7 files changed, 105 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/mde/gui/Gui.d	Sun Jun 29 11:55:55 2008 +0100
+++ b/mde/gui/Gui.d	Sun Jun 29 15:40:37 2008 +0100
@@ -159,6 +159,7 @@
                 windows = w ~ windows[0..i] ~ windows[i+1..$];
                 
                 widg.clickEvent (cast(wdabs)cx,cast(wdabs)cy,b,state);
+                requestRedraw;	// in case we've only moved to front
                 return;     // only pass to first window
             }
         }
--- a/mde/gui/content/Content.d	Sun Jun 29 11:55:55 2008 +0100
+++ b/mde/gui/content/Content.d	Sun Jun 29 15:40:37 2008 +0100
@@ -48,6 +48,16 @@
     char[] toString ();
 }
 
+/** Get a content from the list (what list?). */
+ContentText getContentText (char[] id) {
+    return new ContentText (id);	// forget the list for now
+}
+
+/** ditto */
+ContentInt getContentInt (char[] id) {
+    return new ContentInt (42);	// forget the list for now
+}
+
 /** Text content. */
 /* May end up extending a universal content type.
  *  Services like copy/paste could work on universal content.
@@ -58,10 +68,7 @@
  *  where ContentTextStruct is a struct. */
 class ContentText : Content
 {
-    this () {
-        // NOTE: testing
-        text_ = "\"a@b\" − an example";
-    }
+    this () {}
     this (char[] text) {
         text_ = text;
     }
@@ -93,10 +100,7 @@
 /** Integer content. */
 class ContentInt : Content
 {
-    this () {
-        // NOTE: testing
-        int_ = -496;
-    }
+    this () {}
     this (int integer) {
         int_ = integer;
     }
--- a/mde/gui/widget/Ifaces.d	Sun Jun 29 11:55:55 2008 +0100
+++ b/mde/gui/widget/Ifaces.d	Sun Jun 29 15:40:37 2008 +0100
@@ -17,7 +17,7 @@
 module mde.gui.widget.Ifaces;
 
 public import mde.gui.renderer.IRenderer;
-import mde.gui.IGui;
+public import mde.gui.IGui;
 
 /** Interface for Window, allowing widgets to call some of Window's methods.
  *
@@ -40,9 +40,15 @@
      * been created, creates it using the Window's widget creation data. */
     IWidget makeWidget (widgetID i);
     
+    /** Get a string from the widgetString associative array. */
+    char[] getWidgetString (int i);
+    
     /** Add widget's saveData to the data to be saved, returning it's widgetID. */
     widgetID addCreationData (IWidget widget);
     
+    /** Add a string to the widgetString associative array, returning it's index. */
+    int addWidgetString (char[] str);
+    
     /** Returns the window's gui. */
     IGui gui ();
     
@@ -64,8 +70,14 @@
  * A widget is a region of a GUI window which handles rendering and user-interaction for itself
  * and is able to communicate with it's window and parent/child widgets as necessary.
  *
- * A widget's constructor should have this prototype:
+ * A widget's constructor should have the prototype and doc explaining what initialization data is
+ * used (excluding the widget ID, which every widget recieves):
  * ----------------------------------
+ * /++ Constructor for a ... widget.
+ *  +
+ *  + Widget uses the initialisation data:
+ *  + [widgetID, x, y]
+ *  + where x is ... and y is ... +/
  * this (IWindow window, int[] data);
  * ----------------------------------
  * Where window is the root window (the window to which the widget belongs) and data is an array of
@@ -95,6 +107,9 @@
     
     /** Output data suitible for recreating the widget (data to be passed to this()).
      *
+     * Function may need to call Window's addCreationData() and addWidgetString() methods to save
+     * other data.
+     *
      * Creation data is data only changed when the gui is edited. */
     int[] getCreationData ();
     
--- a/mde/gui/widget/TextWidget.d	Sun Jun 29 11:55:55 2008 +0100
+++ b/mde/gui/widget/TextWidget.d	Sun Jun 29 15:40:37 2008 +0100
@@ -30,10 +30,14 @@
 
 /// Adapter to ease use of ContentText
 struct ContentAdapter(ContentT : IContent) {
-    void set (int col) {
+    void set (char[] cID, int col) {
         if (font is null) font = FontStyle.get("default");
         
-        content = new ContentT;
+        static if (is(ContentT == ContentText)) {
+            content = getContentText (cID);
+        } else static if (is(ContentT == ContentInt)) {
+            content = getContentInt (cID);
+        } else static assert (false, "Unsupported content type");
         colour = Colour (cast(ubyte) (col >> 16u),
                          cast(ubyte) (col >> 8u),
                          cast(ubyte) col );
@@ -58,9 +62,15 @@
 /// Basic text widget
 class ContentWidget(ContentT : IContent) : Widget
 {
+    /** Constructor for a widget containing [fixed] content.
+     *
+     * Widget uses the initialisation data:
+     * [widgetID, contentID, colour]
+     * where contentID is an ID for the string ID of the contained content
+     * and colour is an 8-bit-per-channel RGB colour of the form 0xRRGGBB. */
     this (IWindow wind, int[] data) {
-        if (data.length != 2) throw new WidgetDataException;
-        text.set (data[1]);
+        if (data.length != 3) throw new WidgetDataException;
+        text.set (wind.getWidgetString(data[1]), data[2]);
         text.getDimensions (mw, mh);
         super (wind,data);
     }
--- a/mde/gui/widget/Widget.d	Sun Jun 29 11:55:55 2008 +0100
+++ b/mde/gui/widget/Widget.d	Sun Jun 29 15:40:37 2008 +0100
@@ -32,6 +32,7 @@
 {
 //BEGIN Load and save
     // Base this(). All widgets must check data.length is correct before calling this method.
+    // The widget ID is saved to widgetType, for correct saving.
     this (IWindow wind, int[] data) {
         window = wind;
         widgetType = data[0];
@@ -114,6 +115,11 @@
 /** A base for fixed-size widgets taking their size from the creation data. */
 class FixedWidget : Widget {
     // Check data.length is at least 3 before calling!
+    /** Constructor for a fixed-size [blank] widget.
+     *
+     * Widget uses the initialisation data:
+     * [widgetID, w, h]
+     * where w, h is the fixed size. */
     this (IWindow wind, int[] data) {
         mw = cast(wdim) data[1];
         mh = cast(wdim) data[2];
@@ -129,6 +135,7 @@
 /** A base for resizable widgets. */
 class SizableWidget : Widget {
     // Check data.length is at least 1 before calling!
+    /// Constructor for a completely resizable [blank] widget.
     this (IWindow wind, int[] data) {
         super (wind, data);
     }
--- a/mde/gui/widget/Window.d	Sun Jun 29 11:55:55 2008 +0100
+++ b/mde/gui/widget/Window.d	Sun Jun 29 15:40:37 2008 +0100
@@ -69,7 +69,10 @@
         // Create the primary widget (and indirectly all sub-widgets), throwing on error:
         // Note: GridLayoutWidget's this relies on rend.layoutSpacing.
         widget = makeWidget (0);        // primary widget always has ID 0.
-        widgetData = null;  // data is no longer needed: allow GC to collect (cannot safely delete)
+        // This data is no longer needed by Window, although its sub-arrays may still be used, so
+        // let the GC collect what it can:
+        widgetData = null;
+        widgetStrings = null;
         
         // get border sizes:
         border = rend.setSizable (isWSizable, isHSizable);  // depends on widget
@@ -98,10 +101,14 @@
     //BEGIN Mergetag code
     void addTag (char[] tp, mt.ID id, char[] dt) {
         // Priority is HIGH_LOW, so don't overwrite data which has already been loaded.
-        if (tp == INTAA) {
+        if (tp == INTAINT) {
             if (id == WDGD && widgetData == null) {
                 widgetData = cast(int[][widgetID]) parseTo!(int[][int]) (dt);
             }
+        } else if (tp == CHARAINT) {
+            if (id == WS && widgetStrings == null) {
+                widgetStrings = parseTo!(char[][int]) (dt);
+            }
         } else if (tp == INTA) {
             if (id == MD && mutableData == null) {
                 mutableData = parseTo!(int[]) (dt);
@@ -121,7 +128,8 @@
         /+ NOTE: currently editing is impossible...
         if (edited) {   // only save the widget creation data if it's been adjusted:
             addCreationData (widget);   // generate widget save data
-            dlg (INTAA, WDGD, parseFrom!(int[][int]) (widgetData));
+            dlg (INTAINT, WDGD, parseFrom!(int[][int]) (widgetData));
+            dlg (CHARAINT, WS, parseFrom!(char[][int]) (widgetStrings));
         }+/
         // Save mutable data:
         dlg (INTA, MD, parseFrom!(int[]) (widget.getMutableData));
@@ -130,11 +138,13 @@
         dlg (INT, Y, parseFrom!(int) (y));
     }
     private static const {
-        auto INTAA = "int[][int]";
+        auto CHARAINT = "char[][int]";
+        auto INTAINT = "int[][int]";
         auto INTA = "int[]";
         auto INT = "int";
         auto WDGD = "widgetData";
         auto MD = "mutableData";
+        auto WS = "widgetStrings";
         auto X = "x";
         auto Y = "y";
     }
@@ -161,6 +171,20 @@
         return createWidget (this, *d);
     }
     
+    char[] getWidgetString (int i)
+    in {
+        // widgetStrings is freed at same time as widgetData
+        // but widgetData is guaranteed to be read
+        assert (widgetData !is null, "getWidgetString called after widget creation finished");
+    } body {
+        char[]* p;
+        if (widgetStrings is null ||
+             (p = i in widgetStrings) is null )
+            throw new WindowLoadException ("Needed widgetStrings not set for Window");
+        
+        return *p;
+    }
+    
     /** Add this widget's data to that to be saved, returning it's widgetID. */
     widgetID addCreationData (IWidget widget)
     {
@@ -170,12 +194,31 @@
         else
             i = widgetData.keys[$-1] + 1;
         
+        /+ Doesn't this have no effect except when getCreationData throws, in which case the data
+         + isn't used anyway? I'm sure it was added for a reason... FIXME and below
         widgetData[i] = null;   // Make sure the same ID doesn't get used by a recursive call
+        +/
         widgetData[i] = widget.getCreationData;
         
         return i;
     }
     
+    int addWidgetString (char[] str)
+    {
+        int i;
+        if (widgetStrings is null)
+            i = 0;
+        else
+            i = widgetStrings.keys[$-1] + 1;
+        
+        /+ See above. FIXME
+        widgetStrings[i] = null;   // Make sure the same ID doesn't get used by a recursive call
+        +/
+        widgetStrings[i] = str;
+        
+        return i;
+    }
+    
     IGui gui () {
         return gui_;
     }
@@ -356,6 +399,7 @@
     // Data used for saving and loading (null in between):
     int[][widgetID] widgetData = null;// Data for all widgets under this window
     int[] mutableData = null;       // Widget's mutable data (adjusted sizes, etc.)
+    char[][int] widgetStrings = null;// Strings by ID; string-typed creation data
     
     IGui gui_;                      // The gui managing this window
     IRenderer rend;                 // The window's renderer
--- a/mde/gui/widget/layout.d	Sun Jun 29 11:55:55 2008 +0100
+++ b/mde/gui/widget/layout.d	Sun Jun 29 15:40:37 2008 +0100
@@ -38,6 +38,12 @@
 class GridLayoutWidget : Widget
 {
     //BEGIN Creation & saving
+    /** Constructor for a grid layout widget.
+     *
+     * Widget uses the initialisation data:
+     * [widgetID, r, c, w11, w12, ..., w1c, ..., wr1, ..., wrc]
+     * where r and c are the number of rows and columns, and wij is the ID (from parent Window's
+     * list) for the widget in row i and column j. The number of parameters must be r*c + 3. */
     this (IWindow wind, int[] data) {
         // Get grid size and check data
         // Check sufficient data for rows, cols, and at least one widget: