]> git.mxchange.org Git - simgear.git/blob - simgear/canvas/layout/canvas_layout_test.cxx
canvas::Layout: support for hiding items.
[simgear.git] / simgear / canvas / layout / canvas_layout_test.cxx
1 // Testing canvas layouting system
2 //
3 // Copyright (C) 2014  Thomas Geymayer <tomgey@gmail.com>
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Library General Public
7 // License as published by the Free Software Foundation; either
8 // version 2 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // Library General Public License for more details.
14 //
15 // You should have received a copy of the GNU Library General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
18
19 #define BOOST_TEST_MODULE canvas_layout
20 #include <BoostTestTargetConfig.h>
21
22 #include "BoxLayout.hxx"
23 #include "NasalWidget.hxx"
24
25 #include <simgear/debug/logstream.hxx>
26 #include <simgear/nasal/cppbind/NasalContext.hxx>
27
28 #include <cstdlib>
29
30 //------------------------------------------------------------------------------
31 struct SetLogLevelFixture
32 {
33   SetLogLevelFixture()
34   {
35     sglog().set_log_priority(SG_DEBUG);
36   }
37 };
38 BOOST_GLOBAL_FIXTURE(SetLogLevelFixture);
39
40 //------------------------------------------------------------------------------
41 namespace sc = simgear::canvas;
42
43 class TestWidget:
44   public sc::LayoutItem
45 {
46   public:
47     TestWidget( const SGVec2i& min_size,
48                 const SGVec2i& size_hint,
49                 const SGVec2i& max_size = MAX_SIZE )
50     {
51       _size_hint = size_hint;
52       _min_size = min_size;
53       _max_size = max_size;
54     }
55
56     TestWidget(const TestWidget& rhs)
57     {
58       _size_hint = rhs._size_hint;
59       _min_size = rhs._min_size;
60       _max_size = rhs._max_size;
61     }
62
63     void setMinSize(const SGVec2i& size) { _min_size = size; }
64     void setMaxSize(const SGVec2i& size) { _max_size = size; }
65     void setSizeHint(const SGVec2i& size) { _size_hint = size; }
66
67     virtual void setGeometry(const SGRecti& geom) { _geom = geom; }
68     virtual SGRecti geometry() const { return _geom; }
69
70   protected:
71
72     SGRecti _geom;
73
74     virtual SGVec2i sizeHintImpl() const { return _size_hint; }
75     virtual SGVec2i minimumSizeImpl() const { return _min_size; }
76     virtual SGVec2i maximumSizeImpl() const { return _max_size; }
77
78     virtual void visibilityChanged(bool visible)
79     {
80       if( !visible )
81         _geom.set(0, 0, 0, 0);
82     }
83 };
84
85 class TestWidgetHFW:
86   public TestWidget
87 {
88   public:
89     TestWidgetHFW( const SGVec2i& min_size,
90                    const SGVec2i& size_hint,
91                    const SGVec2i& max_size = MAX_SIZE ):
92       TestWidget(min_size, size_hint, max_size)
93     {
94
95     }
96
97     virtual bool hasHeightForWidth() const
98     {
99       return true;
100     }
101
102     virtual int heightForWidth(int w) const
103     {
104       return _size_hint.x() * _size_hint.y() / w;
105     }
106
107     virtual int minimumHeightForWidth(int w) const
108     {
109       return _min_size.x() * _min_size.y() / w;
110     }
111 };
112
113 typedef SGSharedPtr<TestWidget> TestWidgetRef;
114
115 //------------------------------------------------------------------------------
116 BOOST_AUTO_TEST_CASE( horizontal_layout )
117 {
118   sc::BoxLayout box_layout(sc::BoxLayout::BottomToTop);
119   box_layout.setSpacing(5);
120
121   BOOST_CHECK_EQUAL(box_layout.direction(), sc::BoxLayout::BottomToTop);
122   BOOST_CHECK_EQUAL(box_layout.spacing(), 5);
123
124   box_layout.setDirection(sc::BoxLayout::LeftToRight);
125   box_layout.setSpacing(9);
126
127   BOOST_CHECK_EQUAL(box_layout.direction(), sc::BoxLayout::LeftToRight);
128   BOOST_CHECK_EQUAL(box_layout.spacing(), 9);
129
130   TestWidgetRef fixed_size_widget( new TestWidget( SGVec2i(16, 16),
131                                                    SGVec2i(16, 16),
132                                                    SGVec2i(16, 16) ) );
133   box_layout.addItem(fixed_size_widget);
134
135   BOOST_CHECK_EQUAL(box_layout.minimumSize(), SGVec2i(16, 16));
136   BOOST_CHECK_EQUAL(box_layout.sizeHint(), SGVec2i(16, 16));
137   BOOST_CHECK_EQUAL(box_layout.maximumSize(), SGVec2i(16, 16));
138
139   TestWidgetRef limited_resize_widget( new TestWidget( SGVec2i(16, 16),
140                                                        SGVec2i(32, 32),
141                                                        SGVec2i(256, 64) ) );
142   box_layout.addItem(limited_resize_widget);
143
144   // Combined sizes of both widget plus the padding between them
145   BOOST_CHECK_EQUAL(box_layout.minimumSize(), SGVec2i(41, 16));
146   BOOST_CHECK_EQUAL(box_layout.sizeHint(), SGVec2i(57, 32));
147   BOOST_CHECK_EQUAL(box_layout.maximumSize(), SGVec2i(281, 64));
148
149   // Test with different spacing/padding
150   box_layout.setSpacing(5);
151
152   BOOST_CHECK_EQUAL(box_layout.minimumSize(), SGVec2i(37, 16));
153   BOOST_CHECK_EQUAL(box_layout.sizeHint(), SGVec2i(53, 32));
154   BOOST_CHECK_EQUAL(box_layout.maximumSize(), SGVec2i(277, 64));
155
156   box_layout.setGeometry(SGRecti(0, 0, 128, 32));
157
158   // Fixed size for first widget and remaining space goes to second widget
159   BOOST_CHECK_EQUAL(fixed_size_widget->geometry(), SGRecti(0, 8, 16, 16));
160   BOOST_CHECK_EQUAL(limited_resize_widget->geometry(), SGRecti(21, 0, 107, 32));
161
162   TestWidgetRef stretch_widget( new TestWidget( SGVec2i(16, 16),
163                                                 SGVec2i(32, 32),
164                                                 SGVec2i(128, 32) ) );
165   box_layout.addItem(stretch_widget, 1);
166   box_layout.update();
167
168   BOOST_CHECK_EQUAL(box_layout.minimumSize(), SGVec2i(58, 16));
169   BOOST_CHECK_EQUAL(box_layout.sizeHint(), SGVec2i(90, 32));
170   BOOST_CHECK_EQUAL(box_layout.maximumSize(), SGVec2i(410, 64));
171
172   // Due to the stretch factor only the last widget gets additional space. All
173   // other widgets get the preferred size.
174   BOOST_CHECK_EQUAL(fixed_size_widget->geometry(), SGRecti(0, 8, 16, 16));
175   BOOST_CHECK_EQUAL(limited_resize_widget->geometry(), SGRecti(21, 0, 32, 32));
176   BOOST_CHECK_EQUAL(stretch_widget->geometry(), SGRecti(58, 0, 70, 32));
177
178   // Test stretch factor
179   TestWidgetRef fast_stretch( new TestWidget(*stretch_widget) );
180   sc::BoxLayout box_layout_stretch(sc::BoxLayout::LeftToRight);
181
182   box_layout_stretch.addItem(stretch_widget, 1);
183   box_layout_stretch.addItem(fast_stretch, 2);
184
185   box_layout_stretch.setGeometry(SGRecti(0,0,128,32));
186
187   BOOST_CHECK_EQUAL(stretch_widget->geometry(), SGRecti(0, 0, 41, 32));
188   BOOST_CHECK_EQUAL(fast_stretch->geometry(), SGRecti(46, 0, 82, 32));
189
190   box_layout_stretch.setGeometry(SGRecti(0,0,256,32));
191
192   BOOST_CHECK_EQUAL(stretch_widget->geometry(), SGRecti(0, 0, 123, 32));
193   BOOST_CHECK_EQUAL(fast_stretch->geometry(), SGRecti(128, 0, 128, 32));
194
195   // Test superflous space to padding
196   box_layout_stretch.setGeometry(SGRecti(0,0,512,32));
197
198   BOOST_CHECK_EQUAL(stretch_widget->geometry(), SGRecti(83, 0, 128, 32));
199   BOOST_CHECK_EQUAL(fast_stretch->geometry(), SGRecti(300, 0, 128, 32));
200
201   // Test more space then preferred, but less than maximum
202   {
203     sc::HBoxLayout hbox;
204     TestWidgetRef w1( new TestWidget( SGVec2i(16,   16),
205                                       SGVec2i(32,   32),
206                                       SGVec2i(9999, 32) ) ),
207                   w2( new TestWidget(*w1) );
208
209     hbox.addItem(w1);
210     hbox.addItem(w2);
211
212     hbox.setGeometry( SGRecti(0, 0, 256, 32) );
213
214     BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0,   0, 126, 32));
215     BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(131, 0, 125, 32));
216
217     hbox.setStretch(0, 1);
218     hbox.setStretch(1, 1);
219
220     BOOST_CHECK_EQUAL(hbox.stretch(0), 1);
221     BOOST_CHECK_EQUAL(hbox.stretch(1), 1);
222
223     hbox.update();
224
225     BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0,   0, 125, 32));
226     BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(130, 0, 126, 32));
227
228     BOOST_REQUIRE( hbox.setStretchFactor(w1, 2) );
229     BOOST_REQUIRE( hbox.setStretchFactor(w2, 3) );
230     BOOST_CHECK_EQUAL(hbox.stretch(0), 2);
231     BOOST_CHECK_EQUAL(hbox.stretch(1), 3);
232
233     hbox.removeItem(w1);
234
235     BOOST_CHECK( !hbox.setStretchFactor(w1, 0) );
236   }
237 }
238
239 //------------------------------------------------------------------------------
240 BOOST_AUTO_TEST_CASE( spacer_layouting )
241 {
242   sc::HBoxLayout hbox;
243   TestWidgetRef w1( new TestWidget( SGVec2i(16, 16),
244                                     SGVec2i(32, 32),
245                                     SGVec2i(9999, 9999) ) ),
246                 w2( new TestWidget(*w1) );
247
248   hbox.addItem(w1);
249   hbox.addItem(w2);
250   hbox.addStretch(1);
251
252   BOOST_CHECK_EQUAL(hbox.minimumSize(), SGVec2i(37, 16));
253   BOOST_CHECK_EQUAL(hbox.sizeHint(), SGVec2i(69, 32));
254   BOOST_CHECK_EQUAL(hbox.maximumSize(), sc::LayoutItem::MAX_SIZE);
255
256   hbox.setGeometry(SGRecti(0, 0, 256, 40));
257
258   BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0,  0, 32, 40));
259   BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(37, 0, 32, 40));
260
261   // now center with increased spacing between both widgets
262   hbox.insertStretch(0, 1);
263   hbox.insertSpacing(2, 10);
264
265   BOOST_CHECK_EQUAL(hbox.minimumSize(), SGVec2i(47, 16));
266   BOOST_CHECK_EQUAL(hbox.sizeHint(), SGVec2i(79, 32));
267   BOOST_CHECK_EQUAL(hbox.maximumSize(), sc::LayoutItem::MAX_SIZE);
268
269   hbox.update();
270
271   BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(88,  0, 32, 40));
272   BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(135, 0, 32, 40));
273 }
274
275 //------------------------------------------------------------------------------
276 BOOST_AUTO_TEST_CASE( vertical_layout)
277 {
278   sc::BoxLayout vbox(sc::BoxLayout::TopToBottom);
279   vbox.setSpacing(7);
280
281   TestWidgetRef fixed_size_widget( new TestWidget( SGVec2i(16, 16),
282                                                    SGVec2i(16, 16),
283                                                    SGVec2i(16, 16) ) );
284   TestWidgetRef limited_resize_widget( new TestWidget( SGVec2i(16, 16),
285                                                        SGVec2i(32, 32),
286                                                        SGVec2i(256, 64) ) );
287
288   vbox.addItem(fixed_size_widget);
289   vbox.addItem(limited_resize_widget);
290
291   BOOST_CHECK_EQUAL(vbox.minimumSize(), SGVec2i(16, 39));
292   BOOST_CHECK_EQUAL(vbox.sizeHint(), SGVec2i(32, 55));
293   BOOST_CHECK_EQUAL(vbox.maximumSize(), SGVec2i(256, 87));
294
295   vbox.setGeometry(SGRecti(10, 20, 16, 55));
296
297   BOOST_CHECK_EQUAL(fixed_size_widget->geometry(), SGRecti(10, 20, 16, 16));
298   BOOST_CHECK_EQUAL(limited_resize_widget->geometry(), SGRecti(10, 43, 16, 32));
299
300   vbox.setDirection(sc::BoxLayout::BottomToTop);
301 }
302
303 //------------------------------------------------------------------------------
304 BOOST_AUTO_TEST_CASE( boxlayout_insert_remove )
305 {
306   sc::BoxLayoutRef hbox( new sc::HBoxLayout );
307
308   BOOST_CHECK_EQUAL(hbox->count(), 0);
309   BOOST_CHECK(!hbox->itemAt(0));
310   BOOST_CHECK(!hbox->takeAt(0));
311
312   TestWidgetRef w1( new TestWidget( SGVec2i(16,   16),
313                                     SGVec2i(32,   32),
314                                     SGVec2i(9999, 32) ) ),
315                 w2( new TestWidget(*w1) );
316
317   hbox->addItem(w1);
318   BOOST_CHECK_EQUAL(hbox->count(), 1);
319   BOOST_CHECK_EQUAL(hbox->itemAt(0), w1);
320   BOOST_CHECK_EQUAL(w1->getParent(), hbox);
321
322   hbox->insertItem(0, w2);
323   BOOST_CHECK_EQUAL(hbox->count(), 2);
324   BOOST_CHECK_EQUAL(hbox->itemAt(0), w2);
325   BOOST_CHECK_EQUAL(hbox->itemAt(1), w1);
326   BOOST_CHECK_EQUAL(w2->getParent(), hbox);
327
328   hbox->removeItem(w2);
329   BOOST_CHECK_EQUAL(hbox->count(), 1);
330   BOOST_CHECK_EQUAL(hbox->itemAt(0), w1);
331   BOOST_CHECK( !w2->getParent() );
332
333   hbox->addItem(w2);
334   BOOST_CHECK_EQUAL(hbox->count(), 2);
335   BOOST_CHECK_EQUAL(w2->getParent(), hbox);
336
337   hbox->clear();
338   BOOST_CHECK_EQUAL(hbox->count(), 0);
339   BOOST_CHECK( !w1->getParent() );
340   BOOST_CHECK( !w2->getParent() );
341 }
342
343 //------------------------------------------------------------------------------
344 BOOST_AUTO_TEST_CASE( boxlayout_visibility )
345 {
346   sc::BoxLayoutRef hbox( new sc::HBoxLayout );
347   TestWidgetRef w1( new TestWidget( SGVec2i(16, 16),
348                                     SGVec2i(32, 32) ) ),
349                 w2( new TestWidget(*w1) ),
350                 w3( new TestWidget(*w1) );
351
352   hbox->addItem(w1);
353   hbox->addItem(w2);
354   hbox->addItem(w3);
355
356   BOOST_REQUIRE_EQUAL(hbox->sizeHint().x(), 3 * 32 + 2 * hbox->spacing());
357
358   hbox->setGeometry(SGRecti(0, 0, 69, 32));
359
360   BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0,  0, 20, 32));
361   BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(25, 0, 20, 32));
362   BOOST_CHECK_EQUAL(w3->geometry(), SGRecti(50, 0, 19, 32));
363
364   w2->setVisible(false);
365
366   BOOST_REQUIRE(hbox->isVisible());
367   BOOST_REQUIRE(w1->isVisible());
368   BOOST_REQUIRE(!w2->isVisible());
369   BOOST_REQUIRE(w2->isExplicitlyHidden());
370   BOOST_REQUIRE(w3->isVisible());
371
372   BOOST_CHECK_EQUAL(hbox->sizeHint().x(), 2 * 32 + 1 * hbox->spacing());
373
374   hbox->update();
375
376   BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0,  0, 32, 32));
377   BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(0,  0,  0,  0));
378   BOOST_CHECK_EQUAL(w3->geometry(), SGRecti(37, 0, 32, 32));
379
380   hbox->setVisible(false);
381
382   BOOST_REQUIRE(!hbox->isVisible());
383   BOOST_REQUIRE(hbox->isExplicitlyHidden());
384   BOOST_REQUIRE(!w1->isVisible());
385   BOOST_REQUIRE(!w1->isExplicitlyHidden());
386   BOOST_REQUIRE(!w2->isVisible());
387   BOOST_REQUIRE(w2->isExplicitlyHidden());
388   BOOST_REQUIRE(!w3->isVisible());
389   BOOST_REQUIRE(!w3->isExplicitlyHidden());
390
391   BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0, 0, 0));
392   BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(0, 0, 0, 0));
393   BOOST_CHECK_EQUAL(w3->geometry(), SGRecti(0, 0, 0, 0));
394
395   w2->setVisible(true);
396
397   BOOST_REQUIRE(!w2->isVisible());
398   BOOST_REQUIRE(!w2->isExplicitlyHidden());
399
400   hbox->setVisible(true);
401
402   BOOST_REQUIRE(hbox->isVisible());
403   BOOST_REQUIRE(w1->isVisible());
404   BOOST_REQUIRE(w2->isVisible());
405   BOOST_REQUIRE(w3->isVisible());
406
407   hbox->update();
408
409   BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0,  0, 20, 32));
410   BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(25, 0, 20, 32));
411   BOOST_CHECK_EQUAL(w3->geometry(), SGRecti(50, 0, 19, 32));
412 }
413
414 //------------------------------------------------------------------------------
415 BOOST_AUTO_TEST_CASE( boxlayout_hfw )
416 {
417   TestWidgetRef w1( new TestWidgetHFW( SGVec2i(16,   16),
418                                        SGVec2i(32,   32) ) ),
419                 w2( new TestWidgetHFW( SGVec2i(24,   24),
420                                        SGVec2i(48,   48) ) );
421
422   BOOST_CHECK_EQUAL(w1->heightForWidth(16), 64);
423   BOOST_CHECK_EQUAL(w1->minimumHeightForWidth(16), 16);
424   BOOST_CHECK_EQUAL(w2->heightForWidth(24), 96);
425   BOOST_CHECK_EQUAL(w2->minimumHeightForWidth(24), 24);
426
427   TestWidgetRef w_no_hfw( new TestWidget( SGVec2i(16,   16),
428                                           SGVec2i(32,   32) ) );
429   BOOST_CHECK(!w_no_hfw->hasHeightForWidth());
430   BOOST_CHECK_EQUAL(w_no_hfw->heightForWidth(16), -1);
431   BOOST_CHECK_EQUAL(w_no_hfw->minimumHeightForWidth(16), -1);
432
433   // horizontal
434   sc::HBoxLayout hbox;
435   hbox.setSpacing(5);
436   hbox.addItem(w1);
437   hbox.addItem(w2);
438
439   BOOST_CHECK_EQUAL(hbox.heightForWidth(45), w2->heightForWidth(24));
440   BOOST_CHECK_EQUAL(hbox.heightForWidth(85), w2->heightForWidth(48));
441
442   hbox.addItem(w_no_hfw);
443
444   BOOST_CHECK_EQUAL(hbox.heightForWidth(66), 96);
445   BOOST_CHECK_EQUAL(hbox.heightForWidth(122), 48);
446   BOOST_CHECK_EQUAL(hbox.minimumHeightForWidth(66), 24);
447   BOOST_CHECK_EQUAL(hbox.minimumHeightForWidth(122), 16);
448
449   hbox.setGeometry(SGRecti(0, 0, 66, 24));
450
451   BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0,  16, 24));
452   BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(21, 0, 24, 24));
453   BOOST_CHECK_EQUAL(w_no_hfw->geometry(), SGRecti(50, 0, 16, 24));
454
455   // vertical
456   sc::VBoxLayout vbox;
457   vbox.setSpacing(5);
458   vbox.addItem(w1);
459   vbox.addItem(w2);
460
461   BOOST_CHECK_EQUAL(vbox.heightForWidth(24), 143);
462   BOOST_CHECK_EQUAL(vbox.heightForWidth(48), 74);
463   BOOST_CHECK_EQUAL(vbox.minimumHeightForWidth(24), 39);
464   BOOST_CHECK_EQUAL(vbox.minimumHeightForWidth(48), 22);
465
466   vbox.addItem(w_no_hfw);
467
468   BOOST_CHECK_EQUAL(vbox.heightForWidth(24), 180);
469   BOOST_CHECK_EQUAL(vbox.heightForWidth(48), 111);
470   BOOST_CHECK_EQUAL(vbox.minimumHeightForWidth(24), 60);
471   BOOST_CHECK_EQUAL(vbox.minimumHeightForWidth(48), 43);
472
473   SGVec2i min_size = vbox.minimumSize(),
474           size_hint = vbox.sizeHint();
475
476   BOOST_CHECK_EQUAL(min_size, SGVec2i(24, 66));
477   BOOST_CHECK_EQUAL(size_hint, SGVec2i(48, 122));
478
479   vbox.setGeometry(SGRecti(0, 0, 24, 122));
480
481   BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0,  24, 33));
482   BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(0, 38, 24, 47));
483   BOOST_CHECK_EQUAL(w_no_hfw->geometry(), SGRecti(0, 90, 24, 32));
484
485   // Vertical layouting modifies size hints, so check if they are correctly
486   // restored
487   BOOST_CHECK_EQUAL(min_size, vbox.minimumSize());
488   BOOST_CHECK_EQUAL(size_hint, vbox.sizeHint());
489
490   vbox.setGeometry(SGRecti(0, 0, 50, 122));
491
492   BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0,  50, 25));
493   BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(0, 30, 50, 51));
494   BOOST_CHECK_EQUAL(w_no_hfw->geometry(), SGRecti(0, 86, 50, 36));
495
496   // Same geometry as before -> should get same widget geometry
497   // (check internal size hint cache updates correctly)
498   vbox.setGeometry(SGRecti(0, 0, 24, 122));
499
500   BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0,  24, 33));
501   BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(0, 38, 24, 47));
502   BOOST_CHECK_EQUAL(w_no_hfw->geometry(), SGRecti(0, 90, 24, 32));
503 }
504
505 // TODO extend to_nasal_helper for automatic argument conversion
506 static naRef f_Widget_visibilityChanged(nasal::CallContext ctx)
507 {
508   sc::NasalWidget* w = ctx.from_nasal<sc::NasalWidget*>(ctx.me);
509
510   if( !ctx.requireArg<bool>(0) )
511     w->setGeometry(SGRecti(0, 0, -1, -1));
512
513   return naNil();
514 }
515
516 //------------------------------------------------------------------------------
517 BOOST_AUTO_TEST_CASE( nasal_widget )
518 {
519   nasal::Context c;
520   nasal::Hash globals = c.newHash();
521
522   nasal::Object::setupGhost();
523   nasal::Ghost<sc::LayoutItemRef>::init("LayoutItem");
524   sc::NasalWidget::setupGhost(globals);
525
526   nasal::Hash me = c.newHash();
527   me.set("visibilityChanged", &f_Widget_visibilityChanged);
528   sc::NasalWidgetRef w( new sc::NasalWidget(me.get_naRef()) );
529
530   // Default layout sizes (no user set values)
531   BOOST_CHECK_EQUAL(w->minimumSize(), SGVec2i(16, 16));
532   BOOST_CHECK_EQUAL(w->sizeHint(),    SGVec2i(32, 32));
533   BOOST_CHECK_EQUAL(w->maximumSize(), sc::LayoutItem::MAX_SIZE);
534
535   // Changed layout sizes
536   w->setLayoutMinimumSize( SGVec2i(2, 12) );
537   w->setLayoutSizeHint(    SGVec2i(3, 13) );
538   w->setLayoutMaximumSize( SGVec2i(4, 14) );
539
540   BOOST_CHECK_EQUAL(w->minimumSize(), SGVec2i(2, 12));
541   BOOST_CHECK_EQUAL(w->sizeHint(),    SGVec2i(3, 13));
542   BOOST_CHECK_EQUAL(w->maximumSize(), SGVec2i(4, 14));
543
544   // User set values (overwrite layout sizes)
545   w->setMinimumSize( SGVec2i(15, 16) );
546   w->setSizeHint(    SGVec2i(17, 18) );
547   w->setMaximumSize( SGVec2i(19, 20) );
548
549   BOOST_CHECK_EQUAL(w->minimumSize(), SGVec2i(15, 16));
550   BOOST_CHECK_EQUAL(w->sizeHint(),    SGVec2i(17, 18));
551   BOOST_CHECK_EQUAL(w->maximumSize(), SGVec2i(19, 20));
552
553   // Only vertical user set values (layout/default for horizontal hints)
554   w->setMinimumSize( SGVec2i(0, 21) );
555   w->setSizeHint(    SGVec2i(0, 22) );
556   w->setMaximumSize( SGVec2i(SGLimits<int>::max(), 23) );
557
558   BOOST_CHECK_EQUAL(w->minimumSize(), SGVec2i(2, 21));
559   BOOST_CHECK_EQUAL(w->sizeHint(),    SGVec2i(3, 22));
560   BOOST_CHECK_EQUAL(w->maximumSize(), SGVec2i(4, 23));
561
562   w->setVisible(false);
563   BOOST_CHECK_EQUAL(w->geometry(), SGRecti(0, 0, -1, -1));
564 }