Changeset 105:08651e8a8c51

Show
Ignore:
Timestamp:
11/29/08 07:36:39 (1 month ago)
Author:
Diggory Hardy <diggory.hardy@gmail.com>
branch:
default
Message:

Quit button, big changes to content system.

Moved mde.gui.content to mde.content to reflect it's not only used by the gui.
Split Content module into Content and AStringContent.
New AContent and EventContent? class.
Callbacks are now generic and implemented in AContent.
Renamed TextContent? to StringContent? and ValueContent? to AStringContent.

Files:

Legend:

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

    r91 r105  
    11Copyright © 2007-2008 Diggory Hardy 
    22License: GNU General Public License version 2 or later (see COPYING) 
    3  
    4  
    5 Content: 
    6 Need a way for a single content to contain multiple "sub-contents", and a way for widgets to be bound to a sub-content. 
    7 ->  how 
    8     ->  Use indecies; widget's use an integer value to choose index (or a string)? 
    9     ->  Protection: read-only and read-write contents? 
    10 ->  why 
    11     ->  Dynamic lists of name, value and possibly description fields. 
    12         ->  Done in a basic case, so is it needed? 
    13 Generic Content creation: 
    14 ->  Created centrally, e.g. from options or translation strings. 
    15     ->  Creator keeps a hash-map of all created content, so that if the same content is asked for again the same content object will be returned, not a new object (besides efficiency, this keeps content synchronized). 
    16 ->  Generic ContentList type for instancing on at run-time. 
    17 ->  Items in ContentList may represent a cluster of items; e.g. an option plus it's name and description. These may be special classes, but should use a generic interface allowing getting sub-contents (e.g. value/name/desc.) via an index. 
    183 
    194 
  • data/conf/gui.mtt

    r104 r105  
    44{Working} 
    55<WidgetData|root={0:[0xC100,0,3,3],1:["square","blank","square","blank","floating","blank","square","blank","square"]}> 
    6 <WidgetData|square={0:[0x10,10,10]}> 
     6<WidgetData|square={0:[0x1,6,6]}> 
    77<WidgetData|blank={0:[0x2]}> 
    88<WidgetData|opts={0:[0x2031,0x6030,0],1:["Options","optCls"]}> 
     
    1818<WidgetData|L10n={0:[0x2031,0xC100,0,2,1],1:["Options.MiscOptions.L10n","optBox2","apply"]}> 
    1919<WidgetData|optBox2={0:[0xC100,0,1,3],1:["optName","optSep","optVal"]}>!{cloned to avoid bug #4} 
    20 <WidgetData|apply={0:[0x11],1:["Apply (unimplemented)"]}> 
     20<WidgetData|apply={0:[0x2031,0x4043],1:["quit"]}> 
    2121{Basic} 
    2222<WidgetData|root={0:[0x21,0x90D970],1:["A string!"]}> 
  • mde/content/Content.d

    r104 r105  
    1414along with this program.  If not, see <http://www.gnu.org/licenses/>. */ 
    1515 
    16 /** The content system − common types. 
     16/** The content system − common interface and a few classes without external dependencies. 
    1717 */ 
    18 module mde.gui.content.Content; 
    19  
    20 //FIXME: efficient conversions? Need to dup result when formatting a string anyway? 
    21 import Int = tango.text.convert.Integer; 
    22 import Float = tango.text.convert.Float; 
    23 import derelict.sdl.keysym; 
     18module mde.content.Content; 
    2419 
    2520debug { 
     
    2722    private Logger logger; 
    2823    static this () { 
    29         logger = Log.getLogger ("mde.gui.content.Content"); 
     24        logger = Log.getLogger ("mde.content.Content"); 
    3025    } 
    3126} 
     
    3429 * 
    3530 * Services like copy/paste could work on universal content. However, they would need to run a 
    36  * conversion to the appropriate type (or try next-oldest item on clipboard?). 
    37  * 
    38  * Currently Content instances can only have their data set on creation. 
    39  * Each Content class should provide a method to get it's content, e.g. the method text(). 
    40  * 
    41  * Extensions to content: 
    42  *  
    43  * These extensions require that a content can notify any dependants of changes. 
    44  *  
    45  * Use as a state switch (one option from an enumeration). E.g. a button/selection box could set a 
    46  * state, and a tabbed box could show a tab based on this. Or could represent an option. 
    47  */ 
     31 * conversion to the appropriate type (or try next-oldest item on clipboard?). */ 
    4832interface IContent 
    4933{ 
     
    6347} 
    6448 
    65 /** A generic way to handle a list of type IContent. */ 
    66 class ContentList : IContent 
     49/** The base for $(I most) content classes. 
     50 * 
     51 * Includes generic callback support, toString implementation and symbol access. 
     52 *  
     53 * Derived classes should impement: 
     54 * --- 
     55 *  this (char[] symbol, T val = /+ default value +/); 
     56 *  void opAssign (T val);  // assign val, calling callbacks 
     57 *  T opCall ();        // return value 
     58 *  alias opCall opCast; 
     59 * --- */ 
     60class AContent : IContent 
    6761{ 
    68     this (IContent[] list = null, char[] n = null, char[] d = null) { 
    69     list_ = list; 
     62    this (char[] symbol) { 
     63    this.symbol = symbol; 
     64    } 
     65     
     66    void name (char[] n, char[] d = null) { 
    7067    name_ = n; 
    7168    desc_ = d; 
    7269    } 
    73     this (ValueContent[char[]] l, char[] n = null, char[] d = null) { 
     70     
     71    /// Current implementation has 1 callback; can be changed to allow many. 
     72    EventContent addCallback (void delegate (AContent) cb) { 
     73    this.cb = cb; 
     74    return this; 
     75    } 
     76     
     77    char[] toString (uint i) { 
     78    return i == 0 ? "No value" 
     79    : i == 1 ? name_ 
     80    : i == 2 ? desc_ 
     81    : null; 
     82    } 
     83     
     84    /// End of an event, e.g. a button release or end of an edit (calls callbacks). 
     85    void endEvent () { 
     86    if (cb) 
     87        cb (this); 
     88    } 
     89     
     90    final char[] symbol;    // Symbol name for this content 
     91protected: 
     92    char[] name_, desc_;    // name and description 
     93    void delegate (AContent) cb; 
     94
     95 
     96// FIXME: needs changes to allow updating translated strings. Move to Content and extend AContent? 
     97/** A generic way to handle a list of type IContent. */ 
     98class ContentList : AContent 
     99
     100    this (char[] symbol, AContent[] list = null) { 
     101    list_.length = list.length; 
     102    foreach (i,c; list) 
     103        list_[i] = c; 
     104    super (symbol); 
     105    } 
     106    this (char[] symbol, AContent[char[]] l) { 
    74107    list_.length = l.length; 
    75108    size_t i; 
    76109    foreach (c; l) 
    77110        list_[i++] = c; 
    78     name_ = n; 
    79     desc_ = d; 
    80     } 
    81      
    82     char[] toString (uint i) { 
    83     return i == 0 ? Int.toString (list_.length) ~ " elements" 
    84              : i == 1 ? name_ 
    85              : i == 2 ? desc_ 
    86              : null; 
     111    super (symbol); 
    87112    } 
    88113     
     
    90115    return list_; 
    91116    } 
    92     ContentList list (IContent[] list) { 
    93     list_ = list; 
    94     return this; 
    95     } 
    96117     
    97118protected: 
    98     IContent[] list_; 
    99     char[] name_, desc_;    // name and description 
     119    final IContent[] list_; 
    100120} 
    101121 
     
    117137} 
    118138 
    119 /** Base class for content containing a simple value. 
    120  * 
    121  * All derived classes should have the following functions: 
    122  * --- 
    123  *  this (char[] symbol, T val = /+ default value +/); 
    124  *  BoolContent addChangeCb (void delegate (char[] symbol,T value) cb); // add a callback called on any change 
    125  *  void assignNoCB (T val);    // assign val, but without calling callbacks (for Options) 
    126  *  void opAssign (T val);  // assign val, calling callbacks 
    127  *  T opCall ();        // return value 
    128  *  alias opCall opCast; 
    129  *  void endEdit ();        // Converts sv and assigns to self, calling callbacks 
    130  * --- 
    131  * On any assignation (by this, assignNoCB, opAssign) the value should be converted to a string and 
    132  * assigned to sv, and pos should be clamped to [0,sv.length] (i.e. enforce pos <= sv.length). */ 
    133 abstract class ValueContent : IContent 
    134 
    135     protected this () {} 
    136      
    137     void name (char[] n, char[] d = null) { 
    138         name_ = n; 
    139         desc_ = d; 
    140     } 
    141      
    142     /// Get the text. 
    143     char[] toString (uint i) { 
    144         return i == 0 ? sv 
    145              : i == 1 ? name_ 
    146              : i == 2 ? desc_ 
    147              : null; 
    148     } 
    149      
    150     /** Acts on a keystroke and returns the new value. 
    151      * 
    152      * Supports one-line editing: left/right, home/end, backspace/delete. */ 
    153     char[] keyStroke (ushort sym, char[] i) { 
    154     debug assert (i.length, "TextContent.keyStroke: no value (??)");    // impossible? 
    155     char k = *i; 
    156     if (k > 0x20) { 
    157         if (k == 0x7f) {        // delete 
    158         size_t p = pos; 
    159         if (p < sv.length) ++p; 
    160         while (p < sv.length && (sv[p] & 0x80) && !(sv[p] & 0x40)) 
    161             ++p; 
    162         sv = sv[0..pos] ~ sv[p..$]; 
    163         } else {            // insert character 
    164         char[] tail = sv[pos..$]; 
    165         sv.length = sv.length + i.length; 
    166         size_t npos = pos+i.length; 
    167         if (tail) sv[npos..$] = tail.dup;   // cannot assign with overlapping ranges 
    168             sv[pos..npos] = i; 
    169         pos = npos; 
    170         } 
    171     } else {            // use sym; many keys output 0 
    172         if (sym == SDLK_BACKSPACE) {    // backspace; k == 0x8 
    173         char[] tail = sv[pos..$]; 
    174         if (pos) --pos; 
    175         while (pos && (sv[pos] & 0x80) && !(sv[pos] & 0x40)) 
    176             --pos; 
    177         sv = sv[0..pos] ~ tail; 
    178         } else if (sym == SDLK_LEFT) { 
    179         if (pos) --pos; 
    180         while (pos && (sv[pos] & 0x80) && !(sv[pos] & 0x40)) 
    181             --pos; 
    182         } else if (sym == SDLK_RIGHT) { 
    183         if (pos < sv.length) ++pos; 
    184         while (pos < sv.length && (sv[pos] & 0x80) && !(sv[pos] & 0x40)) 
    185             ++pos; 
    186         } else if (sym == SDLK_HOME || sym == SDLK_UP) { 
    187         pos = 0; 
    188         } else if (sym == SDLK_END || sym == SDLK_DOWN) { 
    189         pos = sv.length; 
    190         } else 
    191         debug logger.trace ("Symbol: {}", sym); 
    192     } 
    193     return sv; 
    194     } 
    195      
    196     size_t editIndex () { 
    197     size_t i = 0; 
    198     for (size_t p = 0; p < pos; ++p) 
    199         if (!(sv[p] & 0x80) || sv[p] & 0x40) 
    200         ++i; 
    201     return i; 
    202     } 
    203      
    204     /// Call at the end of an edit to convert sv to v and call callbacks 
    205     void endEdit (); 
    206 protected: 
    207     char[] sv;      // string of value; updated on assignment for displaying and editing 
    208     size_t pos;     // editing position; used by keyStroke 
    209     char[] symb; 
    210     char[] name_, desc_;// name and description 
    211 
    212  
    213 template VContentN(T) { 
    214     static if (is(T == bool)) { 
    215         const char[] VContentN = "BoolContent"; 
    216     } else static if (is(T == int)) { 
    217         const char[] VContentN = "IntContent"; 
    218     } else static if (is(T == double)) { 
    219         const char[] VContentN = "DoubleContent"; 
    220     } else static if (is(T == char[])) { 
    221         const char[] VContentN = "TextContent"; 
    222     } else 
    223         static assert (false, "No ValueContent of type "~T.stringof); 
    224 
    225  
    226 class BoolContent : ValueContent 
    227 
    228     /** Create a content with _symbol name symbol. */ 
    229     this (char[] symbol, bool val = false) { 
    230         symb = symbol; 
    231     assignNoCB (val); 
    232     } 
    233      
    234     /** Adds cb to the list of callback functions called when the value is changed. Returns this. */ 
    235     BoolContent addChangeCb (void delegate (char[] symbol,bool value) cb) { 
    236         cngCb ~= cb; 
    237         return this; 
    238     } 
    239      
    240     void assignNoCB (bool val) { 
    241     v = val; 
    242     sv = v ? "true" : "false"; 
    243     if (pos > sv.length) pos = sv.length; 
    244     } 
    245     void opAssign (bool val) { 
    246     assignNoCB (val); 
    247     foreach (cb; cngCb) 
    248             cb(symb, val); 
    249     } 
    250     bool opCall () { 
    251         return v; 
    252     } 
    253     alias opCall opCast; 
    254      
    255     override void endEdit () { 
    256     v = sv && (sv[0] == 't' || sv[0] == 'T' || sv[0] == '1'); 
    257     foreach (cb; cngCb) 
    258         cb(symb, v); 
    259     } 
    260      
    261 protected: 
    262     bool v; 
    263     void delegate (char[],bool)[] cngCb;       // change callbacks 
    264 
    265  
    266 /** Text content. */ 
    267 class TextContent : ValueContent 
    268 
    269     this (char[] symbol, char[] val = null) { 
    270         symb = symbol; 
    271     v = val; 
    272     } 
    273      
    274     /** Adds cb to the list of callback functions called when the value is changed. Returns this. */ 
    275     TextContent addChangeCb (void delegate (char[] symbol,char[] value) cb) { 
    276         cngCb ~= cb; 
    277         return this; 
    278     } 
    279      
    280     void assignNoCB (char[] val) { 
    281     v = val; 
    282     if (pos > sv.length) pos = sv.length; 
    283     } 
    284     void opAssign (char[] val) { 
    285     assignNoCB (val); 
    286         foreach (cb; cngCb) 
    287             cb(symb, val); 
    288     } 
    289     char[] opCall () { 
    290         return v; 
    291     } 
    292     alias opCall opCast; 
    293      
    294     override void endEdit () { 
    295     foreach (cb; cngCb) 
    296         cb(symb, v); 
    297     } 
    298      
    299 protected: 
    300     alias sv v;     // don't need separate v and sv in this case 
    301     void delegate (char[],char[])[] cngCb; 
    302 
    303  
    304 /** Integer content. */ 
    305 class IntContent : ValueContent 
    306 
    307     /** Create a content with _symbol name symbol. */ 
    308     this (char[] symbol, int val = 0) { 
    309         symb = symbol; 
    310     assignNoCB (val); 
    311     } 
    312      
    313     /** Adds cb to the list of callback functions called when the value is changed. Returns this. */ 
    314     IntContent addChangeCb (void delegate (char[] symbol,int value) cb) { 
    315         cngCb ~= cb; 
    316         return this; 
    317     } 
    318      
    319     void assignNoCB (int val) { 
    320     v = val; 
    321     sv = Int.toString (v); 
    322     if (pos > sv.length) pos = sv.length; 
    323     } 
    324     void opAssign (int val) { 
    325     assignNoCB (val); 
    326     foreach (cb; cngCb) 
    327             cb(symb, val); 
    328     } 
    329     int opCall () { 
    330         return v; 
    331     } 
    332     alias opCall opCast; 
    333      
    334     override void endEdit () { 
    335     v = Int.toInt (sv); 
    336     foreach (cb; cngCb) 
    337         cb(symb, v); 
    338     } 
    339      
    340 protected: 
    341     int v; 
    342     void delegate (char[],int)[] cngCb; 
    343 
    344  
    345 /** Double content. */ 
    346 class DoubleContent : ValueContent 
    347 
    348     /** Create a content with _symbol name symbol. */ 
    349     this (char[] symbol, double val = 0) { 
    350         symb = symbol; 
    351     assignNoCB (val); 
    352     } 
    353      
    354     /** Adds cb to the list of callback functions called when the value is changed. Returns this. */ 
    355     DoubleContent addChangeCb (void delegate (char[] symbol,double value) cb) { 
    356         cngCb ~= cb; 
    357         return this; 
    358     } 
    359      
    360     void assignNoCB (double val) { 
    361     v = val; 
    362     sv = Float.toString (v); 
    363     if (pos > sv.length) pos = sv.length; 
    364     } 
    365     void opAssign (double val) { 
    366     assignNoCB (val); 
    367     foreach (cb; cngCb) 
    368             cb(symb, val); 
    369     } 
    370     double opCall () { 
    371         return v; 
    372     } 
    373     alias opCall opCast; 
    374      
    375     override void endEdit () { 
    376     v = Float.toFloat (sv); 
    377     foreach (cb; cngCb) 
    378         cb(symb, v); 
    379     } 
    380      
    381 protected: 
    382     double v; 
    383     void delegate (char[],double)[] cngCb; 
    384 
     139/** A Content with no value but able to pass on an event. 
     140
     141* The point being that a button can be tied to one of these. */ 
     142alias AContent EventContent; 
  • mde/content/Items.d

    r104 r105  
    1717 * A generic way to access content items. 
    1818 *************************************************************************************************/ 
    19 module mde.gui.content.ContentItems; 
     19module mde.content.Items; 
    2020 
    21 import mde.gui.content.Content; 
     21import mde.content.Content; 
    2222import mde.gui.exception; 
    2323 
     24import mde.imde; 
    2425import mde.lookup.Options; 
    2526import mde.lookup.Translation; 
     
    3738     * E.g. get ("Options.MiscOptions.L10n") returns miscOpts.L10n, 
    3839     * Items.get ("Options.MiscOptions") returns a ContentList of all misc options. */ 
    39     IContent get (char[] item) { 
     40    AContent get (char[] item) { 
    4041    char[] h = head (item); 
    41     if (h == "Options") 
    42         return getOptions (item); 
    43     throw new ContentItemException (h); 
    44     } 
    45      
    46     /** Same as calling get("Options."~item). */ 
    47     IContent getOptions (char[] item) { 
    48     if (item is null) { 
    49         IContent[] list; 
    50         list.length = Options.optionsClasses.length; 
    51         size_t i; 
    52         foreach (n,opts; Options.optionsClasses) { 
    53         if (opts.name is null) loadTransl (opts, n); 
    54         list[i++] = new ContentList (opts.content, opts.name, opts.desc); 
     42    if (h == "Options") { 
     43        if (item is null) { 
     44        if (Options.allContentList is null) { 
     45            AContent[] list; 
     46            list.length = Options.optionsClasses.length; 
     47            size_t i; 
     48            foreach (n,opts; Options.optionsClasses) { 
     49            if (opts.contentList is null) 
     50                loadTransl (opts, n); 
     51            list[i++] = opts.contentList; 
     52            } 
     53            Options.allContentList = new ContentList (h, list); 
     54            Options.allContentList.name ("Options");    //FIXME 
     55        } 
     56        return Options.allContentList; 
    5557        } 
     58        h = head (item); 
     59        auto p = h in Options.optionsClasses; 
     60        if (p) { 
     61        if (p.contentList is null) 
     62            loadTransl (*p, h); 
    5663         
    57         return new ContentList (list, "Options"); 
    58     } 
    59     char[] h = head (item); 
    60     auto p = h in Options.optionsClasses; 
    61     if (p) { 
    62         if (p.name is null) loadTransl (*p, h); 
    63          
    64         if (item == null) 
    65         return new ContentList (p.content, p.name, p.desc); 
    66          
    67         auto q = (h = head (item)) in p.content; 
    68         if (q && item is null)  // enforce item is an exact match 
    69         return *q; 
     64        if (item == null) 
     65            return p.contentList; 
     66         
     67        auto q = (h = head (item)) in p.content; 
     68        if (q && item is null)  // enforce item is an exact match 
     69            return *q; 
     70        } 
     71    } else if (h == "quit" && item is null) { 
     72        quit.name ("Quit"); //FIXME 
     73        return quit; 
    7074    } 
    7175    throw new ContentItemException (h); 
     
    9195    Translation trans = Translation.load ("L10n/"~n); 
    9296    Translation.Entry transled = trans.getStruct (n); 
    93     p.name = transled.name
    94     p.desc = transled.desc
     97    p.contentList = new ContentList (n, p.content)
     98    p.contentList.name (transled.name, transled.desc)
    9599    foreach (s, v; p.content) { 
    96100        transled = trans.getStruct (s); 
  • mde/content/Services.d

    r61 r105  
    2626 * to know whether caches need updating or not). 
    2727 */ 
    28 module mde.gui.content.Services; 
     28module mde.content.Services; 
    2929 
    3030bool copy (ref Content c) { 
  • mde/gui/WidgetManager.d

    r103 r105  
    213213import mde.gui.exception; 
    214214import mde.gui.widget.Ifaces; 
    215 import mde.gui.content.Content; //NOTE - maybe move IContent to a separate module 
     215import mde.content.Content; 
    216216import mde.gui.widget.createWidget; 
    217217 
  • mde/gui/widget/Ifaces.d

    r103 r105  
    2626public import mde.gui.types; 
    2727public import mde.gui.renderer.IRenderer; 
    28 import mde.gui.content.Content; //NOTE - maybe move IContent to a separate module 
     28import mde.content.Content; 
    2929 
    3030 
  • mde/gui/widget/TextWidget.d

    r103 r105  
    2323import mde.gui.exception; 
    2424import mde.gui.renderer.IRenderer; 
    25 import mde.gui.content.Content; 
     25import mde.content.Content; 
    2626 
    2727import tango.util.log.Log : Log, Logger; 
     
    8787    int index; 
    8888} 
    89  
    90 class 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      
    110 protected: 
    111     IRenderer.TextAdapter adapter; 
    112     IContent content; 
    113     int index; 
    114 } 
  • mde/gui/widget/createWidget.d

    r103 r105  
    2222import mde.gui.widget.Ifaces; 
    2323import mde.gui.exception : WidgetDataException; 
    24 import mde.gui.content.Content; //NOTE - maybe move IContent to a separate module 
     24import mde.content.Content; 
    2525 
    2626// Widgets to create: 
     
    9898    // buttons: 0x10 
    9999    Button      = 0x10, 
    100     TextButton      = 0x11, 
    101100     
    102101    // labels: 0x20 
     
    111110    DisplayContent  = TAKES_CONTENT | 0x40, 
    112111    BoolContent     = TAKES_CONTENT | 0x41, 
    113     ValueContent    = TAKES_CONTENT | 0x42, 
     112    AStringContent  = TAKES_CONTENT | 0x42, 
     113    ButtonContent   = TAKES_CONTENT | 0x43, 
    114114     
    115115    GridLayout      = TAKES_CONTENT | PARENT | 0x100, 
     
    127127        "Debug", 
    128128        "Button", 
    129     "TextButton", 
    130129    "TextLabel", 
    131130    "addContent", 
     
    133132        "DisplayContent", 
    134133        "BoolContent", 
    135     "ValueContent", 
     134    "AStringContent", 
     135    "ButtonContent", 
    136136        "editContent", 
    137137        "FloatingArea", 
  • mde/gui/widget/layout.d

    r103 r105  
    2020import mde.gui.exception; 
    2121 
    22 import mde.gui.content.Content; 
     22import mde.content.Content; 
    2323 
    2424import tango.util.container.HashMap; 
  • mde/gui/widget/miscContent.d

    r103 r105  
    2525 
    2626import mde.gui.renderer.IRenderer; 
    27 import mde.gui.content.Content; 
    28 import Items = mde.gui.content.Items; 
     27import mde.content.AStringContent; 
     28import Items = mde.content.Items; 
    2929 
    3030/************************************************************************************************* 
     
    5353    if (cast(BoolContent) c) 
    5454        return new BoolContentWidget(mgr,id,data,c); 
    55     else if (cast(ValueContent) c) 
    56     return new ValueContentWidget(mgr,id,data,c); 
     55    else if (cast(AStringContent) c) 
     56    return new AStringContentWidget(mgr,id,data,c); 
    5757    else if (cast(ContentList) c) 
    5858    return new ContentListWidget(mgr,id,data,c); 
     
    8686} 
    8787 
     88/// A button connected to an EventContent 
     89class ButtonContentWidget : AButtonWidget 
     90{ 
     91    this (IWidgetManager mgr, widgetID id, WidgetData data, IContent c) { 
     92    WDCheck (data, 1); 
     93    content = cast(EventContent) c; 
     94    if (!content) throw new ContentException (); 
     95    adapter = mgr.renderer.getAdapter (content.toString (1)); 
     96    adapter.getDimensions (mw, mh); 
     97    w = mw; 
     98    h = mh; 
     99    super (mgr, id, data); 
     100    } 
     101     
     102    void draw () { 
     103    super.draw(); 
     104    adapter.draw (x,y); 
     105    } 
     106     
     107    void activated () { 
     108    content.endEvent; 
     109    } 
     110     
     111    protected: 
     112    IRenderer.TextAdapter adapter; 
     113    EventContent content; 
     114    int index; 
     115} 
     116 
  • mde/gui/widget/textContent.d

    r103 r105  
    2222import mde.gui.renderer.IRenderer; 
    2323 
    24 import mde.gui.content.Content; 
     24import mde.content.AStringContent; 
    2525 
    2626debug { 
     
    4343    } 
    4444     
    45     protected: 
    46    IContent content; 
     45protected: 
     46    IContent content; 
    4747} 
    4848 
    4949/// Capable of editing any ValueContent class 
    50 class ValueContentWidget : ATextWidget 
     50class AStringContentWidget : ATextWidget 
    5151{ 
    5252    this (IWidgetManager mgr, widgetID id, WidgetData data, IContent c) { 
    5353        WDMinCheck(data, 1); 
    54         content = cast(ValueContent) c; 
     54        content = cast(AStringContent) c; 
    5555        if (!content) //content = new TextContent (null, null); 
    5656        throw new ContentException (); 
     
    7979     
    8080protected: 
    81     ValueContent content; 
     81    AStringContent content; 
    8282} 
  • mde/imde.d

    r95 r105  
    2020import mde.input.Input; 
    2121import mde.scheduler.Scheduler; 
     22import mde.content.Content; 
    2223 
    2324static this () { 
     
    2526    input = new Input(); 
    2627    mainSchedule = new Scheduler; 
     28     
     29    quit = (new EventContent("quit")).addCallback ((AContent){ 
     30    run = false; 
     31    }); 
    2732} 
    2833 
     34EventContent quit;  /// A content triggering mde to halt 
    2935 
    3036Scheduler mainSchedule; /// The schedule used by the main loop. 
  • mde/lookup/Options.d

    r104 r105  
    2121import mde.exception; 
    2222 
    23 public import mde.gui.content.Content; 
     23public import mde.content.AStringContent; 
    2424 
    2525import mde.file.mergetag.Reader; 
     
    9797    auto p = id in opts; 
    9898    if (p) { 
    99         auto q = cast(`~VContentN!(T)~`) (*p); 
    100         if (q) q.assignNoCB = parseTo!(`~T.stringof~`) (dt); 
     99        auto q = cast(`~ContentN!(T)~`) (*p); 
     100        if (q) q.assignNoCb = parseTo!(`~T.stringof~`) (dt); 
    101101    } 
    102102}`; 
     
    120120        private Options[ID] subClasses; 
    121121        private bool changed = false;   // any changes at all, i.e. do we need to save? 
     122     
     123    ContentList allContentList; /// Initially null; created by mde.content.Items on use. 
    122124     
    123125        /* Load/save options from file. 
     
    184186    //BEGIN Non-static 
    185187    /// Get all Options stored with a ValueContent. 
    186     ValueContent[char[]] content() { 
     188    AContent[char[]] content() { 
    187189        return opts; 
    188190    } 
     
    193195    protected void validate() {} 
    194196     
    195     /** Translated name and description of the instance. mde.gui.content.Items loads these and the 
    196     * translation strings of all enclosed options simultaneously. */ 
    197     char[] name, desc
     197    /** All content in a ContentList. Initially null; mde.content.Items creates this and loads the 
     198    * translation strings of all sub-content upon first request involving this Options instance. */ 
     199    ContentList contentList
    198200     
    199201    protected { 
    200202        OptionChanges optionChanges;    // all changes to options (for saving) 
    201         ValueContent[char[]] opts;    // generic list of option values 
     203   AContent[char[]] opts; // generic list of option values 
    202204    } 
    203205     
     
    268270                const char[] createContents = createContents!(T,A[1..$]); 
    269271            else 
    270                 const char[] createContents = "opts[\""~A[0..cIndex!(A)]~"\"] = " ~ A[0..cIndex!(A)]~ " = (new "~VContentN!(T)~" (\""~A[0..cIndex!(A)]~"\")).addChangeCb (&optionChanges.set);\n"~ 
     272                const char[] createContents = "opts[\""~A[0..cIndex!(A)]~"\"] = (" ~ A[0..cIndex!(A)]~ " = new "~ContentN!(T)~" (\""~A[0..cIndex!(A)]~"\")).addCallback (&optionChanges.set);\n"~ 
    271273                createContents!(T,A[cIndex!(A)+1..$]); 
    272274        } 
     
    281283        template declValsInternal(char[] A, B...) { 
    282284            static if (B.length) { 
    283                 const char[] declValsInternal = catOrNothing!(VContentN!(B[0]),parseT!(B[0].stringof,A)) ~ declValsInternal!(A,B[1..$]); 
     285                const char[] declValsInternal = catOrNothing!(ContentN!(B[0]),parseT!(B[0].stringof,A)) ~ declValsInternal!(A,B[1..$]); 
    284286            } else 
    285287                const char[] declValsInternal = ``; 
     
    354356                const char[] Vars = ``; 
    355357        } 
    356         // For set 
    357         template Set(A...) { 
    358             static if (A.length) { 
    359                 const char[] Set= `void set (char[] s,`~A[0].stringof~` v) { 
    360    Options.changed = true; 
    361    `~TName!(A[0])~`s[s] = v; 
    362 }`~ Set!(A[1..$]); 
    363             } else 
    364                 const char[] Set = ``; 
    365         } 
    366          
    367358        // For addTag 
    368359        template addTagMixin(T, A...) { 
     
    391382    // optsX store pointers to each item added along with the ID and are used for access. 
    392383    mixin(Vars!(TYPES)); 
    393     // set (char[] symbol, T value);    (not templates but for each type T) 
    394     mixin(Set!(TYPES)); 
    395      
     384     
     385    void set (AContent c) { 
     386    union U { 
     387        BoolContent bc; 
     388        StringContent sc; 
     389        IntContent ic; 
     390        DoubleContent dc; 
     391    } 
     392    U u; 
     393    if ((u.bc = cast(BoolContent) c) !is null) 
     394        bools[u.bc.symbol] = u.bc(); 
     395    else if ((u.sc = cast(StringContent) c) !is null) 
     396        charAs[u.sc.symbol] = u.sc(); 
     397    else if ((u.ic = cast(IntContent) c) !is null) 
     398        ints[u.ic.symbol] = u.ic(); 
     399    else if ((u.dc = cast(DoubleContent) c) !is null) 
     400        doubles[u.dc.symbol] = u.dc(); 
     401    Options.changed = true; 
     402    } 
     403     
    396404    this () {} 
    397405