]> git.mxchange.org Git - simgear.git/blobdiff - simgear/canvas/layout/canvas_layout_test.cxx
canvas::NasalWidget: check for empty setGeometry callback.
[simgear.git] / simgear / canvas / layout / canvas_layout_test.cxx
index ffbc1c90208bb79f2e98bda7cc1a76383b27756f..5c81a1d89308855a64661d3d96ba3034fe6d3be1 100644 (file)
@@ -44,7 +44,7 @@ class TestWidget:
   public:
     TestWidget( const SGVec2i& min_size,
                 const SGVec2i& size_hint,
-                const SGVec2i& max_size )
+                const SGVec2i& max_size = MAX_SIZE )
     {
       _size_hint = size_hint;
       _min_size = min_size;
@@ -74,6 +74,34 @@ class TestWidget:
     virtual SGVec2i maximumSizeImpl() const { return _max_size; }
 };
 
+class TestWidgetHFW:
+  public TestWidget
+{
+  public:
+    TestWidgetHFW( const SGVec2i& min_size,
+                   const SGVec2i& size_hint,
+                   const SGVec2i& max_size = MAX_SIZE ):
+      TestWidget(min_size, size_hint, max_size)
+    {
+
+    }
+
+    virtual bool hasHeightForWidth() const
+    {
+      return true;
+    }
+
+    virtual int heightForWidth(int w) const
+    {
+      return _size_hint.x() * _size_hint.y() / w;
+    }
+
+    virtual int minimumHeightForWidth(int w) const
+    {
+      return _min_size.x() * _min_size.y() / w;
+    }
+};
+
 typedef SGSharedPtr<TestWidget> TestWidgetRef;
 
 //------------------------------------------------------------------------------
@@ -188,9 +216,54 @@ BOOST_AUTO_TEST_CASE( horizontal_layout )
 
     BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0,   0, 125, 32));
     BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(130, 0, 126, 32));
+
+    BOOST_REQUIRE( hbox.setStretchFactor(w1, 2) );
+    BOOST_REQUIRE( hbox.setStretchFactor(w2, 3) );
+    BOOST_CHECK_EQUAL(hbox.stretch(0), 2);
+    BOOST_CHECK_EQUAL(hbox.stretch(1), 3);
+
+    hbox.removeItem(w1);
+
+    BOOST_CHECK( !hbox.setStretchFactor(w1, 0) );
   }
 }
 
+//------------------------------------------------------------------------------
+BOOST_AUTO_TEST_CASE( spacer_layouting )
+{
+  sc::HBoxLayout hbox;
+  TestWidgetRef w1( new TestWidget( SGVec2i(16, 16),
+                                    SGVec2i(32, 32),
+                                    SGVec2i(9999, 9999) ) ),
+                w2( new TestWidget(*w1) );
+
+  hbox.addItem(w1);
+  hbox.addItem(w2);
+  hbox.addStretch(1);
+
+  BOOST_CHECK_EQUAL(hbox.minimumSize(), SGVec2i(37, 16));
+  BOOST_CHECK_EQUAL(hbox.sizeHint(), SGVec2i(69, 32));
+  BOOST_CHECK_EQUAL(hbox.maximumSize(), sc::LayoutItem::MAX_SIZE);
+
+  hbox.setGeometry(SGRecti(0, 0, 256, 40));
+
+  BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0,  0, 32, 40));
+  BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(37, 0, 32, 40));
+
+  // now center with increased spacing between both widgets
+  hbox.insertStretch(0, 1);
+  hbox.insertSpacing(2, 10);
+
+  BOOST_CHECK_EQUAL(hbox.minimumSize(), SGVec2i(47, 16));
+  BOOST_CHECK_EQUAL(hbox.sizeHint(), SGVec2i(79, 32));
+  BOOST_CHECK_EQUAL(hbox.maximumSize(), sc::LayoutItem::MAX_SIZE);
+
+  hbox.update();
+
+  BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(88,  0, 32, 40));
+  BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(135, 0, 32, 40));
+}
+
 //------------------------------------------------------------------------------
 BOOST_AUTO_TEST_CASE( vertical_layout)
 {
@@ -220,12 +293,175 @@ BOOST_AUTO_TEST_CASE( vertical_layout)
 }
 
 //------------------------------------------------------------------------------
