changeset 96:dbf332403c6e

Improvements to FloatingAreaWidget: positioning, passing click events and draw order.
author Diggory Hardy <diggory.hardy@gmail.com>
date Thu, 06 Nov 2008 13:16:39 +0000
parents 2a364c7d82c9
children 30470bc19ca4
files data/conf/gui.mtt doc/Readme.txt mde/font/FontTexture.d mde/gui/WidgetManager.d mde/gui/widget/Floating.d mde/gui/widget/Ifaces.d mde/gui/widget/TextWidget.d mde/gui/widget/Widget.d
diffstat 8 files changed, 86 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/data/conf/gui.mtt	Thu Nov 06 11:07:18 2008 +0000
+++ b/data/conf/gui.mtt	Thu Nov 06 13:16:39 2008 +0000
@@ -4,7 +4,7 @@
 {Working}
 <WidgetData|root={0:[0xC100,0,3,3],1:["square","blank","square","blank","content","blank","square","blank","square"]}>
 <WidgetData|square={0:[0x1,6,6]}>
-<WidgetData|content={0:[0xC100,0,4,2],1:["floating","button","blank","blank","f2","opts","blank","blank"]}>
+<WidgetData|content={0:[0xC100,0,3,1],1:["floating","opts","blank"]}>
 <WidgetData|button={0:[0x10,50,50]}>
 <WidgetData|blank={0:[0x2]}>
 <WidgetData|opts={0:[0x8110,0],1:["optDBox","VideoOptions"]}>
@@ -14,8 +14,7 @@
 <WidgetData|optDesc={0:[0x4020, 2, 0xaf6000]}>
 <WidgetData|optVal={0:[0x6030]}>
 <WidgetData|optSep={0:[0x21, 0xff],1:["="]}>
-<WidgetData|floating={0:[0x8200,20,20],1:["text"]}>
-<WidgetData|f2={0:[0x8200,50,20],1:["button"]}>
-<WidgetData|text={0:[0x21,0xFF0000],1:["Floating text"]}>
+<WidgetData|floating={0:[0x8200],1:["text","button"]}>
+<WidgetData|text={0:[0x21,0xE0E000],1:["Floating text"]}>
 {Basic}
 <WidgetData|root={0:[0x21,0x90D970],1:["A string!"]}>
--- a/doc/Readme.txt	Thu Nov 06 11:07:18 2008 +0000
+++ b/doc/Readme.txt	Thu Nov 06 13:16:39 2008 +0000
@@ -30,6 +30,7 @@
 
 Credits:
 Me (Diggory Hardy) for just about everything in mde as of now.
+Someone (?) for the toDg function in mde.util .
 
 Also thanks to:
 Walter Bright and Digital Mars for D and DMD.
--- a/mde/font/FontTexture.d	Thu Nov 06 11:07:18 2008 +0000
+++ b/mde/font/FontTexture.d	Thu Nov 06 13:16:39 2008 +0000
@@ -253,7 +253,7 @@
         }
         // if here, no existing texture had the room for the glyph so create a new texture
         // NOTE: check if using more than one texture impacts performance due to texture switching
-        logger.info ("Creating a new font texture.");
+        debug logger.trace ("Creating a new font texture.");
         tex ~= TexPacker.create();
         assert (tex[$-1].addGlyph (ga), "Failed to fit glyph in a new texture but addGlyph didn't throw");
         
--- a/mde/gui/WidgetManager.d	Thu Nov 06 11:07:18 2008 +0000
+++ b/mde/gui/WidgetManager.d	Thu Nov 06 13:16:39 2008 +0000
@@ -101,6 +101,7 @@
             return;
         }
         IChildWidget widg = child.getWidget (cast(wdabs)cx,cast(wdabs)cy);
+        //debug logger.trace ("Click on {}", widg);
         if (widg !is null)
             widg.clickEvent (cast(wdabs)cx,cast(wdabs)cy,b,state);
     }
--- a/mde/gui/widget/Floating.d	Thu Nov 06 11:07:18 2008 +0000
+++ b/mde/gui/widget/Floating.d	Thu Nov 06 13:16:39 2008 +0000
@@ -33,21 +33,12 @@
 static this () {
     logger = Log.getLogger ("mde.gui.widget.Floating");
 }
-//FIXME - documentation
 
