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.