1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/sizers/boxsizer.cpp
3 // Purpose: Unit tests for wxBoxSizer
4 // Author: Vadim Zeitlin
7 // Copyright: (c) 2010 Vadim Zeitlin <vadim@wxwidgets.org>
8 ///////////////////////////////////////////////////////////////////////////////
10 // ----------------------------------------------------------------------------
12 // ----------------------------------------------------------------------------
23 #include "wx/listbox.h"
26 #include "asserthelper.h"
28 // ----------------------------------------------------------------------------
30 // ----------------------------------------------------------------------------
32 class BoxSizerTestCase
: public CppUnit::TestCase
35 BoxSizerTestCase() { }
38 virtual void tearDown();
41 CPPUNIT_TEST_SUITE( BoxSizerTestCase
);
42 CPPUNIT_TEST( Size1
);
43 CPPUNIT_TEST( Size3
);
44 CPPUNIT_TEST( CalcMin
);
45 CPPUNIT_TEST( BestSizeRespectsMaxSize
);
46 CPPUNIT_TEST( RecalcSizesRespectsMaxSize1
);
47 CPPUNIT_TEST( RecalcSizesRespectsMaxSize2
);
48 CPPUNIT_TEST_SUITE_END();
53 void BestSizeRespectsMaxSize();
54 void RecalcSizesRespectsMaxSize1();
55 void RecalcSizesRespectsMaxSize2();
60 DECLARE_NO_COPY_CLASS(BoxSizerTestCase
)
63 // register in the unnamed registry so that these tests are run by default
64 CPPUNIT_TEST_SUITE_REGISTRATION( BoxSizerTestCase
);
66 // also include in its own registry so that these tests can be run alone
67 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( BoxSizerTestCase
, "BoxSizerTestCase" );
69 // ----------------------------------------------------------------------------
70 // test initialization
71 // ----------------------------------------------------------------------------
73 void BoxSizerTestCase::setUp()
75 m_win
= new wxWindow(wxTheApp
->GetTopWindow(), wxID_ANY
);
76 m_win
->SetClientSize(127, 35);
78 m_sizer
= new wxBoxSizer(wxHORIZONTAL
);
79 m_win
->SetSizer(m_sizer
);
82 void BoxSizerTestCase::tearDown()
90 // ----------------------------------------------------------------------------
92 // ----------------------------------------------------------------------------
94 void BoxSizerTestCase::Size1()
96 const wxSize sizeTotal
= m_win
->GetClientSize();
97 const wxSize sizeChild
= sizeTotal
/ 2;
100 child
= new wxWindow(m_win
, wxID_ANY
, wxDefaultPosition
, sizeChild
);
103 CPPUNIT_ASSERT_EQUAL( sizeChild
, child
->GetSize() );
106 m_sizer
->Add(child
, wxSizerFlags(1));
108 CPPUNIT_ASSERT_EQUAL( wxSize(sizeTotal
.x
, sizeChild
.y
), child
->GetSize() );
111 m_sizer
->Add(child
, wxSizerFlags(1).Expand());
113 CPPUNIT_ASSERT_EQUAL( sizeTotal
, child
->GetSize() );
116 m_sizer
->Add(child
, wxSizerFlags());
117 m_sizer
->SetItemMinSize(child
, sizeTotal
*2);
119 CPPUNIT_ASSERT_EQUAL( sizeTotal
, child
->GetSize() );
122 m_sizer
->Add(child
, wxSizerFlags().Expand());
123 m_sizer
->SetItemMinSize(child
, sizeTotal
*2);
125 CPPUNIT_ASSERT_EQUAL( sizeTotal
, child
->GetSize() );
128 void BoxSizerTestCase::Size3()
130 // check that various combinations of minimal sizes and proportions work as
131 // expected for different window sizes
132 static const struct LayoutTestData
134 // proportions of the elements
137 // minimal sizes of the elements in the sizer direction
140 // total size and the expected sizes of the elements
144 // if true, don't try the permutations of our test data
148 // Add the given window to the sizer with the corresponding parameters
149 void AddToSizer(wxSizer
*sizer
, wxWindow
*win
, int n
) const
151 sizer
->Add(win
, wxSizerFlags(prop
[n
]));
152 sizer
->SetItemMinSize(win
, wxSize(minsize
[n
], -1));
157 // some really simple cases (no need to permute those, they're
158 // symmetrical anyhow)
159 { { 1, 1, 1, }, { 50, 50, 50, }, 150, { 50, 50, 50, }, true },
160 { { 2, 2, 2, }, { 50, 50, 50, }, 600, { 200, 200, 200, }, true },
162 // items with different proportions and min sizes when there is enough
163 // space to lay them out
164 { { 1, 2, 3, }, { 0, 0, 0, }, 600, { 100, 200, 300, } },
165 { { 1, 2, 3, }, { 100, 100, 100, }, 600, { 100, 200, 300, } },
166 { { 1, 2, 3, }, { 100, 50, 50, }, 600, { 100, 200, 300, } },
167 { { 0, 1, 1, }, { 200, 100, 100, }, 600, { 200, 200, 200, } },
168 { { 0, 1, 2, }, { 300, 100, 100, }, 600, { 300, 100, 200, } },
169 { { 0, 1, 1, }, { 100, 50, 50, }, 300, { 100, 100, 100, } },
170 { { 0, 1, 2, }, { 100, 50, 50, }, 400, { 100, 100, 200, } },
172 // cases when there is not enough space to lay out the items correctly
173 // while still respecting their min sizes
174 { { 0, 1, 1, }, { 100, 150, 50, }, 300, { 100, 150, 50, } },
175 { { 1, 2, 3, }, { 100, 100, 100, }, 300, { 100, 100, 100, } },
176 { { 1, 2, 3, }, { 100, 50, 50, }, 300, { 100, 80, 120, } },
177 { { 1, 2, 3, }, { 100, 10, 10, }, 150, { 100, 20, 30, } },
179 // cases when there is not enough space even for the min sizes (don't
180 // permute in these cases as the layout does depend on the item order
181 // because the first ones have priority)
182 { { 1, 2, 3, }, { 100, 50, 50, }, 150, { 100, 50, 0, }, true },
183 { { 1, 2, 3, }, { 100, 100, 100, }, 200, { 100, 100, 0, }, true },
184 { { 1, 2, 3, }, { 100, 100, 100, }, 150, { 100, 50, 0, }, true },
185 { { 1, 2, 3, }, { 100, 100, 100, }, 50, { 50, 0, 0, }, true },
186 { { 1, 2, 3, }, { 100, 100, 100, }, 0, { 0, 0, 0, }, true },
190 child
[0] = new wxWindow(m_win
, wxID_ANY
);
191 child
[1] = new wxWindow(m_win
, wxID_ANY
);
192 child
[2] = new wxWindow(m_win
, wxID_ANY
);
194 for ( unsigned i
= 0; i
< WXSIZEOF(layoutTestData
); i
++ )
196 LayoutTestData ltd
= layoutTestData
[i
];
198 // the results shouldn't depend on the order of items except in the
199 // case when there is not enough space for even the fixed width items
200 // (in which case the first ones might get enough of it but not the
201 // last ones) so test a couple of permutations of test data unless
202 // specifically disabled for this test case
203 for ( unsigned p
= 0; p
< 3; p
++)
208 // nothing to do, use original data
212 // exchange first and last elements
213 wxSwap(ltd
.prop
[0], ltd
.prop
[2]);
214 wxSwap(ltd
.minsize
[0], ltd
.minsize
[2]);
215 wxSwap(ltd
.sizes
[0], ltd
.sizes
[2]);
219 // exchange the original third and second elements
220 wxSwap(ltd
.prop
[0], ltd
.prop
[1]);
221 wxSwap(ltd
.minsize
[0], ltd
.minsize
[1]);
222 wxSwap(ltd
.sizes
[0], ltd
.sizes
[1]);
229 for ( j
= 0; j
< WXSIZEOF(child
); j
++ )
230 ltd
.AddToSizer(m_sizer
, child
[j
], j
);
232 m_win
->SetClientSize(ltd
.x
, -1);
235 for ( j
= 0; j
< WXSIZEOF(child
); j
++ )
237 WX_ASSERT_EQUAL_MESSAGE
240 "test %lu, permutation #%lu: wrong size for child #%d "
242 static_cast<unsigned long>(i
),
243 static_cast<unsigned long>(p
),
247 ltd
.sizes
[j
], child
[j
]->GetSize().x
251 // don't try other permutations if explicitly disabled
252 if ( ltd
.dontPermute
)
258 void BoxSizerTestCase::CalcMin()
260 static const unsigned NUM_TEST_ITEM
= 3;
262 static const struct CalcMinTestData
264 // proportions of the elements, if one of them is -1 it means to not
265 // use this window at all in this test
266 int prop
[NUM_TEST_ITEM
];
268 // minimal sizes of the elements in the sizer direction
269 int minsize
[NUM_TEST_ITEM
];
271 // the expected minimal sizer size
273 } calcMinTestData
[] =
275 { { 1, 1, -1 }, { 30, 50, 0 }, 100 },
276 { { 1, 1, 0 }, { 30, 50, 20 }, 120 },
277 { { 10, 10, -1 }, { 30, 50, 0 }, 100 },
278 { { 1, 2, 2 }, { 50, 50, 80 }, 250 },
279 { { 1, 2, 2 }, { 100, 50, 80 }, 500 },
283 wxWindow
*child
[NUM_TEST_ITEM
];
284 for ( n
= 0; n
< NUM_TEST_ITEM
; n
++ )
285 child
[n
] = new wxWindow(m_win
, wxID_ANY
);
287 for ( unsigned i
= 0; i
< WXSIZEOF(calcMinTestData
); i
++ )
291 const CalcMinTestData
& cmtd
= calcMinTestData
[i
];
292 for ( n
= 0; n
< NUM_TEST_ITEM
; n
++ )
294 if ( cmtd
.prop
[n
] != -1 )
296 child
[n
]->SetInitialSize(wxSize(cmtd
.minsize
[n
], -1));
297 m_sizer
->Add(child
[n
], wxSizerFlags(cmtd
.prop
[n
]));
301 WX_ASSERT_EQUAL_MESSAGE
304 cmtd
.total
, m_sizer
->CalcMin().x
309 void BoxSizerTestCase::BestSizeRespectsMaxSize()
313 const int maxWidth
= 100;
315 wxSizer
* sizer
= new wxBoxSizer(wxVERTICAL
);
316 wxListBox
* listbox
= new wxListBox(m_win
, wxID_ANY
);
317 listbox
->Append("some very very very very very very very very very very very long string");
318 listbox
->SetMaxSize(wxSize(maxWidth
, -1));
324 CPPUNIT_ASSERT_EQUAL(maxWidth
, listbox
->GetSize().GetWidth());
327 void BoxSizerTestCase::RecalcSizesRespectsMaxSize1()
331 const int maxWidth
= 100;
333 m_win
->SetClientSize(300, 300);
335 wxSizer
* sizer1
= new wxBoxSizer(wxVERTICAL
);
336 m_sizer
->Add(sizer1
);
338 wxListBox
* listbox1
= new wxListBox(m_win
, wxID_ANY
);
339 listbox1
->Append("some very very very very very very very very very very very long string");
340 sizer1
->Add(listbox1
);
342 wxSizer
* sizer2
= new wxBoxSizer(wxHORIZONTAL
);
343 sizer1
->Add(sizer2
, wxSizerFlags().Expand());
345 wxListBox
* listbox2
= new wxListBox(m_win
, wxID_ANY
);
346 listbox2
->Append("some string");
347 listbox2
->SetMaxSize(wxSize(100, -1));
348 sizer2
->Add(listbox2
, wxSizerFlags().Proportion(1));
352 CPPUNIT_ASSERT_EQUAL(maxWidth
, listbox2
->GetSize().GetWidth());
355 void BoxSizerTestCase::RecalcSizesRespectsMaxSize2()
359 m_win
->SetClientSize(300, 300);
361 wxSizer
* sizer1
= new wxBoxSizer(wxVERTICAL
);
362 m_sizer
->Add(sizer1
, wxSizerFlags().Expand());
364 wxWindow
* child1
= new wxWindow(m_win
, wxID_ANY
);
365 sizer1
->Add(child1
, wxSizerFlags().Proportion(1));
367 wxWindow
* child2
= new wxWindow(m_win
, wxID_ANY
);
368 child2
->SetMaxSize(wxSize(-1, 50));
369 sizer1
->Add(child2
, wxSizerFlags().Proportion(1));
371 wxWindow
* child3
= new wxWindow(m_win
, wxID_ANY
);
372 sizer1
->Add(child3
, wxSizerFlags().Proportion(1));
376 CPPUNIT_ASSERT_EQUAL(125, child1
->GetSize().GetHeight());
377 CPPUNIT_ASSERT_EQUAL(50, child2
->GetSize().GetHeight());
378 CPPUNIT_ASSERT_EQUAL(125, child3
->GetSize().GetHeight());