view mde/gui/WidgetDataSet.d @ 144:66c58e5b0062

Added a BoolContent-based collapsible widget.
author Diggory Hardy <diggory.hardy@gmail.com>
date Tue, 10 Feb 2009 12:57:09 +0000
parents 9f035cd139c6
children 1048b5c7cab1
line wrap: on
line source

/* LICENSE BLOCK
Part of mde: a Modular D game-oriented Engine
Copyright © 2007-2008 Diggory Hardy

This program is free software: you can redistribute it and/or modify it under the terms
of the GNU General Public License as published by the Free Software Foundation, either
version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>. */

/*************************************************************************************************
 * Code to manage the data used to create widgets and save changes to it.
 * 
 * When loading, a WidgetDataSet instance is loaded from file and its data used to create the
 * widgets. An empty WidgetDataChanges instance is also created.
 * 
 * If any data requires changing, it is added to the WidgetDataChanges instance, which also
 * updates the the WidgetDataSet instance used to load the widgets (in case of a re-load from this
 * data). When the data should be saved, if the WidgetDataChanges instance is not empty, data from
 * the highest priority (i.e. the user) file is merged into it, preserving both the current
 * changes and previous changes saved to the use file, before saving to the user file.
 *************************************************************************************************/
module mde.gui.WidgetDataSet;

public import mde.gui.types;
import mde.content.AStringContent;

// For loading from file:
import mt = mde.file.mergetag.DataSet;
import mt = mde.file.mergetag.DefaultData;
import mde.file.serialize;

import tango.util.log.Log : Log, Logger;

private Logger logger;
static this () {
    logger = Log.getLogger ("mde.gui.WidgetDataSet");
}

/******************************************************************************
 * Contains data for all widgets in a GUI.
 *****************************************************************************/
class WidgetDataSet : mt.IDataSection
{
    //BEGIN Mergetag code
    void addTag (char[] tp, mt.ID id, char[] dt) {
        // Priority is HIGH_LOW. Only load tag if it doesn't already exist.
        if (tp == "WidgetData" && (id in widgetData) is null) {
            widgetData[id] = deserialize!(WidgetData) (dt);
        } else if (tp == "WDims" && (id in dimData) is null) {
            dimData[id] = cast(wdims) deserialize!(int[]) (dt);
        } else if (tp == "BoolContent" && (id in Content.allContent) is null) {
            new BoolContent (id);
        } else if (tp == "EnumContent" && (id in Content.allContent) is null) {
            new EnumContent (id, deserialize!(char[][]) (dt));
        }
    }
    // Only WidgetDataChanges is used for writing.
    void writeAll (ItemDelg dlg) {}
    //END Mergetag code
    
    /** Get the widget data for widget i. */
    WidgetData opIndex (widgetID id) {
        auto p = id in widgetData;
        if (p is null) {
            logger.error ("No data for widget "~id~"; creating a debug widget instead.");
            return WidgetData.dbg;
        }
        return *p;
    }
    
    /** Get the widget dimensions for widget i (null if none). */
    wdims dims (widgetID id) {
        auto p = id in dimData;
        return p ? *p : null;
    }
    
protected:
    WidgetData[widgetID] widgetData;    // Per-widget data
    wdims[widgetID] dimData;            // Per-widget sizes
}

/*************************************************************************************************
 * Contains changes to widget data.
 * 
 * Can be read as normal and written.
 *************************************************************************************************/
class WidgetDataChanges : WidgetDataSet
{
    /**
     * Params:
     *  wds = The base WidgetDataSet these changes are applied against.
     *  
     * Base's enumContent is used directly; this.enumContent is null. */
    this (WidgetDataSet wds) {
        base = wds;
    }
    
    //BEGIN Mergetag code
    // HIGH_LOW priority of addTag allows existing entries (i.e. the changes) to be preserved while
    // other entries are read from files.
    void writeAll (ItemDelg dlg) {
        foreach (id,data; widgetData)
            dlg ("WidgetData", id, serialize!(WidgetData) (data));
        foreach (id,dim; dimData)
            dlg ("WDims", id, serialize!(int[]) (cast(int[]) dim));
    }
    //END Mergetag code
    
    /** Set the widget data for widget i.
     */
    void opIndexAssign (WidgetData d, widgetID i) {
        widgetData[i] = d;
        base.widgetData[i] = d;
    }
    
    /** Set the widget dimensions for widget i. */
    void setDims (widgetID id, wdims d) {
        dimData[id] = d;
        base.dimData[id] = d;
    }
    
    /** Do any changes exist? True if no changes have been stored. */
    bool noChanges () {
        return widgetData.length == 0 && dimData.length == 0;
    }
    
    protected WidgetDataSet base;
}