diff mde/gui/widget/layout.d @ 39:5132301e9ed7

Implemented widget saving. Widget creation data saving (sub-widgets, etc:) code there but not used. Widget mutable data saving & loading: window size/position, row/column dimensions saved (still needs a fix in GridWidget.setSize()). committer: Diggory Hardy <diggory.hardy@gmail.com>
author Diggory Hardy <diggory.hardy@gmail.com>
date Wed, 07 May 2008 13:07:03 +0100
parents 8c4c96f04e7f
children b28d7adc786b
line wrap: on
line diff
--- a/mde/gui/widget/layout.d	Mon May 05 17:02:21 2008 +0100
+++ b/mde/gui/widget/layout.d	Wed May 07 13:07:03 2008 +0100
@@ -17,34 +17,74 @@
 module mde.gui.widget.layout;
 
 import mde.gui.widget.Widget;
-import mde.gui.exception : WidgetDataException;
+import mde.gui.exception;
 
 /** Encapsulates a grid of Widgets.
 *
 * Since a grid with either dimension zero is not useful, there must be at least one sub-widget. */
 class GridLayoutWidget : Widget
 {
-    this (IWindow wind, IWidget, int[] data) {
+    this (IWindow wind, int[] data) {
         // Get grid size and check data
         // Check sufficient data for rows, cols, and at least one widget:
-        if (data.length < 3) throw new WidgetDataException;
-        rows = data[0];
-        cols = data[1];
-        if (data.length != 2 + rows * cols) throw new WidgetDataException;
+        if (data.length < 4) throw new WidgetDataException;
+        super (wind, data);
+        
+        rows = data[1];
+        cols = data[2];
+        if (data.length != 3 + rows * cols) throw new WidgetDataException;
         /* data.length >= 3 so besides checking the length is correct, this tells us:
-         *      rows * cols >= 3 - 2 = 1            a free check!
+         *      rows * cols >= 4 - 3 = 1            a free check!
          * The only thing not checked is whether both rows and cols are negative, which would
          * cause an exception when dynamic arrays are allocated later (and is unlikely). */
         
-        window = wind;
-        
         // Get all sub-widgets
         subWidgets.length = rows*cols;
         foreach (i, inout subWidget; subWidgets) {
-            subWidget = window.makeWidget (data[i+2], this);
+            subWidget = window.makeWidget (data[i+3]);
         }
     }
     
+    int[] adjust (int[] data) {
+        // Give all sub-widgets their data:
+        foreach (widget; subWidgets)
+            data = widget.adjust (data);
+        if (data.length < rows + cols) throw new MutableDataException;
+        
+        /* We basically short-cut setSize by loading previous col/row sizes and doing the final
+         * calculations. There isn't checks that the data is valid/up-to-date... worst case is too
+         * small overlapping widgets or huge ones?
+         * Note: if setSize gets called afterwards, it should have same dimensions and so not do
+         * anything. */
+        colW = data[0..cols];
+        rowH = data[cols..rows+cols];
+        setColRowSizes;
+        w = colW[$-1] + colX[$-1];
+        h = rowY[$-1] + rowH[$-1];
+        
+        return data[rows+cols..$];
+    }
+    
+    int[] getCreationData () {
+        int[] ret;
+        ret.length = 3 + subWidgets.length;
+        
+        ret [0..3] = [widgetType, rows, cols];  // first data
+        
+        foreach (i,widget; subWidgets)          // sub widgets
+            ret[i+3] = window.addCreationData (widget);
+        
+        return ret;
+    }
+    int[] getMutableData () {
+        int[] ret;
+        foreach (widget; subWidgets)
+            ret ~= widget.getMutableData;
+        
+        ret ~= colW ~ rowH;
+        return ret;
+    }
+    
     bool isWSizable () {
         if (colSizable == -2) {     // check whether any columns are resizable
             for1:
@@ -108,6 +148,19 @@
     }
     
     void setSize (int nw, int nh) {
+        /* For each of width and height, there are several cases:
+         *  [new value is] more than old value
+         *  ->  enlarge any row/column
+         *  same as old value
+         *  ->  do nothing
+         *  more than min but less than current value
+         *  ->  find an enlarged row/col and reduce size
+         *  ->  repeat if necessary
+         *  minimal value or less
+         *  -> clamp to min and use min col/row sizes
+         */
+        // FIXME: implement!
+        
         // Step 1: calculate the minimal row/column sizes.
         alias w mw;             // no need for extra vars, just use these
         alias h mh;
@@ -132,34 +185,15 @@
                 rowH[$-1] += nh - mh;
         }
         
-        // Step 3: set each sub-widget's size.
-        foreach (i,widget; subWidgets)
-            widget.setSize (colW[i % cols], rowH[i / cols]);
-        
         w = nw;
         h = nh;
         
+        // Step 3: set each sub-widget's size.
         // Step 4: calculate the column and row positions
-        colX.length = cols;
-        rowY.length = rows;
-        int spacing = window.renderer.layoutSpacing;
-        
-        int cum = 0;
-        foreach (i, x; rowH) {
-            rowY[i] = cum;
-            cum += x + spacing;
-        }
-        
-        cum = 0;
-        foreach (i, x; colW) {
-            colX[i] = cum;
-            cum += x + spacing;
-        }
+        setColRowSizes;
         
         // Step 5: position needs resetting
-        // FIXME: find a more efficient method of doing this?
-        // maybe setPosition should ALWAYS be called after setSize?
-        setPosition (x,y);
+        // Currently this happens by specifying that setPosition should be run after setSize.
     }
     
     void setPosition (int x, int y) {
@@ -228,6 +262,29 @@
         }
     }
     
+    void setColRowSizes () {
+        // Calculate column and row locations:
+        colX.length = cols;
+        rowY.length = rows;
+        int spacing = window.renderer.layoutSpacing;
+        
+        int cum = 0;
+        foreach (i, x; rowH) {
+            rowY[i] = cum;
+            cum += x + spacing;
+        }
+        
+        cum = 0;
+        foreach (i, x; colW) {
+            colX[i] = cum;
+            cum += x + spacing;
+        }
+        
+        // Tell subwidgets their new sizes:
+        foreach (i,widget; subWidgets)
+            widget.setSize (colW[i % cols], rowH[i / cols]);
+    }
+    
 protected:
     int cols, rows;     // number of cells in grid