1 // Testing canvas layouting system
3 // Copyright (C) 2014 Thomas Geymayer <tomgey@gmail.com>
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.
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.
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
19 #define BOOST_TEST_MODULE canvas_layout
20 #include <BoostTestTargetConfig.h>
22 #include "BoxLayout.hxx"
23 #include "NasalWidget.hxx"
25 #include <simgear/debug/logstream.hxx>
26 #include <simgear/nasal/cppbind/NasalContext.hxx>
30 //------------------------------------------------------------------------------
31 struct SetLogLevelFixture
35 sglog().set_log_priority(SG_DEBUG);
38 BOOST_GLOBAL_FIXTURE(SetLogLevelFixture);
40 //------------------------------------------------------------------------------
41 namespace sc = simgear::canvas;
47 TestWidget( const SGVec2i& min_size,
48 const SGVec2i& size_hint,
49 const SGVec2i& max_size = MAX_SIZE )
51 _size_hint = size_hint;
56 TestWidget(const TestWidget& rhs)
58 _size_hint = rhs._size_hint;
59 _min_size = rhs._min_size;
60 _max_size = rhs._max_size;
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; }
69 virtual SGVec2i sizeHintImpl() const { return _size_hint; }
70 virtual SGVec2i minimumSizeImpl() const { return _min_size; }
71 virtual SGVec2i maximumSizeImpl() const { return _max_size; }
73 virtual void visibilityChanged(bool visible)
76 _geometry.set(0, 0, 0, 0);
84 TestWidgetHFW( const SGVec2i& min_size,
85 const SGVec2i& size_hint,
86 const SGVec2i& max_size = MAX_SIZE ):
87 TestWidget(min_size, size_hint, max_size)
92 virtual bool hasHeightForWidth() const
97 virtual int heightForWidthImpl(int w) const
99 return _size_hint.x() * _size_hint.y() / w;
102 virtual int minimumHeightForWidthImpl(int w) const
104 return _min_size.x() * _min_size.y() / w;
108 typedef SGSharedPtr<TestWidget> TestWidgetRef;
110 //------------------------------------------------------------------------------
111 BOOST_AUTO_TEST_CASE( horizontal_layout )
113 sc::BoxLayoutRef box_layout(new sc::BoxLayout(sc::BoxLayout::BottomToTop));
114 box_layout->setSpacing(5);
116 BOOST_CHECK_EQUAL(box_layout->direction(), sc::BoxLayout::BottomToTop);
117 BOOST_CHECK_EQUAL(box_layout->spacing(), 5);
119 box_layout->setDirection(sc::BoxLayout::LeftToRight);
120 box_layout->setSpacing(9);
122 BOOST_CHECK_EQUAL(box_layout->direction(), sc::BoxLayout::LeftToRight);
123 BOOST_CHECK_EQUAL(box_layout->spacing(), 9);
125 TestWidgetRef fixed_size_widget( new TestWidget( SGVec2i(16, 16),
128 box_layout->addItem(fixed_size_widget);
130 BOOST_CHECK_EQUAL(box_layout->minimumSize(), SGVec2i(16, 16));
131 BOOST_CHECK_EQUAL(box_layout->sizeHint(), SGVec2i(16, 16));
132 BOOST_CHECK_EQUAL(box_layout->maximumSize(), SGVec2i(16, 16));
134 TestWidgetRef limited_resize_widget( new TestWidget( SGVec2i(16, 16),
136 SGVec2i(256, 64) ) );
137 box_layout->addItem(limited_resize_widget);
139 // Combined sizes of both widget plus the padding between them
140 BOOST_CHECK_EQUAL(box_layout->minimumSize(), SGVec2i(41, 16));
141 BOOST_CHECK_EQUAL(box_layout->sizeHint(), SGVec2i(57, 32));
142 BOOST_CHECK_EQUAL(box_layout->maximumSize(), SGVec2i(281, 64));
144 // Test with different spacing/padding
145 box_layout->setSpacing(5);
147 BOOST_CHECK_EQUAL(box_layout->minimumSize(), SGVec2i(37, 16));
148 BOOST_CHECK_EQUAL(box_layout->sizeHint(), SGVec2i(53, 32));
149 BOOST_CHECK_EQUAL(box_layout->maximumSize(), SGVec2i(277, 64));
151 box_layout->setGeometry(SGRecti(0, 0, 128, 32));
153 // Fixed size for first widget and remaining space goes to second widget
154 BOOST_CHECK_EQUAL(fixed_size_widget->geometry(), SGRecti(0, 8, 16, 16));
155 BOOST_CHECK_EQUAL(limited_resize_widget->geometry(), SGRecti(21, 0, 107, 32));
157 TestWidgetRef stretch_widget( new TestWidget( SGVec2i(16, 16),
159 SGVec2i(128, 32) ) );
160 box_layout->addItem(stretch_widget, 1);
161 box_layout->update();
163 BOOST_CHECK_EQUAL(box_layout->minimumSize(), SGVec2i(58, 16));
164 BOOST_CHECK_EQUAL(box_layout->sizeHint(), SGVec2i(90, 32));
165 BOOST_CHECK_EQUAL(box_layout->maximumSize(), SGVec2i(410, 64));
167 // Due to the stretch factor only the last widget gets additional space. All
168 // other widgets get the preferred size.
169 BOOST_CHECK_EQUAL(fixed_size_widget->geometry(), SGRecti(0, 8, 16, 16));
170 BOOST_CHECK_EQUAL(limited_resize_widget->geometry(), SGRecti(21, 0, 32, 32));
171 BOOST_CHECK_EQUAL(stretch_widget->geometry(), SGRecti(58, 0, 70, 32));
173 // Test stretch factor
174 TestWidgetRef fast_stretch( new TestWidget(*stretch_widget) );
175 sc::BoxLayoutRef box_layout_stretch(
176 new sc::BoxLayout(sc::BoxLayout::LeftToRight)
179 box_layout_stretch->addItem(stretch_widget, 1);
180 box_layout_stretch->addItem(fast_stretch, 2);
182 box_layout_stretch->setGeometry(SGRecti(0,0,128,32));
184 BOOST_CHECK_EQUAL(stretch_widget->geometry(), SGRecti(0, 0, 41, 32));
185 BOOST_CHECK_EQUAL(fast_stretch->geometry(), SGRecti(46, 0, 82, 32));
187 box_layout_stretch->setGeometry(SGRecti(0,0,256,32));
189 BOOST_CHECK_EQUAL(stretch_widget->geometry(), SGRecti(0, 0, 123, 32));
190 BOOST_CHECK_EQUAL(fast_stretch->geometry(), SGRecti(128, 0, 128, 32));
192 // Test superflous space to padding
193 box_layout_stretch->setGeometry(SGRecti(0,0,512,32));
195 BOOST_CHECK_EQUAL(stretch_widget->geometry(), SGRecti(83, 0, 128, 32));
196 BOOST_CHECK_EQUAL(fast_stretch->geometry(), SGRecti(300, 0, 128, 32));
198 // ...and now with alignment
200 // All widgets without alignment get their maximum space and the remaining
201 // space is equally distributed to the remaining items. All items with
202 // alignment are set to their size hint and positioned according to their
205 // Left widget: size hint and positioned on the left
206 // Right widget: maximum size and positioned on the right
207 stretch_widget->setAlignment(sc::AlignLeft);
208 box_layout_stretch->update();
209 BOOST_CHECK_EQUAL(stretch_widget->geometry(), SGRecti(0, 0, 32, 32));
210 BOOST_CHECK_EQUAL(fast_stretch->geometry(), SGRecti(384, 0, 128, 32));
212 // Left widget: align right
213 stretch_widget->setAlignment(sc::AlignRight);
214 box_layout_stretch->update();
215 BOOST_CHECK_EQUAL(stretch_widget->geometry(), SGRecti(347, 0, 32, 32));
216 BOOST_CHECK_EQUAL(fast_stretch->geometry(), SGRecti(384, 0, 128, 32));
218 // Left widget: size hint and positioned on the right
219 // Right widget: size hint and positioned on the left of the right half
220 fast_stretch->setAlignment(sc::AlignLeft);
221 box_layout_stretch->update();
222 BOOST_CHECK_EQUAL(stretch_widget->geometry(), SGRecti(221, 0, 32, 32));
223 BOOST_CHECK_EQUAL(fast_stretch->geometry(), SGRecti(258, 0, 32, 32));
225 // Also check vertical alignment
226 stretch_widget->setAlignment(sc::AlignLeft | sc::AlignTop);
227 fast_stretch->setAlignment(sc::AlignLeft | sc::AlignBottom);
228 box_layout_stretch->setGeometry(SGRecti(0,0,512,64));
229 BOOST_CHECK_EQUAL(stretch_widget->geometry(), SGRecti(0, 0, 32, 32));
230 BOOST_CHECK_EQUAL(fast_stretch->geometry(), SGRecti(258, 32, 32, 32));
233 //------------------------------------------------------------------------------
234 // Test more space then preferred, but less than maximum
235 BOOST_AUTO_TEST_CASE( hbox_pref_to_max )
237 sc::BoxLayoutRef hbox(new sc::HBoxLayout());
238 TestWidgetRef w1( new TestWidget( SGVec2i(16, 16),
240 SGVec2i(9999, 32) ) ),
241 w2( new TestWidget(*w1) );
246 hbox->setGeometry( SGRecti(0, 0, 256, 32) );
248 BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0, 126, 32));
249 BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(131, 0, 125, 32));
251 hbox->setStretch(0, 1);
252 hbox->setStretch(1, 1);
254 BOOST_CHECK_EQUAL(hbox->stretch(0), 1);
255 BOOST_CHECK_EQUAL(hbox->stretch(1), 1);
259 BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0, 125, 32));
260 BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(130, 0, 126, 32));
262 BOOST_REQUIRE( hbox->setStretchFactor(w1, 2) );
263 BOOST_REQUIRE( hbox->setStretchFactor(w2, 3) );
264 BOOST_CHECK_EQUAL(hbox->stretch(0), 2);
265 BOOST_CHECK_EQUAL(hbox->stretch(1), 3);
267 hbox->removeItem(w1);
269 BOOST_CHECK( !hbox->setStretchFactor(w1, 0) );
272 //------------------------------------------------------------------------------
273 BOOST_AUTO_TEST_CASE( spacer_layouting )
276 TestWidgetRef w1( new TestWidget( SGVec2i(16, 16),
278 SGVec2i(9999, 9999) ) ),
279 w2( new TestWidget(*w1) );
285 BOOST_CHECK_EQUAL(hbox.minimumSize(), SGVec2i(37, 16));
286 BOOST_CHECK_EQUAL(hbox.sizeHint(), SGVec2i(69, 32));
287 BOOST_CHECK_EQUAL(hbox.maximumSize(), sc::LayoutItem::MAX_SIZE);
289 hbox.setGeometry(SGRecti(0, 0, 256, 40));
291 BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0, 32, 40));
292 BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(37, 0, 32, 40));
294 // now center with increased spacing between both widgets
295 hbox.insertStretch(0, 1);
296 hbox.insertSpacing(2, 10);
298 BOOST_CHECK_EQUAL(hbox.minimumSize(), SGVec2i(47, 16));
299 BOOST_CHECK_EQUAL(hbox.sizeHint(), SGVec2i(79, 32));
300 BOOST_CHECK_EQUAL(hbox.maximumSize(), sc::LayoutItem::MAX_SIZE);
304 BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(88, 0, 32, 40));
305 BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(135, 0, 32, 40));
308 //------------------------------------------------------------------------------
309 BOOST_AUTO_TEST_CASE( vertical_layout)
311 sc::BoxLayout vbox(sc::BoxLayout::TopToBottom);
314 TestWidgetRef fixed_size_widget( new TestWidget( SGVec2i(16, 16),
317 TestWidgetRef limited_resize_widget( new TestWidget( SGVec2i(16, 16),
319 SGVec2i(256, 64) ) );
321 vbox.addItem(fixed_size_widget);
322 vbox.addItem(limited_resize_widget);
324 BOOST_CHECK_EQUAL(vbox.minimumSize(), SGVec2i(16, 39));
325 BOOST_CHECK_EQUAL(vbox.sizeHint(), SGVec2i(32, 55));
326 BOOST_CHECK_EQUAL(vbox.maximumSize(), SGVec2i(256, 87));
328 vbox.setGeometry(SGRecti(10, 20, 16, 55));
330 BOOST_CHECK_EQUAL(fixed_size_widget->geometry(), SGRecti(10, 20, 16, 16));
331 BOOST_CHECK_EQUAL(limited_resize_widget->geometry(), SGRecti(10, 43, 16, 32));
333 vbox.setDirection(sc::BoxLayout::BottomToTop);
336 //------------------------------------------------------------------------------
337 BOOST_AUTO_TEST_CASE( boxlayout_insert_remove )
339 sc::BoxLayoutRef hbox( new sc::HBoxLayout );
341 BOOST_CHECK_EQUAL(hbox->count(), 0);
342 BOOST_CHECK(!hbox->itemAt(0));
343 BOOST_CHECK(!hbox->takeAt(0));
345 TestWidgetRef w1( new TestWidget( SGVec2i(16, 16),
347 SGVec2i(9999, 32) ) ),
348 w2( new TestWidget(*w1) );
351 BOOST_CHECK_EQUAL(hbox->count(), 1);
352 BOOST_CHECK_EQUAL(hbox->itemAt(0), w1);
353 BOOST_CHECK_EQUAL(w1->getParent(), hbox);
355 hbox->insertItem(0, w2);
356 BOOST_CHECK_EQUAL(hbox->count(), 2);
357 BOOST_CHECK_EQUAL(hbox->itemAt(0), w2);
358 BOOST_CHECK_EQUAL(hbox->itemAt(1), w1);
359 BOOST_CHECK_EQUAL(w2->getParent(), hbox);
361 hbox->removeItem(w2);
362 BOOST_CHECK_EQUAL(hbox->count(), 1);
363 BOOST_CHECK_EQUAL(hbox->itemAt(0), w1);
364 BOOST_CHECK( !w2->getParent() );
367 BOOST_CHECK_EQUAL(hbox->count(), 2);
368 BOOST_CHECK_EQUAL(w2->getParent(), hbox);
371 BOOST_CHECK_EQUAL(hbox->count(), 0);
372 BOOST_CHECK( !w1->getParent() );
373 BOOST_CHECK( !w2->getParent() );
376 //------------------------------------------------------------------------------
377 BOOST_AUTO_TEST_CASE( boxlayout_visibility )
379 sc::BoxLayoutRef hbox( new sc::HBoxLayout );
380 TestWidgetRef w1( new TestWidget( SGVec2i(16, 16),
382 w2( new TestWidget(*w1) ),
383 w3( new TestWidget(*w1) );
389 BOOST_REQUIRE_EQUAL(hbox->sizeHint().x(), 3 * 32 + 2 * hbox->spacing());
391 hbox->setGeometry(SGRecti(0, 0, 69, 32));
393 BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0, 20, 32));
394 BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(25, 0, 20, 32));
395 BOOST_CHECK_EQUAL(w3->geometry(), SGRecti(50, 0, 19, 32));
397 w2->setVisible(false);
399 BOOST_REQUIRE(hbox->isVisible());
400 BOOST_REQUIRE(w1->isVisible());
401 BOOST_REQUIRE(!w2->isVisible());
402 BOOST_REQUIRE(w2->isExplicitlyHidden());
403 BOOST_REQUIRE(w3->isVisible());
405 BOOST_CHECK_EQUAL(hbox->sizeHint().x(), 2 * 32 + 1 * hbox->spacing());
409 BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0, 32, 32));
410 BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(0, 0, 0, 0));
411 BOOST_CHECK_EQUAL(w3->geometry(), SGRecti(37, 0, 32, 32));
413 hbox->setVisible(false);
415 BOOST_REQUIRE(!hbox->isVisible());
416 BOOST_REQUIRE(hbox->isExplicitlyHidden());
417 BOOST_REQUIRE(!w1->isVisible());
418 BOOST_REQUIRE(!w1->isExplicitlyHidden());
419 BOOST_REQUIRE(!w2->isVisible());
420 BOOST_REQUIRE(w2->isExplicitlyHidden());
421 BOOST_REQUIRE(!w3->isVisible());
422 BOOST_REQUIRE(!w3->isExplicitlyHidden());
424 BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0, 0, 0));
425 BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(0, 0, 0, 0));
426 BOOST_CHECK_EQUAL(w3->geometry(), SGRecti(0, 0, 0, 0));
428 w2->setVisible(true);
430 BOOST_REQUIRE(!w2->isVisible());
431 BOOST_REQUIRE(!w2->isExplicitlyHidden());
433 hbox->setVisible(true);
435 BOOST_REQUIRE(hbox->isVisible());
436 BOOST_REQUIRE(w1->isVisible());
437 BOOST_REQUIRE(w2->isVisible());
438 BOOST_REQUIRE(w3->isVisible());
442 BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0, 20, 32));
443 BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(25, 0, 20, 32));
444 BOOST_CHECK_EQUAL(w3->geometry(), SGRecti(50, 0, 19, 32));
447 //------------------------------------------------------------------------------
448 BOOST_AUTO_TEST_CASE( boxlayout_contents_margins )
452 BOOST_REQUIRE(m.isNull());
456 BOOST_REQUIRE_EQUAL(m.l, 5);
457 BOOST_REQUIRE_EQUAL(m.t, 5);
458 BOOST_REQUIRE_EQUAL(m.r, 5);
459 BOOST_REQUIRE_EQUAL(m.b, 5);
461 m = sc::Margins(6, 7);
463 BOOST_REQUIRE_EQUAL(m.l, 6);
464 BOOST_REQUIRE_EQUAL(m.t, 7);
465 BOOST_REQUIRE_EQUAL(m.r, 6);
466 BOOST_REQUIRE_EQUAL(m.b, 7);
468 BOOST_REQUIRE_EQUAL(m.horiz(), 12);
469 BOOST_REQUIRE_EQUAL(m.vert(), 14);
470 BOOST_REQUIRE(!m.isNull());
472 m = sc::Margins(1, 2, 3, 4);
474 BOOST_REQUIRE_EQUAL(m.l, 1);
475 BOOST_REQUIRE_EQUAL(m.t, 2);
476 BOOST_REQUIRE_EQUAL(m.r, 3);
477 BOOST_REQUIRE_EQUAL(m.b, 4);
479 BOOST_REQUIRE_EQUAL(m.horiz(), 4);
480 BOOST_REQUIRE_EQUAL(m.vert(), 6);
481 BOOST_REQUIRE_EQUAL(m.size(), SGVec2i(4, 6));
483 sc::BoxLayoutRef hbox( new sc::HBoxLayout );
485 hbox->setContentsMargins(5, 10, 15, 20);
487 BOOST_CHECK_EQUAL(hbox->minimumSize(), SGVec2i(20, 30));
488 BOOST_CHECK_EQUAL(hbox->sizeHint(), SGVec2i(20, 30));
489 BOOST_CHECK_EQUAL(hbox->maximumSize(), SGVec2i(20, 30));
491 hbox->setGeometry(SGRecti(0, 0, 30, 40));
493 BOOST_CHECK_EQUAL(hbox->geometry(), SGRecti(0, 0, 30, 40));
494 BOOST_CHECK_EQUAL(hbox->contentsRect(), SGRecti(5, 10, 10, 10));
496 TestWidgetRef w1( new TestWidget( SGVec2i(16, 16),
498 w2( new TestWidget(*w1) ),
499 w3( new TestWidget(*w1) );
501 w1->setContentsMargin(5);
502 w2->setContentsMargin(6);
503 w3->setContentsMargin(7);
505 BOOST_CHECK_EQUAL(w1->minimumSize(), SGVec2i(26, 26));
506 BOOST_CHECK_EQUAL(w1->sizeHint(), SGVec2i(42, 42));
507 BOOST_CHECK_EQUAL(w1->maximumSize(), sc::LayoutItem::MAX_SIZE);
509 BOOST_CHECK_EQUAL(w2->minimumSize(), SGVec2i(28, 28));
510 BOOST_CHECK_EQUAL(w2->sizeHint(), SGVec2i(44, 44));
511 BOOST_CHECK_EQUAL(w2->maximumSize(), sc::LayoutItem::MAX_SIZE);
513 BOOST_CHECK_EQUAL(w3->minimumSize(), SGVec2i(30, 30));
514 BOOST_CHECK_EQUAL(w3->sizeHint(), SGVec2i(46, 46));
515 BOOST_CHECK_EQUAL(w3->maximumSize(), sc::LayoutItem::MAX_SIZE);
521 BOOST_CHECK_EQUAL(hbox->minimumSize(), SGVec2i(114, 60));
522 BOOST_CHECK_EQUAL(hbox->sizeHint(), SGVec2i(162, 76));
523 BOOST_CHECK_EQUAL(hbox->maximumSize(), sc::LayoutItem::MAX_SIZE);
525 hbox->setGeometry(SGRecti(0, 0, hbox->sizeHint().x(), hbox->sizeHint().y()));
527 BOOST_CHECK_EQUAL(hbox->contentsRect(), SGRecti(5, 10, 142, 46));
529 BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(5, 10, 42, 46));
530 BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(52, 10, 44, 46));
531 BOOST_CHECK_EQUAL(w3->geometry(), SGRecti(101, 10, 46, 46));
533 BOOST_CHECK_EQUAL(w1->contentsRect(), SGRecti(10, 15, 32, 36));
534 BOOST_CHECK_EQUAL(w2->contentsRect(), SGRecti(58, 16, 32, 34));
535 BOOST_CHECK_EQUAL(w3->contentsRect(), SGRecti(108, 17, 32, 32));
538 //------------------------------------------------------------------------------
539 BOOST_AUTO_TEST_CASE( boxlayout_hfw )
541 TestWidgetRef w1( new TestWidgetHFW( SGVec2i(16, 16),
543 w2( new TestWidgetHFW( SGVec2i(24, 24),
546 BOOST_CHECK_EQUAL(w1->heightForWidth(16), 64);
547 BOOST_CHECK_EQUAL(w1->minimumHeightForWidth(16), 16);
548 BOOST_CHECK_EQUAL(w2->heightForWidth(24), 96);
549 BOOST_CHECK_EQUAL(w2->minimumHeightForWidth(24), 24);
551 TestWidgetRef w_no_hfw( new TestWidget( SGVec2i(16, 16),
553 BOOST_CHECK(!w_no_hfw->hasHeightForWidth());
554 BOOST_CHECK_EQUAL(w_no_hfw->heightForWidth(16), -1);
555 BOOST_CHECK_EQUAL(w_no_hfw->minimumHeightForWidth(16), -1);
563 BOOST_CHECK_EQUAL(hbox.heightForWidth(45), w2->heightForWidth(24));
564 BOOST_CHECK_EQUAL(hbox.heightForWidth(85), w2->heightForWidth(48));
566 hbox.addItem(w_no_hfw);
568 BOOST_CHECK_EQUAL(hbox.heightForWidth(66), 96);
569 BOOST_CHECK_EQUAL(hbox.heightForWidth(122), 48);
570 BOOST_CHECK_EQUAL(hbox.minimumHeightForWidth(66), 24);
571 BOOST_CHECK_EQUAL(hbox.minimumHeightForWidth(122), 16);
573 hbox.setGeometry(SGRecti(0, 0, 66, 24));
575 BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0, 16, 24));
576 BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(21, 0, 24, 24));
577 BOOST_CHECK_EQUAL(w_no_hfw->geometry(), SGRecti(50, 0, 16, 24));
585 BOOST_CHECK_EQUAL(vbox.heightForWidth(24), 143);
586 BOOST_CHECK_EQUAL(vbox.heightForWidth(48), 74);
587 BOOST_CHECK_EQUAL(vbox.minimumHeightForWidth(24), 39);
588 BOOST_CHECK_EQUAL(vbox.minimumHeightForWidth(48), 22);
590 vbox.addItem(w_no_hfw);
592 BOOST_CHECK_EQUAL(vbox.heightForWidth(24), 180);
593 BOOST_CHECK_EQUAL(vbox.heightForWidth(48), 111);
594 BOOST_CHECK_EQUAL(vbox.minimumHeightForWidth(24), 60);
595 BOOST_CHECK_EQUAL(vbox.minimumHeightForWidth(48), 43);
597 SGVec2i min_size = vbox.minimumSize(),
598 size_hint = vbox.sizeHint();
600 BOOST_CHECK_EQUAL(min_size, SGVec2i(24, 66));
601 BOOST_CHECK_EQUAL(size_hint, SGVec2i(48, 122));
603 vbox.setGeometry(SGRecti(0, 0, 24, 122));
605 BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0, 24, 33));
606 BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(0, 38, 24, 47));
607 BOOST_CHECK_EQUAL(w_no_hfw->geometry(), SGRecti(0, 90, 24, 32));
609 // Vertical layouting modifies size hints, so check if they are correctly
611 BOOST_CHECK_EQUAL(min_size, vbox.minimumSize());
612 BOOST_CHECK_EQUAL(size_hint, vbox.sizeHint());
614 vbox.setGeometry(SGRecti(0, 0, 50, 122));
616 BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0, 50, 25));
617 BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(0, 30, 50, 51));
618 BOOST_CHECK_EQUAL(w_no_hfw->geometry(), SGRecti(0, 86, 50, 36));
620 // Same geometry as before -> should get same widget geometry
621 // (check internal size hint cache updates correctly)
622 vbox.setGeometry(SGRecti(0, 0, 24, 122));
624 BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0, 24, 33));
625 BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(0, 38, 24, 47));
626 BOOST_CHECK_EQUAL(w_no_hfw->geometry(), SGRecti(0, 90, 24, 32));
629 //------------------------------------------------------------------------------
630 BOOST_AUTO_TEST_CASE( item_alignment_rect )
632 TestWidgetRef w1( new TestWidget( SGVec2i(16, 16),
635 const SGRecti r(10, 10, 64, 64);
637 // Default: AlignFill -> fill up to maximum size
638 BOOST_CHECK_EQUAL(w1->alignmentRect(r), r);
642 // AlignLeft -> width from size hint, positioned on the left
643 w1->setAlignment(sc::AlignLeft);
644 BOOST_CHECK_EQUAL(w1->alignmentRect(r), SGRecti(10, 10, 32, 64));
646 // AlignRight -> width from size hint, positioned on the left
647 w1->setAlignment(sc::AlignRight);
648 BOOST_CHECK_EQUAL(w1->alignmentRect(r), SGRecti(42, 10, 32, 64));
650 // AlignHCenter -> width from size hint, positioned in the center
651 w1->setAlignment(sc::AlignHCenter);
652 BOOST_CHECK_EQUAL(w1->alignmentRect(r), SGRecti(26, 10, 32, 64));
657 // AlignTop -> height from size hint, positioned on the top
658 w1->setAlignment(sc::AlignTop);
659 BOOST_CHECK_EQUAL(w1->alignmentRect(r), SGRecti(10, 10, 64, 32));
661 // AlignBottom -> height from size hint, positioned on the bottom
662 w1->setAlignment(sc::AlignBottom);
663 BOOST_CHECK_EQUAL(w1->alignmentRect(r), SGRecti(10, 42, 64, 32));
665 // AlignVCenter -> height from size hint, positioned in the center
666 w1->setAlignment(sc::AlignVCenter);
667 BOOST_CHECK_EQUAL(w1->alignmentRect(r), SGRecti(10, 26, 64, 32));
670 // Vertical + Horizontal
671 w1->setAlignment(sc::AlignCenter);
672 BOOST_CHECK_EQUAL(w1->alignmentRect(r), SGRecti(26, 26, 32, 32));
675 //------------------------------------------------------------------------------
676 // TODO extend to_nasal_helper for automatic argument conversion
677 static naRef f_Widget_visibilityChanged(nasal::CallContext ctx)
679 sc::NasalWidget* w = ctx.from_nasal<sc::NasalWidget*>(ctx.me);
681 if( !ctx.requireArg<bool>(0) )
682 w->setGeometry(SGRecti(0, 0, -1, -1));
687 //------------------------------------------------------------------------------
688 BOOST_AUTO_TEST_CASE( nasal_widget )
691 nasal::Hash globals = c.newHash();
693 nasal::Object::setupGhost();
694 nasal::Ghost<sc::LayoutItemRef>::init("LayoutItem");
695 sc::NasalWidget::setupGhost(globals);
697 nasal::Hash me = c.newHash();
698 me.set("visibilityChanged", &f_Widget_visibilityChanged);
699 sc::NasalWidgetRef w( new sc::NasalWidget(me.get_naRef()) );
701 // Default layout sizes (no user set values)
702 BOOST_CHECK_EQUAL(w->minimumSize(), SGVec2i(16, 16));
703 BOOST_CHECK_EQUAL(w->sizeHint(), SGVec2i(32, 32));
704 BOOST_CHECK_EQUAL(w->maximumSize(), sc::LayoutItem::MAX_SIZE);
706 // Changed layout sizes
707 w->setLayoutMinimumSize( SGVec2i(2, 12) );
708 w->setLayoutSizeHint( SGVec2i(3, 13) );
709 w->setLayoutMaximumSize( SGVec2i(4, 14) );
711 BOOST_CHECK_EQUAL(w->minimumSize(), SGVec2i(2, 12));
712 BOOST_CHECK_EQUAL(w->sizeHint(), SGVec2i(3, 13));
713 BOOST_CHECK_EQUAL(w->maximumSize(), SGVec2i(4, 14));
715 // User set values (overwrite layout sizes)
716 w->setMinimumSize( SGVec2i(15, 16) );
717 w->setSizeHint( SGVec2i(17, 18) );
718 w->setMaximumSize( SGVec2i(19, 20) );
720 BOOST_CHECK_EQUAL(w->minimumSize(), SGVec2i(15, 16));
721 BOOST_CHECK_EQUAL(w->sizeHint(), SGVec2i(17, 18));
722 BOOST_CHECK_EQUAL(w->maximumSize(), SGVec2i(19, 20));
724 // Only vertical user set values (layout/default for horizontal hints)
725 w->setMinimumSize( SGVec2i(0, 21) );
726 w->setSizeHint( SGVec2i(0, 22) );
727 w->setMaximumSize( SGVec2i(SGLimits<int>::max(), 23) );
729 BOOST_CHECK_EQUAL(w->minimumSize(), SGVec2i(2, 21));
730 BOOST_CHECK_EQUAL(w->sizeHint(), SGVec2i(3, 22));
731 BOOST_CHECK_EQUAL(w->maximumSize(), SGVec2i(4, 23));
733 w->setVisible(false);
734 BOOST_CHECK_EQUAL(w->geometry(), SGRecti(0, 0, -1, -1));