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