Changeset 103:42e241e7be3e
- Timestamp:
- 11/25/08 13:01:44 (2 months ago)
- Files:
-
- codeDoc/jobs.txt (modified) (2 diffs)
- data/conf/gui.mtt (modified) (2 diffs)
- data/conf/options.mtt (modified) (1 diff)
- mde/gui/WidgetManager.d (modified) (2 diffs)
- mde/gui/content/Content.d (modified) (13 diffs)
- mde/gui/content/Items.d (modified) (1 diff)
- mde/gui/content/options.d (deleted)
- mde/gui/exception.d (modified) (2 diffs)
- mde/gui/renderer/IRenderer.d (modified) (2 diffs)
- mde/gui/renderer/SimpleRenderer.d (modified) (3 diffs)
- mde/gui/types.d (modified) (1 diff)
- mde/gui/widget/Floating.d (modified) (1 diff)
- mde/gui/widget/Ifaces.d (modified) (1 diff)
- mde/gui/widget/TextWidget.d (modified) (2 diffs)
- mde/gui/widget/Widget.d (modified) (2 diffs)
- mde/gui/widget/createWidget.d (modified) (3 diffs)
- mde/gui/widget/layout.d (modified) (3 diffs)
- mde/gui/widget/miscContent.d (modified) (1 diff)
- mde/gui/widget/textContent.d (modified) (3 diffs)
- mde/lookup/Options.d (modified) (6 diffs)
- mde/lookup/Translation.d (modified) (2 diffs)
- mde/mde.d (modified) (2 diffs)
- mde/setup/Init.d (modified) (3 diffs)
- mde/setup/paths.d (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
codeDoc/jobs.txt
r97 r103 7 7 8 8 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 15 9 To do (importance 0-5: 0 pointless, 1 no obvious impact now, 2 todo sometime, 3 useful, 4 important, 5 urgent): 16 10 Also see todo.txt and FIXME/NOTE comment marks. 11 3 Widget saving: how to deal with modifier functions, esp. when they discard parameters? Remove feature except for dimdata and handle gui editing separately? 17 12 3 Use of dtors - don't rely on them? Or what happens when init throws during creation - relying on undefined behaviour. 18 13 3 glBindTexture not working with non-0 index - perhaps use a higher level graphics library at some point. … … 54 49 55 50 56 Done ( for mercurial log message):51 Done (since last commit): data/conf/gui.mtt
r101 r103 3 3 <char[]|Design="Working"> 4 4 {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]}> 9 7 <WidgetData|blank={0:[0x2]}> 10 <WidgetData|opts={0:[0x 8110,0],1:["optDBox","MiscOptions"]}>8 <WidgetData|opts={0:[0x2031,0x6030,0],1:["Options.VideoOptions","optDBox"]}> 11 9 <WidgetData|optDBox={0:[0xC100,1,2,1],1:["optBox","optDesc"]}> 12 10 <WidgetData|optBox={0:[0xC100,1,1,3],1:["optName","optSep","optVal"]}> … … 15 13 <WidgetData|optVal={0:[0x6030]}> 16 14 <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)"]}> 18 19 {Basic} 19 20 <WidgetData|root={0:[0x21,0x90D970],1:["A string!"]}> data/conf/options.mtt
r101 r103 22 22 <int|screenW=1280> 23 23 <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 400 400 } 401 401 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 enumeration410 * given in that module has the flag TAKES_CONTENT. */411 402 IChildWidget makeWidget (widgetID id, IContent content = null) { 412 403 debug (mdeWidgets) logger.trace ("Creating widget \""~id~'"'); 413 404 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); 414 409 } 415 410 … … 445 440 } 446 441 447 /** Get dimension data for a widget. */448 442 wdims dimData (widgetID id) { 449 443 return curData.dims (id); 450 444 } 451 452 /** For making changes to widget structure. */453 445 void setData (widgetID id, WidgetData d) { 454 446 changes[id] = d; // also updates WidgetDataSet in data. 455 447 } 456 457 /** For making changes to widget dimensions. */458 448 void setDimData (widgetID id, wdims d) { 459 449 changes.setDims(id, d); // also updates WidgetDataSet in data. mde/gui/content/Content.d
r101 r103 46 46 * state, and a tabbed box could show a tab based on this. Or could represent an option. 47 47 */ 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?51 48 interface IContent 52 49 { 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 (); /// ditto63 +/64 65 66 67 50 /** Generically return strings. 68 51 * … … 80 63 } 81 64 65 /** A generic way to handle a list of type IContent. */ 66 class 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 92 protected: 93 IContent[] list_; 94 } 95 96 /** Created on errors to display and log a message. */ 97 class 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 109 protected: 110 char[] msg_; 111 } 112 82 113 /** Base class for content containing a simple value. 83 114 * 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). */ 86 127 abstract class ValueContent : IContent 87 128 { … … 96 137 char[] toString (uint i) { 97 138 return (i == 0) ? sv 98 : (i == 1) ? name_99 : (i == 2) ? desc_100 : null;139 : (i == 1) ? name_ 140 : (i == 2) ? desc_ 141 : null; 101 142 } 102 143 … … 147 188 } 148 189 149 size_t getEditIndex () {190 size_t editIndex () { 150 191 size_t i = 0; 151 192 for (size_t p = 0; p < pos; ++p) … … 194 235 v = val; 195 236 sv = v ? "true" : "false"; 237 if (pos > sv.length) pos = sv.length; 196 238 } 197 239 void opAssign (bool val) { … … 205 247 alias opCall opCast; 206 248 207 void endEdit () {249 override void endEdit () { 208 250 v = sv && (sv[0] == 't' || sv[0] == 'T' || sv[0] == '1'); 209 251 foreach (cb; cngCb) … … 221 263 this (char[] symbol, char[] val = null) { 222 264 symb = symbol; 223 v = val;265 v = val; 224 266 } 225 267 … … 232 274 void assignNoCB (char[] val) { 233 275 v = val; 276 if (pos > sv.length) pos = sv.length; 234 277 } 235 278 void opAssign (char[] val) { 236 v = val;279 assignNoCB (val); 237 280 foreach (cb; cngCb) 238 281 cb(symb, val); … … 243 286 alias opCall opCast; 244 287 245 void endEdit () {288 override void endEdit () { 246 289 foreach (cb; cngCb) 247 290 cb(symb, v); … … 271 314 v = val; 272 315 sv = Int.toString (v); 316 if (pos > sv.length) pos = sv.length; 273 317 } 274 318 void opAssign (int val) { … … 282 326 alias opCall opCast; 283 327 284 void endEdit () {328 override void endEdit () { 285 329 v = Int.toInt (sv); 286 330 foreach (cb; cngCb) … … 311 355 v = val; 312 356 sv = Float.toString (v); 357 if (pos > sv.length) pos = sv.length; 313 358 } 314 359 void opAssign (double val) { … … 322 367 alias opCall opCast; 323 368 324 void endEdit () {369 override void endEdit () { 325 370 v = Float.toFloat (sv); 326 371 foreach (cb; cngCb) mde/gui/content/Items.d
r62 r103 14 14 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 15 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 *************************************************************************************************/ 19 module mde.gui.content.ContentItems; 20 21 import mde.gui.content.Content; 22 import mde.gui.exception; 23 24 import mde.lookup.Options; 25 import 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 62 private: 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 33 33 class WidgetDataException : GuiException 34 34 { 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); 37 40 } 38 41 } … … 50 53 } 51 54 } 55 56 /// Thrown when getting a content item fails 57 class ContentItemException : GuiException { 58 this (char[] msg) { 59 super ("Bad content item specifier: "~msg); 60 } 61 } mde/gui/renderer/IRenderer.d
r100 r103 88 88 * interfaces when available to allow flexibility. */ 89 89 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; 92 95 textCache.cacheVer = -1; // force update 93 96 } 94 97 95 void setColour (int col= 0xFFFFFF) {96 colour = Colour (col);98 void colour (int colour = 0xFFFFFF) { 99 colour_ = Colour (colour); 97 100 } 98 101 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; 101 105 } 102 106 … … 108 112 109 113 void draw (wdabs x, wdabs y) { 110 font.textBlock (x,y, content, textCache, colour , index);114 font.textBlock (x,y, content, textCache, colour_, index_); 111 115 } 112 116 113 117 char[] content; 114 118 TextBlock textCache; 115 size_t index ;116 Colour colour ;119 size_t index_; 120 Colour colour_; 117 121 FontStyle font; 118 122 } mde/gui/renderer/SimpleRenderer.d
r100 r103 60 60 61 61 //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. 62 64 void restrict (wdim x, wdim y, wdim w, wdim h) {} 63 65 void relax () {} … … 68 70 69 71 if (border.capability != 0) { 70 glColor3f (0f, 0f, . 7f);72 glColor3f (0f, 0f, .6f); 71 73 glBegin (GL_TRIANGLES); 72 74 wdim t = border.x1 + border.y1; … … 135 137 a.font = defaultFont; 136 138 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; 139 141 return a; 140 142 } mde/gui/types.d
r93 r103 20 20 21 21 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. */ 25 23 alias char[] widgetID; 26 24 mde/gui/widget/Floating.d
r99 r103 67 67 mw = widg.minWidth + border.x1 + border.x2; 68 68 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; 71 71 widg.setWidth (w - border.x1 - border.x2, -1); 72 72 widg.setHeight (h - border.y1 - border.y2, -1); mde/gui/widget/Ifaces.d
r99 r103 55 55 * Params: 56 56 * 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. 57 58 * content = An IContent may be passed to some widgets on creation. 58 59 * 59 60 * Creates a widget, using the widget data with index id. Widget data is loaded from files, 60 61 * 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. */ 62 65 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. */ 65 69 wdims dimData (widgetID id); 66 70 mde/gui/widget/TextWidget.d
r99 r103 25 25 import mde.gui.content.Content; 26 26 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 } 27 import tango.util.log.Log : Log, Logger; 28 private Logger logger; 29 static this () { 30 logger = Log.getLogger ("mde.gui.widget.TextWidget"); 33 31 } 34 32 … … 89 87 int index; 90 88 } 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/Widget.d
r99 r103 141 141 /********************************************************************************************** 142 142 * 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. 144 145 * 145 146 * Params: … … 149 150 *********************************************************************************************/ 150 151 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); 154 161 } 155 162 mde/gui/widget/createWidget.d
r101 r103 98 98 // buttons: 0x10 99 99 Button = 0x10, 100 TextButton = 0x11, 100 101 101 102 // labels: 0x20 … … 103 104 TextLabel = 0x21, 104 105 105 // content editables: 0x30106 // content functions: 0x30 106 107 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, 110 114 111 115 GridLayout = TAKES_CONTENT | PARENT | 0x100, 112 TrialContentLayout =PARENT | 0x110,116 ContentList = TAKES_CONTENT | PARENT | 0x110, 113 117 114 118 FloatingArea = PARENT | 0x200, … … 123 127 "Debug", 124 128 "Button", 125 "TextLabel", 126 "ContentLabel", 129 "TextButton", 130 "TextLabel", 131 "addContent", 132 "ContentLabel", 127 133 "DisplayContent", 128 134 "BoolContent", 129 135 "ValueContent", 130 136 "editContent", 131 "TrialContentLayout",132 137 "FloatingArea", 133 "GridLayout"]; 138 "GridLayout", 139 "ContentList"]; 134 140 135 141 /* Generates a binary search algorithm. */ mde/gui/widget/layout.d
r99 r103 20 20 import mde.gui.exception; 21 21 22 import mde.gui.widget.TextWidget;23 import mde.gui.content.options;24 22 import mde.gui.content.Content; 25 23 … … 94 92 95 93 /************************************************************************************************* 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. 97 98 *************************************************************************************************/ 98 class TrialContentLayoutWidget : GridWidget99 class ContentListWidget : GridWidget 99 100 { 100 this (IWidgetManager mgr, widgetID id, WidgetData data ) {101 this (IWidgetManager mgr, widgetID id, WidgetData data, IContent content) { 101 102 debug scope (failure) 102 103 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 106 110 cols = 1; 107 if ((rows = optsList.list.length) > 0) { 108 // Get all sub-widgets 111 if ((rows = cList.list.length) > 0) { 109 112 subWidgets.length = rows; 110 foreach (i, c; optsList.list) {113 foreach (i, c; cList.list) { 111 114 subWidgets[i] = mgr.makeWidget (data.strings[0], c); 112 115 } 113 116 } else { 114 117 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>"))]; 116 119 } 117 120 super (mgr, id, data); … … 126 129 127 130 private: 128 OptionList optsList;131 ContentList cList; 129 132 } 130 133 mde/gui/widget/miscContent.d
r101 r103 14 14 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 15 16 /** Some content widgets. */ 16 /************************************************************************************************* 17 * A function to return content widgets and some miscellaneous content widgets. 18 *************************************************************************************************/ 17 19 module mde.gui.widget.miscContent; 18 20 21 import mde.gui.widget.Widget; 22 import mde.gui.exception; 19 23 import mde.gui.widget.textContent; 20 import mde.gui.widget.Widget; 21 import mde.gui.widget.TextWidget; 22 import mde.gui.exception; 24 import mde.gui.widget.layout; 25 23 26 import mde.gui.renderer.IRenderer; 27 import mde.gui.content.Content; 28 import Items = mde.gui.content.Items; 24 29 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 *************************************************************************************************/ 37 IChildWidget 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 } 26 44 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 *************************************************************************************************/ 28 51 IChildWidget editContent (IWidgetManager mgr, widgetID id, WidgetData data, IContent c) { 52 if (c is null) throw new ContentException; 29 53 if (cast(BoolContent) c) 30 54 return new BoolContentWidget(mgr,id,data,c); 31 55 else if (cast(ValueContent) c) 32 56 return new ValueContentWidget(mgr,id,data,c); 57 else if (cast(ContentList) c) 58 return new ContentListWidget(mgr,id,data,c); 33 59 else // generic uneditable option 34 60 return new DisplayContentWidget(mgr,id,data,c); 35 }36 37 /// Just displays the content38 class DisplayContentWidget : ATextWidget39 {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;50 61 } 51 62 mde/gui/widget/textContent.d
r101 r103 32 32 } 33 33 34 /// Just displays the content 35 class 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 34 49 /// Capable of editing any ValueContent class 35 50 class ValueContentWidget : ATextWidget 36 51 { 37 52 this (IWidgetManager mgr, widgetID id, WidgetData data, IContent c) { 38 WD Check(data, 1);53 WDMinCheck(data, 1); 39 54 content = cast(ValueContent) c; 40 55 if (!content) //content = new TextContent (null, null); … … 46 61 /** On click, request keyboard input. */ 47 62 int clickEvent (wdabs, wdabs, ubyte, bool state) { 48 adapter. setIndex = content.getEditIndex;63 adapter.index = content.editIndex; 49 64 mgr.requestRedraw; 50 65 return 1; // get keyboard input via keyEvent … … 52 67 53 68 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; 56 71 adapter.getDimensions (mw, mh); // NOTE: only passively change size: next resize will see new minimal size 57 72 mgr.requestRedraw; 58 73 } 59 74 void keyFocusLost () { 60 adapter. setIndex;75 adapter.index; 61 76 content.endEdit; // update other users of content relying on callbacks 62 77 mgr.requestRedraw; mde/lookup/Options.d
r102 r103 14 14 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 15 16 //FIXME: Ddoc is outdated 16 17 /** This module handles stored options, currently all except input maps. 17 18 * … … 45 46 } 46 47 48 //FIXME: Ddoc is outdated 47 49 /** Base class for handling options. 48 50 * … … 166 168 subClasses[cast(ID) i] = c; 167 169 } 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 173 180 /* Load/save options from file. 174 181 * … … 247 254 const char[] setMixin = ``; 248 255 }+/ 256 /+ 249 257 /** Set option symbol of an Options sub-class to val. 250 258 * … … 265 273 } 266 274 }+/ 267 /+268 275 /** Get option symbol of an Options sub-class. 269 276 * … … 294 301 } 295 302 296 /// Variable validate function. This implementation does nothing. 303 /** Variable validate function, called when options are loaded from file. This implementation 304 * does nothing. */ 297 305 void validate() {} 306 307 /** Boolean, telling whether translation strings have been loaded for the instance. */ 308 bool transLoaded; 298 309 299 310 protected { mde/lookup/Translation.d
r98 r103 226 226 // Hack a specific locale... 227 227 // 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"); 230 230 231 231 Translation transl = load ("unittest/Translation"); … … 246 246 247 247 // Restore 248 miscOpts.L10n = currentL10n; 248 delete miscOpts.L10n; 249 miscOpts.L10n = realL10n; 249 250 250 251 logger.info ("Unittest complete."); mde/mde.d
r102 r103 1 /* LICENSE BLOCK1 /* LICENSE BLOCK 2 2 Part of mde: a Modular D game-oriented Engine 3 Copyright © 2007-2008 Diggory Hardy3 Copyright © 2007-2008 Diggory Hardy 4 4 5 5 This program is free software: you can redistribute it and/or modify it under the terms … … 82 82 //END Main loop setup 83 83 84 double pollInterval = miscOpts.pollInterval();84 double pollInterval = miscOpts.pollInterval(); 85 85 while (run) { 86 86 mainSchedule.execute (Clock.now()); mde/setup/Init.d
r102 r103 326 326 // Do a job: 327 327 try { 328 // FIXME - old stage start&finish trace messages - we don't have a name!329 328 static if (startup) { 330 329 debug logger.trace ("({}) InitStage {}: starting init", threadNum, stage.name); … … 450 449 foreach (name; stage_p.depends) 451 450 stages[name].rdepends ~= key; 452 int
