Remove all lines containing cvs/svn "$Id$" keyword.
[wxWidgets.git] / tests / sizers / boxsizer.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/sizers/boxsizer.cpp
3 // Purpose: Unit tests for wxBoxSizer
4 // Author: Vadim Zeitlin
5 // Created: 2010-03-06
6 // Copyright: (c) 2010 Vadim Zeitlin <vadim@wxwidgets.org>
7 ///////////////////////////////////////////////////////////////////////////////
8
9 // ----------------------------------------------------------------------------
10 // headers
11 // ----------------------------------------------------------------------------
12
13 #include "testprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #ifndef WX_PRECOMP
20 #include "wx/app.h"
21 #include "wx/sizer.h"
22 #include "wx/listbox.h"
23 #endif // WX_PRECOMP
24
25 #include "asserthelper.h"
26
27 // ----------------------------------------------------------------------------
28 // test class
29 // ----------------------------------------------------------------------------
30
31 class BoxSizerTestCase : public CppUnit::TestCase
32 {
33 public:
34 BoxSizerTestCase() { }
35
36 virtual void setUp();
37 virtual void tearDown();
38
39 private:
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();
48
49 void Size1();
50 void Size3();
51 void CalcMin();
52 void BestSizeRespectsMaxSize();
53 void RecalcSizesRespectsMaxSize1();
54 void RecalcSizesRespectsMaxSize2();
55
56 wxWindow *m_win;
57 wxSizer *m_sizer;
58
59 DECLARE_NO_COPY_CLASS(BoxSizerTestCase)
60 };
61
62 // register in the unnamed registry so that these tests are run by default
63 CPPUNIT_TEST_SUITE_REGISTRATION( BoxSizerTestCase );
64
65 // also include in its own registry so that these tests can be run alone
66 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( BoxSizerTestCase, "BoxSizerTestCase" );
67
68 // ----------------------------------------------------------------------------
69 // test initialization
70 // ----------------------------------------------------------------------------
71
72 void BoxSizerTestCase::setUp()
73 {
74 m_win = new wxWindow(wxTheApp->GetTopWindow(), wxID_ANY);
75 m_win->SetClientSize(127, 35);
76
77 m_sizer = new wxBoxSizer(wxHORIZONTAL);
78 m_win->SetSizer(m_sizer);
79 }
80
81 void BoxSizerTestCase::tearDown()
82 {
83 delete m_win;
84 m_win = NULL;
85
86 m_sizer = NULL;
87 }
88
89 // ----------------------------------------------------------------------------
90 // tests themselves
91 // ----------------------------------------------------------------------------
92
93 void BoxSizerTestCase::Size1()
94 {
95 const wxSize sizeTotal = m_win->GetClientSize();
96 const wxSize sizeChild = sizeTotal / 2;
97
98 wxWindow * const
99 child = new wxWindow(m_win, wxID_ANY, wxDefaultPosition, sizeChild);
100 m_sizer->Add(child);
101 m_win->Layout();
102 CPPUNIT_ASSERT_EQUAL( sizeChild, child->GetSize() );
103
104 m_sizer->Clear();
105 m_sizer->Add(child, wxSizerFlags(1));
106 m_win->Layout();
107 CPPUNIT_ASSERT_EQUAL( wxSize(sizeTotal.x, sizeChild.y), child->GetSize() );
108
109 m_sizer->Clear();
110 m_sizer->Add(child, wxSizerFlags(1).Expand());
111 m_win->Layout();
112 CPPUNIT_ASSERT_EQUAL( sizeTotal, child->GetSize() );
113
114 m_sizer->Clear();
115 m_sizer->Add(child, wxSizerFlags());
116 m_sizer->SetItemMinSize(child, sizeTotal*2);
117 m_win->Layout();
118 CPPUNIT_ASSERT_EQUAL( sizeTotal, child->GetSize() );
119
120 m_sizer->Clear();
121 m_sizer->Add(child, wxSizerFlags().Expand());
122 m_sizer->SetItemMinSize(child, sizeTotal*2);
123 m_win->Layout();
124 CPPUNIT_ASSERT_EQUAL( sizeTotal, child->GetSize() );
125 }
126
127 void BoxSizerTestCase::Size3()
128 {
129 // check that various combinations of minimal sizes and proportions work as
130 // expected for different window sizes
131 static const struct LayoutTestData
132 {
133 // proportions of the elements
134 int prop[3];
135
136 // minimal sizes of the elements in the sizer direction
137 int minsize[3];
138
139 // total size and the expected sizes of the elements
140 int x,
141 sizes[3];
142
143 // if true, don't try the permutations of our test data
144 bool dontPermute;
145
146
147 // Add the given window to the sizer with the corresponding parameters
148 void AddToSizer(wxSizer *sizer, wxWindow *win, int n) const
149 {
150 sizer->Add(win, wxSizerFlags(prop[n]));
151 sizer->SetItemMinSize(win, wxSize(minsize[n], -1));
152 }
153
154 } layoutTestData[] =
155 {
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 },
160
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, } },
170
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, } },
177
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 },
186 };
187
188 wxWindow *child[3];
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);
192
193 for ( unsigned i = 0; i < WXSIZEOF(layoutTestData); i++ )
194 {
195 LayoutTestData ltd = layoutTestData[i];
196
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++)
203 {
204 switch ( p )
205 {
206 case 0:
207 // nothing to do, use original data
208 break;
209
210 case 1:
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]);
215 break;
216
217 case 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]);
222 break;
223 }
224
225 m_sizer->Clear();
226
227 unsigned j;
228 for ( j = 0; j < WXSIZEOF(child); j++ )
229 ltd.AddToSizer(m_sizer, child[j], j);
230
231 m_win->SetClientSize(ltd.x, -1);
232 m_win->Layout();
233
234 for ( j = 0; j < WXSIZEOF(child); j++ )
235 {
236 WX_ASSERT_EQUAL_MESSAGE
237 (
238 (
239 "test %lu, permutation #%lu: wrong size for child #%d "
240 "for total size %d",
241 static_cast<unsigned long>(i),
242 static_cast<unsigned long>(p),
243 j,
244 ltd.x
245 ),
246 ltd.sizes[j], child[j]->GetSize().x
247 );
248 }
249
250 // don't try other permutations if explicitly disabled
251 if ( ltd.dontPermute )
252 break;
253 }
254 }
255 }
256
257 void BoxSizerTestCase::CalcMin()
258 {
259 static const unsigned NUM_TEST_ITEM = 3;
260
261 static const struct CalcMinTestData
262 {
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];
266
267 // minimal sizes of the elements in the sizer direction
268 int minsize[NUM_TEST_ITEM];
269
270 // the expected minimal sizer size
271 int total;
272 } calcMinTestData[] =
273 {
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 },
279 };
280
281 unsigned n;
282 wxWindow *child[NUM_TEST_ITEM];
283 for ( n = 0; n < NUM_TEST_ITEM; n++ )
284 child[n] = new wxWindow(m_win, wxID_ANY);
285
286 for ( unsigned i = 0; i < WXSIZEOF(calcMinTestData); i++ )
287 {
288 m_sizer->Clear();
289
290 const CalcMinTestData& cmtd = calcMinTestData[i];
291 for ( n = 0; n < NUM_TEST_ITEM; n++ )
292 {
293 if ( cmtd.prop[n] != -1 )
294 {
295 child[n]->SetInitialSize(wxSize(cmtd.minsize[n], -1));
296 m_sizer->Add(child[n], wxSizerFlags(cmtd.prop[n]));
297 }
298 }
299
300 WX_ASSERT_EQUAL_MESSAGE
301 (
302 ("In test #%u", i),
303 cmtd.total, m_sizer->CalcMin().x
304 );
305 }
306 }
307
308 void BoxSizerTestCase::BestSizeRespectsMaxSize()
309 {
310 m_sizer->Clear();
311
312 const int maxWidth = 100;
313
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));
318 sizer->Add(listbox);
319
320 m_sizer->Add(sizer);
321 m_win->Layout();
322
323 CPPUNIT_ASSERT_EQUAL(maxWidth, listbox->GetSize().GetWidth());
324 }
325
326 void BoxSizerTestCase::RecalcSizesRespectsMaxSize1()
327 {
328 m_sizer->Clear();
329
330 const int maxWidth = 100;
331
332 m_win->SetClientSize(300, 300);
333
334 wxSizer* sizer1 = new wxBoxSizer(wxVERTICAL);
335 m_sizer->Add(sizer1);
336
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);
340
341 wxSizer* sizer2 = new wxBoxSizer(wxHORIZONTAL);
342 sizer1->Add(sizer2, wxSizerFlags().Expand());
343
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));
348
349 m_win->Layout();
350
351 CPPUNIT_ASSERT_EQUAL(maxWidth, listbox2->GetSize().GetWidth());
352 }
353
354 void BoxSizerTestCase::RecalcSizesRespectsMaxSize2()
355 {
356 m_sizer->Clear();
357
358 m_win->SetClientSize(300, 300);
359
360 wxSizer* sizer1 = new wxBoxSizer(wxVERTICAL);
361 m_sizer->Add(sizer1, wxSizerFlags().Expand());
362
363 wxWindow* child1 = new wxWindow(m_win, wxID_ANY);
364 sizer1->Add(child1, wxSizerFlags().Proportion(1));
365
366 wxWindow* child2 = new wxWindow(m_win, wxID_ANY);
367 child2->SetMaxSize(wxSize(-1, 50));
368 sizer1->Add(child2, wxSizerFlags().Proportion(1));
369
370 wxWindow* child3 = new wxWindow(m_win, wxID_ANY);
371 sizer1->Add(child3, wxSizerFlags().Proportion(1));
372
373 m_win->Layout();
374
375 CPPUNIT_ASSERT_EQUAL(125, child1->GetSize().GetHeight());
376 CPPUNIT_ASSERT_EQUAL(50, child2->GetSize().GetHeight());
377 CPPUNIT_ASSERT_EQUAL(125, child3->GetSize().GetHeight());
378 }