Changeset 103:42e241e7be3e

Show
Ignore:
Timestamp:
11/25/08 13:01:44 (2 months ago)
Author:
Diggory Hardy <diggory.hardy@gmail.com>
branch:
default
Message:

ContentList? content type; getting content items/lists from Options generically via content.Items, and a new addContent widget function. Several improvements to generic handling of content. New button-with-text widget.

Some tidy-up.
Some name changes, to increase uniformity.
Bug-fix: floating widgets of fixed size could previously be made larger than intended from config dimdata.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • codeDoc/jobs.txt

    r97 r103  
    77 
    88 
    9 Bugs: 
    10 Sometimes nothing is drawn until a resize, and fonts are blocks. Cause: init-stages always appear to get divided between two threads. If Inpt, Font and SWnd are called by the main thread and not a sub-thread, the bug doesn't occur. A temporary fix is just to set maxThreads=1. A redesign of threading init stages could solve this, but doesn't seem worth the effort right now. 
    11 Drawing of floating widgets is not restricted to the floating area; see SimpleRenderer.restrict(). 
    12  
    13  
    14  
    159To do (importance 0-5: 0 pointless, 1 no obvious impact now, 2 todo sometime, 3 useful, 4 important, 5 urgent): 
    1610Also see todo.txt and FIXME/NOTE comment marks. 
     113   Widget saving: how to deal with modifier functions, esp. when they discard parameters? Remove feature except for dimdata and handle gui editing separately? 
    17123   Use of dtors - don't rely on them? Or what happens when init throws during creation - relying on undefined behaviour. 
    18133   glBindTexture not working with non-0 index - perhaps use a higher level graphics library at some point. 
     
    5449 
    5550 
    56 Done (for mercurial log message): 
     51Done (since last commit): 
  • data/conf/gui.mtt

    r101 r103  
    33<char[]|Design="Working"> 
    44{Working} 
    5 <WidgetData|root={0:[0xC100,0,3,3],1:["square","blank","square","blank","content","blank","square","blank","square"]}> 
    6 <WidgetData|square={0:[0x1,6,6]}> 
    7 <WidgetData|content={0:[0xC100,0,3,1],1:["floating","opts","blank"]}> 
    8 <WidgetData|button={0:[0x10,50,50]}> 
     5<WidgetData|root={0:[0xC100,0,3,3],1:["square","blank","square","blank","floating","blank","square","blank","square"]}> 
     6<WidgetData|square={0:[0x10,10,10]}> 
    97<WidgetData|blank={0:[0x2]}> 
    10 <WidgetData|opts={0:[0x8110,0],1:["optDBox","MiscOptions"]}> 
     8<WidgetData|opts={0:[0x2031,0x6030,0],1:["Options.VideoOptions","optDBox"]}> 
    119<WidgetData|optDBox={0:[0xC100,1,2,1],1:["optBox","optDesc"]}> 
    1210<WidgetData|optBox={0:[0xC100,1,1,3],1:["optName","optSep","optVal"]}> 
     
    1513<WidgetData|optVal={0:[0x6030]}> 
    1614<WidgetData|optSep={0:[0x21, 0xff],1:["="]}> 
    17 <WidgetData|floating={0:[0x8200,6,14],1:["button","blank"]}> 
     15<WidgetData|floating={0:[0x8200,6,14,6],1:["L10n","blank","opts"]}> 
     16<WidgetData|L10n={0:[0x2031,0xC100,0,2,1],1:["Options.MiscOptions.L10n","optBox2","apply"]}> 
     17<WidgetData|optBox2={0:[0xC100,0,1,3],1:["optName","optSep","optVal"]}>!{cloned to avoid bug #4} 
     18<WidgetData|apply={0:[0x11],1:["Apply (unimplemented)"]}> 
    1819{Basic} 
    1920<WidgetData|root={0:[0x21,0x90D970],1:["A string!"]}> 
  • data/conf/options.mtt

    r101 r103  
    2222<int|screenW=1280> 
    2323<int|screenH=1024> 
    24 <int|windowW=800> 
    25 <int|windowH=600> 
    26  
     24<int|windowW=1024> 
     25<int|windowH=768> 
  • mde/gui/WidgetManager.d

    r99 r103  
    400400    } 
    401401     
    402      
    403     /** Create a widget by ID. 
    404      * 
    405      * A widget instance is created from data found under ID. Multiple instances may be created. 
    406      * NOTE - data conflicts when saving? 
    407      * 
    408      * An IContent may be passed. This could contain many things, e.g. some basic data, a widget, 
    409      * multiple sub-IContents. It is only passed to the widget by createWidget if it's enumeration 
    410      * given in that module has the flag TAKES_CONTENT. */ 
    411402    IChildWidget makeWidget (widgetID id, IContent content = null) { 
    412403        debug (mdeWidgets) logger.trace ("Creating widget \""~id~'"'); 
    413404        return createWidget (this, id, curData[id], content); 
     405    } 
     406    IChildWidget makeWidget (widgetID id, WidgetData data, IContent content = null) { 
     407    debug (mdeWidgets) logger.trace ("Creating widget \""~id~'"'); 
     408    return createWidget (this, id, data, content); 
    414409    } 
    415410     
     
    445440    } 
    446441     
    447     /** Get dimension data for a widget. */ 
    448442    wdims dimData (widgetID id) { 
    449443        return curData.dims (id); 
    450444    } 
    451      
    452     /** For making changes to widget structure. */ 
    453445    void setData (widgetID id, WidgetData d) { 
    454446        changes[id] = d;        // also updates WidgetDataSet in data. 
    455447    } 
    456      
    457     /** For making changes to widget dimensions. */ 
    458448    void setDimData (widgetID id, wdims d) { 
    459449        changes.setDims(id, d);    // also updates WidgetDataSet in data. 
  • mde/gui/content/Content.d

    r101 r103  
    4646 * state, and a tabbed box could show a tab based on this. Or could represent an option. 
    4747 */ 
    48 //TODO - write a generic IContent displaying widget. Also a generic editable? 
    49 // Don't include dimension/drawing stuff because it's renderer specific and content should not be! 
    50 // NOTE: an interface or a class? 
    5148interface IContent 
    5249{ 
    53     /+ NOTE: None of this is really used yet, but was (mostly) intended for clipboard copying. 
    54     /** Return a copy of self. */ 
    55     IContent dup (); 
    56      
    57     /** Attempt to convert the content to a specific type (may simply return this if appropriate). 
    58      * 
    59      * Annoyingly we can't use cast because overloading by return type isn't supported. */ 
    60     // FIXME: throw or return null on error or unsupported conversion? 
    61     ContentText toText (); 
    62     ContentInt  toInt ();   /// ditto 
    63     +/ 
    64      
    65      
    66      
    6750    /** Generically return strings. 
    6851     * 
     
    8063} 
    8164 
     65/** A generic way to handle a list of type IContent. */ 
     66class ContentList : IContent 
     67{ 
     68    this (IContent[] list = null) { 
     69    list_ = list; 
     70    } 
     71    this (ValueContent[char[]] l) { 
     72    list_.length = l.length; 
     73    size_t i; 
     74    foreach (c; l) 
     75        list_[i++] = c; 
     76    } 
     77     
     78    char[] toString (uint i) { 
     79    return i == 0 ? Int.toString (list_.length) ~ " elements" 
     80    : i == 1 ? "ContentList" 
     81    : null; 
     82    } 
     83     
     84    IContent[] list () { 
     85    return list_; 
     86    } 
     87    ContentList list (IContent[] list) { 
     88    list_ = list; 
     89    return this; 
     90    } 
     91     
     92protected: 
     93    IContent[] list_; 
     94} 
     95 
     96/** Created on errors to display and log a message. */ 
     97class ErrorContent : IContent 
     98{ 
     99    this (char[] msg) { 
     100    msg_ = msg; 
     101    } 
     102     
     103    char[] toString (uint i) { 
     104    return i == 0 ? msg_ 
     105         : i == 1 ? "Error" 
     106         : null; 
     107    } 
     108     
     109protected: 
     110    char[] msg_; 
     111} 
     112 
    82113/** Base class for content containing a simple value. 
    83114 * 
    84  * All derived classes should support functions to set/get any ValueContent type, but return the  
    85  * default value of any type other than it's own. */ 
     115 * All derived classes should have the following functions: 
     116 * --- 
     117 *  this (char[] symbol, T val = /+ default value +/); 
     118 *  BoolContent addChangeCb (void delegate (char[] symbol,T value) cb); // add a callback called on any change 
     119 *  void assignNoCB (T val);    // assign val, but without calling callbacks (for Options) 
     120 *  void opAssign (T val);  // assign val, calling callbacks 
     121 *  T opCall ();        // return value 
     122 *  alias opCall opCast; 
     123 *  void endEdit ();        // Converts sv and assigns to self, calling callbacks 
     124 * --- 
     125 * On any assignation (by this, assignNoCB, opAssign) the value should be converted to a string and 
     126 * assigned to sv, and pos should be clamped to [0,sv.length] (i.e. enforce pos <= sv.length). */ 
    86127abstract class ValueContent : IContent 
    87128{ 
     
    96137    char[] toString (uint i) { 
    97138        return (i == 0) ? sv 
    98             : (i == 1) ? name_ 
    99             : (i == 2) ? desc_ 
    100             : null; 
     139            : (i == 1) ? name_ 
     140            : (i == 2) ? desc_ 
     141            : null; 
    101142    } 
    102143     
     
    147188    } 
    148189     
    149     size_t getEditIndex () { 
     190    size_t editIndex () { 
    150191    size_t i = 0; 
    151192    for (size_t p = 0; p < pos; ++p) 
     
    194235    v = val; 
    195236    sv = v ? "true" : "false"; 
     237    if (pos > sv.length) pos = sv.length; 
    196238    } 
    197239    void opAssign (bool val) { 
     
    205247    alias opCall opCast; 
    206248     
    207     void endEdit () { 
     249    override void endEdit () { 
    208250    v = sv && (sv[0] == 't' || sv[0] == 'T' || sv[0] == '1'); 
    209251    foreach (cb; cngCb) 
     
    221263    this (char[] symbol, char[] val = null) { 
    222264        symb = symbol; 
    223         v = val; 
     265   v = val; 
    224266    } 
    225267     
     
    232274    void assignNoCB (char[] val) { 
    233275    v = val; 
     276    if (pos > sv.length) pos = sv.length; 
    234277    } 
    235278    void opAssign (char[] val) { 
    236         v = val
     279   assignNoCB (val)
    237280        foreach (cb; cngCb) 
    238281            cb(symb, val); 
     
    243286    alias opCall opCast; 
    244287     
    245     void endEdit () { 
     288    override void endEdit () { 
    246289    foreach (cb; cngCb) 
    247290        cb(symb, v); 
     
    271314    v = val; 
    272315    sv = Int.toString (v); 
     316    if (pos > sv.length) pos = sv.length; 
    273317    } 
    274318    void opAssign (int val) { 
     
    282326    alias opCall opCast; 
    283327     
    284     void endEdit () { 
     328    override void endEdit () { 
    285329    v = Int.toInt (sv); 
    286330    foreach (cb; cngCb) 
     
    311355    v = val; 
    312356    sv = Float.toString (v); 
     357    if (pos > sv.length) pos = sv.length; 
    313358    } 
    314359    void opAssign (double val) { 
     
    322367    alias opCall opCast; 
    323368     
    324     void endEdit () { 
     369    override void endEdit () { 
    325370    v = Float.toFloat (sv); 
    326371    foreach (cb; cngCb) 
  • mde/gui/content/Items.d

    r62 r103  
    1414along with this program.  If not, see <http://www.gnu.org/licenses/>. */ 
    1515 
    16 /** List of content items, somewhat like options. 
    17  * 
    18  * Both named and non-named items like options, but each item is a content. 
    19  * Separation by types of content or not? 
    20  */ 
    21 module mde.gui.content.Items; 
     16/************************************************************************************************** 
     17 * A generic way to access content items. 
     18 *************************************************************************************************/ 
     19module mde.gui.content.ContentItems; 
     20 
     21import mde.gui.content.Content; 
     22import mde.gui.exception; 
     23 
     24import mde.lookup.Options; 
     25import mde.lookup.Translation; 
     26 
     27    /** Get a specific content item. 
     28     * 
     29     * E.g. get ("Options.MiscOptions.L10n") returns miscOpts.L10n, 
     30     * Items.get ("Options.MiscOptions") returns a ContentList of all misc options. */ 
     31    IContent get (char[] item) { 
     32    char[] h = head (item); 
     33    if (h == "Options") 
     34        return getOptions (item); 
     35    throw new ContentItemException (h); 
     36    } 
     37     
     38    /** Same as calling get("Options."~item). */ 
     39    IContent getOptions (char[] item) { 
     40    char[] h = head (item); 
     41    auto p = h in Options.optionsClasses; 
     42    if (p) { 
     43        if (!p.transLoaded) { 
     44        Translation trans = Translation.load ("L10n/"~h); 
     45        foreach (s, v; p.content) { 
     46            Translation.Entry transled = trans.getStruct (s); 
     47            v.name (transled.name, transled.desc); 
     48        } 
     49        p.transLoaded = true; 
     50        } 
     51         
     52        if (item == null) 
     53        return new ContentList (p.content); 
     54         
     55        auto q = (h = head (item)) in p.content; 
     56        if (q && item is null)  // enforce item is an exact match 
     57        return *q; 
     58    } 
     59    throw new ContentItemException (h); 
     60    } 
     61     
     62private: 
     63    /** Takes the string "head.tail" where tail may contain '.' but head does not, returns "head", 
     64     * with str set to "tail". */ 
     65    char[] head (ref char[] str) { 
     66    size_t i = 0; 
     67    while (i < str.length && str[i] != '.') 
     68        ++i; 
     69    char[] ret = str[0..i]; 
     70    if (i == str.length) 
     71        str = null; 
     72    else 
     73        str = str[i+1..$]; 
     74    return ret; 
     75    } 
  • mde/gui/exception.d

    r91 r103  
    3333class WidgetDataException : GuiException 
    3434{ 
    35     this (Object o) {   // Default, by Widget class's this / WDCheck 
    36         super ("Bad widget data for "~o.classinfo.name); 
     35    this () {       // Other CTOR should be used by classes 
     36        super ("Bad widget data"); 
     37    } 
     38    this (Object o) {   // Default, by Widget class's this / WDCheck 
     39    super ("Bad widget data for "~o.classinfo.name); 
    3740    } 
    3841} 
     
    5053    } 
    5154} 
     55 
     56/// Thrown when getting a content item fails 
     57class ContentItemException : GuiException { 
     58    this (char[] msg) { 
     59    super ("Bad content item specifier: "~msg); 
     60    } 
     61} 
  • mde/gui/renderer/IRenderer.d

    r100 r103  
    8888     * interfaces when available to allow flexibility. */ 
    8989    struct TextAdapter { 
    90         void setText (char[] c) { 
    91             content = c; 
     90    char[] text () { 
     91        return content; 
     92    } 
     93        void text (char[] str) { 
     94            content = str; 
    9295        textCache.cacheVer = -1;    // force update 
    9396        } 
    9497     
    95     void setColour (int col = 0xFFFFFF) { 
    96         colour = Colour (col); 
     98    void colour (int colour = 0xFFFFFF) { 
     99        colour_ = Colour (colour); 
    97100    } 
    98101     
    99     void setIndex (size_t index = size_t.max) { 
    100         this.index = index; 
     102    /** If not size_t.max, an edit marker is drawn before character index. */ 
     103    void index (size_t index = size_t.max) { 
     104        index_ = index; 
    101105    } 
    102106         
     
    108112         
    109113        void draw (wdabs x, wdabs y) { 
    110             font.textBlock (x,y, content, textCache, colour, index); 
     114            font.textBlock (x,y, content, textCache, colour_, index_); 
    111115        } 
    112116         
    113117        char[] content; 
    114118        TextBlock textCache; 
    115     size_t index
    116         Colour colour
     119    size_t index_
     120        Colour colour_
    117121        FontStyle font; 
    118122    } 
  • mde/gui/renderer/SimpleRenderer.d

    r100 r103  
    6060     
    6161    //FIXME - make these do something 
     62    // They should restrict the drawing of floating widgets to the floating area, for instance, 
     63    // although this isn't strictly necessary. 
    6264    void restrict (wdim x, wdim y, wdim w, wdim h) {} 
    6365    void relax () {} 
     
    6870         
    6971        if (border.capability != 0) { 
    70             glColor3f (0f, 0f, .7f); 
     72            glColor3f (0f, 0f, .6f); 
    7173            glBegin (GL_TRIANGLES); 
    7274            wdim t = border.x1 + border.y1; 
     
    135137        a.font = defaultFont; 
    136138        a.content = text; 
    137     a.colour = Colour (col); 
    138     a.index = size_t.max; 
     139    a.colour_ = Colour (col); 
     140    a.index_ = size_t.max; 
    139141    return a; 
    140142    } 
  • mde/gui/types.d

    r93 r103  
    2020 
    2121 
    22 /** Widget ID type. Each ID is unique under this window. 
    23 
    24 * Type is int since this is the widget data type. */ 
     22/** Widget ID type. Each ID is unique under this window. */ 
    2523alias char[] widgetID; 
    2624 
  • mde/gui/widget/Floating.d

    r99 r103  
    6767            mw = widg.minWidth  + border.x1 + border.x2; 
    6868            mh = widg.minHeight + border.y1 + border.y2; 
    69             if (w < mw) w = mw; 
    70             if (h < mh) h = mh; 
     69       if (w < mw || !widg.isWSizable) w = mw; 
     70       if (h < mh || !widg.isHSizable) h = mh; 
    7171            widg.setWidth  (w - border.x1 - border.x2, -1); 
    7272            widg.setHeight (h - border.y1 - border.y2, -1); 
  • mde/gui/widget/Ifaces.d

    r99 r103  
    5555     * Params: 
    5656     *  id      = Identifier, within data files, of the data for the widget. 
     57     *  data    = Pass this data to the widget, not data looked up via id. 
    5758     *  content = An IContent may be passed to some widgets on creation. 
    5859     * 
    5960     * Creates a widget, using the widget data with index id. Widget data is loaded from files, 
    6061     * and per design (multiple gui layouts, called designs, may exist; data is per design). 
    61      */ 
     62     *  
     63     * The function taking a WidgetData is intended for modifier functions and only exists to 
     64     * avoid circular dependencies between the modifier function's module and createWidget. */ 
    6265    IChildWidget makeWidget (widgetID id, IContent content = null); 
    63      
    64     /// Get dimensional data. 
     66    IChildWidget makeWidget (widgetID id, WidgetData data, IContent content = null); 
     67     
     68    /** Get dimension data for a widget. */ 
    6569    wdims dimData (widgetID id); 
    6670     
  • mde/gui/widget/TextWidget.d

    r99 r103  
    2525import mde.gui.content.Content; 
    2626 
    27 debug { 
    28     import tango.util.log.Log : Log, Logger; 
    29     private Logger logger; 
    30     static this () { 
    31         logger = Log.getLogger ("mde.gui.widget.TextWidget"); 
    32     } 
     27import tango.util.log.Log : Log, Logger; 
     28private Logger logger; 
     29static this () { 
     30    logger = Log.getLogger ("mde.gui.widget.TextWidget"); 
    3331} 
    3432 
     
    8987    int index; 
    9088} 
     89 
     90class TextButtonWidget : AButtonWidget 
     91{ 
     92    this (IWidgetManager mgr, widgetID id, WidgetData data) { 
     93    WDCheck (data, 1, 1); 
     94    adapter = mgr.renderer.getAdapter (data.strings[0]); 
     95    adapter.getDimensions (mw, mh); 
     96    w = mw; 
     97    h = mh; 
     98    super (mgr, id, data); 
     99    } 
     100     
     101    void draw () { 
     102    super.draw(); 
     103    adapter.draw (x,y); 
     104    } 
     105     
     106    void activated () { 
     107    logger.info ("Button \""~adapter.text~"\" pressed"); 
     108    } 
     109     
     110protected: 
     111    IRenderer.TextAdapter adapter; 
     112    IContent content; 
     113    int index; 
     114} 
  • mde/gui/widget/Widget.d

    r99 r103  
    141141    /********************************************************************************************** 
    142142     * Widgets may use WDCheck as a utility to check what data holds. Its use is encouraged, so 
    143      * that the checks can easily be updated should WidgetData be changed. 
     143     * that the checks can easily be updated should WidgetData be changed. WDMinCheck is similar, 
     144     * but allows more data than required; it is used by some generic content widgets. 
    144145     *  
    145146     * Params: 
     
    149150     *********************************************************************************************/ 
    150151    void WDCheck (WidgetData data, size_t n_ints, size_t n_strings = 0) { 
    151     if (data.ints.length    != n_ints || 
    152         data.strings.length != n_strings) 
    153         throw new WidgetDataException (this); 
     152    if (data.ints.length    != n_ints || 
     153        data.strings.length != n_strings) 
     154        throw new WidgetDataException (this); 
     155    } 
     156    /** ditto */ 
     157    void WDMinCheck (WidgetData data, size_t n_ints, size_t n_strings = 0) { 
     158    if (data.ints.length    < n_ints || 
     159        data.strings.length < n_strings) 
     160        throw new WidgetDataException (this); 
    154161    } 
    155162     
  • mde/gui/widget/createWidget.d

    r101 r103  
    9898    // buttons: 0x10 
    9999    Button      = 0x10, 
     100    TextButton      = 0x11, 
    100101     
    101102    // labels: 0x20 
     
    103104    TextLabel       = 0x21, 
    104105     
    105     // content editables: 0x30 
     106    // content functions: 0x30 
    106107    editContent     = FUNCTION | TAKES_CONTENT | 0x30, 
    107     DisplayContent  = TAKES_CONTENT | 0x30, 
    108     BoolContent     = TAKES_CONTENT | 0x31, 
    109     ValueContent        = TAKES_CONTENT | 0x32, 
     108    addContent      = FUNCTION | 0x31, 
     109     
     110    // content widgets: 0x40 
     111    DisplayContent  = TAKES_CONTENT | 0x40, 
     112    BoolContent     = TAKES_CONTENT | 0x41, 
     113    ValueContent    = TAKES_CONTENT | 0x42, 
    110114     
    111115    GridLayout      = TAKES_CONTENT | PARENT | 0x100, 
    112     TrialContentLayout = PARENT | 0x110, 
     116    ContentList        = TAKES_CONTENT | PARENT | 0x110, 
    113117     
    114118    FloatingArea    = PARENT | 0x200, 
     
    123127        "Debug", 
    124128        "Button", 
    125         "TextLabel", 
    126         "ContentLabel", 
     129    "TextButton", 
     130    "TextLabel", 
     131    "addContent", 
     132    "ContentLabel", 
    127133        "DisplayContent", 
    128134        "BoolContent", 
    129135    "ValueContent", 
    130136        "editContent", 
    131         "TrialContentLayout", 
    132137        "FloatingArea", 
    133         "GridLayout"]; 
     138        "GridLayout", 
     139    "ContentList"]; 
    134140 
    135141/* Generates a binary search algorithm. */ 
  • mde/gui/widget/layout.d

    r99 r103  
    2020import mde.gui.exception; 
    2121 
    22 import mde.gui.widget.TextWidget; 
    23 import mde.gui.content.options; 
    2422import mde.gui.content.Content; 
    2523 
     
    9492 
    9593/************************************************************************************************* 
    96  * Trial layout of sub-widgets of one type only. 
     94 * Iterates on an ContentList to produce a list of widgets, each of which is created with widgetID 
     95 * data.strings[0]. If an IContent is passed, this is cast to a ContentList, otherwise 
     96 * content.Items is used to get an IContent. It is an error if the content fails to cast to 
     97 * ContentList. 
    9798 *************************************************************************************************/ 
    98 class TrialContentLayoutWidget : GridWidget 
     99class ContentListWidget : GridWidget 
    99100{ 
    100     this (IWidgetManager mgr, widgetID id, WidgetData data) { 
     101    this (IWidgetManager mgr, widgetID id, WidgetData data, IContent content) { 
    101102        debug scope (failure) 
    102103                logger.warn ("TrialContentLayoutWidget: failure"); 
    103         WDCheck (data, 2, 2); 
    104          
    105         OptionList optsList = new OptionList(data.strings[1]); 
     104        WDCheck (data, 2, 1); 
     105     
     106    cList = cast(ContentList) content; 
     107    if (cList is null) 
     108        throw new ContentException; 
     109     
    106110        cols = 1; 
    107         if ((rows = optsList.list.length) > 0) { 
    108             // Get all sub-widgets 
     111        if ((rows = cList.list.length) > 0) { 
    109112            subWidgets.length = rows; 
    110             foreach (i, c; optsList.list) { 
     113            foreach (i, c; cList.list) { 
    111114                subWidgets[i] = mgr.makeWidget (data.strings[0], c); 
    112115            } 
    113116        } else { 
    114117            rows = 1; 
    115             subWidgets = [mgr.makeWidget (data.strings[0], new TextContent (data.strings[1], "Invalid Options section"))]; 
     118            subWidgets = [mgr.makeWidget (data.strings[0], new ErrorContent ("<empty list>"))]; 
    116119        } 
    117120        super (mgr, id, data); 
     
    126129     
    127130private: 
    128     OptionList optsList; 
     131    ContentList cList; 
    129132} 
    130133 
  • mde/gui/widget/miscContent.d

    r101 r103  
    1414along with this program.  If not, see <http://www.gnu.org/licenses/>. */ 
    1515 
    16 /** Some content widgets. */ 
     16/************************************************************************************************* 
     17 * A function to return content widgets and some miscellaneous content widgets. 
     18 *************************************************************************************************/ 
    1719module mde.gui.widget.miscContent; 
    1820 
     21import mde.gui.widget.Widget; 
     22import mde.gui.exception; 
    1923import mde.gui.widget.textContent; 
    20 import mde.gui.widget.Widget; 
    21 import mde.gui.widget.TextWidget; 
    22 import mde.gui.exception; 
     24import mde.gui.widget.layout; 
     25 
    2326import mde.gui.renderer.IRenderer; 
     27import mde.gui.content.Content; 
     28import Items = mde.gui.content.Items; 
    2429 
    25 import mde.gui.content.Content; 
     30/************************************************************************************************* 
     31 * A function which uses Items.get (data.strings[0]) to get a content and creates a widget from 
     32 * data.ints[1]. The first item in each ints and strings is removed before passing data to the new 
     33 * widget. 
     34 *  
     35 * The function only takes an IContent parameter to satisfy createWidget; it's value is ignored. 
     36 *************************************************************************************************/ 
     37IChildWidget addContent (IWidgetManager mgr, widgetID id, WidgetData data, IContent) { 
     38    if (data.ints.length < 2 || data.strings.length < 1) throw new WidgetDataException; 
     39    char[] cItem = data.strings[0]; 
     40    data.strings = data.strings[1..$]; 
     41    data.ints    = data.ints   [1..$]; 
     42    return mgr.makeWidget (id, data, Items.get (cItem)); 
     43
    2644 
    27 /// Chooses the most appropriate content editing widget 
     45/************************************************************************************************* 
     46 * A function which returns the most appropriate content editing widget. 
     47 * 
     48 * Widgets which can be returned: BoolContentWidget (toggle button), ValueContentWidget (generic 
     49 * text-box editor), DisplayContentWidget (generic text label). 
     50 *************************************************************************************************/ 
    2851IChildWidget editContent (IWidgetManager mgr, widgetID id, WidgetData data, IContent c) { 
     52    if (c is null) throw new ContentException; 
    2953    if (cast(BoolContent) c) 
    3054        return new BoolContentWidget(mgr,id,data,c); 
    3155    else if (cast(ValueContent) c) 
    3256    return new ValueContentWidget(mgr,id,data,c); 
     57    else if (cast(ContentList) c) 
     58    return new ContentListWidget(mgr,id,data,c); 
    3359    else        // generic uneditable option 
    3460        return new DisplayContentWidget(mgr,id,data,c); 
    35 } 
    36  
    37 /// Just displays the content 
    38 class DisplayContentWidget : ATextWidget 
    39 { 
    40     this (IWidgetManager mgr, widgetID id, WidgetData data, IContent c) { 
    41         WDCheck(data, 1); 
    42         content = c; 
    43         if (!content) throw new ContentException (); 
    44         adapter = mgr.renderer.getAdapter (content.toString(0)); 
    45         super (mgr, id, data); 
    46     } 
    47      
    48 protected: 
    49     IContent content; 
    5061} 
    5162 
  • mde/gui/widget/textContent.d

    r101 r103  
    3232} 
    3333 
     34/// Just displays the content 
     35class DisplayContentWidget : ATextWidget 
     36{ 
     37    this (IWidgetManager mgr, widgetID id, WidgetData data, IContent c) { 
     38    WDMinCheck(data, 1); 
     39    content = c; 
     40    if (!content) throw new ContentException (); 
     41    adapter = mgr.renderer.getAdapter (content.toString(0)); 
     42    super (mgr, id, data); 
     43    } 
     44     
     45    protected: 
     46    IContent content; 
     47} 
     48 
    3449/// Capable of editing any ValueContent class 
    3550class ValueContentWidget : ATextWidget 
    3651{ 
    3752    this (IWidgetManager mgr, widgetID id, WidgetData data, IContent c) { 
    38         WDCheck(data, 1); 
     53        WDMinCheck(data, 1); 
    3954        content = cast(ValueContent) c; 
    4055        if (!content) //content = new TextContent (null, null); 
     
    4661    /** On click, request keyboard input. */ 
    4762    int clickEvent (wdabs, wdabs, ubyte, bool state) { 
    48     adapter.setIndex = content.getEditIndex; 
     63    adapter.index = content.editIndex; 
    4964    mgr.requestRedraw; 
    5065    return 1;   // get keyboard input via keyEvent 
     
    5267     
    5368    void keyEvent (ushort s, char[] i) { 
    54     adapter.setText = content.keyStroke (s, i); 
    55     adapter.setIndex = content.getEditIndex; 
     69    adapter.text = content.keyStroke (s, i); 
     70    adapter.index = content.editIndex; 
    5671    adapter.getDimensions (mw, mh); // NOTE: only passively change size: next resize will see new minimal size 
    5772    mgr.requestRedraw; 
    5873    } 
    5974    void keyFocusLost () { 
    60     adapter.setIndex; 
     75    adapter.index; 
    6176    content.endEdit;    // update other users of content relying on callbacks 
    6277    mgr.requestRedraw; 
  • mde/lookup/Options.d

    r102 r103  
    1414along with this program.  If not, see <http://www.gnu.org/licenses/>. */ 
    1515 
     16//FIXME: Ddoc is outdated 
    1617/** This module handles stored options, currently all except input maps. 
    1718 * 
     
    4546} 
    4647 
     48//FIXME: Ddoc is outdated 
    4749/** Base class for handling options. 
    4850* 
     
    166168            subClasses[cast(ID) i] = c; 
    167169        } 
    168      
    169         // Track all sections for saving/loading/other generic handling. 
    170         Options[ID] subClasses; 
    171         bool changed = false;    // any changes at all, i.e. do we need to save? 
    172      
     170     
     171    /** Get the hash map of Options classes. */ 
     172    Options[ID] optionsClasses () { 
     173        return subClasses; 
     174    } 
     175     
     176    // Track all sections for saving/loading/other generic handling. 
     177        private Options[ID] subClasses; 
     178        private bool changed = false;   // any changes at all, i.e. do we need to save? 
     179     
    173180        /* Load/save options from file. 
    174181         * 
     
    247254                const char[] setMixin = ``; 
    248255        }+/ 
     256    /+ 
    249257    /** Set option symbol of an Options sub-class to val. 
    250258     * 
     
    265273        } 
    266274    }+/ 
    267     /+ 
    268275    /** Get option symbol of an Options sub-class. 
    269276     * 
     
    294301    } 
    295302     
    296     /// Variable validate function. This implementation does nothing. 
     303    /** Variable validate function, called when options are loaded from file. This implementation 
     304     * does nothing. */ 
    297305    void validate() {} 
     306     
     307    /** Boolean, telling whether translation strings have been loaded for the instance. */ 
     308    bool transLoaded; 
    298309     
    299310    protected { 
  • mde/lookup/Translation.d

    r98 r103  
    226226        // Hack a specific locale... 
    227227        // Also to allow unittest to run without init. 
    228         char[] currentL10n = miscOpts.L10n; 
    229         miscOpts.L10n = "test-1"
     228        TextContent realL10n = miscOpts.L10n; 
     229        miscOpts.L10n = new TextContent ("L10n", "test-1")
    230230         
    231231        Translation transl = load ("unittest/Translation"); 
     
    246246         
    247247        // Restore 
    248         miscOpts.L10n = currentL10n; 
     248    delete miscOpts.L10n; 
     249        miscOpts.L10n = realL10n; 
    249250         
    250251        logger.info ("Unittest complete."); 
  • mde/mde.d

    r102 r103  
    1 /* LICENSE BLOCK 
     1/* LICENSE BLOCK 
    22Part of mde: a Modular D game-oriented Engine 
    3 Copyright © 2007-2008 Diggory Hardy 
     3Copyright © 2007-2008 Diggory Hardy 
    44 
    55This program is free software: you can redistribute it and/or modify it under the terms 
     
    8282    //END Main loop setup 
    8383     
    84    double pollInterval = miscOpts.pollInterval(); 
     84    double pollInterval = miscOpts.pollInterval(); 
    8585    while (run) { 
    8686        mainSchedule.execute (Clock.now()); 
  • mde/setup/Init.d

    r102 r103  
    326326                    // Do a job: 
    327327                    try { 
    328                         // FIXME - old stage start&finish trace messages - we don't have a name! 
    329328                        static if (startup) { 
    330329                            debug logger.trace ("({}) InitStage {}: starting init", threadNum, stage.name); 
     
    450449            foreach (name; stage_p.depends) 
    451450                stages[name].rdepends ~= key; 
    452         int