// Purpose: Unit tests for wxBoxSizer
// Author: Vadim Zeitlin
// Created: 2010-03-06
-// RCS-ID: $Id$
// Copyright: (c) 2010 Vadim Zeitlin <vadim@wxwidgets.org>
///////////////////////////////////////////////////////////////////////////////
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/sizer.h"
+ #include "wx/listbox.h"
#endif // WX_PRECOMP
-inline std::ostream& operator<<(std::ostream& o, const wxSize& s)
-{
- return o << s.x << 'x' << s.y;
-}
+#include "asserthelper.h"
// ----------------------------------------------------------------------------
// test class
private:
CPPUNIT_TEST_SUITE( BoxSizerTestCase );
CPPUNIT_TEST( Size1 );
+ CPPUNIT_TEST( Size3 );
+ CPPUNIT_TEST( CalcMin );
+ CPPUNIT_TEST( BestSizeRespectsMaxSize );
+ CPPUNIT_TEST( RecalcSizesRespectsMaxSize1 );
+ CPPUNIT_TEST( RecalcSizesRespectsMaxSize2 );
CPPUNIT_TEST_SUITE_END();
void Size1();
+ void Size3();
+ void CalcMin();
+ void BestSizeRespectsMaxSize();
+ void RecalcSizesRespectsMaxSize1();
+ void RecalcSizesRespectsMaxSize2();
wxWindow *m_win;
wxSizer *m_sizer;
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( BoxSizerTestCase );
-// also include in it's own registry so that these tests can be run alone
+// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( BoxSizerTestCase, "BoxSizerTestCase" );
// ----------------------------------------------------------------------------
m_sizer->Add(child);
m_win->Layout();
CPPUNIT_ASSERT_EQUAL( sizeChild, child->GetSize() );
-;
+
m_sizer->Clear();
m_sizer->Add(child, wxSizerFlags(1));
m_win->Layout();
CPPUNIT_ASSERT_EQUAL( sizeTotal, child->GetSize() );
}
+void BoxSizerTestCase::Size3()
+{
+ // check that various combinations of minimal sizes and proportions work as
+ // expected for different window sizes
+ static const struct LayoutTestData
+ {
+ // proportions of the elements
+ int prop[3];
+
+ // minimal sizes of the elements in the sizer direction
+ int minsize[3];
+
+ // total size and the expected sizes of the elements
+ int x,
+ sizes[3];
+
+ // if true, don't try the permutations of our test data
+ bool dontPermute;
+
+
+ // Add the given window to the sizer with the corresponding parameters
+ void AddToSizer(wxSizer *sizer, wxWindow *win, int n) const
+ {
+ sizer->Add(win, wxSizerFlags(prop[n]));
+ sizer->SetItemMinSize(win, wxSize(minsize[n], -1));
+ }
+
+ } layoutTestData[] =
+ {
+ // some really simple cases (no need to permute those, they're
+ // symmetrical anyhow)
+ { { 1, 1, 1, }, { 50, 50, 50, }, 150, { 50, 50, 50, }, true },
+ { { 2, 2, 2, }, { 50, 50, 50, }, 600, { 200, 200, 200, }, true },
+
+ // items with different proportions and min sizes when there is enough
+ // space to lay them out
+ { { 1, 2, 3, }, { 0, 0, 0, }, 600, { 100, 200, 300, } },
+ { { 1, 2, 3, }, { 100, 100, 100, }, 600, { 100, 200, 300, } },
+ { { 1, 2, 3, }, { 100, 50, 50, }, 600, { 100, 200, 300, } },
+ { { 0, 1, 1, }, { 200, 100, 100, }, 600, { 200, 200, 200, } },
+ { { 0, 1, 2, }, { 300, 100, 100, }, 600, { 300, 100, 200, } },
+ { { 0, 1, 1, }, { 100, 50, 50, }, 300, { 100, 100, 100, } },
+ { { 0, 1, 2, }, { 100, 50, 50, }, 400, { 100, 100, 200, } },
+
+ // cases when there is not enough space to lay out the items correctly
+ // while still respecting their min sizes
+ { { 0, 1, 1, }, { 100, 150, 50, }, 300, { 100, 150, 50, } },
+ { { 1, 2, 3, }, { 100, 100, 100, }, 300, { 100, 100, 100, } },
+ { { 1, 2, 3, }, { 100, 50, 50, }, 300, { 100, 80, 120, } },
+ { { 1, 2, 3, }, { 100, 10, 10, }, 150, { 100, 20, 30, } },
+
+ // cases when there is not enough space even for the min sizes (don't
+ // permute in these cases as the layout does depend on the item order
+ // because the first ones have priority)
+ { { 1, 2, 3, }, { 100, 50, 50, }, 150, { 100, 50, 0, }, true },
+ { { 1, 2, 3, }, { 100, 100, 100, }, 200, { 100, 100, 0, }, true },
+ { { 1, 2, 3, }, { 100, 100, 100, }, 150, { 100, 50, 0, }, true },
+ { { 1, 2, 3, }, { 100, 100, 100, }, 50, { 50, 0, 0, }, true },
+ { { 1, 2, 3, }, { 100, 100, 100, }, 0, { 0, 0, 0, }, true },
+ };
+
+ wxWindow *child[3];
+ child[0] = new wxWindow(m_win, wxID_ANY);
+ child[1] = new wxWindow(m_win, wxID_ANY);
+ child[2] = new wxWindow(m_win, wxID_ANY);
+
+ for ( unsigned i = 0; i < WXSIZEOF(layoutTestData); i++ )
+ {
+ LayoutTestData ltd = layoutTestData[i];
+
+ // the results shouldn't depend on the order of items except in the
+ // case when there is not enough space for even the fixed width items
+ // (in which case the first ones might get enough of it but not the
+ // last ones) so test a couple of permutations of test data unless
+ // specifically disabled for this test case
+ for ( unsigned p = 0; p < 3; p++)
+ {
+ switch ( p )
+ {
+ case 0:
+ // nothing to do, use original data
+ break;
+
+ case 1:
+ // exchange first and last elements
+ wxSwap(ltd.prop[0], ltd.prop[2]);
+ wxSwap(ltd.minsize[0], ltd.minsize[2]);
+ wxSwap(ltd.sizes[0], ltd.sizes[2]);
+ break;
+
+ case 2:
+ // exchange the original third and second elements
+ wxSwap(ltd.prop[0], ltd.prop[1]);
+ wxSwap(ltd.minsize[0], ltd.minsize[1]);
+ wxSwap(ltd.sizes[0], ltd.sizes[1]);
+ break;
+ }
+
+ m_sizer->Clear();
+
+ unsigned j;
+ for ( j = 0; j < WXSIZEOF(child); j++ )
+ ltd.AddToSizer(m_sizer, child[j], j);
+
+ m_win->SetClientSize(ltd.x, -1);
+ m_win->Layout();
+
+ for ( j = 0; j < WXSIZEOF(child); j++ )
+ {
+ WX_ASSERT_EQUAL_MESSAGE
+ (
+ (
+ "test %lu, permutation #%lu: wrong size for child #%d "
+ "for total size %d",
+ static_cast<unsigned long>(i),
+ static_cast<unsigned long>(p),
+ j,
+ ltd.x
+ ),
+ ltd.sizes[j], child[j]->GetSize().x
+ );
+ }
+
+ // don't try other permutations if explicitly disabled
+ if ( ltd.dontPermute )
+ break;
+ }
+ }
+}
+
+void BoxSizerTestCase::CalcMin()
+{
+ static const unsigned NUM_TEST_ITEM = 3;
+
+ static const struct CalcMinTestData
+ {
+ // proportions of the elements, if one of them is -1 it means to not
+ // use this window at all in this test
+ int prop[NUM_TEST_ITEM];
+
+ // minimal sizes of the elements in the sizer direction
+ int minsize[NUM_TEST_ITEM];
+
+ // the expected minimal sizer size
+ int total;
+ } calcMinTestData[] =
+ {
+ { { 1, 1, -1 }, { 30, 50, 0 }, 100 },
+ { { 1, 1, 0 }, { 30, 50, 20 }, 120 },
+ { { 10, 10, -1 }, { 30, 50, 0 }, 100 },
+ { { 1, 2, 2 }, { 50, 50, 80 }, 250 },
+ { { 1, 2, 2 }, { 100, 50, 80 }, 500 },
+ };
+
+ unsigned n;
+ wxWindow *child[NUM_TEST_ITEM];
+ for ( n = 0; n < NUM_TEST_ITEM; n++ )
+ child[n] = new wxWindow(m_win, wxID_ANY);
+
+ for ( unsigned i = 0; i < WXSIZEOF(calcMinTestData); i++ )
+ {
+ m_sizer->Clear();
+
+ const CalcMinTestData& cmtd = calcMinTestData[i];
+ for ( n = 0; n < NUM_TEST_ITEM; n++ )
+ {
+ if ( cmtd.prop[n] != -1 )
+ {
+ child[n]->SetInitialSize(wxSize(cmtd.minsize[n], -1));
+ m_sizer->Add(child[n], wxSizerFlags(cmtd.prop[n]));
+ }
+ }
+
+ WX_ASSERT_EQUAL_MESSAGE
+ (
+ ("In test #%u", i),
+ cmtd.total, m_sizer->CalcMin().x
+ );
+ }
+}
+
+void BoxSizerTestCase::BestSizeRespectsMaxSize()
+{
+ m_sizer->Clear();
+
+ const int maxWidth = 100;
+
+ wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
+ wxListBox* listbox = new wxListBox(m_win, wxID_ANY);
+ listbox->Append("some very very very very very very very very very very very long string");
+ listbox->SetMaxSize(wxSize(maxWidth, -1));
+ sizer->Add(listbox);
+
+ m_sizer->Add(sizer);
+ m_win->Layout();
+
+ CPPUNIT_ASSERT_EQUAL(maxWidth, listbox->GetSize().GetWidth());
+}
+
+void BoxSizerTestCase::RecalcSizesRespectsMaxSize1()
+{
+ m_sizer->Clear();
+
+ const int maxWidth = 100;
+
+ m_win->SetClientSize(300, 300);
+
+ wxSizer* sizer1 = new wxBoxSizer(wxVERTICAL);
+ m_sizer->Add(sizer1);
+
+ wxListBox* listbox1 = new wxListBox(m_win, wxID_ANY);
+ listbox1->Append("some very very very very very very very very very very very long string");
+ sizer1->Add(listbox1);
+
+ wxSizer* sizer2 = new wxBoxSizer(wxHORIZONTAL);
+ sizer1->Add(sizer2, wxSizerFlags().Expand());
+
+ wxListBox* listbox2 = new wxListBox(m_win, wxID_ANY);
+ listbox2->Append("some string");
+ listbox2->SetMaxSize(wxSize(100, -1));
+ sizer2->Add(listbox2, wxSizerFlags().Proportion(1));
+
+ m_win->Layout();
+
+ CPPUNIT_ASSERT_EQUAL(maxWidth, listbox2->GetSize().GetWidth());
+}
+
+void BoxSizerTestCase::RecalcSizesRespectsMaxSize2()
+{
+ m_sizer->Clear();
+
+ m_win->SetClientSize(300, 300);
+
+ wxSizer* sizer1 = new wxBoxSizer(wxVERTICAL);
+ m_sizer->Add(sizer1, wxSizerFlags().Expand());
+
+ wxWindow* child1 = new wxWindow(m_win, wxID_ANY);
+ sizer1->Add(child1, wxSizerFlags().Proportion(1));
+
+ wxWindow* child2 = new wxWindow(m_win, wxID_ANY);
+ child2->SetMaxSize(wxSize(-1, 50));
+ sizer1->Add(child2, wxSizerFlags().Proportion(1));
+
+ wxWindow* child3 = new wxWindow(m_win, wxID_ANY);
+ sizer1->Add(child3, wxSizerFlags().Proportion(1));
+
+ m_win->Layout();
+
+ CPPUNIT_ASSERT_EQUAL(125, child1->GetSize().GetHeight());
+ CPPUNIT_ASSERT_EQUAL(50, child2->GetSize().GetHeight());
+ CPPUNIT_ASSERT_EQUAL(125, child3->GetSize().GetHeight());
+}