Mercurial > projects > mde
comparison mde/gui/widget/layout.d @ 121:5b37d0400732
Widgets now receive and store their parent (IParentWidget). Infinite widget recursion checks. WidgetManager code redistributed.
WidgetManager code redistributed between classes; WMScreen class moved to WMScreen.d.
addContent function now calls makeWidget with another id.
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Fri, 02 Jan 2009 18:07:10 +0000 |
parents | 9ac208b53582 |
children | d3b2cefd46c9 |
comparison
equal
deleted
inserted
replaced
120:46c63cb1c74f | 121:5b37d0400732 |
---|---|
54 * --- | 54 * --- |
55 * where R and C are the number of rows and columns, and wij is the ID (from parent Window's | 55 * where R and C are the number of rows and columns, and wij is the ID (from parent Window's |
56 * list) for the widget in row i and column j. The number of parameters must be r*c + 3. | 56 * list) for the widget in row i and column j. The number of parameters must be r*c + 3. |
57 * | 57 * |
58 * The content parameter is passed on to all children accepting an IContent. */ | 58 * The content parameter is passed on to all children accepting an IContent. */ |
59 this (IWidgetManager mgr, widgetID id, WidgetData data, IContent content) { | 59 this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData data, IContent content) { |
60 // Get grid size and check data | 60 // Get grid size and check data |
61 // Check sufficient data for type, align-flags, rows, cols, and possibly row/col widths. | 61 // Check sufficient data for type, align-flags, rows, cols, and possibly row/col widths. |
62 if (data.ints.length != 4) throw new WidgetDataException (this); | 62 if (data.ints.length != 4) throw new WidgetDataException (this); |
63 | 63 |
64 rows = data.ints[2]; | 64 rows = data.ints[2]; |
65 cols = data.ints[3]; | 65 cols = data.ints[3]; |
66 // Check: at least one sub-widget, ints length == 3, strings' length is correct: | 66 // Check: at least one sub-widget and strings's length is correct: |
67 if (rows < 1 || cols < 1 || data.ints.length != 4 || data.strings.length != rows * cols) | 67 if (rows < 1 || cols < 1 || data.strings.length != rows * cols) |
68 throw new WidgetDataException (this); | 68 throw new WidgetDataException (this); |
69 super (mgr, parent, id, data); | |
69 | 70 |
70 // Get all sub-widgets | 71 // Get all sub-widgets |
71 subWidgets.length = rows*cols; | 72 subWidgets.length = rows*cols; |
72 foreach (i, ref subWidget; subWidgets) { | 73 foreach (i, ref subWidget; subWidgets) { |
73 subWidget = mgr.makeWidget (data.strings[i], content); | 74 subWidget = mgr.makeWidget (this, data.strings[i], content); |
74 } | 75 } |
75 | 76 |
76 initWidths = mgr.dimData (id); // may be null, tested later | 77 initWidths = mgr.dimData (id); // may be null, tested later |
77 | |
78 super (mgr, id, data); | |
79 } | 78 } |
80 | 79 |
81 // Save column/row sizes. Currently always do so. | 80 // Save column/row sizes. Currently always do so. |
82 override bool saveChanges () { | 81 override bool saveChanges () { |
83 foreach (widget; subWidgets) // recurse on subwidgets | 82 foreach (widget; subWidgets) // recurse on subwidgets |
84 widget.saveChanges (); | 83 widget.saveChanges (); |
85 | 84 |
86 mgr.setDimData (id, col.width ~ row.width); | 85 mgr.dimData (id, col.width ~ row.width); |
87 return true; | 86 return true; |
88 } | 87 } |
89 protected: | 88 protected: |
90 } | 89 } |
91 | 90 |
96 * content.Items is used to get an IContent. It is an error if the content fails to cast to | 95 * content.Items is used to get an IContent. It is an error if the content fails to cast to |
97 * ContentList. | 96 * ContentList. |
98 *************************************************************************************************/ | 97 *************************************************************************************************/ |
99 class ContentListWidget : GridWidget | 98 class ContentListWidget : GridWidget |
100 { | 99 { |
101 this (IWidgetManager mgr, widgetID id, WidgetData data, IContent content) { | 100 this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData data, IContent content) { |
102 cList = cast(IContentList) content; | 101 cList = cast(IContentList) content; |
103 WDCCheck (data, 2, 1, cList); | 102 WDCCheck (data, 2, 1, cList); |
104 | 103 logger.trace ("Got data: {} and {}", data.ints, data.strings); |
105 cols = 1; | 104 cols = 1; |
106 if ((rows = cList.list.length) > 0) { | 105 rows = cList.list.length; |
107 subWidgets.length = rows; | 106 subWidgets.length = rows; |
108 foreach (i, c; cList.list) { | |
109 subWidgets[i] = mgr.makeWidget (data.strings[0], c); | |
110 } | |
111 } else { | |
112 rows = 1; | |
113 subWidgets = [mgr.makeWidget (data.strings[0], new ErrorContent ("<empty list>"))]; | |
114 } | |
115 if (data.ints[1] & 8) { // orient horizontally | 107 if (data.ints[1] & 8) { // orient horizontally |
116 cols = rows; | 108 cols = rows; |
117 rows = 1; | 109 rows = 1; |
118 } | 110 } |
119 super (mgr, id, data); | 111 super (mgr, parent, id, data); |
112 | |
113 if (subWidgets) { // i.e. rows*cols > 0 | |
114 foreach (i, c; cList.list) { | |
115 subWidgets[i] = mgr.makeWidget (this, data.strings[0], c); | |
116 } | |
117 } else { | |
118 rows = cols = 1; | |
119 subWidgets = [mgr.makeWidget (this, data.strings[0], new ErrorContent ("<empty list>"))]; | |
120 } | |
120 } | 121 } |
121 | 122 |
122 override bool saveChanges () { | 123 override bool saveChanges () { |
123 // Since all sub-widgets have the same id, it only makes sense to call on one | 124 // Since all sub-widgets have the same id, it only makes sense to call on one |
124 if (subWidgets is null) | 125 if (subWidgets is null) |
144 abstract class GridWidget : AParentWidget | 145 abstract class GridWidget : AParentWidget |
145 { | 146 { |
146 //BEGIN Creation & saving | 147 //BEGIN Creation & saving |
147 /** Partial constructor for a grid layout widget. | 148 /** Partial constructor for a grid layout widget. |
148 * | 149 * |
149 * Deriving classes should check data lengths, and set rows, cols, and the subWidgets array, | 150 * Deriving classes should check data lengths, and set rows and cols |
150 * before calling this super constructor. (If it's necessary to call super(...) first, | 151 * before calling this super constructor. |
151 * the call to genCachedConstructionData can be moved to the derived this() methods.) | |
152 * | 152 * |
153 * Derived constructors may also set initWidths to the array of column widths followed by | 153 * Derived constructors may also set initWidths to the array of column widths followed by |
154 * row heights used to initially set the row/column dimensions. */ | 154 * row heights used to initially set the row/column dimensions. */ |
155 protected this (IWidgetManager mgr, widgetID id, WidgetData data) { | 155 protected this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData data) { |
156 super (mgr, id, data); | 156 super (mgr, parent, id); |
157 | 157 |
158 // Create cell aligners with appropriate col/row adjustment function | 158 // Create cell aligners with appropriate col/row adjustment function |
159 if (data.ints[1] & 1) | 159 if (data.ints[1] & 1) |
160 col = AlignColumns.getInstance (id, cols); | 160 col = AlignColumns.getInstance (id, cols); |
161 else | 161 else |
171 | 171 |
172 /** Responsible for calculating the minimal size and initializing some stuff. | 172 /** Responsible for calculating the minimal size and initializing some stuff. |
173 * | 173 * |
174 * As such, this must be the first function called after this(). */ | 174 * As such, this must be the first function called after this(). */ |
175 override bool setup (uint n, uint flags) { | 175 override bool setup (uint n, uint flags) { |
176 // Run all internal calculations regardless of changes, then check dimensions for changes. | 176 debug (mdeWidgets) logger.trace ("GridWidget.setup"); |
177 // Run all internal calculations regardless of changes, then check dimensions for changes. | |
177 // Don't try shortcutting internal calculations when there are no changes - I've tried, and | 178 // Don't try shortcutting internal calculations when there are no changes - I've tried, and |
178 // doing so adds enough overhead to make doing so almost(?) worthless (or at least large | 179 // doing so adds enough overhead to make doing so almost(?) worthless (or at least large |
179 // increases in complexity). | 180 // increases in complexity). |
180 wdim ow = w, oh = h; | 181 wdim ow = w, oh = h; |
181 | 182 |
200 foreach (i,widget; subWidgets) { | 201 foreach (i,widget; subWidgets) { |
201 // Resizing direction is arbitrarily set to negative: | 202 // Resizing direction is arbitrarily set to negative: |
202 widget.setWidth (col.width[i % cols], -1); | 203 widget.setWidth (col.width[i % cols], -1); |
203 widget.setHeight (row.width[i / cols], -1); | 204 widget.setHeight (row.width[i / cols], -1); |
204 } | 205 } |
205 return (ow != w || oh != h); | 206 return (ow != w || oh != h); |
206 } | 207 } |
207 //END Creation & saving | 208 //END Creation & saving |
208 | 209 |
209 //BEGIN Size & position | 210 //BEGIN Size & position |
210 override bool isWSizable () { | 211 override bool isWSizable () { |
291 * (col and row). subWidgets need to know their minimal size and resizability. */ | 292 * (col and row). subWidgets need to know their minimal size and resizability. */ |
292 override void setupAlignDimData (uint n, uint flags) { | 293 override void setupAlignDimData (uint n, uint flags) { |
293 if (sADD_n == n) return; // cached data is current | 294 if (sADD_n == n) return; // cached data is current |
294 sADD_n = n; | 295 sADD_n = n; |
295 | 296 |
297 debug (mdeWidgets) logger.trace ("GridWidget: setup on subWidgets..."); | |
296 foreach (widg; subWidgets) { // make sure all subwidgets have been set up | 298 foreach (widg; subWidgets) { // make sure all subwidgets have been set up |
297 debug assert (widg); | 299 debug assert (widg); |
298 widg.setup (n,flags); | 300 widg.setup (n,flags); |
299 } | 301 } |
302 debug (mdeWidgets) logger.trace ("GridWidget: setup on subWidgets...done"); | |
300 // make sure both AlignColumns are set up (since first call to setup(n) calls reset): | 303 // make sure both AlignColumns are set up (since first call to setup(n) calls reset): |
301 col.setup (n, flags); | 304 col.setup (n, flags); |
302 row.setup (n, flags); | 305 row.setup (n, flags); |
303 | 306 |
304 // Note: shared AlignColumns get this set by all sharing GridWidgets | 307 // Note: shared AlignColumns get this set by all sharing GridWidgets |
305 col.spacing = row.spacing = useSpacing ? mgr.renderer.layoutSpacing : 0; | 308 col.spacing = row.spacing = useSpacing ? mgr.renderer.layoutSpacing : 0; |
306 | 309 |
307 // Calculate the minimal column and row sizes: | 310 // Calculate the minimal column and row sizes: |
308 // AlignColumns (row, col) takes care of initializing minWidth. | 311 // AlignColumns (row, col) takes care of initializing minWidth. |