Mercurial > projects > dynamin
annotate dynamin/gui/layout.d @ 106:acdbb30fee7e
Port to D2.
Most of the effort was dealing with immutable and const.
author | Jordan Miner <jminer7@gmail.com> |
---|---|
date | Mon, 17 Dec 2012 23:41:50 -0600 |
parents | 5c8c1c2e12c0 |
children |
rev | line source |
---|---|
0 | 1 |
2 /* | |
103
73060bc3f004
Change license to Boost 1.0 and MPL 2.0.
Jordan Miner <jminer7@gmail.com>
parents:
100
diff
changeset
|
3 * Copyright Jordan Miner |
0 | 4 * |
103
73060bc3f004
Change license to Boost 1.0 and MPL 2.0.
Jordan Miner <jminer7@gmail.com>
parents:
100
diff
changeset
|
5 * This Source Code Form is subject to the terms of the Mozilla Public |
73060bc3f004
Change license to Boost 1.0 and MPL 2.0.
Jordan Miner <jminer7@gmail.com>
parents:
100
diff
changeset
|
6 * License, v. 2.0. If a copy of the MPL was not distributed with this |
73060bc3f004
Change license to Boost 1.0 and MPL 2.0.
Jordan Miner <jminer7@gmail.com>
parents:
100
diff
changeset
|
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
0 | 8 * |
9 */ | |
10 | |
11 module dynamin.gui.layout; | |
12 | |
13 import dynamin.all_gui; | |
14 import dynamin.gui.control; | |
15 import dynamin.all_painting; | |
16 import dynamin.core.string; | |
17 import tango.io.Stdout; | |
18 import dynamin.core.benchmark; | |
19 | |
20 // this is a temporary file to hold layout code until I figure out what | |
21 // files to put it in | |
22 | |
23 /* | |
24 Opera's find dialog: | |
25 | |
26 auto whatLabel = win.content.add(new Label("Find What")); | |
27 ... | |
28 | |
29 V( whatLabel | |
30 H( findBox findButton ) | |
31 H( V(wholeWordCheck caseCheck) ~ V(upRadio downRadio) ~) | |
32 H( ~ closeButton ) | |
33 ) | |
34 */ | |
35 | |
36 enum LayoutType { | |
106 | 37 Table, Control, Filler, Spacer |
0 | 38 } |
39 enum Elasticity { | |
40 No, Semi, Yes | |
41 } | |
42 struct LayoutGroup { | |
43 LayoutType type; | |
44 LayoutGroup* parent; | |
37
f9fea816b1fb
Correct a comment and remove an unused variable.
Jordan Miner <jminer7@gmail.com>
parents:
11
diff
changeset
|
45 LayoutGroup[] children; // used if type == LayoutType.Table |
0 | 46 Control control; // used if type == LayoutType.Control |
47 int numColumns; // used if type == LayoutType.Table | |
48 int numRows() { return children.length / numColumns; } | |
49 | |
50 bool cacheActive; | |
51 private Elasticity _elasticXCache, _elasticYCache; | |
52 private Size _bestSizeCache; | |
53 private int _baselineCache; | |
54 | |
55 // spacing variables | |
56 int spacing = 8; | |
57 static LayoutGroup opCall(LayoutType type, LayoutGroup* parent) { | |
58 LayoutGroup layout; | |
59 layout.type = type; | |
60 layout.parent = parent; | |
61 layout.children.length = 3; | |
62 layout.children.length = 0; | |
63 return layout; | |
64 } | |
65 | |
66 void setCache() { | |
67 for(int i = 0; i < children.length; ++i) // can't use foreach--copies | |
68 children[i].setCache(); | |
69 _elasticXCache = _elasticX; | |
70 _elasticYCache = _elasticY; | |
71 _bestSizeCache = _bestSize; | |
72 _baselineCache = _baseline; | |
73 cacheActive = true; | |
74 } | |
75 void clearCache() { | |
76 cacheActive = false; | |
77 for(int i = 0; i < children.length; ++i) // can't use foreach--copies | |
78 children[i].clearCache(); | |
79 } | |
80 Elasticity elasticX() { return cacheActive ? _elasticXCache : _elasticX; } | |
81 Elasticity elasticY() { return cacheActive ? _elasticYCache : _elasticY; } | |
82 Size bestSize() { return cacheActive ? _bestSizeCache : _bestSize; } | |
83 int baseline() { return cacheActive ? _baselineCache : _baseline; } | |
84 | |
85 //{{{ _elasticX() | |
86 private Elasticity _elasticX() { | |
106 | 87 final switch(type) { |
0 | 88 case LayoutType.Control: |
89 return control.elasticX ? Elasticity.Yes : Elasticity.No; | |
90 case LayoutType.Table: | |
91 auto e = Elasticity.No; | |
92 foreach(layout; children) { | |
93 if(layout.elasticX > e) | |
94 e = layout.elasticX; | |
95 if(e == Elasticity.Yes) | |
96 return e; | |
97 } | |
98 return e; | |
99 case LayoutType.Filler: | |
38
69df5369c5f7
Fix filler to only be elastic in the direction of its parent.
Jordan Miner <jminer7@gmail.com>
parents:
37
diff
changeset
|
100 if(!parent || parent.numColumns > 1 || children.length == 1) |
69df5369c5f7
Fix filler to only be elastic in the direction of its parent.
Jordan Miner <jminer7@gmail.com>
parents:
37
diff
changeset
|
101 return Elasticity.Semi; |
69df5369c5f7
Fix filler to only be elastic in the direction of its parent.
Jordan Miner <jminer7@gmail.com>
parents:
37
diff
changeset
|
102 else |
69df5369c5f7
Fix filler to only be elastic in the direction of its parent.
Jordan Miner <jminer7@gmail.com>
parents:
37
diff
changeset
|
103 return Elasticity.No; |
0 | 104 case LayoutType.Spacer: |
105 return Elasticity.No; | |
106 } | |
107 } | |
108 //}}} | |
109 //{{{ _elasticY() | |
110 private Elasticity _elasticY() { | |
106 | 111 final switch(type) { |
0 | 112 case LayoutType.Control: |
113 return control.elasticY ? Elasticity.Yes : Elasticity.No; | |
114 case LayoutType.Table: | |
115 auto e = Elasticity.No; | |
116 foreach(layout; children) { | |
117 if(layout.elasticY > e) | |
118 e = layout.elasticY; | |
119 if(e == Elasticity.Yes) | |
120 return e; | |
121 } | |
122 return e; | |
123 case LayoutType.Filler: | |
38
69df5369c5f7
Fix filler to only be elastic in the direction of its parent.
Jordan Miner <jminer7@gmail.com>
parents:
37
diff
changeset
|
124 if(!parent || parent.numRows > 1 || children.length == 1) |
69df5369c5f7
Fix filler to only be elastic in the direction of its parent.
Jordan Miner <jminer7@gmail.com>
parents:
37
diff
changeset
|
125 return Elasticity.Semi; |
69df5369c5f7
Fix filler to only be elastic in the direction of its parent.
Jordan Miner <jminer7@gmail.com>
parents:
37
diff
changeset
|
126 else |
69df5369c5f7
Fix filler to only be elastic in the direction of its parent.
Jordan Miner <jminer7@gmail.com>
parents:
37
diff
changeset
|
127 return Elasticity.No; |
0 | 128 case LayoutType.Spacer: |
129 return Elasticity.No; | |
130 } | |
131 } | |
132 //}}} | |
133 | |
134 //{{{ _bestSize() | |
135 private Size _bestSize() { | |
106 | 136 final switch(type) { |
0 | 137 case LayoutType.Control: |
138 return control.bestSize; | |
139 case LayoutType.Table: | |
140 scope colsInfo = new ColRowInfo[numColumns]; | |
141 scope rowsInfo = new ColRowInfo[numRows]; | |
142 TableInfo info; | |
143 getTableSizes(colsInfo, rowsInfo, info); | |
144 return info.bestSize; | |
145 case LayoutType.Filler: | |
146 case LayoutType.Spacer: | |
147 return Size(0, 0); | |
148 } | |
149 } | |
150 //}}} | |
151 //{{{ _baseline() | |
152 private int _baseline() { | |
106 | 153 final switch(type) { |
0 | 154 case LayoutType.Control: |
155 return control.baseline; | |
156 case LayoutType.Table: | |
40
735223842a85
Make horizontal layouts align along their baseline.
Jordan Miner <jminer7@gmail.com>
parents:
39
diff
changeset
|
157 if(numRows != 1) |
735223842a85
Make horizontal layouts align along their baseline.
Jordan Miner <jminer7@gmail.com>
parents:
39
diff
changeset
|
158 return 0; |
735223842a85
Make horizontal layouts align along their baseline.
Jordan Miner <jminer7@gmail.com>
parents:
39
diff
changeset
|
159 scope colsInfo = new ColRowInfo[numColumns]; |
735223842a85
Make horizontal layouts align along their baseline.
Jordan Miner <jminer7@gmail.com>
parents:
39
diff
changeset
|
160 scope rowsInfo = new ColRowInfo[numRows]; |
735223842a85
Make horizontal layouts align along their baseline.
Jordan Miner <jminer7@gmail.com>
parents:
39
diff
changeset
|
161 TableInfo info; |
735223842a85
Make horizontal layouts align along their baseline.
Jordan Miner <jminer7@gmail.com>
parents:
39
diff
changeset
|
162 getTableSizes(colsInfo, rowsInfo, info); |
735223842a85
Make horizontal layouts align along their baseline.
Jordan Miner <jminer7@gmail.com>
parents:
39
diff
changeset
|
163 return cast(int)rowsInfo[0].baseline; |
0 | 164 case LayoutType.Filler: |
165 case LayoutType.Spacer: | |
166 return 0; | |
167 } | |
168 } | |
169 //}}} | |
170 | |
171 //{{{ layout() | |
172 void layout(Rect rect) { | |
106 | 173 final switch(type) { |
0 | 174 case LayoutType.Control: |
175 control.location = Point(rect.x, rect.y); | |
176 control.size = Size(rect.width, rect.height); | |
177 return; | |
178 case LayoutType.Table: | |
179 scope colsInfo = new ColRowInfo[numColumns]; | |
180 scope rowsInfo = new ColRowInfo[numRows]; | |
181 TableInfo info; | |
182 getTableSizes(colsInfo, rowsInfo, info); | |
183 | |
104
5c8c1c2e12c0
Change from real to double.
Jordan Miner <jminer7@gmail.com>
parents:
103
diff
changeset
|
184 double extraWidth = rect.width - bestSize.width; |
5c8c1c2e12c0
Change from real to double.
Jordan Miner <jminer7@gmail.com>
parents:
103
diff
changeset
|
185 double extraHeight = rect.height - bestSize.height; |
0 | 186 |
104
5c8c1c2e12c0
Change from real to double.
Jordan Miner <jminer7@gmail.com>
parents:
103
diff
changeset
|
187 void distExtra(ref double extra, ref ColRowInfo info, |
5c8c1c2e12c0
Change from real to double.
Jordan Miner <jminer7@gmail.com>
parents:
103
diff
changeset
|
188 ref double totalElastic, ref int semis, Elasticity e) { |
0 | 189 if(info.elastic == Elasticity.No || extra <= 0) |
190 return; | |
191 if(e == Elasticity.Semi && | |
192 info.elastic == Elasticity.Semi) { | |
193 auto thisExtra = extra / semis; | |
194 extra -= thisExtra; | |
195 semis--; | |
196 info.bestSize += thisExtra; | |
197 } else if(e == Elasticity.Yes && | |
198 info.elastic == Elasticity.Yes) { | |
199 auto thisExtra = extra * info.bestSize/totalElastic; | |
200 extra -= thisExtra; | |
201 totalElastic -= info.bestSize; // subtract original size | |
202 info.bestSize += thisExtra; | |
203 } | |
204 } | |
104
5c8c1c2e12c0
Change from real to double.
Jordan Miner <jminer7@gmail.com>
parents:
103
diff
changeset
|
205 double y = 0; |
0 | 206 for(int row = 0; row < numRows; ++row) { // go over each row |
207 distExtra(extraHeight, rowsInfo[row], info.elasticHeight, info.semiRows, elasticY); | |
208 | |
104
5c8c1c2e12c0
Change from real to double.
Jordan Miner <jminer7@gmail.com>
parents:
103
diff
changeset
|
209 double x = 0; |
0 | 210 for(int col = 0; col < numColumns; ++col) { |
211 distExtra(extraWidth, colsInfo[col], info.elasticWidth, info.semiColumns, elasticX); | |
212 | |
213 auto layout = children[row * numColumns + col]; | |
214 | |
215 Rect r = Point(x, y) + layout.bestSize; | |
216 | |
217 if(layout.baseline > 0) | |
218 r.y = r.y + rowsInfo[row].baseline - layout.baseline; | |
219 if(layout.elasticX) | |
220 r.width = colsInfo[col].bestSize; | |
221 if(layout.elasticY) | |
222 r.height = rowsInfo[row].bestSize; | |
223 | |
224 layout.layout(r + Point(rect.x, rect.y)); | |
225 | |
226 x += colsInfo[col].bestSize + | |
227 (colsInfo[col].filler ? 0 : spacing); | |
228 } | |
229 y += rowsInfo[row].bestSize + | |
230 (rowsInfo[row].filler ? 0 : spacing); | |
231 } | |
232 return; | |
233 case LayoutType.Filler: | |
234 case LayoutType.Spacer: | |
235 return; | |
236 } | |
237 } | |
238 //}}} | |
239 | |
240 struct ColRowInfo { | |
104
5c8c1c2e12c0
Change from real to double.
Jordan Miner <jminer7@gmail.com>
parents:
103
diff
changeset
|
241 double bestSize = 0; // large enough to hold the largest control |
0 | 242 Elasticity elastic = Elasticity.No; |
243 bool filler = true; // if the entire column/row is filler | |
104
5c8c1c2e12c0
Change from real to double.
Jordan Miner <jminer7@gmail.com>
parents:
103
diff
changeset
|
244 double baseline; // only applies to rows: max baseline in row |
0 | 245 } |
246 struct TableInfo { | |
247 // number of semi-elastic columns/rows | |
248 int semiColumns = 0; int semiRows = 0; | |
249 // the sum of fully elastic width/height, not including semi | |
104
5c8c1c2e12c0
Change from real to double.
Jordan Miner <jminer7@gmail.com>
parents:
103
diff
changeset
|
250 double elasticWidth = 0, elasticHeight = 0; |
100
4f2d709760eb
Change from individual fields to a static array for x, y, width, height, etc.
Jordan Miner <jminer7@gmail.com>
parents:
42
diff
changeset
|
251 Size bestSize; |
0 | 252 } |
253 //{{{ getTableSizes() | |
254 // Fills in the passed in array with the column and row sizes, as well | |
255 // as whether they are elastic. The passed in arrays must be the right | |
256 // sizes. They may be stack allocated. The table best size does | |
257 // including spacing, but column and row best sizes do not. | |
258 private void getTableSizes(ColRowInfo[] colsInfo, ColRowInfo[] rowsInfo, ref TableInfo info) { | |
259 assert(children.length % numColumns == 0); | |
260 assert(type == LayoutType.Table); | |
261 | |
262 assert(colsInfo.length == numColumns); | |
263 assert(rowsInfo.length == numRows); | |
264 | |
104
5c8c1c2e12c0
Change from real to double.
Jordan Miner <jminer7@gmail.com>
parents:
103
diff
changeset
|
265 double max = 0; |
0 | 266 LayoutGroup* l; |
267 | |
39
04d2867d335c
Fix possible incorrect extra space after the last control in a layout.
Jordan Miner <jminer7@gmail.com>
parents:
38
diff
changeset
|
268 bool prevNonFiller = false; |
0 | 269 int sp = 0; |
270 for(int col = 0; col < numColumns; ++col) { // go down each column | |
271 for(int row = 0; row < numRows; ++row) { | |
272 l = &children[row * numColumns + col]; | |
273 max = l.bestSize.width > max ? l.bestSize.width : max; | |
274 if(l.elasticX > colsInfo[col].elastic) | |
275 colsInfo[col].elastic = l.elasticX; | |
276 if(l.type != LayoutType.Filler) | |
277 colsInfo[col].filler = false; | |
278 } | |
279 colsInfo[col].bestSize = max; | |
280 if(colsInfo[col].elastic == Elasticity.Yes) | |
281 info.elasticWidth += max; | |
282 else if(colsInfo[col].elastic == Elasticity.Semi) | |
283 info.semiColumns++; | |
39
04d2867d335c
Fix possible incorrect extra space after the last control in a layout.
Jordan Miner <jminer7@gmail.com>
parents:
38
diff
changeset
|
284 // this won't add spacing to the first non-filler |
04d2867d335c
Fix possible incorrect extra space after the last control in a layout.
Jordan Miner <jminer7@gmail.com>
parents:
38
diff
changeset
|
285 sp = (!colsInfo[col].filler && prevNonFiller) ? spacing : 0; |
0 | 286 info.bestSize.width = info.bestSize.width + sp + max; |
39
04d2867d335c
Fix possible incorrect extra space after the last control in a layout.
Jordan Miner <jminer7@gmail.com>
parents:
38
diff
changeset
|
287 prevNonFiller = !colsInfo[col].filler ? true : prevNonFiller ; |
0 | 288 max = 0; |
289 } | |
290 | |
39
04d2867d335c
Fix possible incorrect extra space after the last control in a layout.
Jordan Miner <jminer7@gmail.com>
parents:
38
diff
changeset
|
291 prevNonFiller = false; |
104
5c8c1c2e12c0
Change from real to double.
Jordan Miner <jminer7@gmail.com>
parents:
103
diff
changeset
|
292 double maxBl = 0; |
0 | 293 sp = 0; |
294 for(int row = 0; row < numRows; ++row) { // go over each row | |
295 for(int col = 0; col < numColumns; ++col) { | |
296 l = &children[row * numColumns + col]; | |
297 max = l.bestSize.height > max ? l.bestSize.height : max; | |
298 maxBl = l.baseline > maxBl ? l.baseline : maxBl; | |
299 if(l.elasticY > rowsInfo[row].elastic) | |
300 rowsInfo[row].elastic = l.elasticY; | |
301 if(l.type != LayoutType.Filler) | |
302 rowsInfo[row].filler = false; | |
303 } | |
304 rowsInfo[row].bestSize = max; | |
305 rowsInfo[row].baseline = maxBl; | |
306 if(rowsInfo[row].elastic == Elasticity.Yes) | |
307 info.elasticHeight += max; | |
308 else if(rowsInfo[row].elastic == Elasticity.Semi) | |
309 info.semiRows++; | |
39
04d2867d335c
Fix possible incorrect extra space after the last control in a layout.
Jordan Miner <jminer7@gmail.com>
parents:
38
diff
changeset
|
310 // this won't add spacing to the first non-filler |
04d2867d335c
Fix possible incorrect extra space after the last control in a layout.
Jordan Miner <jminer7@gmail.com>
parents:
38
diff
changeset
|
311 sp = (!rowsInfo[row].filler && prevNonFiller) ? spacing : 0; |
0 | 312 info.bestSize.height = info.bestSize.height + sp + max; |
39
04d2867d335c
Fix possible incorrect extra space after the last control in a layout.
Jordan Miner <jminer7@gmail.com>
parents:
38
diff
changeset
|
313 prevNonFiller = !rowsInfo[row].filler ? true : prevNonFiller ; |
0 | 314 max = maxBl = 0; |
315 } | |
316 } | |
317 //}}} | |
318 } | |
319 | |
320 //{{{ LayoutPanel class | |
321 class LayoutPanel : Panel { | |
322 LayoutGroup root; | |
323 LayoutGroup* current; | |
324 void startLayout(int ncolumns) { | |
325 if(current is null) { | |
326 root = LayoutGroup(LayoutType.Table, null); | |
327 root.numColumns = ncolumns; | |
328 current = &root; | |
329 return; | |
330 } | |
331 current.children.length = current.children.length+1; | |
332 current.children[$-1] = LayoutGroup(LayoutType.Table, current); | |
333 current.children[$-1].numColumns = ncolumns; | |
334 current = ¤t.children[$-1]; | |
335 } | |
336 void endLayout() { | |
337 current = current.parent; | |
338 } | |
339 override void add(Control c) { | |
340 if(current is null) | |
341 throw new Exception("Cannot add a control until a layout is started"); | |
342 current.children.length = current.children.length+1; | |
343 current.children[$-1] = LayoutGroup(LayoutType.Control, current); | |
344 current.children[$-1].control = c; | |
345 super.add(c); | |
346 } | |
347 void addFiller() { | |
348 current.children.length = current.children.length+1; | |
349 current.children[$-1] = LayoutGroup(LayoutType.Filler, current); | |
350 } | |
351 void addSpacer() { | |
352 current.children.length = current.children.length+1; | |
353 current.children[$-1] = LayoutGroup(LayoutType.Spacer, current); | |
354 } | |
355 | |
356 override Size bestSize() { | |
357 return root.bestSize + Size(root.spacing*2, root.spacing*2); | |
358 } | |
359 override bool elasticX() { return root.elasticX == Elasticity.Yes; } | |
360 override bool elasticY() { return root.elasticY == Elasticity.Yes; } | |
361 override void layout() { | |
362 //benchmarkAndWrite("layout", { | |
363 root.setCache(); | |
364 int sp = root.spacing; | |
365 root.layout(Rect(sp, sp, width-2*sp, height-2*sp)); | |
366 root.clearCache(); | |
367 //}); | |
368 } | |
369 } | |
370 //}}} | |
371 | |
372 //{{{ createLayout() etc. | |
373 /** | |
374 * Note: if you do this: | |
375 * ----- | |
376 * char[] s = createLayout("V( b1 H(b2 b3) )"); | |
377 * ----- | |
378 * Then the program will crash when compiled with the -release flag. (I am | |
379 * pretty sure it is a DMD bug, but I don't have time to make a testcase | |
380 * for a bug that does not bother me.) This will work correctly: | |
381 * ----- | |
106 | 382 * enum char[] s = createLayout("V( b1 H(b2 b3) )"); |
0 | 383 * ----- |
384 * Because then the function is interpreted at compile time with CTFE. | |
385 */ | |
386 string createLayout(string layout) { | |
387 string code = "delegate LayoutPanel() {\n"; | |
388 code ~= "auto panel = new LayoutPanel;\n"; | |
389 assert(getToken(layout) == "H" || getToken(layout) == "V" || | |
390 getToken(layout) == "T", "layout type 'H', 'V', or 'T' expected"); | |
391 code ~= parseLayout(layout); | |
392 code ~= "return panel;\n"; | |
393 code ~= "}()"; | |
394 return code; | |
395 } | |
396 | |
397 void skipWS(ref string str) { | |
398 int i = 0; | |
399 while(" \t\n\r\v\f".contains(str[i])) | |
400 i++; | |
401 str = str[i..$]; | |
402 } | |
403 // advances to the next token and returns it | |
404 string nextToken(ref string str) { | |
405 skipWS(str); | |
406 str = str[getToken(str).length..$]; | |
407 return getToken(str); | |
408 } | |
409 // returns H or V or ( or ) or myControl | |
410 // gets the current token | |
411 string getToken(string str) { | |
412 string idChars = | |
413 "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; | |
414 | |
415 // TODO: // for line comments? | |
416 skipWS(str); | |
11
df1c8e659b75
Change layout language to use * for filler and ~ for spacing. Ticket #24
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
417 if("()[]*~".contains(str[0])) { |
0 | 418 return str[0..1]; |
419 } else if(idChars.contains(str[0])) { | |
420 int i = 1; | |
421 while(idChars.contains(str[i])) | |
422 i++; | |
423 return str[0..i]; | |
424 } else { | |
425 assert(0, "unknown character: " ~ str[0]); | |
426 } | |
427 } | |
428 | |
429 // {{{ copied from Phobos | |
106 | 430 string ctfeUintToString(uint u) { |
0 | 431 char[uint.sizeof * 3] buffer = void; |
432 int ndigits; | |
106 | 433 string result; |
434 string digits = "0123456789"; | |
0 | 435 |
436 ndigits = 0; | |
437 if (u < 10) | |
438 // Avoid storage allocation for simple stuff | |
439 result = digits[u .. u + 1]; | |
440 else | |
441 { | |
442 while (u) | |
443 { | |
444 uint c = (u % 10) + '0'; | |
445 u /= 10; | |
446 ndigits++; | |
447 buffer[buffer.length - ndigits] = cast(char)c; | |
448 } | |
106 | 449 result = buffer[$ - ndigits .. $].idup; |
0 | 450 } |
451 return result; | |
452 } | |
106 | 453 uint ctfeStringToUint(string s) |
0 | 454 { |
455 int length = s.length; | |
456 | |
457 if (!length) | |
458 return 0; | |
459 | |
460 uint v = 0; | |
461 | |
462 for (int i = 0; i < length; i++) | |
463 { | |
464 char c = s[i]; | |
465 if (c >= '0' && c <= '9') | |
466 { | |
467 if (v < uint.max/10 || (v == uint.max/10 && c <= '5')) | |
468 v = v * 10 + (c - '0'); | |
469 else | |
470 return 0; | |
471 } | |
472 else | |
473 return 0; | |
474 } | |
475 return v; | |
476 } | |
477 //}}} | |
478 | |
479 uint parseBody(ref string layout, ref string bcode) { | |
480 uint count = 0; | |
481 assert(nextToken(layout) == "(", "open parenthesis expected"); | |
482 while(nextToken(layout) != ")") { | |
11
df1c8e659b75
Change layout language to use * for filler and ~ for spacing. Ticket #24
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
483 if(getToken(layout) == "*") |
0 | 484 bcode = bcode ~ "panel.addFiller();\n"; |
11
df1c8e659b75
Change layout language to use * for filler and ~ for spacing. Ticket #24
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
485 else if(getToken(layout) == "~") |
0 | 486 bcode = bcode ~ "panel.addSpacer();\n"; |
487 else | |
488 bcode = bcode ~ parseLayout(layout); | |
489 count++; | |
490 } | |
491 bcode = bcode ~ "panel.endLayout();\n"; | |
492 return count; | |
493 } | |
494 | |
495 string parseLayout(ref string layout) { | |
496 string code = ""; | |
497 | |
498 if(getToken(layout) == "H") { | |
499 string bodyCode; | |
500 auto count = parseBody(layout, bodyCode); | |
501 code ~= "panel.startLayout(" ~ ctfeUintToString(count) ~ ");\n"; | |
502 code ~= bodyCode; | |
503 } else if(getToken(layout) == "V") { | |
504 code ~= "panel.startLayout(1);\n"; | |
505 parseBody(layout, code); | |
506 } else if(getToken(layout) == "T") { | |
507 assert(nextToken(layout) == "[", "open bracket expected"); | |
508 nextToken(layout); | |
509 assert("0123456789".contains(getToken(layout)[0]), | |
510 "number of table columns expected"); | |
511 uint columns = ctfeStringToUint(getToken(layout)); | |
512 code ~= "panel.startLayout(" ~ getToken(layout) ~ ");\n"; | |
513 assert(nextToken(layout) == "]", "close bracket expected"); | |
514 assert(parseBody(layout, code) % columns == 0, | |
515 "number of controls must be a multiple of number of columns"); | |
516 } else { | |
517 code ~= "panel.add(" ~ getToken(layout) ~ ");\n"; | |
518 } | |
519 | |
520 return code; | |
521 } | |
522 | |
523 //{{{ parser tests | |
524 static assert(createLayout("H()") != "not evaluatable at compile time"); | |
525 //pragma(msg, createLayout("V()")); | |
526 | |
527 static assert(createLayout("V(c1 c2)") == | |
528 `delegate LayoutPanel() { | |
529 auto panel = new LayoutPanel; | |
530 panel.startLayout(1); | |
531 panel.add(c1); | |
532 panel.add(c2); | |
533 panel.endLayout(); | |
534 return panel; | |
535 }()`); | |
11
df1c8e659b75
Change layout language to use * for filler and ~ for spacing. Ticket #24
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
536 static assert(createLayout("V(c1 * c2 H(c3 ~) c4)") == |
0 | 537 `delegate LayoutPanel() { |
538 auto panel = new LayoutPanel; | |
539 panel.startLayout(1); | |
540 panel.add(c1); | |
541 panel.addFiller(); | |
542 panel.add(c2); | |
543 panel.startLayout(2); | |
544 panel.add(c3); | |
545 panel.addSpacer(); | |
546 panel.endLayout(); | |
547 panel.add(c4); | |
548 panel.endLayout(); | |
549 return panel; | |
550 }()`); | |
551 static assert(createLayout("V( c1 T[2](c2 c3) c4 )") == | |
552 `delegate LayoutPanel() { | |
553 auto panel = new LayoutPanel; | |
554 panel.startLayout(1); | |
555 panel.add(c1); | |
556 panel.startLayout(2); | |
557 panel.add(c2); | |
558 panel.add(c3); | |
559 panel.endLayout(); | |
560 panel.add(c4); | |
561 panel.endLayout(); | |
562 return panel; | |
563 }()`); | |
564 //}}} | |
565 | |
566 //}}} | |
567 | |
568 unittest { | |
41
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
569 class FakeButton : Control { |
106 | 570 override Size bestSize() { return Size(80, 30); } |
571 override bool elasticX() { return false; } | |
572 override bool elasticY() { return false; } | |
573 override int baseline() { return 20; } | |
41
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
574 } |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
575 class FakeTextBox : Control { |
106 | 576 override Size bestSize() { return Size(100, 20); } |
577 override bool elasticX() { return true; } | |
578 override bool elasticY() { return false; } | |
579 override int baseline() { return 18; } | |
41
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
580 } |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
581 class FakeListBox : Control { |
106 | 582 override Size bestSize() { return Size(100, 300); } |
583 override bool elasticX() { return false; } | |
584 override bool elasticY() { return true; } | |
585 override int baseline() { return 15; } | |
41
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
586 } |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
587 class FakeLabel : Control { |
106 | 588 override Size bestSize() { return Size(70, 15); } |
589 override bool elasticX() { return false; } | |
590 override bool elasticY() { return false; } | |
591 override int baseline() { return 13; } | |
41
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
592 } |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
593 auto button1 = new FakeButton(); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
594 auto tb1 = new FakeTextBox(); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
595 auto tb2 = new FakeTextBox(); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
596 auto lb1 = new FakeListBox(); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
597 auto label1 = new FakeLabel(); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
598 auto label2 = new FakeLabel(); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
599 |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
600 Panel panel; |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
601 auto sp = 8; // TODO: get from same place as layout |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
602 |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
603 // vertical layout |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
604 panel = mixin(createLayout(`V( label1 button1 )`)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
605 assert(panel.bestSize == Size(80+sp*2, 30+15+sp*3)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
606 assert(panel.elasticX == false); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
607 assert(panel.elasticY == false); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
608 panel.size = [1000, 1000]; |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
609 assert(label1.location == Point(sp, sp)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
610 assert(label1.size == label1.bestSize); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
611 assert(button1.location == Point(sp, 15+sp*2)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
612 assert(button1.size == button1.bestSize); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
613 |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
614 // horizontal layout |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
615 panel = mixin(createLayout(`H( label1 button1 * )`)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
616 assert(panel.bestSize == Size(80+70+sp*3, 30+sp*2)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
617 assert(panel.elasticX == false); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
618 assert(panel.elasticY == false); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
619 panel.size = [1000, 1000]; |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
620 assert(label1.location == Point(sp, 20-13+sp)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
621 assert(label1.size == label1.bestSize); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
622 assert(button1.location == Point(70+sp*2, sp)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
623 assert(button1.size == button1.bestSize); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
624 |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
625 // filler is last priority |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
626 panel = mixin(createLayout(`H( * label1 tb1 )`)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
627 assert(panel.bestSize == Size(70+100+sp*3, 20+sp*2)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
628 assert(panel.elasticX == true); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
629 assert(panel.elasticY == false); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
630 panel.size = [500, 1000]; |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
631 assert(label1.location == Point(sp, 18-13+sp)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
632 assert(label1.size == label1.bestSize); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
633 assert(tb1.location == Point(70+sp*2, sp)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
634 assert(tb1.size == Size(panel.width-70-sp*3, tb1.bestSize.height)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
635 |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
636 // extra space is distributed evenly between elastic controls |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
637 panel = mixin(createLayout(`V( H( tb1 label1 tb2 ) H( * label2 button1) )`)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
638 assert(panel.bestSize == Size(270+sp*4, 20+30+sp*3)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
639 assert(panel.elasticX == true); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
640 assert(panel.elasticY == false); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
641 panel.size = [500, 1000]; |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
642 assert(tb1.location == Point(sp, sp)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
643 assert(tb1.size == Size((panel.width-70-sp*4) / 2, 20)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
644 assert(label1.location == Point(tb1.width+sp*2, 18-13+sp)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
645 assert(label1.size == label1.bestSize); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
646 assert(tb2.location == Point(tb1.width+70+sp*3, sp)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
647 assert(tb2.size == Size(tb1.width, 20)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
648 assert(label2.location == Point(panel.width-80-70-sp*2, 20+(20-13)+sp*2)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
649 assert(label2.size == label2.bestSize); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
650 assert(button1.location == Point(panel.width-80-sp, 20+sp*2)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
651 assert(button1.size == button1.bestSize); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
652 |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
653 // extra space is distributed evenly between filler |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
654 panel = mixin(createLayout(`V( * label1 * label2 * )`)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
655 assert(panel.bestSize == Size(70+sp*2, 15+15+sp*3)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
656 assert(panel.elasticX == false); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
657 assert(panel.elasticY == false); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
658 panel.size = [500, 120]; |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
659 assert(label1.location == Point(sp, 30)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
660 assert(label1.size == label1.bestSize); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
661 assert(label2.location == Point(sp, 75)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
662 assert(label2.size == label2.bestSize); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
663 |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
664 // spacing |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
665 panel = mixin(createLayout(`H( ~ label1 ~ button1 ~ )`)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
666 assert(panel.bestSize == Size(70+80+sp*6, 30+sp*2)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
667 assert(panel.elasticX == false); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
668 assert(panel.elasticY == false); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
669 panel.size = [500, 500]; |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
670 assert(label1.location == Point(sp*2, 20-13+sp)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
671 assert(button1.location == Point(70+sp*4, sp)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
672 |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
673 // semielastic |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
674 panel = mixin(createLayout(`T[2]( H(*label1) tb1 H(*button1) tb2 )`)); |
42
2e466b478c0b
Fix a bug in a test that somehow slipped by in last commits.
Jordan Miner <jminer7@gmail.com>
parents:
41
diff
changeset
|
675 assert(panel.bestSize == Size(80+100+sp*3, 20+30+sp*3)); |
41
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
676 assert(panel.elasticX == true); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
677 assert(panel.elasticY == false); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
678 panel.size = [500, 500]; |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
679 assert(label1.location == Point(10+sp, 18-13+sp)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
680 assert(label1.size == label1.bestSize); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
681 assert(button1.location == Point(sp, 20+sp*2)); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
682 assert(button1.size == button1.bestSize); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
683 |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
684 //assert(.location == Point()); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
685 //assert(.size == Size()); |
c25e8b83c5b8
Add a few layout tests (with decent coverage).
Jordan Miner <jminer7@gmail.com>
parents:
40
diff
changeset
|
686 //Stdout("1:")(panel.bestSize).newline; |
0 | 687 } |
688 |