1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/sizers/boxsizer.cpp
3 // Purpose: Unit tests for wxBoxSizer
4 // Author: Vadim Zeitlin
6 // Copyright: (c) 2010 Vadim Zeitlin <vadim@wxwidgets.org>
7 ///////////////////////////////////////////////////////////////////////////////
9 // ----------------------------------------------------------------------------
11 // ----------------------------------------------------------------------------
22 #include "wx/listbox.h"
25 #include "asserthelper.h"
27 // ----------------------------------------------------------------------------
29 // ----------------------------------------------------------------------------
31 class BoxSizerTestCase
: public CppUnit::TestCase
34 BoxSizerTestCase() { }
37 virtual void tearDown();
40 CPPUNIT_TEST_SUITE( BoxSizerTestCase
);
41 CPPUNIT_TEST( Size1
);
42 CPPUNIT_TEST( Size3
);
43 CPPUNIT_TEST( CalcMin
);
44 CPPUNIT_TEST( BestSizeRespectsMaxSize
);
45 CPPUNIT_TEST( RecalcSizesRespectsMaxSize1
);
46 CPPUNIT_TEST( RecalcSizesRespectsMaxSize2
);
47 CPPUNIT_TEST_SUITE_END();
52 void BestSizeRespectsMaxSize();
53 void RecalcSizesRespectsMaxSize1();
54 void RecalcSizesRespectsMaxSize2();
59 DECLARE_NO_COPY_CLASS(BoxSizerTestCase
)
62 // register in the unnamed registry so that these tests are run by default
63 CPPUNIT_TEST_SUITE_REGISTRATION( BoxSizerTestCase
);
65 // also include in its own registry so that these tests can be run alone
66 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( BoxSizerTestCase
, "BoxSizerTestCase" );
68 // ----------------------------------------------------------------------------
69 // test initialization
70 // ----------------------------------------------------------------------------
72 void BoxSizerTestCase::setUp()
74 m_win
= new wxWindow(wxTheApp
->GetTopWindow(), wxID_ANY
);
75 m_win
->SetClientSize(127, 35);
77 m_sizer
= new wxBoxSizer(wxHORIZONTAL
);
78 m_win
->SetSizer(m_sizer
);
81 void BoxSizerTestCase::tearDown()
89 // ----------------------------------------------------------------------------
91 // ----------------------------------------------------------------------------
93 void BoxSizerTestCase::Size1()
95 const wxSize sizeTotal
= m_win
->GetClientSize();
96 const wxSize sizeChild
= sizeTotal
/ 2;
99 child
= new wxWindow(m_win
, wxID_ANY
, wxDefaultPosition
, sizeChild
);
102 CPPUNIT_ASSERT_EQUAL( sizeChild
, child
->GetSize() );
105 m_sizer
->Add(child
, wxSizerFlags(1));
107 CPPUNIT_ASSERT_EQUAL( wxSize(sizeTotal
.x
, sizeChild
.y
), child
->GetSize() );
110 m_sizer
->Add(child
, wxSizerFlags(1).Expand());
112 CPPUNIT_ASSERT_EQUAL( sizeTotal
, child
->GetSize() );
115 m_sizer
->Add(child
, wxSizerFlags());
116 m_sizer
->SetItemMinSize(child
, sizeTotal
*2);
118 CPPUNIT_ASSERT_EQUAL( sizeTotal
, child
->GetSize() );
121 m_sizer
->Add(child
, wxSizerFlags().Expand());
122 m_sizer
->SetItemMinSize(child
, sizeTotal
*2);
124 CPPUNIT_ASSERT_EQUAL( sizeTotal
, child
->GetSize() );
127 void BoxSizerTestCase::Size3()
129 // check that various combinations of minimal sizes and proportions work as
130 // expected for different window sizes
131 static const struct LayoutTestData
133 // proportions of the elements
136 // minimal sizes of the elements in the sizer direction
139 // total size and the expected sizes of the elements
143 // if true, don't try the permutations of our test data
147 // Add the given window to the sizer with the corresponding parameters
148 void AddToSizer(wxSizer
*sizer
, wxWindow
*win
, int n
) const
150 sizer
->Add(win
, wxSizerFlags(prop
[n
]));
151 sizer
->SetItemMinSize(win
, wxSize(minsize
[n
], -1));
156 // some really simple cases (no need to permute those, they're
157 // symmetrical anyhow)
158 { { 1, 1, 1, }, { 50, 50, 50, }, 150, { 50, 50, 50, }, true },
159 { { 2, 2, 2, }, { 50, 50, 50, }, 600, { 200, 200, 200, }, true },
161 // items with different proportions and min sizes when there is enough
162 // space to lay them out
163 { { 1, 2, 3, }, { 0, 0, 0, }, 600, { 100, 200, 300, } },
164 { { 1, 2, 3, }, { 100, 100, 100, }, 600, { 100, 200, 300, } },
165 { { 1, 2, 3, }, { 100, 50, 50, }, 600, { 100, 200, 300, } },
166 { { 0, 1, 1, }, { 200, 100, 100, }, 600, { 200, 200, 200, } },
167 { { 0, 1, 2, }, { 300, 100, 100, }, 600, { 300, 100, 200, } },
168 { { 0, 1, 1, }, { 100, 50, 50, }, 300, { 100, 100, 100, } },
169 { { 0, 1, 2, }, { 100, 50, 50, }, 400, { 100, 100, 200, } },
171 // cases when there is not enough space to lay out the items correctly
172 // while still respecting their min sizes
173 { { 0, 1, 1, }, { 100, 150, 50, }, 300, { 100, 150, 50, } },
174 { { 1, 2, 3, }, { 100, 100, 100, }, 300, { 100, 100, 100, } },
175 { { 1, 2, 3, }, { 100, 50, 50, }, 300, { 100, 80, 120, } },
176 { { 1, 2, 3, }, { 100, 10, 10, }, 150, { 100, 20, 30, } },
178 // cases when there is not enough space even for the min sizes (don't
179 // permute in these cases as the layout does depend on the item order
180 // because the first ones have priority)
181 { { 1, 2, 3, }, { 100, 50, 50, }, 150, { 100, 50, 0, }, true },
182 { { 1, 2, 3, }, { 100, 100, 100, }, 200, { 100, 100, 0, }, true },
183 { { 1, 2, 3, }, { 100, 100, 100, }, 150, { 100, 50, 0, }, true },
184 { { 1, 2, 3, }, { 100, 100, 100, }, 50, { 50, 0, 0, }, true },
185 { { 1, 2, 3, }, { 100, 100, 100, }, 0, { 0, 0, 0, }, true },
189 child
[0] = new wxWindow(m_win
, wxID_ANY
);
190 child
[1] = new wxWindow(m_win
, wxID_ANY
);
191 child
[2] = new wxWindow(m_win
, wxID_ANY
);
193 for ( unsigned i
= 0; i
< WXSIZEOF(layoutTestData
); i
++ )
195 LayoutTestData ltd
= layoutTestData
[i
];
197 // the results shouldn't depend on the order of items except in the
198 // case when there is not enough space for even the fixed width items
199 // (in which case the first ones might get enough of it but not the
200 // last ones) so test a couple of permutations of test data unless
201 // specifically disabled for this test case
202 for ( unsigned p
= 0; p
< 3; p
++)
207 // nothing to do, use original data
211 // exchange first and last elements
212 wxSwap(ltd
.prop
[0], ltd
.prop
[2]);
213 wxSwap(ltd
.minsize
[0], ltd
.minsize
[2]);
214 wxSwap(ltd
.sizes
[0], ltd
.sizes
[2]);
218 // exchange the original third and second elements
219 wxSwap(ltd
.prop
[0], ltd
.prop
[1]);
220 wxSwap(ltd
.minsize
[0], ltd
.minsize
[1]);
221 wxSwap(ltd
.sizes
[0], ltd
.sizes
[1]);
228 for ( j
= 0; j
< WXSIZEOF(child
); j
++ )
229 ltd
.AddToSizer(m_sizer
, child
[j
], j
);
231 m_win
->SetClientSize(ltd
.x
, -1);
234 for ( j
= 0; j
< WXSIZEOF(child
); j
++ )
236 WX_ASSERT_EQUAL_MESSAGE
239 "test %lu, permutation #%lu: wrong size for child #%d "
241 static_cast<unsigned long>(i
),
242 static_cast<unsigned long>(p
),
246 ltd
.sizes
[j
], child
[j
]->GetSize().x
250 // don't try other permutations if explicitly disabled
251 if ( ltd
.dontPermute
)
257 void BoxSizerTestCase::CalcMin()
259 static const unsigned NUM_TEST_ITEM
= 3;
261 static const struct CalcMinTestData
263 // proportions of the elements, if one of them is -1 it means to not
264 // use this window at all in this test
265 int prop
[NUM_TEST_ITEM
];
267 // minimal sizes of the elements in the sizer direction
268 int minsize
[NUM_TEST_ITEM
];
270 // the expected minimal sizer size
272 } calcMinTestData
[] =
274 { { 1, 1, -1 }, { 30, 50, 0 }, 100 },
275 { { 1, 1, 0 }, { 30, 50, 20 }, 120 },
276 { { 10, 10, -1 }, { 30, 50, 0 }, 100 },
277 { { 1, 2, 2 }, { 50, 50, 80 }, 250 },
278 { { 1, 2, 2 }, { 100, 50, 80 }, 500 },
282 wxWindow
*child
[NUM_TEST_ITEM
];
283 for ( n
= 0; n
< NUM_TEST_ITEM
; n
++ )
284 child
[n
] = new wxWindow(m_win
, wxID_ANY
);
286 for ( unsigned i
= 0; i
< WXSIZEOF(calcMinTestData
); i
++ )
290 const CalcMinTestData
& cmtd
= calcMinTestData
[i
];
291 for ( n
= 0; n
< NUM_TEST_ITEM
; n
++ )
293 if ( cmtd
.prop
[n
] != -1 )
295 child
[n
]->SetInitialSize(wxSize(cmtd
.minsize
[n
], -1));
296 m_sizer
->Add(child
[n
], wxSizerFlags(cmtd
.prop
[n
]));
300 WX_ASSERT_EQUAL_MESSAGE
303 cmtd
.total
, m_sizer
->CalcMin().x
308 void BoxSizerTestCase::BestSizeRespectsMaxSize()
312 const int maxWidth
= 100;
314 wxSizer
* sizer
= new wxBoxSizer(wxVERTICAL
);
315 wxListBox
* listbox
= new wxListBox(m_win
, wxID_ANY
);
316 listbox
->Append("some very very very very very very very very very very very long string");
317 listbox
->SetMaxSize(wxSize(maxWidth
, -1));
323 CPPUNIT_ASSERT_EQUAL(maxWidth
, listbox
->GetSize().GetWidth());
326 void BoxSizerTestCase::RecalcSizesRespectsMaxSize1()
330 const int maxWidth
= 100;
332 m_win
->SetClientSize(300, 300);
334 wxSizer
* sizer1
= new wxBoxSizer(wxVERTICAL
);
335 m_sizer
->Add(sizer1
);
337 wxListBox
* listbox1
= new wxListBox(m_win
, wxID_ANY
);
338 listbox1
->Append("some very very very very very very very very very very very long string");
339 sizer1
->Add(listbox1
);
341 wxSizer
* sizer2
= new wxBoxSizer(wxHORIZONTAL
);
342 sizer1
->Add(sizer2
, wxSizerFlags().Expand());
344 wxListBox
* listbox2
= new wxListBox(m_win
, wxID_ANY
);
345 listbox2
->Append("some string");
346 listbox2
->SetMaxSize(wxSize(100, -1));
347 sizer2
->Add(listbox2
, wxSizerFlags().Proportion(1));
351 CPPUNIT_ASSERT_EQUAL(maxWidth
, listbox2
->GetSize().GetWidth());
354 void BoxSizerTestCase::RecalcSizesRespectsMaxSize2()
358 m_win
->SetClientSize(300, 300);
360 wxSizer
* sizer1
= new wxBoxSizer(wxVERTICAL
);
361 m_sizer
->Add(sizer1
, wxSizerFlags().Expand());
363 wxWindow
* child1
= new wxWindow(m_win
, wxID_ANY
);
364 sizer1
->Add(child1
, wxSizerFlags().Proportion(1));
366 wxWindow
* child2
= new wxWindow(m_win
, wxID_ANY
);
367 child2
->SetMaxSize(wxSize(-1, 50));
368 sizer1
->Add(child2
, wxSizerFlags().Proportion(1));
370 wxWindow
* child3
= new wxWindow(m_win
, wxID_ANY
);
371 sizer1
->Add(child3
, wxSizerFlags().Proportion(1));
375 CPPUNIT_ASSERT_EQUAL(125, child1
->GetSize().GetHeight());
376 CPPUNIT_ASSERT_EQUAL(50, child2
->GetSize().GetHeight());
377 CPPUNIT_ASSERT_EQUAL(125, child3
->GetSize().GetHeight());