Changeset 65:891211f034f2
- Timestamp:
- 06/29/08 10:40:37
(6 months ago)
- Author:
- Diggory Hardy <diggory.hardy@gmail.com>
- Children:
66:f54ae4fc2b2f 67:108d123238c0
- branch:
- default
- Message:
Changes to widgets: widgets may now get strings as creation data. Strings for TextWidgets? can be set in files (in a temporary mannor).
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r63 |
r65 |
|
| 160 | 160 | |
|---|
| 161 | 161 | widg.clickEvent (cast(wdabs)cx,cast(wdabs)cy,b,state); |
|---|
| | 162 | requestRedraw; // in case we've only moved to front |
|---|
| 162 | 163 | return; // only pass to first window |
|---|
| 163 | 164 | } |
|---|
| r61 |
r65 |
|
| 49 | 49 | } |
|---|
| 50 | 50 | |
|---|
| | 51 | /** Get a content from the list (what list?). */ |
|---|
| | 52 | ContentText getContentText (char[] id) { |
|---|
| | 53 | return new ContentText (id); // forget the list for now |
|---|
| | 54 | } |
|---|
| | 55 | |
|---|
| | 56 | /** ditto */ |
|---|
| | 57 | ContentInt getContentInt (char[] id) { |
|---|
| | 58 | return new ContentInt (42); // forget the list for now |
|---|
| | 59 | } |
|---|
| | 60 | |
|---|
| 51 | 61 | /** Text content. */ |
|---|
| 52 | 62 | /* May end up extending a universal content type. |
|---|
| … | … | |
| 59 | 69 | class ContentText : Content |
|---|
| 60 | 70 | { |
|---|
| 61 | | this () { |
|---|
| 62 | | // NOTE: testing |
|---|
| 63 | | text_ = "\"a@b\" â an example"; |
|---|
| 64 | | } |
|---|
| | 71 | this () {} |
|---|
| 65 | 72 | this (char[] text) { |
|---|
| 66 | 73 | text_ = text; |
|---|
| … | … | |
| 94 | 101 | class ContentInt : Content |
|---|
| 95 | 102 | { |
|---|
| 96 | | this () { |
|---|
| 97 | | // NOTE: testing |
|---|
| 98 | | int_ = -496; |
|---|
| 99 | | } |
|---|
| | 103 | this () {} |
|---|
| 100 | 104 | this (int integer) { |
|---|
| 101 | 105 | int_ = integer; |
|---|
| r58 |
r65 |
|
| 18 | 18 | |
|---|
| 19 | 19 | public import mde.gui.renderer.IRenderer; |
|---|
| 20 | | import mde.gui.IGui; |
|---|
| | 20 | public import mde.gui.IGui; |
|---|
| 21 | 21 | |
|---|
| 22 | 22 | /** Interface for Window, allowing widgets to call some of Window's methods. |
|---|
| … | … | |
| 41 | 41 | IWidget makeWidget (widgetID i); |
|---|
| 42 | 42 | |
|---|
| | 43 | /** Get a string from the widgetString associative array. */ |
|---|
| | 44 | char[] getWidgetString (int i); |
|---|
| | 45 | |
|---|
| 43 | 46 | /** Add widget's saveData to the data to be saved, returning it's widgetID. */ |
|---|
| 44 | 47 | widgetID addCreationData (IWidget widget); |
|---|
| | 48 | |
|---|
| | 49 | /** Add a string to the widgetString associative array, returning it's index. */ |
|---|
| | 50 | int addWidgetString (char[] str); |
|---|
| 45 | 51 | |
|---|
| 46 | 52 | /** Returns the window's gui. */ |
|---|
| … | … | |
| 65 | 71 | * and is able to communicate with it's window and parent/child widgets as necessary. |
|---|
| 66 | 72 | * |
|---|
| 67 | | * A widget's constructor should have this prototype: |
|---|
| | 73 | * A widget's constructor should have the prototype and doc explaining what initialization data is |
|---|
| | 74 | * used (excluding the widget ID, which every widget recieves): |
|---|
| 68 | 75 | * ---------------------------------- |
|---|
| | 76 | * /++ Constructor for a ... widget. |
|---|
| | 77 | * + |
|---|
| | 78 | * + Widget uses the initialisation data: |
|---|
| | 79 | * + [widgetID, x, y] |
|---|
| | 80 | * + where x is ... and y is ... +/ |
|---|
| 69 | 81 | * this (IWindow window, int[] data); |
|---|
| 70 | 82 | * ---------------------------------- |
|---|
| … | … | |
| 95 | 107 | |
|---|
| 96 | 108 | /** Output data suitible for recreating the widget (data to be passed to this()). |
|---|
| | 109 | * |
|---|
| | 110 | * Function may need to call Window's addCreationData() and addWidgetString() methods to save |
|---|
| | 111 | * other data. |
|---|
| 97 | 112 | * |
|---|
| 98 | 113 | * Creation data is data only changed when the gui is edited. */ |
|---|
| r63 |
r65 |
|
| 31 | 31 | /// Adapter to ease use of ContentText |
|---|
| 32 | 32 | struct ContentAdapter(ContentT : IContent) { |
|---|
| 33 | | void set (int col) { |
|---|
| | 33 | void set (char[] cID, int col) { |
|---|
| 34 | 34 | if (font is null) font = FontStyle.get("default"); |
|---|
| 35 | 35 | |
|---|
| 36 | | content = new ContentT; |
|---|
| | 36 | static if (is(ContentT == ContentText)) { |
|---|
| | 37 | content = getContentText (cID); |
|---|
| | 38 | } else static if (is(ContentT == ContentInt)) { |
|---|
| | 39 | content = getContentInt (cID); |
|---|
| | 40 | } else static assert (false, "Unsupported content type"); |
|---|
| 37 | 41 | colour = Colour (cast(ubyte) (col >> 16u), |
|---|
| 38 | 42 | cast(ubyte) (col >> 8u), |
|---|
| … | … | |
| 59 | 63 | class ContentWidget(ContentT : IContent) : Widget |
|---|
| 60 | 64 | { |
|---|
| | 65 | /** Constructor for a widget containing [fixed] content. |
|---|
| | 66 | * |
|---|
| | 67 | * Widget uses the initialisation data: |
|---|
| | 68 | * [widgetID, contentID, colour] |
|---|
| | 69 | * where contentID is an ID for the string ID of the contained content |
|---|
| | 70 | * and colour is an 8-bit-per-channel RGB colour of the form 0xRRGGBB. */ |
|---|
| 61 | 71 | this (IWindow wind, int[] data) { |
|---|
| 62 | | if (data.length != 2) throw new WidgetDataException; |
|---|
| 63 | | text.set (data[1]); |
|---|
| | 72 | if (data.length != 3) throw new WidgetDataException; |
|---|
| | 73 | text.set (wind.getWidgetString(data[1]), data[2]); |
|---|
| 64 | 74 | text.getDimensions (mw, mh); |
|---|
| 65 | 75 | super (wind,data); |
|---|
| r58 |
r65 |
|
| 33 | 33 | //BEGIN Load and save |
|---|
| 34 | 34 | // Base this(). All widgets must check data.length is correct before calling this method. |
|---|
| | 35 | // The widget ID is saved to widgetType, for correct saving. |
|---|
| 35 | 36 | this (IWindow wind, int[] data) { |
|---|
| 36 | 37 | window = wind; |
|---|
| … | … | |
| 115 | 116 | class FixedWidget : Widget { |
|---|
| 116 | 117 | // Check data.length is at least 3 before calling! |
|---|
| | 118 | /** Constructor for a fixed-size [blank] widget. |
|---|
| | 119 | * |
|---|
| | 120 | * Widget uses the initialisation data: |
|---|
| | 121 | * [widgetID, w, h] |
|---|
| | 122 | * where w, h is the fixed size. */ |
|---|
| 117 | 123 | this (IWindow wind, int[] data) { |
|---|
| 118 | 124 | mw = cast(wdim) data[1]; |
|---|
| … | … | |
| 130 | 136 | class SizableWidget : Widget { |
|---|
| 131 | 137 | // Check data.length is at least 1 before calling! |
|---|
| | 138 | /// Constructor for a completely resizable [blank] widget. |
|---|
| 132 | 139 | this (IWindow wind, int[] data) { |
|---|
| 133 | 140 | super (wind, data); |
|---|
| r58 |
r65 |
|
| 70 | 70 | // Note: GridLayoutWidget's this relies on rend.layoutSpacing. |
|---|
| 71 | 71 | widget = makeWidget (0); // primary widget always has ID 0. |
|---|
| 72 | | widgetData = null; // data is no longer needed: allow GC to collect (cannot safely delete) |
|---|
| | 72 | // This data is no longer needed by Window, although its sub-arrays may still be used, so |
|---|
| | 73 | // let the GC collect what it can: |
|---|
| | 74 | widgetData = null; |
|---|
| | 75 | widgetStrings = null; |
|---|
| 73 | 76 | |
|---|
| 74 | 77 | // get border sizes: |
|---|
| … | … | |
| 99 | 102 | void addTag (char[] tp, mt.ID id, char[] dt) { |
|---|
| 100 | 103 | // Priority is HIGH_LOW, so don't overwrite data which has already been loaded. |
|---|
| 101 | | if (tp == INTAA) { |
|---|
| | 104 | if (tp == INTAINT) { |
|---|
| 102 | 105 | if (id == WDGD && widgetData == null) { |
|---|
| 103 | 106 | widgetData = cast(int[][widgetID]) parseTo!(int[][int]) (dt); |
|---|
| | 107 | } |
|---|
| | 108 | } else if (tp == CHARAINT) { |
|---|
| | 109 | if (id == WS && widgetStrings == null) { |
|---|
| | 110 | widgetStrings = parseTo!(char[][int]) (dt); |
|---|
| 104 | 111 | } |
|---|
| 105 | 112 | } else if (tp == INTA) { |
|---|
| … | … | |
| 122 | 129 | if (edited) { // only save the widget creation data if it's been adjusted: |
|---|
| 123 | 130 | addCreationData (widget); // generate widget save data |
|---|
| 124 | | dlg (INTAA, WDGD, parseFrom!(int[][int]) (widgetData)); |
|---|
| | 131 | dlg (INTAINT, WDGD, parseFrom!(int[][int]) (widgetData)); |
|---|
| | 132 | dlg (CHARAINT, WS, parseFrom!(char[][int]) (widgetStrings)); |
|---|
| 125 | 133 | }+/ |
|---|
| 126 | 134 | // Save mutable data: |
|---|
| … | … | |
| 131 | 139 | } |
|---|
| 132 | 140 | private static const { |
|---|
| 133 | | auto INTAA = "int[][int]"; |
|---|
| | 141 | auto CHARAINT = "char[][int]"; |
|---|
| | 142 | auto INTAINT = "int[][int]"; |
|---|
| 134 | 143 | auto INTA = "int[]"; |
|---|
| 135 | 144 | auto INT = "int"; |
|---|
| 136 | 145 | auto WDGD = "widgetData"; |
|---|
| 137 | 146 | auto MD = "mutableData"; |
|---|
| | 147 | auto WS = "widgetStrings"; |
|---|
| 138 | 148 | auto X = "x"; |
|---|
| 139 | 149 | auto Y = "y"; |
|---|
| … | … | |
| 162 | 172 | } |
|---|
| 163 | 173 | |
|---|
| | 174 | char[] getWidgetString (int i) |
|---|
| | 175 | in { |
|---|
| | 176 | // widgetStrings is freed at same time as widgetData |
|---|
| | 177 | // but widgetData is guaranteed to be read |
|---|
| | 178 | assert (widgetData !is null, "getWidgetString called after widget creation finished"); |
|---|
| | 179 | } body { |
|---|
| | 180 | char[]* p; |
|---|
| | 181 | if (widgetStrings is null || |
|---|
| | 182 | (p = i in widgetStrings) is null ) |
|---|
| | 183 | throw new WindowLoadException ("Needed widgetStrings not set for Window"); |
|---|
| | 184 | |
|---|
| | 185 | return *p; |
|---|
| | 186 | } |
|---|
| | 187 | |
|---|
| 164 | 188 | /** Add this widget's data to that to be saved, returning it's widgetID. */ |
|---|
| 165 | 189 | widgetID addCreationData (IWidget widget) |
|---|
| … | … | |
| 171 | 195 | i = widgetData.keys[$-1] + 1; |
|---|
| 172 | 196 | |
|---|
| | 197 | /+ Doesn't this have no effect except when getCreationData throws, in which case the data |
|---|
| | 198 | + isn't used anyway? I'm sure it was added for a reason... FIXME and below |
|---|
| 173 | 199 | widgetData[i] = null; // Make sure the same ID doesn't get used by a recursive call |
|---|
| | 200 | +/ |
|---|
| 174 | 201 | widgetData[i] = widget.getCreationData; |
|---|
| | 202 | |
|---|
| | 203 | return i; |
|---|
| | 204 | } |
|---|
| | 205 | |
|---|
| | 206 | int addWidgetString (char[] str) |
|---|
| | 207 | { |
|---|
| | 208 | int i; |
|---|
| | 209 | if (widgetStrings is null) |
|---|
| | 210 | i = 0; |
|---|
| | 211 | else |
|---|
| | 212 | i = widgetStrings.keys[$-1] + 1; |
|---|
| | 213 | |
|---|
| | 214 | /+ See above. FIXME |
|---|
| | 215 | widgetStrings[i] = null; // Make sure the same ID doesn't get used by a recursive call |
|---|
| | 216 | +/ |
|---|
| | 217 | widgetStrings[i] = str; |
|---|
| 175 | 218 | |
|---|
| 176 | 219 | return i; |
|---|
| … | … | |
| 357 | 400 | int[][widgetID] widgetData = null;// Data for all widgets under this window |
|---|
| 358 | 401 | int[] mutableData = null; // Widget's mutable data (adjusted sizes, etc.) |
|---|
| | 402 | char[][int] widgetStrings = null;// Strings by ID; string-typed creation data |
|---|
| 359 | 403 | |
|---|
| 360 | 404 | IGui gui_; // The gui managing this window |
|---|
| r58 |
r65 |
|
| 39 | 39 | { |
|---|
| 40 | 40 | //BEGIN Creation & saving |
|---|
| | 41 | /** Constructor for a grid layout widget. |
|---|
| | 42 | * |
|---|
| | 43 | * Widget uses the initialisation data: |
|---|
| | 44 | * [widgetID, r, c, w11, w12, ..., w1c, ..., wr1, ..., wrc] |
|---|
| | 45 | * where r and c are the number of rows and columns, and wij is the ID (from parent Window's |
|---|
| | 46 | * list) for the widget in row i and column j. The number of parameters must be r*c + 3. */ |
|---|
| 41 | 47 | this (IWindow wind, int[] data) { |
|---|
| 42 | 48 | // Get grid size and check data |
|---|