-/** GUI Window class
- *
- * A window class instance does two things: (1) specify a region of the screen upon which the window
- * and its associated widgets are drawn, and (2) load, save, and generally manage all its widgets.
- *
- * Let the window load a table of widget data, of type int[][widgetID]. Each widget will, when
- * created, be given its int[] of data, which this() must confirm is valid (or throw).
- */
 /** An area to contain floating widgets.
  *
- * The position of each sub-widget is set from data, but not the size.
+ * The position of each sub-widget is set from dimension data, but not the size.
  * Rationale: parents' need to set subwidgets' positions when its position is set, so it needs to
- * know their positions. Size setting is still under work FIXME.
+ * know their positions.
  *
  * Data: Each string item is interpreted as a subwidget widgetID.
  * Ints supplied may consist of just the widget type or
@@ -56,29 +47,57 @@
 class FloatingAreaWidget : AParentWidget
 {
     this (IWidgetManager mgr, widgetID id, WidgetData data) {
-        subWidgets.length = data.strings.length;
-        foreach (i,s; data.strings)
-            subWidgets[i] = mgr.makeWidget (s);
-        foreach (w; subWidgets)
-            w.finalize;
-        sWCoords.length = subWidgets.length;
+        if (data.ints.length != 1)
+            throw new WidgetDataException (this);
         
-        if (data.ints.length != 1) {
-            if (data.ints.length != 2*subWidgets.length + 1) {
-                throw new WidgetDataException (this);
-            }
-            foreach (i, ref c; sWCoords) {
-                c.x = cast(wdim) data.ints[i + 1];
-                c.y = cast(wdim) data.ints[i + 1 + sWCoords.length];
-            }
+        subWidgets.length = data.strings.length;        // widgets created from string data
+        sWOrder.length = subWidgets.length;
+        foreach (i,s; data.strings) {
+            subWidgets[i] = mgr.makeWidget (s);
+            sWOrder[i] = i;
+        }
+        
+        sWCoords = mgr.dimData (id);
+        if (sWCoords.length != subWidgets.length * 2) {
+            // don't bother logging a warning; correct data will be saved anyway
+            sWCoords.length = subWidgets.length * 2;    // maybe some data kept
         }
         
         super (mgr, id, data);
+    }
+    
+    bool saveChanges () {
+        foreach (widget; subWidgets)
+            widget.saveChanges ();
         
-        foreach (w; subWidgets) {
-            //FIXME: set default size
-            w.setWidth  (w.minWidth, -1);
-            w.setHeight (w.minHeight, -1);
+        mgr.setDimData (id, sWCoords);  // save positions
+        return true;
+    }
+    
+    void setWidth (wdim nw, int) {
+        w = nw;
+        // check all floating widgets are visible
+        foreach (i, widg; subWidgets) {
+            wdim d;
+            if (sWCoords[i] + (d = widg.width) > w) {
+                if (d > w)
+                    sWCoords[i] = 0;
+                else
+                    sWCoords[i] = w - d;
+            }
+        }
+    }
+    void setHeight (wdim nh, int) {
+        h = nh;
+        foreach (i, widg; subWidgets) {
+            wdim d;
+            size_t n = i + subWidgets.length;
+            if (sWCoords[n] + (d = widg.height) > h) {
+                if (d > h)
+                    sWCoords[n] = 0;
+                else
+                    sWCoords[n] = h - d;
+            }
         }
     }
     
@@ -88,8 +107,9 @@
     void setPosition (wdim x, wdim y) {
         super.setPosition (x,y);
         
-        foreach (i,c; sWCoords)
-            subWidgets[i].setPosition (x+c.x, y+c.y);
+        size_t n = subWidgets.length;
+        foreach (i,widg; subWidgets)
+            widg.setPosition (x+sWCoords[i], y+sWCoords[i+n]);
     }
     
     void draw () {
@@ -97,12 +117,32 @@
         
         mgr.renderer.restrict (x,y, w,h);
         
-        foreach (w; subWidgets)
-            w.draw;
+        foreach (i; sWOrder)
+            subWidgets[i].draw;
+    }
+    
+    IChildWidget getWidget (wdim cx, wdim cy) {
+        debug assert (cx >= x && cx < x + w && cy >= y && cy < y + h, "getWidget: not on widget (code error)");
+        
+        size_t n = subWidgets.length;
+        foreach_reverse (j,i; sWOrder) {
+            wdim lx = cx - (x + sWCoords[i  ]);
+            wdim ly = cy - (y + sWCoords[i+n]);
+            if (lx >= 0 && lx < subWidgets[i].width &&
+                ly >= 0 && ly < subWidgets[i].height)
+            {
+                sWOrder[j..$-1] = sWOrder[j+1..$].dup;
+                sWOrder[$-1] = i;
+                mgr.requestRedraw;
+                return subWidgets[i];
+            }
+        }
+        return this;    // no match
     }
     
 protected:
-    wdimPair[] sWCoords;        // coords for subwidgets, relative to this widget
+    wdim[] sWCoords;    // coords for subwidgets, relative to this widget: [x1,x2,...,y1,y2,...]
+    size_t[] sWOrder;   // indexes for draw order (top widget at end of list)
     
     /+
     /** Call after loading is finished to setup the window and confirm that it's valid.
--- a/mde/gui/widget/Ifaces.d	Thu Nov 06 11:07:18 2008 +0000
+++ b/mde/gui/widget/Ifaces.d	Thu Nov 06 13:16:39 2008 +0000
@@ -138,9 +138,9 @@
  * initialisation data. The method should throw a WidgetDataException (created without
  * parameters) if the data has wrong length or is otherwise invalid.
  *
- * A parent widget is responsible for setting the size of its children widgets, however it must
- * satisfy their minimal sizes as available from minWidth() and minHeight(). setWidth() and
- * setHeight() are called on all widgets after creation.
+ * All widgets should set their own size in this() or finalize(), although some parents may set
+ * child-widgets' size during their creation. Widgets may rely on setPosition() being called after
+ * finalize().
  * 
  * Also see finalize().
  *************************************************************************************************/
--- a/mde/gui/widget/TextWidget.d	Thu Nov 06 11:07:18 2008 +0000
+++ b/mde/gui/widget/TextWidget.d	Thu Nov 06 13:16:39 2008 +0000
@@ -41,6 +41,8 @@
      * adapter = mgr.renderer.getAdapter ("string", 0xRRGGBB); */
     this (IWidgetManager mgr, widgetID id, WidgetData data) {
         adapter.getDimensions (mw, mh);
+        w = mw;
+        h = mh;
         super (mgr, id, data);
     }
     
--- a/mde/gui/widget/Widget.d	Thu Nov 06 11:07:18 2008 +0000
+++ b/mde/gui/widget/Widget.d	Thu Nov 06 13:16:39 2008 +0000
@@ -208,7 +208,7 @@
 
 /** For pressable buttons.
  *
- * Normally overriding classes implement this, draw and activated. */
+ * Overriding classes should implement this() (setting the size), draw() and activated(). */
 abstract class AButtonWidget : AWidget
 {
     protected this (IWidgetManager mgr, widgetID id, WidgetData data) {