# HG changeset patch # User Diggory Hardy # Date 1228585302 0 # Node ID 1655693702fc8476c7920a11579130c5614276c9 # Parent 6acd96f8685f28fb353590cf0ed36b2817b4128d Resolved ticket #4, allowing widgets to reload strings and recalculate sizes mid-run. Removed prefinalize and finalize and added setup as the new second initialization phase, which can be re-run. diff -r 6acd96f8685f -r 1655693702fc codeDoc/jobs.txt --- a/codeDoc/jobs.txt Fri Dec 05 11:29:39 2008 +0000 +++ b/codeDoc/jobs.txt Sat Dec 06 17:41:42 2008 +0000 @@ -8,6 +8,7 @@ To do (importance 0-5: 0 pointless, 1 no obvious impact now, 2 todo sometime, 3 useful, 4 important, 5 urgent): Also see todo.txt and FIXME/NOTE comment marks. +3 Synchronization of IContent with gui (e.g. multiple edit widgets): worth adding (temporary) callbacks? 3 Widget saving: how to deal with modifier functions, esp. when they discard parameters? Remove feature except for dimdata and handle gui editing separately? 3 Use of dtors - don't rely on them? Or what happens when init throws during creation - relying on undefined behaviour. 3 glBindTexture not working with non-0 index - perhaps use a higher level graphics library at some point. diff -r 6acd96f8685f -r 1655693702fc data/L10n/en-GB.mtt --- a/data/L10n/en-GB.mtt Fri Dec 05 11:29:39 2008 +0000 +++ b/data/L10n/en-GB.mtt Sat Dec 06 17:41:42 2008 +0000 @@ -1,4 +1,5 @@ {MT01} +!{en-GB British English} {imde} {Options} diff -r 6acd96f8685f -r 1655693702fc data/conf/gui.mtt --- a/data/conf/gui.mtt Fri Dec 05 11:29:39 2008 +0000 +++ b/data/conf/gui.mtt Sat Dec 06 17:41:42 2008 +0000 @@ -2,10 +2,10 @@ {Working} - + - + @@ -17,7 +17,5 @@ - {Basic} diff -r 6acd96f8685f -r 1655693702fc mde/file/mergetag/Reader.d --- a/mde/file/mergetag/Reader.d Fri Dec 05 11:29:39 2008 +0000 +++ b/mde/file/mergetag/Reader.d Sat Dec 06 17:41:42 2008 +0000 @@ -356,7 +356,7 @@ After analysing tags, the function passes the type, ID and data to addTag. - NOTE: from performance tests on indexing char[]'s and dereferencing char*'s, the char*'s are + Note: from performance tests on indexing char[]'s and dereferencing char*'s, the char*'s are slightly faster, but a tiny difference isn't worth the extra effort/risk of using char*'s. */ private size_t parseSection (size_t pos, IDataSection dsec) { diff -r 6acd96f8685f -r 1655693702fc mde/gui/WidgetManager.d --- a/mde/gui/WidgetManager.d Fri Dec 05 11:29:39 2008 +0000 +++ b/mde/gui/WidgetManager.d Sat Dec 06 17:41:42 2008 +0000 @@ -173,6 +173,10 @@ return rend; } + /** Place a pop-up widget near px,py. + * + * WidgetManager sets its position, draws it, passes it click events and removes it; other + * functionality should be handled by the widget's parent. */ void addPopup (wdabs px, wdabs py, IChildWidget widg) { ActivePopup popup; with (popup) { @@ -214,7 +218,7 @@ popups = new CircularList!(ActivePopup); child = makeWidget ("root"); - finalize; + child.setup (0, 3); mw = child.minWidth; mh = child.minHeight; @@ -444,7 +448,8 @@ /** Called when translation strings have been reloaded. */ void reloadStrings (AContent c) { Items.loadTranslation; - child.reloadStrings; //FIXME : all widgets, resize + child.setup (++setupN, 2); + child.setPosition (0,0); requestRedraw; } @@ -455,45 +460,16 @@ * --- * // 1. Create the root widget: * child = makeWidget ("root"); - * finalize; - * // 2. Set the setSize, e.g.: + * child.setup (0, 3); + * // 2. Set the size: * child.setWidth (child.minWidth, 1); * child.setHeight (child.minHeight, 1); + * // 3. Set the position (necessary part of initialization): + * child.setPosition (0,0); * --- */ void createRootWidget(); - /** Runs finalize for all descendants, in a deepest first order. */ - /* NOTE: The way this function works may seem a little odd, but it's designed to allow - * shared alignments to be initialized properly: - * 1. all sharing members need to know their children's min size - * 2. all sharing members need to add their children's min size to the alignment - * 3. all sharing members can only then get their min size - * This method will fail if alignment members are not all of the same generation. An alternate - * method without this drawback would be to have shared alignments created with a list of - * pointers to their members, and once all members have been created the alignment could - * initialize itself, first making sure each members' children have been initialized. */ - void finalize () { - IChildWidget[][] descendants; // first index: depth; is a list of widgets at each depth - - void recurseChildren (size_t depth, IChildWidget widget) { - foreach (child; widget.children) - recurseChildren (depth+1, child); - - if (descendants.length <= depth) - descendants.length = depth * 2 + 1; - descendants[depth] ~= widget; - } - - recurseChildren (0, child); - foreach_reverse (generation; descendants) { - foreach (widget; generation) - widget.prefinalize; - foreach (widget; generation) - widget.finalize; - } - } - /** Called before saving (usually when the GUI is about to be destroyed, although not * necessarily). */ void preSave (); @@ -534,6 +510,7 @@ bool loadUserFile = true; // still need to load user file for saving? scope IChildWidget child; // The primary widget. + uint setupN; // n to pass to IChildWidget.setup Mutex mutex; // lock on methods for use outside the package. } diff -r 6acd96f8685f -r 1655693702fc mde/gui/renderer/IRenderer.d --- a/mde/gui/renderer/IRenderer.d Fri Dec 05 11:29:39 2008 +0000 +++ b/mde/gui/renderer/IRenderer.d Sat Dec 06 17:41:42 2008 +0000 @@ -170,6 +170,6 @@ /** Get a TextAdapter to draw some text. * * If no colour is passes, a default is used (white). */ - TextAdapter getAdapter (char[] text, int colour = 0xFFFFFF); + TextAdapter getAdapter (int colour = 0xFFFFFF); //END Methods } diff -r 6acd96f8685f -r 1655693702fc mde/gui/renderer/SimpleRenderer.d --- a/mde/gui/renderer/SimpleRenderer.d Fri Dec 05 11:29:39 2008 +0000 +++ b/mde/gui/renderer/SimpleRenderer.d Sat Dec 06 17:41:42 2008 +0000 @@ -148,10 +148,9 @@ glRecti (x+2,y+14, x+14,y+2); } - TextAdapter getAdapter (char[] text, int col) { + TextAdapter getAdapter (int col) { TextAdapter a; a.font = defaultFont; - a.content = text; a.colour_ = Colour (col); a.index_ = size_t.max; return a; diff -r 6acd96f8685f -r 1655693702fc mde/gui/widget/Floating.d --- a/mde/gui/widget/Floating.d Fri Dec 05 11:29:39 2008 +0000 +++ b/mde/gui/widget/Floating.d Sat Dec 06 17:41:42 2008 +0000 @@ -60,10 +60,13 @@ super (mgr, id, data); } - void finalize () { + bool setup (uint n, uint flags) { foreach (i, ref d; sWData) with (d) { auto widg = subWidgets[i]; - d.border = mgr.renderer.getBorder (borderType, widg.isWSizable, widg.isHSizable); + if (!widg.setup (n, flags) && n != 0 && !(flags & 1)) + continue; // no changes; skip the rest + + d.border = mgr.renderer.getBorder (borderType, widg.isWSizable, widg.isHSizable); mw = widg.minWidth + border.x1 + border.x2; mh = widg.minHeight + border.y1 + border.y2; if (w < mw || !widg.isWSizable) w = mw; @@ -71,6 +74,7 @@ widg.setWidth (w - border.x1 - border.x2, -1); widg.setHeight (h - border.y1 - border.y2, -1); } + return false; // floating area size is not changed } bool saveChanges () { diff -r 6acd96f8685f -r 1655693702fc mde/gui/widget/Ifaces.d --- a/mde/gui/widget/Ifaces.d Fri Dec 05 11:29:39 2008 +0000 +++ b/mde/gui/widget/Ifaces.d Sat Dec 06 17:41:42 2008 +0000 @@ -133,35 +133,39 @@ * + Widget uses the initialisation data: * + [widgetID, x, y] * + where x is ... and y is ... +/ - * this (IWidgetManager mgr, WidgetData data); + * this (IWidgetManager mgr, widgetID id, WidgetData data); * * /// The CTOR may take an IContent reference: - * this (IWidgetManager mgr, WidgetData data, IContent content); + * this (IWidgetManager mgr, widgetID id, WidgetData data, IContent content); * ---------------------------------- - * Where mgr is the widget manager and data is + * Where mgr is the widget manager, id is the _id passed to makeWidget() and data is * initialisation data. The method should throw a WidgetDataException (created without * parameters) if the data has wrong length or is otherwise invalid. * - * All widgets should set their own size in this() or finalize(), although some parents may set - * child-widgets' size during their creation. Widgets may rely on setPosition() being called after - * finalize(). - * - * Also see finalize(). + * All widgets should set their own size in this() or setup() (must be setup() if it could change), + * although some parents may set child-widgets' size during their creation. *************************************************************************************************/ //NOTE: add another this() without the data for default initialization, for the GUI editor? interface IChildWidget : IWidget { //BEGIN Load and save - // NOTE - change? - /** Called on all widgets after all widgets have been created in a deepest first order. + /** 2nd stage of initialization for widgets; also called on some changes. * - * finalize must be called before any other methods on the widget, which means this() cannot - * call sub-widgets' methods, but finalize() can. */ - void prefinalize (); - void finalize (); /// ditto - - /** Widget should return a list of all its children. */ - IChildWidget[] children (); + * Widgets should call recursively on their children, redo anything indicated by flags, and + * adjust their size and other cached data dependant on any thing which may have changed. + * Widgets may rely on setPosition being called afterwards. + * + * Params: + * n = Indicates this is the (n+1)-th time the function has been called. + * flags = if (flags & 1) the renderer has been changed, + * if (flags & 2) translation strings are being reloaded. + * These flags are always true on first run. + * + * Returns: + * The method should return true if the dimensions (may) have been changed. This may not be + * the case on the first run (when n == 0)!. + */ + bool setup (uint n, uint flags); /** When this is called, if the widget has any changed data to save it should call * IWidgetManager.setData (id, data) to set it and return true. Otherwise it should return @@ -171,14 +175,6 @@ * ids). */ bool saveChanges (); - /** Called when the renderer is changed (at least when the changes affect dimensions). - * Also called after widget creation, before any other methods are called. - * - * Returns: true when widget's dimensions (may) have changed. - * - * Should be propegated down to all child widgets. */ - bool rendererChanged (); - /+ Use when widget editing is available? Requires widgets to know their parents. /** Called when a child widget's size has changed. * @@ -186,13 +182,6 @@ void childChanged (); +/ - /** Called if translated strings have been reloaded and widgets need to reload theirs. - * - * Returns: true when widget's dimensions (may) have changed. - * - * Should be propegated down to all child widgets. */ - bool reloadStrings (); - //END Load and save //BEGIN Size and position @@ -232,7 +221,7 @@ void setWidth (wdim nw, int dir); void setHeight (wdim nh, int dir); /// ditto - /** Set the current position (i.e. called on init and move). */ + /** Set the current position (called after setup and to move widget). */ void setPosition (wdim x, wdim y); //END Size and position diff -r 6acd96f8685f -r 1655693702fc mde/gui/widget/Popup.d --- a/mde/gui/widget/Popup.d Fri Dec 05 11:29:39 2008 +0000 +++ b/mde/gui/widget/Popup.d Sat Dec 06 17:41:42 2008 +0000 @@ -26,13 +26,22 @@ WDCheck (data, 1,2); subWidget = mgr.makeWidget (data.strings[0], content); - adapter = mgr.renderer.getAdapter (data.strings[1]); + adapter = mgr.renderer.getAdapter; + adapter.text = data.strings[1]; adapter.getDimensions (mw, mh); w = mw; h = mh; super (mgr, id, data); } + bool setup (uint n, uint flags) { + return subWidget.setup (n,flags); + } + + bool saveChanges () { + return subWidget.saveChanges; + } + void activated () { mgr.addPopup (x,y, subWidget); } diff -r 6acd96f8685f -r 1655693702fc mde/gui/widget/TextWidget.d --- a/mde/gui/widget/TextWidget.d Fri Dec 05 11:29:39 2008 +0000 +++ b/mde/gui/widget/TextWidget.d Sat Dec 06 17:41:42 2008 +0000 @@ -38,18 +38,20 @@ /** Set the adapter first: * adapter = mgr.renderer.getAdapter ("string", 0xRRGGBB); */ this (IWidgetManager mgr, widgetID id, WidgetData data) { - adapter.getDimensions (mw, mh); - w = mw; - h = mh; super (mgr, id, data); } - bool reloadStrings () { - adapter.getDimensions (mw, mh); - bool r = (mw != w || mh != h) ? true : false; - w = mw; - h = mh; - return true; + /** Recalculates dims if the renderer changed. */ + bool setup (uint,uint flags) { + if (flags & 1) { + adapter.getDimensions (mw, mh); + if (mw != w || mh != h) { + w = mw; + h = mh; + return true; + } + } + return false; } void draw () { @@ -73,7 +75,8 @@ * and colour is an 8-bit-per-channel RGB colour of the form 0xRRGGBB. */ this (IWidgetManager mgr, widgetID id, WidgetData data) { WDCheck (data, 2, 1); - adapter = mgr.renderer.getAdapter (data.strings[0], data.ints[1]); + adapter = mgr.renderer.getAdapter (data.ints[1]); + adapter.text = data.strings[0]; super (mgr, id, data); } } @@ -86,13 +89,14 @@ content = c; if (!content) throw new ContentException (); index = data.ints[1]; - adapter = mgr.renderer.getAdapter (content.toString(index), data.ints[2]); + adapter = mgr.renderer.getAdapter (data.ints[2]); super (mgr, id,data); } - bool reloadStrings () { + bool setup (uint n, uint flags) { + if (!(flags & 3)) return false; // string or renderer (and possibly font) changed adapter.text = content.toString(index); - return super.reloadStrings; + return super.setup (n, 3); // force redimensioning } protected: diff -r 6acd96f8685f -r 1655693702fc mde/gui/widget/Widget.d --- a/mde/gui/widget/Widget.d Fri Dec 05 11:29:39 2008 +0000 +++ b/mde/gui/widget/Widget.d Sat Dec 06 17:41:42 2008 +0000 @@ -53,29 +53,15 @@ this.id = id; } - // Most widgets don't need this; all initialization os usually done in this() - void prefinalize () {} - void finalize () {} - - // ParentWidget is inteded for parent widgets to derive - IChildWidget[] children () { - return null; + // Widgets need to do their initialization either in this() or setup(). + bool setup (uint,uint) { + return false; } // Don't save any data: fine for many widgets. bool saveChanges () { return false; } - - // Very basic implementation which assumes the renderer cannot affect the widget's size. - bool rendererChanged () { - return false; - } - - // Widgets displaying strings will need this. - bool reloadStrings () { - return false; - } //END Load and save //BEGIN Size and position @@ -174,23 +160,22 @@ } /************************************************************************************************* -* An abstract base widget class for parent widgets. -*************************************************************************************************/ + * An abstract base widget class for parent widgets (many parent widgets don't use these methods). + * + * Parent widgets probably need to overload these functions (from AWidget): + * setup, saveChanges, setPosition, getWidget, draw, setWidth and setHeight. + *************************************************************************************************/ abstract class AParentWidget : AWidget { this (IWidgetManager mgr, widgetID id, WidgetData data) { super (mgr, id, data); } - // Tells all subWidgets to reload strings, but cannot adjust size of self, so not ultimately useful. - bool reloadStrings () { - foreach (widg; subWidgets) - widg.reloadStrings; - return false; - } - - IChildWidget[] children () { - return subWidgets; + bool setup (uint n, uint flags) { + bool c = false; + foreach (w; subWidgets) + c |= w.setup (n,flags); + return c; } bool saveChanges () { diff -r 6acd96f8685f -r 1655693702fc mde/gui/widget/layout.d --- a/mde/gui/widget/layout.d Fri Dec 05 11:29:39 2008 +0000 +++ b/mde/gui/widget/layout.d Sat Dec 06 17:41:42 2008 +0000 @@ -152,57 +152,58 @@ * the call to genCachedConstructionData can be moved to the derived this() methods.) * * Derived constructors may also set initWidths to the array of column widths followed by - * row heights used to initially set the row/column dimensions. - * - * Sub-widgets are finalized here, so no methods should be called on sub-widgets before calling - * this super. */ + * row heights used to initially set the row/column dimensions. */ protected this (IWidgetManager mgr, widgetID id, WidgetData data) { super (mgr, id, data); // Create cell aligners with appropriate col/row adjustment function if (data.ints[1] & 1) - col = AlignColumns.getInstance (id, cols); - else - col = (new AlignColumns (cols)); - col.addSetCallback (&setColWidth); - if (data.ints[1] & 2) - row = AlignColumns.getInstance (id~"R", rows); // id must be unique to that for cols! + col = AlignColumns.getInstance (id, cols); else - row = (new AlignColumns (rows)); - row.addSetCallback (&setRowHeight); + col = (new AlignColumns (cols)); + col.addCallbacks (&setColWidth, &setupAlignDimData); + if (data.ints[1] & 2) + row = AlignColumns.getInstance (id~"R", rows); // id must be unique to that for cols! + else + row = (new AlignColumns (rows)); + row.addCallbacks (&setRowHeight, &setupAlignDimData); useSpacing = (data.ints[1] & 4) != 0; } - /** Prior to finalizing but after sub-widgets are finalized, some information needs to be - * passed to the AlignColumns. */ - void prefinalize () { - genCachedConstructionData; // min widths, sizableness - } - /** Responsible for calculating the minimal size and initializing some stuff. * * As such, this must be the first function called after this(). */ - void finalize () { - if (initWidths.length == cols + rows) { - col.setWidths (initWidths[0..cols]); - row.setWidths (initWidths[cols..$]); - } else { - col.setWidths; - row.setWidths; - } - initWidths = null; // free - - mw = col.mw; - mh = row.mw; - w = col.w; - h = row.w; - - // Tell subwidgets their new sizes. Positions are given by a later call to setPosition. - foreach (i,widget; subWidgets) { - // Resizing direction is arbitrarily set to negative: - widget.setWidth (col.width[i % cols], -1); - widget.setHeight (row.width[i / cols], -1); - } + bool setup (uint n, uint flags) { + // Run all internal calculations regardless of changes, then check dimensions for changes. + // Don't try shortcutting internal calculations when there are no changes - I've tried, and + // doing so adds enough overhead to make doing so almost(?) worthless (or at least large + // increases in complexity). + wdim ow = w, oh = h; + + col.setup (n, flags); + row.setup (n, flags); + + if (initWidths.length == cols + rows) { + col.setWidths (initWidths[0..cols]); + row.setWidths (initWidths[cols..$]); + } else { + col.setWidths; + row.setWidths; + } + initWidths = null; // free + + mw = col.mw; + mh = row.mw; + w = col.w; + h = row.w; + + // Tell subwidgets their new sizes. Positions are given by a later call to setPosition. + foreach (i,widget; subWidgets) { + // Resizing direction is arbitrarily set to negative: + widget.setWidth (col.width[i % cols], -1); + widget.setHeight (row.width[i / cols], -1); + } + return (ow != w || oh != h); } //END Creation & saving @@ -284,26 +285,34 @@ package: /* Calculations which need to be run whenever a new sub-widget structure is set - * (i.e. to produce cached data calculated from construction data). - * Also need to be re-run if the renderer changes. + * or other changes affecting widget sizes. Most of these need to happen regardless of whether + * changes have occurred, since AlignColumns have been reset. * * rows, cols and subWidgets must be set before calling. Part of the set-up for AlignColumns * (col and row). subWidgets need to know their minimal size and resizability. */ - void genCachedConstructionData () { - // Will only change if renderer changes: - // NOTE shared AlignColumns get this set by all sharing GridWidgets + void setupAlignDimData (uint n, uint flags) { + if (sADD_n == n) return; // cached data is current + sADD_n = n; + + foreach (widg; subWidgets) // make sure all subwidgets have been set up + widg.setup (n,flags); + // make sure both AlignColumns are set up (since first call to setup(n) calls reset): + col.setup (n, flags); + row.setup (n, flags); + + // Note: shared AlignColumns get this set by all sharing GridWidgets col.spacing = row.spacing = useSpacing ? mgr.renderer.layoutSpacing : 0; // Calculate the minimal column and row sizes: // AlignColumns (row, col) takes care of initializing minWidth. foreach (i,widget; subWidgets) { // Increase dimensions if current minimal size is larger: - myIt n = i % cols; // column + myIt j = i % cols; // column wdim md = widget.minWidth; - if (col.minWidth[n] < md) col.minWidth[n] = md; - n = i / cols; // row + if (col.minWidth[j] < md) col.minWidth[j] = md; + j = i / cols; // row md = widget.minHeight; - if (row.minWidth[n] < md) row.minWidth[n] = md; + if (row.minWidth[j] < md) row.minWidth[j] = md; } // Find which cols/rows are resizable: @@ -370,7 +379,8 @@ myIt cols, rows; // number of cells in grid wdim[] initWidths; // see this / setInitialSize - bool useSpacing; // true if spacing should be applied + uint sADD_n = uint.max; // param n of last setup call after setupAlignDimData has run + bool useSpacing; // add inter-row/col spacing? /* All widgets in the grid, by row. Order: [ 0 1 ] * [ 2 3 ] */ @@ -417,18 +427,31 @@ * After creation, minimal widths should be set for all columns (minWidth) and * setWidths must be called before other functions are used. */ this (myIt columns) { - reset (columns); + if (columns < 1) + throw new GuiException("AlignColumns: created with <1 column (code error)"); + minWidth.length = columns; + sizable.length = columns; + } + + /** Like IChildWidget's setup; calls sADD delegates. */ + void setup (uint n, uint flags) { + if (n != setup_n) { + logger.trace ("AlignColumns.setup ({}): {}", n, cast(void*)this); + setup_n = n; + setupWidths = false; + reset (minWidth.length); + + foreach (dg; sADD) + dg (n, flags); // set flag 1 + } } /** Reset all column information (only keep set callbacks). * * Widths should be set after calling, as on creation. */ void reset (myIt columns) { - if (columns < 1) - throw new GuiException("AlignColumns: created with <1 column (code error)"); - minWidth = new wdim[columns]; - sizable = new bool[columns]; - width = null; // enforce calling setWidths after this + minWidth[] = 0; + sizable[] = false; firstSizable = -1; lastSizable = -1; } @@ -438,11 +461,14 @@ * Also calculates first/lastSizable from sizable, overall minimal width and column positions. */ void setWidths (wdim[] data = null) { - if (!width) { - if (data) { - debug assert (data.length == minWidth.length, "setWidths called with bad data length (code error)"); - width = data.dup; // data is shared by other widgets with same id so must be .dup'ed - // And check sizes are valid: + if (!setupWidths) { + logger.trace ("setWidths"); + setupWidths = true; + if (data || width) { // use existing/external data: need to check validity + if (data) { + assert (data.length == minWidth.length, "setWidths called with bad data length (code error)"); + width = data.dup; // data is shared by other widgets with same id so must be .dup'ed + } foreach (i, m; minWidth) { if (!sizable[i] || width[i] < m) // if width is fixed or less than minimum width[i] = m; @@ -474,13 +500,12 @@ } } - /** Add a callback to be called to notify changes in a column's width. - * - * All callbacks added are called on a width change so that multiple objects may share a - * CellAlign object. */ - typeof(this) addSetCallback (void delegate (myIt,wdim,int) setCW) { - assert (setCW, "CellAlign.this: setCW is null (code error)"); + /** Add a callback to be called to notify changes in a column's width, and the sADD callback. + */ + typeof(this) addCallbacks (void delegate (myIt,wdim,int) setCW, void delegate (uint,uint) sDg) { + assert (setCW && sDg, "AlignColumns.addCallbacks: null callback (code error)"); setWidthCb ~= setCW; + sADD ~= sDg; return this; } @@ -669,6 +694,10 @@ myDiff firstSizable = -1, lastSizable = -1; // set by calcFLSbl // Callbacks used to actually adjust a column's width: void delegate (myIt,wdim,int) setWidthCb[]; // set width of a column, with resize direction + void delegate (uint,uint) sADD[]; // setupAlignDimData dlgs + + uint setup_n = uint.max; // param n of last setup call + bool setupWidths; // setWidths has been run static HashMap!(widgetID,AlignColumns) instances; static this () { diff -r 6acd96f8685f -r 1655693702fc mde/gui/widget/miscContent.d --- a/mde/gui/widget/miscContent.d Fri Dec 05 11:29:39 2008 +0000 +++ b/mde/gui/widget/miscContent.d Sat Dec 06 17:41:42 2008 +0000 @@ -92,11 +92,19 @@ WDCheck (data, 1); content = cast(EventContent) c; if (!content) throw new ContentException (); - adapter = mgr.renderer.getAdapter (content.toString (1)); + adapter = mgr.renderer.getAdapter (); + super (mgr, id, data); + } + + bool setup (uint n, uint flags) { + if (!(flags & 3)) return false; // string or renderer (and possibly font) changed + adapter.text = content.toString(1); adapter.getDimensions (mw, mh); - w = mw; - h = mh; - super (mgr, id, data); + if (mw != w || mh != h) { + w = mw; + h = mh; + } + return true; } void draw () { diff -r 6acd96f8685f -r 1655693702fc mde/gui/widget/textContent.d --- a/mde/gui/widget/textContent.d Fri Dec 05 11:29:39 2008 +0000 +++ b/mde/gui/widget/textContent.d Sat Dec 06 17:41:42 2008 +0000 @@ -38,7 +38,8 @@ WDMinCheck(data, 1); content = c; if (!content) throw new ContentException (); - adapter = mgr.renderer.getAdapter (content.toString(0)); + adapter = mgr.renderer.getAdapter (); + adapter.text = content.toString(0); super (mgr, id, data); } @@ -54,10 +55,14 @@ content = cast(AStringContent) c; if (!content) //content = new TextContent (null, null); throw new ContentException (); - adapter = mgr.renderer.getAdapter (content.toString(0)); - super (mgr, id, data); + adapter = mgr.renderer.getAdapter (); + adapter.text = content.toString(0); + super (mgr, id, data); } + bool isWSizable () { return true; } + bool isHSizable () { return true; } + /** On click, request keyboard input. */ int clickEvent (wdabs, wdabs, ubyte, bool state) { adapter.index = content.editIndex; diff -r 6acd96f8685f -r 1655693702fc mde/setup/InitStage.d --- a/mde/setup/InitStage.d Fri Dec 05 11:29:39 2008 +0000 +++ b/mde/setup/InitStage.d Sat Dec 06 17:41:42 2008 +0000 @@ -27,7 +27,7 @@ // use as hash type for better performance than char[] alias uint StageName; StageName toStageName (char[4] x) { - return *cast(uint*) x.ptr; // NOTE - little hack to read as a uint + return *cast(uint*) x.ptr; // convert to a unique uint } /** Initialization and cleanup functions for one stage.