view mde/gui/widget/createWidget.d @ 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 7cab2af4ba21
children 25cb7420dc91
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/>. */

/// GUI Widget module.
module mde.gui.widget.createWidget;

import mde.gui.widget.Ifaces;
import mde.gui.exception : WidgetDataException;

// Widgets to create:
import mde.gui.widget.layout;
import mde.gui.widget.miscWidgets;
import mde.gui.widget.TextWidget;

/** Create a widget of type data[0] (see enum WIDGET_TYPES) for _window window, with initialisation
* data [1..$]. */
IWidget createWidget (IWindow window, int[] data)
in {
    assert (window !is null, "createWidget: window is null");
} body {
    if (data.length < 1) throw new WidgetDataException ("No widget data");
    int type = data[0];     // type is first element of data
    // the whole of data is passed to the Widget
    
    mixin (binarySearch ("type", WIDGETS));
    throw new WidgetDataException ("Bad widget type");
}

/+ for converting to a char[] name (unused)
static this() {
    WIDGET_NAMES = [
            FixedBlank : "FixedBlank",
            SizableBlank : "SizableBlank",
            Button : "Button",
            GridLayout : "GridLayout"
                    ];
}+/

private:
/// Widget types.
enum WIDGET_TYPE : int {
    WSIZABLE                = 0x1000,   // horizontally resizable
    HSIZABLE                = 0x2000,   // vertically resizable
    INTERACTIBLE            = 0x4000,   // any specific interaction
    LAYOUT                  = 0x8000,   // is a layout widget (i.e. has sub-widgets)?
    
    // Use widget names rather than usual capitals convention
    
    // blank: 0x1
    FixedBlank              = 0x1,
    SizableBlank            = WSIZABLE | HSIZABLE | 0x1,
    
    // buttons: 0x10
    Button                  = INTERACTIBLE | 0x10,
    
    // content: 0x20
    Text		    = 0x21,
    Int			    = 0x22,
    
    GridLayout              = LAYOUT | WSIZABLE | HSIZABLE | 0x4,
    TrialContentLayout      = LAYOUT | WSIZABLE | HSIZABLE | 0x5
}

//const char[][int] WIDGET_NAMES;

// Only used for binarySearch algorithm generation; must be ordered by numerical values.
const char[][] WIDGETS = [
        "FixedBlank",
        "Text",
        "Int",
        "SizableBlank",
        "Button",
        "GridLayout",
        "TrialContentLayout"];

// Purely to add indentation. Could just return "" without affecting functionality.
static char[] indent (uint i) {
    char[] ret;
    for (; i > 0; --i) ret ~= "  ";
        // This is not executable at compile time:
        //ret.length = i * 4;		// number of characters for each indentation
        //ret[] = ' ';		// character to indent with
    return ret;
}
//char[] indent (uint) {  return "";  }

/* Generates a binary search algorithm. */
char[] binarySearch (char[] var, char[][] consts, int indents = 0) {
    if (consts.length > 3) {
        return indent(indents) ~ "if (" ~ var ~ " <= WIDGET_TYPE." ~ consts[$/2 - 1] ~ ") {\n" ~
                binarySearch (var, consts[0 .. $/2], indents + 1) ~
                indent(indents) ~ "} else {\n" ~
                binarySearch (var, consts[$/2 .. $], indents + 1) ~
                indent(indents) ~ "}\n";
    } else {
        char[] ret;
        ret ~= indent(indents);
        foreach (c; consts) {
            ret ~= "if (" ~ var ~ " == WIDGET_TYPE." ~ c ~ ") {\n" ~
                    indent(indents+1) ~ "return new " ~ c ~ "Widget (window, data);\n" ~
                    indent(indents) ~ "} else ";
        }
        ret = ret[0..$-6] ~ '\n';  // remove last else
        return ret;
    }
}