-BOOST_AUTO_TEST_CASE( nasal_layout )
+BOOST_AUTO_TEST_CASE( boxlayout_insert_remove )
+{
+  sc::BoxLayoutRef hbox( new sc::HBoxLayout );
+
+  BOOST_CHECK_EQUAL(hbox->count(), 0);
+  BOOST_CHECK(!hbox->itemAt(0));
+  BOOST_CHECK(!hbox->takeAt(0));
+
+  TestWidgetRef w1( new TestWidget( SGVec2i(16,   16),
+                                    SGVec2i(32,   32),
+                                    SGVec2i(9999, 32) ) ),
+                w2( new TestWidget(*w1) );
+
+  hbox->addItem(w1);
+  BOOST_CHECK_EQUAL(hbox->count(), 1);
+  BOOST_CHECK_EQUAL(hbox->itemAt(0), w1);
+  BOOST_CHECK_EQUAL(w1->getParent(), hbox);
+
+  hbox->insertItem(0, w2);
+  BOOST_CHECK_EQUAL(hbox->count(), 2);
+  BOOST_CHECK_EQUAL(hbox->itemAt(0), w2);
+  BOOST_CHECK_EQUAL(hbox->itemAt(1), w1);
+  BOOST_CHECK_EQUAL(w2->getParent(), hbox);
+
+  hbox->removeItem(w2);
+  BOOST_CHECK_EQUAL(hbox->count(), 1);
+  BOOST_CHECK_EQUAL(hbox->itemAt(0), w1);
+  BOOST_CHECK( !w2->getParent() );
+
+  hbox->addItem(w2);
+  BOOST_CHECK_EQUAL(hbox->count(), 2);
+  BOOST_CHECK_EQUAL(w2->getParent(), hbox);
+
+  hbox->clear();
+  BOOST_CHECK_EQUAL(hbox->count(), 0);
+  BOOST_CHECK( !w1->getParent() );
+  BOOST_CHECK( !w2->getParent() );
+}
+
+//------------------------------------------------------------------------------
+BOOST_AUTO_TEST_CASE( boxlayout_hfw )
+{
+  TestWidgetRef w1( new TestWidgetHFW( SGVec2i(16,   16),
+                                       SGVec2i(32,   32) ) ),
+                w2( new TestWidgetHFW( SGVec2i(24,   24),
+                                       SGVec2i(48,   48) ) );
+
+  BOOST_CHECK_EQUAL(w1->heightForWidth(16), 64);
+  BOOST_CHECK_EQUAL(w1->minimumHeightForWidth(16), 16);
+  BOOST_CHECK_EQUAL(w2->heightForWidth(24), 96);
+  BOOST_CHECK_EQUAL(w2->minimumHeightForWidth(24), 24);
+
+  TestWidgetRef w_no_hfw( new TestWidget( SGVec2i(16,   16),
+                                          SGVec2i(32,   32) ) );
+  BOOST_CHECK(!w_no_hfw->hasHeightForWidth());
+  BOOST_CHECK_EQUAL(w_no_hfw->heightForWidth(16), -1);
+  BOOST_CHECK_EQUAL(w_no_hfw->minimumHeightForWidth(16), -1);
+
+  // horizontal
+  sc::HBoxLayout hbox;
+  hbox.setSpacing(5);
+  hbox.addItem(w1);
+  hbox.addItem(w2);
+
+  BOOST_CHECK_EQUAL(hbox.heightForWidth(45), w2->heightForWidth(24));
+  BOOST_CHECK_EQUAL(hbox.heightForWidth(85), w2->heightForWidth(48));
+
+  hbox.addItem(w_no_hfw);
+
+  BOOST_CHECK_EQUAL(hbox.heightForWidth(66), 96);
+  BOOST_CHECK_EQUAL(hbox.heightForWidth(122), 48);
+  BOOST_CHECK_EQUAL(hbox.minimumHeightForWidth(66), 24);
+  BOOST_CHECK_EQUAL(hbox.minimumHeightForWidth(122), 16);
+
+  hbox.setGeometry(SGRecti(0, 0, 66, 24));
+
+  BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0,  16, 24));
+  BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(21, 0, 24, 24));
+  BOOST_CHECK_EQUAL(w_no_hfw->geometry(), SGRecti(50, 0, 16, 24));
+
+  // vertical
+  sc::VBoxLayout vbox;
+  vbox.setSpacing(5);
+  vbox.addItem(w1);
+  vbox.addItem(w2);
+
+  BOOST_CHECK_EQUAL(vbox.heightForWidth(24), 143);
+  BOOST_CHECK_EQUAL(vbox.heightForWidth(48), 74);
+  BOOST_CHECK_EQUAL(vbox.minimumHeightForWidth(24), 39);
+  BOOST_CHECK_EQUAL(vbox.minimumHeightForWidth(48), 22);
+
+  vbox.addItem(w_no_hfw);
+
+  BOOST_CHECK_EQUAL(vbox.heightForWidth(24), 180);
+  BOOST_CHECK_EQUAL(vbox.heightForWidth(48), 111);
+  BOOST_CHECK_EQUAL(vbox.minimumHeightForWidth(24), 60);
+  BOOST_CHECK_EQUAL(vbox.minimumHeightForWidth(48), 43);
+
+  SGVec2i min_size = vbox.minimumSize(),
+          size_hint = vbox.sizeHint();
+
+  BOOST_CHECK_EQUAL(min_size, SGVec2i(24, 66));
+  BOOST_CHECK_EQUAL(size_hint, SGVec2i(48, 122));
+
+  vbox.setGeometry(SGRecti(0, 0, 24, 122));
+
+  BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0,  24, 33));
+  BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(0, 38, 24, 47));
+  BOOST_CHECK_EQUAL(w_no_hfw->geometry(), SGRecti(0, 90, 24, 32));
+
+  // Vertical layouting modifies size hints, so check if they are correctly
+  // restored
+  BOOST_CHECK_EQUAL(min_size, vbox.minimumSize());
+  BOOST_CHECK_EQUAL(size_hint, vbox.sizeHint());
+
+  vbox.setGeometry(SGRecti(0, 0, 50, 122));
+
+  BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0,  50, 25));
+  BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(0, 30, 50, 51));
+  BOOST_CHECK_EQUAL(w_no_hfw->geometry(), SGRecti(0, 86, 50, 36));
+
+  // Same geometry as before -> should get same widget geometry
+  // (check internal size hint cache updates correctly)
+  vbox.setGeometry(SGRecti(0, 0, 24, 122));
+
+  BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0, 0,  24, 33));
+  BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(0, 38, 24, 47));
+  BOOST_CHECK_EQUAL(w_no_hfw->geometry(), SGRecti(0, 90, 24, 32));
+}
+
+//------------------------------------------------------------------------------
+BOOST_AUTO_TEST_CASE( nasal_widget )
 {
   naContext c = naNewContext();
   naRef me = naNewHash(c);
 
-  sc::LayoutItemRef nasal_item( new sc::NasalWidget(me) );
+  sc::NasalWidgetRef w( new sc::NasalWidget(me) );
+
+  // Default layout sizes (no user set values)
+  BOOST_CHECK_EQUAL(w->minimumSize(), SGVec2i(16, 16));
+  BOOST_CHECK_EQUAL(w->sizeHint(),    SGVec2i(32, 32));
+  BOOST_CHECK_EQUAL(w->maximumSize(), sc::LayoutItem::MAX_SIZE);
+
+  // Changed layout sizes
+  w->setLayoutMinimumSize( SGVec2i(2, 12) );
+  w->setLayoutSizeHint(    SGVec2i(3, 13) );
+  w->setLayoutMaximumSize( SGVec2i(4, 14) );
+
+  BOOST_CHECK_EQUAL(w->minimumSize(), SGVec2i(2, 12));
+  BOOST_CHECK_EQUAL(w->sizeHint(),    SGVec2i(3, 13));
+  BOOST_CHECK_EQUAL(w->maximumSize(), SGVec2i(4, 14));
+
+  // User set values (overwrite layout sizes)
+  w->setMinimumSize( SGVec2i(15, 16) );
+  w->setSizeHint(    SGVec2i(17, 18) );
+  w->setMaximumSize( SGVec2i(19, 20) );
+
+  BOOST_CHECK_EQUAL(w->minimumSize(), SGVec2i(15, 16));
+  BOOST_CHECK_EQUAL(w->sizeHint(),    SGVec2i(17, 18));
+  BOOST_CHECK_EQUAL(w->maximumSize(), SGVec2i(19, 20));
+
+  // Only vertical user set values (layout/default for horizontal hints)
+  w->setMinimumSize( SGVec2i(0, 21) );
+  w->setSizeHint(    SGVec2i(0, 22) );
+  w->setMaximumSize( SGVec2i(SGLimits<int>::max(), 23) );
+
+  BOOST_CHECK_EQUAL(w->minimumSize(), SGVec2i(2, 21));
+  BOOST_CHECK_EQUAL(w->sizeHint(),    SGVec2i(3, 22));
+  BOOST_CHECK_EQUAL(w->maximumSize(), SGVec2i(4, 23));
 
   naFreeContext(c);
 }