# HG changeset patch # User Diggory Hardy # Date 1214750437 -3600 # Node ID 891211f034f2e71ed5ac29bbf1a8ef212f1de612 # Parent cc3763817b8a34d1b623faa064e643daff9cd6b4 Changes to widgets: widgets may now get strings as creation data. Strings for TextWidgets can be set in files (in a temporary mannor). diff -r cc3763817b8a -r 891211f034f2 mde/gui/Gui.d --- a/mde/gui/Gui.d Sun Jun 29 11:55:55 2008 +0100 +++ b/mde/gui/Gui.d Sun Jun 29 15:40:37 2008 +0100 @@ -159,6 +159,7 @@ windows = w ~ windows[0..i] ~ windows[i+1..$]; widg.clickEvent (cast(wdabs)cx,cast(wdabs)cy,b,state); + requestRedraw; // in case we've only moved to front return; // only pass to first window } } diff -r cc3763817b8a -r 891211f034f2 mde/gui/content/Content.d --- a/mde/gui/content/Content.d Sun Jun 29 11:55:55 2008 +0100 +++ b/mde/gui/content/Content.d Sun Jun 29 15:40:37 2008 +0100 @@ -48,6 +48,16 @@ char[] toString (); } +/** Get a content from the list (what list?). */ +ContentText getContentText (char[] id) { + return new ContentText (id); // forget the list for now +} + +/** ditto */ +ContentInt getContentInt (char[] id) { + return new ContentInt (42); // forget the list for now +} + /** Text content. */ /* May end up extending a universal content type. * Services like copy/paste could work on universal content. @@ -58,10 +68,7 @@ * where ContentTextStruct is a struct. */ class ContentText : Content { - this () { - // NOTE: testing - text_ = "\"a@b\" − an example"; - } + this () {} this (char[] text) { text_ = text; } @@ -93,10 +100,7 @@ /** Integer content. */ class ContentInt : Content { - this () { - // NOTE: testing - int_ = -496; - } + this () {} this (int integer) { int_ = integer; } diff -r cc3763817b8a -r 891211f034f2 mde/gui/widget/Ifaces.d --- a/mde/gui/widget/Ifaces.d Sun Jun 29 11:55:55 2008 +0100 +++ b/mde/gui/widget/Ifaces.d Sun Jun 29 15:40:37 2008 +0100 @@ -17,7 +17,7 @@ module mde.gui.widget.Ifaces; public import mde.gui.renderer.IRenderer; -import mde.gui.IGui; +public import mde.gui.IGui; /** Interface for Window, allowing widgets to call some of Window's methods. * @@ -40,9 +40,15 @@ * been created, creates it using the Window's widget creation data. */ IWidget makeWidget (widgetID i); + /** Get a string from the widgetString associative array. */ + char[] getWidgetString (int i); + /** Add widget's saveData to the data to be saved, returning it's widgetID. */ widgetID addCreationData (IWidget widget); + /** Add a string to the widgetString associative array, returning it's index. */ + int addWidgetString (char[] str); + /** Returns the window's gui. */ IGui gui (); @@ -64,8 +70,14 @@ * A widget is a region of a GUI window which handles rendering and user-interaction for itself * and is able to communicate with it's window and parent/child widgets as necessary. * - * A widget's constructor should have this prototype: + * A widget's constructor should have the prototype and doc explaining what initialization data is + * used (excluding the widget ID, which every widget recieves): * ---------------------------------- + * /++ Constructor for a ... widget. + * + + * + Widget uses the initialisation data: + * + [widgetID, x, y] + * + where x is ... and y is ... +/ * this (IWindow window, int[] data); * ---------------------------------- * Where window is the root window (the window to which the widget belongs) and data is an array of @@ -95,6 +107,9 @@ /** Output data suitible for recreating the widget (data to be passed to this()). * + * Function may need to call Window's addCreationData() and addWidgetString() methods to save + * other data. + * * Creation data is data only changed when the gui is edited. */ int[] getCreationData (); diff -r cc3763817b8a -r 891211f034f2 mde/gui/widget/TextWidget.d --- a/mde/gui/widget/TextWidget.d Sun Jun 29 11:55:55 2008 +0100 +++ b/mde/gui/widget/TextWidget.d Sun Jun 29 15:40:37 2008 +0100 @@ -30,10 +30,14 @@ /// Adapter to ease use of ContentText struct ContentAdapter(ContentT : IContent) { - void set (int col) { + void set (char[] cID, int col) { if (font is null) font = FontStyle.get("default"); - content = new ContentT; + static if (is(ContentT == ContentText)) { + content = getContentText (cID); + } else static if (is(ContentT == ContentInt)) { + content = getContentInt (cID); + } else static assert (false, "Unsupported content type"); colour = Colour (cast(ubyte) (col >> 16u), cast(ubyte) (col >> 8u), cast(ubyte) col ); @@ -58,9 +62,15 @@ /// Basic text widget class ContentWidget(ContentT : IContent) : Widget { + /** Constructor for a widget containing [fixed] content. + * + * Widget uses the initialisation data: + * [widgetID, contentID, colour] + * where contentID is an ID for the string ID of the contained content + * and colour is an 8-bit-per-channel RGB colour of the form 0xRRGGBB. */ this (IWindow wind, int[] data) { - if (data.length != 2) throw new WidgetDataException; - text.set (data[1]); + if (data.length != 3) throw new WidgetDataException; + text.set (wind.getWidgetString(data[1]), data[2]); text.getDimensions (mw, mh); super (wind,data); } diff -r cc3763817b8a -r 891211f034f2 mde/gui/widget/Widget.d --- a/mde/gui/widget/Widget.d Sun Jun 29 11:55:55 2008 +0100 +++ b/mde/gui/widget/Widget.d Sun Jun 29 15:40:37 2008 +0100 @@ -32,6 +32,7 @@ { //BEGIN Load and save // Base this(). All widgets must check data.length is correct before calling this method. + // The widget ID is saved to widgetType, for correct saving. this (IWindow wind, int[] data) { window = wind; widgetType = data[0]; @@ -114,6 +115,11 @@ /** A base for fixed-size widgets taking their size from the creation data. */ class FixedWidget : Widget { // Check data.length is at least 3 before calling! + /** Constructor for a fixed-size [blank] widget. + * + * Widget uses the initialisation data: + * [widgetID, w, h] + * where w, h is the fixed size. */ this (IWindow wind, int[] data) { mw = cast(wdim) data[1]; mh = cast(wdim) data[2]; @@ -129,6 +135,7 @@ /** A base for resizable widgets. */ class SizableWidget : Widget { // Check data.length is at least 1 before calling! + /// Constructor for a completely resizable [blank] widget. this (IWindow wind, int[] data) { super (wind, data); } diff -r cc3763817b8a -r 891211f034f2 mde/gui/widget/Window.d --- a/mde/gui/widget/Window.d Sun Jun 29 11:55:55 2008 +0100 +++ b/mde/gui/widget/Window.d Sun Jun 29 15:40:37 2008 +0100 @@ -69,7 +69,10 @@ // Create the primary widget (and indirectly all sub-widgets), throwing on error: // Note: GridLayoutWidget's this relies on rend.layoutSpacing. widget = makeWidget (0); // primary widget always has ID 0. - widgetData = null; // data is no longer needed: allow GC to collect (cannot safely delete) + // This data is no longer needed by Window, although its sub-arrays may still be used, so + // let the GC collect what it can: + widgetData = null; + widgetStrings = null; // get border sizes: border = rend.setSizable (isWSizable, isHSizable); // depends on widget @@ -98,10 +101,14 @@ //BEGIN Mergetag code void addTag (char[] tp, mt.ID id, char[] dt) { // Priority is HIGH_LOW, so don't overwrite data which has already been loaded. - if (tp == INTAA) { + if (tp == INTAINT) { if (id == WDGD && widgetData == null) { widgetData = cast(int[][widgetID]) parseTo!(int[][int]) (dt); } + } else if (tp == CHARAINT) { + if (id == WS && widgetStrings == null) { + widgetStrings = parseTo!(char[][int]) (dt); + } } else if (tp == INTA) { if (id == MD && mutableData == null) { mutableData = parseTo!(int[]) (dt); @@ -121,7 +128,8 @@ /+ NOTE: currently editing is impossible... if (edited) { // only save the widget creation data if it's been adjusted: addCreationData (widget); // generate widget save data - dlg (INTAA, WDGD, parseFrom!(int[][int]) (widgetData)); + dlg (INTAINT, WDGD, parseFrom!(int[][int]) (widgetData)); + dlg (CHARAINT, WS, parseFrom!(char[][int]) (widgetStrings)); }+/ // Save mutable data: dlg (INTA, MD, parseFrom!(int[]) (widget.getMutableData)); @@ -130,11 +138,13 @@ dlg (INT, Y, parseFrom!(int) (y)); } private static const { - auto INTAA = "int[][int]"; + auto CHARAINT = "char[][int]"; + auto INTAINT = "int[][int]"; auto INTA = "int[]"; auto INT = "int"; auto WDGD = "widgetData"; auto MD = "mutableData"; + auto WS = "widgetStrings"; auto X = "x"; auto Y = "y"; } @@ -161,6 +171,20 @@ return createWidget (this, *d); } + char[] getWidgetString (int i) + in { + // widgetStrings is freed at same time as widgetData + // but widgetData is guaranteed to be read + assert (widgetData !is null, "getWidgetString called after widget creation finished"); + } body { + char[]* p; + if (widgetStrings is null || + (p = i in widgetStrings) is null ) + throw new WindowLoadException ("Needed widgetStrings not set for Window"); + + return *p; + } + /** Add this widget's data to that to be saved, returning it's widgetID. */ widgetID addCreationData (IWidget widget) { @@ -170,12 +194,31 @@ else i = widgetData.keys[$-1] + 1; + /+ Doesn't this have no effect except when getCreationData throws, in which case the data + + isn't used anyway? I'm sure it was added for a reason... FIXME and below widgetData[i] = null; // Make sure the same ID doesn't get used by a recursive call + +/ widgetData[i] = widget.getCreationData; return i; } + int addWidgetString (char[] str) + { + int i; + if (widgetStrings is null) + i = 0; + else + i = widgetStrings.keys[$-1] + 1; + + /+ See above. FIXME + widgetStrings[i] = null; // Make sure the same ID doesn't get used by a recursive call + +/ + widgetStrings[i] = str; + + return i; + } + IGui gui () { return gui_; } @@ -356,6 +399,7 @@ // Data used for saving and loading (null in between): int[][widgetID] widgetData = null;// Data for all widgets under this window int[] mutableData = null; // Widget's mutable data (adjusted sizes, etc.) + char[][int] widgetStrings = null;// Strings by ID; string-typed creation data IGui gui_; // The gui managing this window IRenderer rend; // The window's renderer diff -r cc3763817b8a -r 891211f034f2 mde/gui/widget/layout.d --- a/mde/gui/widget/layout.d Sun Jun 29 11:55:55 2008 +0100 +++ b/mde/gui/widget/layout.d Sun Jun 29 15:40:37 2008 +0100 @@ -38,6 +38,12 @@ class GridLayoutWidget : Widget { //BEGIN Creation & saving + /** Constructor for a grid layout widget. + * + * Widget uses the initialisation data: + * [widgetID, r, c, w11, w12, ..., w1c, ..., wr1, ..., wrc] + * where r and c are the number of rows and columns, and wij is the ID (from parent Window's + * list) for the widget in row i and column j. The number of parameters must be r*c + 3. */ this (IWindow wind, int[] data) { // Get grid size and check data // Check sufficient data for rows, cols, and at least one widget: