Changeset 93:08a4ae11454b
- Timestamp:
- 10/21/08 06:35:15
(3 months ago)
- Author:
- Diggory Hardy <diggory.hardy@gmail.com>
- branch:
- default
- Message:
Widgets now save dimensions without preventing structural changes in the base config file from applying.
Widget dimensional data separated from other data in files, hence above change.
Moved TextAdapter? from TextWidget? to IRenderer.
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r92 |
r93 |
|
| 5 | 5 | <WidgetData|root={0:[0xC100,0,3,3],1:["square","blank","square","blank","content","blank","square","blank","square"]}> |
|---|
| 6 | 6 | <WidgetData|square={0:[0x1,6,6]}> |
|---|
| 7 | | <WidgetData|content={0:[0xC100,0,4,2],1:["floating","button","blank","blank","blank","opts","blank","blank"]}> |
|---|
| | 7 | <WidgetData|content={0:[0xC100,0,4,2],1:["floating","button","blank","blank","f2","opts","blank","blank"]}> |
|---|
| 8 | 8 | <WidgetData|button={0:[0x10,50,50]}> |
|---|
| 9 | 9 | <WidgetData|blank={0:[0x2]}> |
|---|
| … | … | |
| 16 | 16 | <WidgetData|optSep={0:[0x21, 0xff],1:["="]}> |
|---|
| 17 | 17 | <WidgetData|floating={0:[0x8200,20,20],1:["text"]}> |
|---|
| | 18 | <WidgetData|f2={0:[0x8200,50,20],1:["button"]}> |
|---|
| 18 | 19 | <WidgetData|text={0:[0x21,0xFF0000],1:["Floating text"]}> |
|---|
| 19 | 20 | {Basic} |
|---|
| r91 |
r93 |
|
| 51 | 51 | if (tp == "WidgetData" && (id in widgetData) is null) { |
|---|
| 52 | 52 | widgetData[id] = deserialize!(WidgetData) (dt); |
|---|
| | 53 | } else if (tp == "WDims" && (id in dimData) is null) { |
|---|
| | 54 | dimData[id] = cast(wdims) deserialize!(int[]) (dt); |
|---|
| 53 | 55 | } |
|---|
| 54 | 56 | } |
|---|
| … | … | |
| 67 | 69 | } |
|---|
| 68 | 70 | |
|---|
| | 71 | /** Get the widget dimensions for widget i (null if none). */ |
|---|
| | 72 | wdims dims (widgetID id) { |
|---|
| | 73 | auto p = id in dimData; |
|---|
| | 74 | return p ? *p : null; |
|---|
| | 75 | } |
|---|
| | 76 | |
|---|
| 69 | 77 | protected: |
|---|
| 70 | | WidgetData[widgetID] widgetData; // Per-widget data: |
|---|
| | 78 | WidgetData[widgetID] widgetData; // Per-widget data |
|---|
| | 79 | wdims[widgetID] dimData; // Per-widget sizes |
|---|
| 71 | 80 | } |
|---|
| 72 | 81 | |
|---|
| … | … | |
| 91 | 100 | foreach (id,data; widgetData) |
|---|
| 92 | 101 | dlg ("WidgetData", id, serialize!(WidgetData) (data)); |
|---|
| | 102 | foreach (id,dim; dimData) |
|---|
| | 103 | dlg ("WDims", id, serialize!(int[]) (cast(int[]) dim)); |
|---|
| 93 | 104 | } |
|---|
| 94 | 105 | //END Mergetag code |
|---|
| … | … | |
| 101 | 112 | } |
|---|
| 102 | 113 | |
|---|
| | 114 | /** Set the widget dimensions for widget i. */ |
|---|
| | 115 | void setDims (widgetID id, wdims d) { |
|---|
| | 116 | dimData[id] = d; |
|---|
| | 117 | base.dimData[id] = d; |
|---|
| | 118 | } |
|---|
| | 119 | |
|---|
| 103 | 120 | /** Do any changes exist? True if no changes have been stored. */ |
|---|
| 104 | 121 | bool none () { |
|---|
| r92 |
r93 |
|
| 334 | 334 | |
|---|
| 335 | 335 | // Make all widgets save any changed data; return if no changes: |
|---|
| 336 | | if (!child.saveChanges ("root")) |
|---|
| | 336 | if (!child.saveChanges) |
|---|
| 337 | 337 | return; |
|---|
| 338 | 338 | |
|---|
| … | … | |
| 426 | 426 | } |
|---|
| 427 | 427 | |
|---|
| 428 | | /** For making changes. */ |
|---|
| | 428 | /** Get dimension data for a widget. */ |
|---|
| | 429 | wdims dimData (widgetID id) { |
|---|
| | 430 | return curData.dims (id); |
|---|
| | 431 | } |
|---|
| | 432 | |
|---|
| | 433 | /** For making changes to widget structure. */ |
|---|
| 429 | 434 | void setData (widgetID id, WidgetData d) { |
|---|
| 430 | 435 | changes[id] = d; // also updates WidgetDataSet in data. |
|---|
| | 436 | } |
|---|
| | 437 | |
|---|
| | 438 | /** For making changes to widget dimensions. */ |
|---|
| | 439 | void setDimData (widgetID id, wdims d) { |
|---|
| | 440 | changes.setDims(id, d); // also updates WidgetDataSet in data. |
|---|
| 431 | 441 | } |
|---|
| 432 | 442 | |
|---|
| r80 |
r93 |
|
| 18 | 18 | |
|---|
| 19 | 19 | public import mde.gui.types; |
|---|
| | 20 | import mde.font.font; |
|---|
| 20 | 21 | |
|---|
| 21 | 22 | /** Interface for renderers. |
|---|
| … | … | |
| 91 | 92 | /** Draws a button frame, in if pushed == true. */ |
|---|
| 92 | 93 | void drawButton (wdim x, wdim y, wdim w, wdim h, bool pushed); |
|---|
| | 94 | |
|---|
| | 95 | /** Get a TextAdapter to draw some text. */ |
|---|
| | 96 | TextAdapter getAdapter (char[] text, int colour); |
|---|
| | 97 | |
|---|
| | 98 | /** For drawing text - one instance per string. |
|---|
| | 99 | * |
|---|
| | 100 | * NOTE: currently inflexible. Could use (function) pointers, class interfaces or struct |
|---|
| | 101 | * interfaces when available to allow flexibility. */ |
|---|
| | 102 | struct TextAdapter { |
|---|
| | 103 | void set (char[] c, int col) { |
|---|
| | 104 | content = c; |
|---|
| | 105 | colour = Colour (col); |
|---|
| | 106 | } |
|---|
| | 107 | |
|---|
| | 108 | void getDimensions (out wdsize w, out wdsize h) { |
|---|
| | 109 | font.updateBlock (content, textCache); |
|---|
| | 110 | w = cast(wdim) textCache.w; |
|---|
| | 111 | h = cast(wdim) textCache.h; |
|---|
| | 112 | } |
|---|
| | 113 | |
|---|
| | 114 | void draw (wdabs x, wdabs y) { |
|---|
| | 115 | font.textBlock (x,y, content, textCache, colour); |
|---|
| | 116 | } |
|---|
| | 117 | |
|---|
| | 118 | char[] content; |
|---|
| | 119 | TextBlock textCache; |
|---|
| | 120 | Colour colour; |
|---|
| | 121 | FontStyle font; |
|---|
| | 122 | } |
|---|
| 93 | 123 | //END draw routines |
|---|
| 94 | 124 | } |
|---|
| r91 |
r93 |
|
| 20 | 20 | |
|---|
| 21 | 21 | import gl = mde.gl.basic; |
|---|
| | 22 | import mde.font.font; |
|---|
| 22 | 23 | |
|---|
| 23 | 24 | /** Interface for renderers. |
|---|
| … | … | |
| 30 | 31 | class SimpleRenderer : IRenderer |
|---|
| 31 | 32 | { |
|---|
| | 33 | this () { |
|---|
| | 34 | defaultFont = FontStyle.get("default"); |
|---|
| | 35 | } |
|---|
| | 36 | |
|---|
| 32 | 37 | BorderDimensions setSizable (bool wS, bool hS) { |
|---|
| 33 | 38 | wSizable = wS; |
|---|
| … | … | |
| 115 | 120 | } |
|---|
| 116 | 121 | |
|---|
| | 122 | TextAdapter getAdapter (char[] text, int col) { |
|---|
| | 123 | TextAdapter a; |
|---|
| | 124 | a.font = defaultFont; |
|---|
| | 125 | a.set (text, col); |
|---|
| | 126 | return a; |
|---|
| | 127 | } |
|---|
| | 128 | |
|---|
| 117 | 129 | protected: |
|---|
| 118 | 130 | bool wSizable, hSizable; |
|---|
| 119 | 131 | BorderDimensions border; |
|---|
| 120 | 132 | BorderDimensions resize; |
|---|
| | 133 | FontStyle defaultFont; |
|---|
| 121 | 134 | } |
|---|
| r80 |
r93 |
|
| 48 | 48 | } |
|---|
| 49 | 49 | |
|---|
| | 50 | /// Used to save column sizes, etc. |
|---|
| | 51 | alias wdim[] wdims; |
|---|
| | 52 | |
|---|
| 50 | 53 | |
|---|
| 51 | 54 | /************************************************************************************************* |
|---|
| r92 |
r93 |
|
| 62 | 62 | IChildWidget makeWidget (widgetID id, IContent content = null); |
|---|
| 63 | 63 | |
|---|
| | 64 | /// Get dimensional data. |
|---|
| | 65 | wdims dimData (widgetID id); |
|---|
| | 66 | |
|---|
| 64 | 67 | /** Record some changes, for saving. Should only be called from IWidget.saveChanges() to avoid |
|---|
| 65 | | * multiple calls for instanced widgets of same id. */ |
|---|
| | 68 | * multiple calls for instanced widgets of same id. |
|---|
| | 69 | * |
|---|
| | 70 | * WidgetData is for most data, dimensional data (wdims) is for dimensions. */ |
|---|
| 66 | 71 | void setData (widgetID id, WidgetData); |
|---|
| | 72 | void setDimData (widgetID id, wdims d); /// ditto |
|---|
| 67 | 73 | |
|---|
| 68 | 74 | // Rendering: |
|---|
| … | … | |
| 160 | 166 | * If the widget has subwidgets, it should also be recursively called on these (passing their |
|---|
| 161 | 167 | * ids). */ |
|---|
| 162 | | // FIXME - no longer necessary to pass id! |
|---|
| 163 | | bool saveChanges (widgetID id); |
|---|
| | 168 | bool saveChanges (); |
|---|
| 164 | 169 | |
|---|
| 165 | 170 | /** Called when the renderer is changed (at least when the changes affect dimensions). |
|---|
| r91 |
r93 |
|
| 25 | 25 | import mde.gui.content.Content; |
|---|
| 26 | 26 | |
|---|
| 27 | | import mde.font.font; |
|---|
| 28 | | |
|---|
| 29 | | /// Adapter to ease use of ContentLabelWidget |
|---|
| 30 | | struct TextAdapter { |
|---|
| 31 | | void set (char[] c, int col) { |
|---|
| 32 | | //FIXME tie font to renderer or so |
|---|
| 33 | | if (font is null) font = FontStyle.get("default"); |
|---|
| 34 | | |
|---|
| 35 | | content = c; |
|---|
| 36 | | colour = Colour (col); |
|---|
| 37 | | } |
|---|
| 38 | | |
|---|
| 39 | | void getDimensions (out wdsize w, out wdsize h) { |
|---|
| 40 | | font.updateBlock (content, textCache); |
|---|
| 41 | | w = cast(wdim) textCache.w; |
|---|
| 42 | | h = cast(wdim) textCache.h; |
|---|
| 43 | | } |
|---|
| 44 | | |
|---|
| 45 | | void draw (wdabs x, wdabs y) { |
|---|
| 46 | | font.textBlock (x,y, content, textCache, colour); |
|---|
| 47 | | } |
|---|
| 48 | | |
|---|
| 49 | | char[] content; |
|---|
| 50 | | TextBlock textCache; |
|---|
| 51 | | Colour colour; |
|---|
| 52 | | static FontStyle font; |
|---|
| 53 | | } |
|---|
| 54 | | |
|---|
| 55 | 27 | /// Basic text widget |
|---|
| 56 | 28 | class TextLabelWidget : Widget |
|---|
| … | … | |
| 64 | 36 | this (IWidgetManager mgr, widgetID id, WidgetData data) { |
|---|
| 65 | 37 | WDCheck (data, 2, 1); |
|---|
| 66 | | adapter.set (data.strings[0], data.ints[1]); |
|---|
| | 38 | adapter = mgr.renderer.getAdapter (data.strings[0], data.ints[1]); |
|---|
| 67 | 39 | adapter.getDimensions (mw, mh); |
|---|
| 68 | 40 | super (mgr, id, data); |
|---|
| … | … | |
| 75 | 47 | |
|---|
| 76 | 48 | protected: |
|---|
| 77 | | TextAdapter adapter; |
|---|
| | 49 | IRenderer.TextAdapter adapter; |
|---|
| 78 | 50 | } |
|---|
| 79 | 51 | |
|---|
| … | … | |
| 85 | 57 | content = c; |
|---|
| 86 | 58 | index = data.ints[1]; |
|---|
| 87 | | adapter.set (content.toString(index), data.ints[2]); |
|---|
| | 59 | adapter = mgr.renderer.getAdapter (content.toString(index), data.ints[2]); |
|---|
| 88 | 60 | adapter.getDimensions (mw, mh); |
|---|
| 89 | 61 | super (mgr, id,data); |
|---|
| … | … | |
| 96 | 68 | |
|---|
| 97 | 69 | protected: |
|---|
| 98 | | TextAdapter adapter; |
|---|
| | 70 | IRenderer.TextAdapter adapter; |
|---|
| 99 | 71 | IContent content; |
|---|
| 100 | 72 | int index; |
|---|
| r92 |
r93 |
|
| 46 | 46 | //BEGIN Load and save |
|---|
| 47 | 47 | // Base this() for child Widgets. |
|---|
| 48 | | this (IWidgetManager mgr, widgetID, WidgetData) { |
|---|
| | 48 | this (IWidgetManager mgr, widgetID id, WidgetData) { |
|---|
| 49 | 49 | this.mgr = mgr; |
|---|
| | 50 | this.id = id; |
|---|
| 50 | 51 | } |
|---|
| 51 | 52 | |
|---|
| … | … | |
| 60 | 61 | |
|---|
| 61 | 62 | // Don't save any data: fine for many widgets. |
|---|
| 62 | | // FIXME: implementation could be added to ParentWidget |
|---|
| 63 | | bool saveChanges (widgetID) { |
|---|
| | 63 | bool saveChanges () { |
|---|
| 64 | 64 | return false; |
|---|
| 65 | 65 | } |
|---|
| … | … | |
| 145 | 145 | } |
|---|
| 146 | 146 | |
|---|
| | 147 | widgetID id; // The widget's ID, used for saving data |
|---|
| 147 | 148 | IWidgetManager mgr; // the enclosing window |
|---|
| 148 | 149 | wdim x, y; // position |
|---|
| … | … | |
| 163 | 164 | IChildWidget[] children () { |
|---|
| 164 | 165 | return subWidgets; |
|---|
| | 166 | } |
|---|
| | 167 | |
|---|
| | 168 | bool saveChanges () { |
|---|
| | 169 | bool c = false; |
|---|
| | 170 | foreach (w; subWidgets) |
|---|
| | 171 | c |= w.saveChanges; |
|---|
| | 172 | return c; |
|---|
| 165 | 173 | } |
|---|
| 166 | 174 | |
|---|
| r92 |
r93 |
|
| 62 | 62 | // Get grid size and check data |
|---|
| 63 | 63 | // Check sufficient data for type, align-flags, rows, cols, and possibly row/col widths. |
|---|
| 64 | | if (data.ints.length < 4) throw new WidgetDataException (this); |
|---|
| | 64 | if (data.ints.length != 4) throw new WidgetDataException (this); |
|---|
| 65 | 65 | |
|---|
| 66 | 66 | rows = data.ints[2]; |
|---|
| 67 | 67 | cols = data.ints[3]; |
|---|
| 68 | | // Check: at least one sub-widget, ints length == 3 or also contains row & col widths, |
|---|
| 69 | | // strings' length is correct: |
|---|
| 70 | | if (rows < 1 || cols < 1 || |
|---|
| 71 | | (data.ints.length != 4 && data.ints.length != 4 + rows + cols) || |
|---|
| 72 | | data.strings.length != rows * cols) |
|---|
| | 68 | // Check: at least one sub-widget, ints length == 3, strings' length is correct: |
|---|
| | 69 | if (rows < 1 || cols < 1 || data.ints.length != 4 || data.strings.length != rows * cols) |
|---|
| 73 | 70 | throw new WidgetDataException (this); |
|---|
| 74 | | this.data = data; |
|---|
| 75 | 71 | |
|---|
| 76 | 72 | // Get all sub-widgets |
|---|
| … | … | |
| 80 | 76 | } |
|---|
| 81 | 77 | |
|---|
| 82 | | if (data.ints.length == 4 + rows + cols) |
|---|
| 83 | | initWidths = cast(wdim[]) data.ints[4..$]; |
|---|
| | 78 | initWidths = mgr.dimData (id); // may be null, tested later |
|---|
| 84 | 79 | |
|---|
| 85 | 80 | super (mgr, id, data); |
|---|
| … | … | |
| 87 | 82 | |
|---|
| 88 | 83 | // Save column/row sizes. Currently always do so. |
|---|
| 89 | | bool saveChanges (widgetID id) { |
|---|
| 90 | | with (data) { |
|---|
| 91 | | foreach (i, widget; subWidgets) // recurse on subwidgets |
|---|
| 92 | | widget.saveChanges (strings[i]); |
|---|
| 93 | | |
|---|
| 94 | | ints = ints[0..4] ~ cast(int[])col.width ~ cast(int[])row.width; |
|---|
| 95 | | } |
|---|
| 96 | | mgr.setData (id, data); |
|---|
| | 84 | bool saveChanges () { |
|---|
| | 85 | foreach (widget; subWidgets) // recurse on subwidgets |
|---|
| | 86 | widget.saveChanges (); |
|---|
| | 87 | |
|---|
| | 88 | mgr.setDimData (id, col.width ~ row.width); |
|---|
| 97 | 89 | return true; |
|---|
| 98 | 90 | } |
|---|
| 99 | 91 | protected: |
|---|
| 100 | | WidgetData data; |
|---|
| 101 | 92 | } |
|---|
| 102 | 93 | |
|---|
| … | … | |
| 115 | 106 | rows = optsList.list.length; |
|---|
| 116 | 107 | cols = 1; |
|---|
| 117 | | sWId = data.strings[0]; |
|---|
| 118 | 108 | |
|---|
| 119 | 109 | // Get all sub-widgets |
|---|
| 120 | 110 | subWidgets.length = rows*cols; |
|---|
| 121 | 111 | foreach (i, c; optsList.list) { |
|---|
| 122 | | subWidgets[i] = mgr.makeWidget (sWId, c); |
|---|
| | 112 | subWidgets[i] = mgr.makeWidget (data.strings[0], c); |
|---|
| 123 | 113 | } |
|---|
| 124 | 114 | super (mgr, id, data); |
|---|
| 125 | 115 | } |
|---|
| 126 | 116 | |
|---|
| 127 | | bool saveChanges (widgetID id) { |
|---|
| | 117 | bool saveChanges () { |
|---|
| 128 | 118 | // Since all sub-widgets have the same id, it only makes sense to call on one |
|---|
| 129 | 119 | if (subWidgets is null) |
|---|
| 130 | 120 | return false; |
|---|
| 131 | | return subWidgets[0].saveChanges (sWId); |
|---|
| | 121 | return subWidgets[0].saveChanges; |
|---|
| 132 | 122 | } |
|---|
| 133 | 123 | |
|---|
| 134 | 124 | private: |
|---|
| 135 | 125 | OptionList optsList; |
|---|
| 136 | | widgetID sWId; // sub-widget's ID, for calling saveChanges FIXME no longer pass? |
|---|
| 137 | 126 | } |
|---|
| 138 | 127 | |
|---|
| … | … | |
| 188 | 177 | * As such, this must be the first function called after this(). */ |
|---|
| 189 | 178 | void finalize () { |
|---|
| 190 | | if (initWidths) { |
|---|
| 191 | | debug assert (initWidths.length == cols + rows, "initWidths provided but has bad length"); |
|---|
| | 179 | logger.trace ("initWidths.length: {}", initWidths.length); |
|---|
| | 180 | if (initWidths.length == cols + rows) { |
|---|
| 192 | 181 | col.setWidths (initWidths[0..cols]); |
|---|
| 193 | 182 | row.setWidths (initWidths[cols..$]); |
|---|
| 194 | | initWidths = null; // free |
|---|
| 195 | 183 | } else { |
|---|
| 196 | 184 | col.setWidths; |
|---|
| 197 | 185 | row.setWidths; |
|---|
| 198 | 186 | } |
|---|
| | 187 | initWidths = null; // free |
|---|
| 199 | 188 | |
|---|
| 200 | 189 | mw = col.mw; |
|---|