changeset 72:159775502bb4

The first dynamically generated widget lists, based on Options, are here!
author Diggory Hardy <diggory.hardy@gmail.com>
date Sat, 05 Jul 2008 18:27:46 +0100
parents 77c7d3235114
children 08d3b6bcf891
files codeDoc/jobs.txt data/conf/gui.mtt mde/gui/content/Content.d mde/gui/widget/Ifaces.d mde/gui/widget/TextWidget.d mde/gui/widget/createWidget.d mde/gui/widget/layout.d mde/lookup/Options.d
diffstat 8 files changed, 110 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/codeDoc/jobs.txt	Sat Jul 05 15:36:39 2008 +0100
+++ b/codeDoc/jobs.txt	Sat Jul 05 18:27:46 2008 +0100
@@ -3,7 +3,6 @@
 
 
 In progress:
-in mdeOld branch: GUI Content.
 
 
 
@@ -53,5 +52,3 @@
 
 
 Done (for mercurial log message):
-Added content IDs...
-Added widget strings...
\ No newline at end of file
--- a/data/conf/gui.mtt	Sat Jul 05 15:36:39 2008 +0100
+++ b/data/conf/gui.mtt	Sat Jul 05 18:27:46 2008 +0100
@@ -12,4 +12,4 @@
 {WEmbedded}
 <int|x=20>
 <int|y=100>
-<int[][int]|widgetData=[1:[0x4010,50,50],2:[0xB004,3,1,1,3,1],3:[0x3001],0:[0xB004,7,1,3,2,3,1,3,2,3]]>
+<int[][int]|widgetData=[0:[0xB005,0,0xB04000]]>
--- a/mde/gui/content/Content.d	Sat Jul 05 15:36:39 2008 +0100
+++ b/mde/gui/content/Content.d	Sat Jul 05 18:27:46 2008 +0100
@@ -29,10 +29,9 @@
  */
 // Don't include dimension/drawing stuff because it's renderer specific and content should not be!
 // NOTE: an interface or a class?
-alias IContent Content;	// use either name until it's settled...
-/** ditto */
 interface IContent
 {
+    /+ NOTE: None of this is really used yet, but was (mostly) intended for clipboard copying.
     /** Return a copy of self. */
     IContent dup ();
     
@@ -42,6 +41,7 @@
     // FIXME: throw or return null on error or unsupported conversion?
     ContentText	toText ();
     ContentInt	toInt ();	/// ditto
+    +/
     
     /** Every Content should be convertible to a string, which, if possible, should be a sensible
      * conversion of its content. */
@@ -66,7 +66,7 @@
  *  Could alternately be:
  *      alias ContentTextStruct* ContentText
  *  where ContentTextStruct is a struct. */
-class ContentText : Content
+class ContentText : IContent
 {
     this () {}
     this (char[] text) {
@@ -98,7 +98,7 @@
 }
 
 /** Integer content. */
-class ContentInt : Content
+class ContentInt : IContent
 {
     this () {}
     this (int integer) {
--- a/mde/gui/widget/Ifaces.d	Sat Jul 05 15:36:39 2008 +0100
+++ b/mde/gui/widget/Ifaces.d	Sat Jul 05 18:27:46 2008 +0100
@@ -70,8 +70,9 @@
  * 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 the prototype and doc explaining what initialization data is
- * used (excluding the widget ID, which every widget recieves):
+ * If a widget is to be creatable by Window.makeWidget, it must be listed in the createWidget
+ * module, have a constructor of the following form, and should implement getCreationData().
+ * Use Ddoc to explain what initialization data is used.
  * ----------------------------------
  * /++ Constructor for a ... widget.
  *  +
--- a/mde/gui/widget/TextWidget.d	Sat Jul 05 15:36:39 2008 +0100
+++ b/mde/gui/widget/TextWidget.d	Sat Jul 05 18:27:46 2008 +0100
@@ -86,3 +86,50 @@
 
 alias ContentWidget!(ContentText) TextWidget;
 alias ContentWidget!(ContentInt) IntWidget;
+
+
+/// Adapter to ease use of ContentOptionWidget
+struct ContentOptionAdapter {
+    void set (IContent c, int col) {
+        if (font is null) font = FontStyle.get("default");
+        
+        content = c;
+        colour = Colour (cast(ubyte) (col >> 16u),
+                         cast(ubyte) (col >> 8u),
+                         cast(ubyte) col );
+    }
+    
+    void getDimensions (out wdsize w, out wdsize h) {
+        font.updateBlock (content.toString, textCache);
+        w = cast(wdim) textCache.w;
+        h = cast(wdim) textCache.h;
+    }
+    
+    void draw (wdabs x, wdabs y) {
+        font.textBlock (x,y, content.toString, textCache, colour);
+    }
+    
+    IContent content;
+    TextBlock textCache;
+    Colour colour;
+    static FontStyle font;
+}
+
+/// Basic text widget
+class ContentOptionWidget : Widget
+{
+    this (IWindow wind, int[] data, IContent c) {
+        if (data.length != 2) throw new WidgetDataException;
+        content.set (c, data[1]);
+        content.getDimensions (mw, mh);
+        super (wind,data);
+    }
+    
+    void draw () {
+        super.draw();
+        content.draw (x,y);
+    }
+    
+protected:
+    ContentOptionAdapter content;
+}
--- a/mde/gui/widget/createWidget.d	Sat Jul 05 15:36:39 2008 +0100
+++ b/mde/gui/widget/createWidget.d	Sat Jul 05 18:27:46 2008 +0100
@@ -69,7 +69,8 @@
     Text		    = 0x21,
     Int			    = 0x22,
     
-    GridLayout              = LAYOUT | WSIZABLE | HSIZABLE | 0x4
+    GridLayout              = LAYOUT | WSIZABLE | HSIZABLE | 0x4,
+    TrialContentLayout      = LAYOUT | WSIZABLE | HSIZABLE | 0x5
 }
 
 //const char[][int] WIDGET_NAMES;
@@ -81,7 +82,8 @@
         "Int",
         "SizableBlank",
         "Button",
-        "GridLayout"   ];
+        "GridLayout",
+        "TrialContentLayout"];
 
 // Purely to add indentation. Could just return "" without affecting functionality.
 static char[] indent (uint i) {
--- a/mde/gui/widget/layout.d	Sat Jul 05 15:36:39 2008 +0100
+++ b/mde/gui/widget/layout.d	Sat Jul 05 18:27:46 2008 +0100
@@ -19,6 +19,9 @@
 import mde.gui.widget.Widget;
 import mde.gui.exception;
 
+import mde.gui.widget.TextWidget;
+import mde.gui.content.options;
+
 debug {
     import tango.util.log.Log : Log, Logger;
     private Logger logger;
@@ -84,24 +87,31 @@
 /*************************************************************************************************
  * Trial layout of sub-widgets of one type only.
  *************************************************************************************************/
-class TrialLayout : GridWidget
+class TrialContentLayoutWidget : GridWidget
 {
     this (IWindow wind, int[] data) {
-        assert (false, "Not ready");
-        if (data.length != 6) throw new WidgetDataException;
-        super (wind, data);
+        debug scope (failure)
+                logger.warn ("TrialContentLayoutWidget: failure");
+        if (data.length != 3) throw new WidgetDataException;
         
-        rows = data[1];
-        cols = data[2];
+        OptionList optsList = OptionList.trial();
+        rows = optsList.list.length;
+        cols = 1;
         
         // Get all sub-widgets
         subWidgets.length = rows*cols;
-        foreach (i, ref subWidget; subWidgets) {
-            //subWidget = new ContentWidget (data[3..6]);
+        foreach (i, c; optsList.list) {
+            subWidgets[i] = new ContentOptionWidget (wind, data[1..3], c);
         }
+        super (wind, data);
     }
     
+    int[] getCreationData () {
+        return [widgetType];
+    }
     
+private:
+    OptionList optsList;
 }
 
 
@@ -115,7 +125,7 @@
  *
  * The grid has no border but has spacing between widgets.
  *************************************************************************************************/
-class GridWidget : Widget
+abstract class GridWidget : Widget
 {
     //BEGIN Creation & saving
     /** Partial constructor for a grid layout widget.
--- a/mde/lookup/Options.d	Sat Jul 05 15:36:39 2008 +0100
+++ b/mde/lookup/Options.d	Sat Jul 05 18:27:46 2008 +0100
@@ -206,7 +206,7 @@
         static if (!TIsIn!(T,TYPES))
             static assert (false, "Options.set does not currently support type "~T.stringof);
         
-        mixin (`alias opts`~T.stringof~` optsVars;`);
+        mixin (`alias opts`~TName!(T)~` optsVars;`);
         
         changed = true;     // something got set (don't bother checking this isn't what it already was)
         
@@ -215,10 +215,37 @@
             optionChanges.set!(T) (cast(ID) symbol, val);
         } catch (ArrayBoundsException) {
             // log and ignore:
-            logger.error ("Options.set: unkw!");
+            logger.error ("Options.set: invalid symbol");
         }
     }
     
+    /** Get option symbol of an Options sub-class.
+     *
+     * Using this method to read an option is not necessary, but allows for generic use.  */
+    T get(T) (char[] symbol) {
+        static if (!TIsIn!(T,TYPES))
+            static assert (false, "Options.get does not currently support type "~T.stringof);
+        
+        mixin (`alias opts`~TName!(T)~` optsVars;`);
+        
+        try {
+            return *(optsVars[cast(ID) symbol]);
+        } catch (ArrayBoundsException) {
+            // log and ignore:
+            logger.error ("Options.get: invalid symbol");
+        }
+    }
+    
+    /** List the names of all options of a specific type. */
+    char[][] list(T) () {
+        static if (!TIsIn!(T,TYPES))
+            static assert (false, "Options.list does not currently support type "~T.stringof);
+        
+        mixin (`alias opts`~TName!(T)~` optsVars;`);
+        
+        return optsVars.keys;
+    }
+    
     protected {
         OptionChanges optionChanges;	// all changes to options (for saving)
     	
@@ -385,8 +412,8 @@
         static if (!TIsIn!(T,TYPES))
             static assert (false, "OptionChanges.set does not currently support type "~T.stringof);
         
-        mixin (`alias opts`~T.stringof~` optsVars;`);
-        mixin (`alias `~T.stringof~`s vars;`);
+        mixin (`alias opts`~TName!(T)~` optsVars;`);
+        mixin (`alias `~TName!(T)~`s vars;`);
         
         T** p = id in optsVars;
         if (p !is null) **p = x;
@@ -416,7 +443,7 @@
 /** A home for all miscellaneous options, at least for now. */
 OptionsMisc miscOpts;
 class OptionsMisc : Options {
-    mixin (impl!("bool useThreads, exitImmediately; int logOptions; double pollInterval; char[] L10n;"));
+    mixin (impl!("bool useThreads, exitImmediately; int logOptions; double pollInterval; char[] L10n, a,b,c;"));
     
     static this() {
         miscOpts = new OptionsMisc;