Fix another bad format string in the testsuite.
[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 #endif // WX_PRECOMP
24
25 inline std::ostream& operator<<(std::ostream& o, const wxSize& s)
26 {
27 return o << s.x << 'x' << s.y;
28 }
29
30 // ----------------------------------------------------------------------------
31 // test class
32 // ----------------------------------------------------------------------------
33
34 class BoxSizerTestCase : public CppUnit::TestCase
35 {
36 public:
37 BoxSizerTestCase() { }
38
39 virtual void setUp();
40 virtual void tearDown();
41
42 private:
43 CPPUNIT_TEST_SUITE( BoxSizerTestCase );
44 CPPUNIT_TEST( Size1 );
45 CPPUNIT_TEST( Size3 );
46 CPPUNIT_TEST( CalcMin );
47 CPPUNIT_TEST_SUITE_END();
48
49 void Size1();
50 void Size3();
51 void CalcMin();
52
53 wxWindow *m_win;
54 wxSizer *m_sizer;
55
56 DECLARE_NO_COPY_CLASS(BoxSizerTestCase)
57 };
58
59 // register in the unnamed registry so that these tests are run by default
60 CPPUNIT_TEST_SUITE_REGISTRATION( BoxSizerTestCase );
61
62 // also include in it's own registry so that these tests can be run alone
63 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( BoxSizerTestCase, "BoxSizerTestCase" );
64
65 // ----------------------------------------------------------------------------
66 // test initialization
67 // ----------------------------------------------------------------------------
68
69 void BoxSizerTestCase::setUp()
70 {
71 m_win = new wxWindow(wxTheApp->GetTopWindow(), wxID_ANY);
72 m_win->SetClientSize(127, 35);
73
74 m_sizer = new wxBoxSizer(wxHORIZONTAL);
75 m_win->SetSizer(m_sizer);
76 }
77
78 void BoxSizerTestCase::tearDown()
79 {
80 delete m_win;
81 m_win = NULL;
82
83 m_sizer = NULL;
84 }
85
86 // ----------------------------------------------------------------------------
87 // tests themselves
88 // ----------------------------------------------------------------------------
89
90 void BoxSizerTestCase::Size1()
91 {
92 const wxSize sizeTotal = m_win->GetClientSize();
93 const wxSize sizeChild = sizeTotal / 2;
94
95 wxWindow * const
96 child = new wxWindow(m_win, wxID_ANY, wxDefaultPosition, sizeChild);
97 m_sizer->Add(child);
98 m_win->Layout();
99 CPPUNIT_ASSERT_EQUAL( sizeChild, child->GetSize() );
100
101 m_sizer->Clear();
102 m_sizer->Add(child, wxSizerFlags(1));
103 m_win->Layout();
104 CPPUNIT_ASSERT_EQUAL( wxSize(sizeTotal.x, sizeChild.y), child->GetSize() );
105
106 m_sizer->Clear();
107 m_sizer->Add(child, wxSizerFlags(1).Expand());
108 m_win->Layout();
109 CPPUNIT_ASSERT_EQUAL( sizeTotal, child->GetSize() );
110
111 m_sizer->Clear();
112 m_sizer->Add(child, wxSizerFlags());
113 m_sizer->SetItemMinSize(child, sizeTotal*2);
114 m_win->Layout();
115 CPPUNIT_ASSERT_EQUAL( sizeTotal, child->GetSize() );
116
117 m_sizer->Clear();
118 m_sizer->Add(child, wxSizerFlags().Expand());
119 m_sizer->SetItemMinSize(child, sizeTotal*2);
120 m_win->Layout();
121 CPPUNIT_ASSERT_EQUAL( sizeTotal, child->GetSize() );
122 }
123
124 void BoxSizerTestCase::Size3()
125 {
126 // check that various combinations of minimal sizes and proportions work as
127 // expected for different window sizes
128 static const struct LayoutTestData
129 {
130 // proportions of the elements
131 int prop[3];
132
133 // minimal sizes of the elements in the sizer direction
134 int minsize[3];
135
136 // total size and the expected sizes of the elements
137 int x,
138 sizes[3];
139
140 // if true, don't try the permutations of our test data
141 bool dontPermute;
142
143
144 // Add the given window to the sizer with the corresponding parameters
145 void AddToSizer(wxSizer *sizer, wxWindow *win, int n) const
146 {
147 sizer->Add(win, wxSizerFlags(prop[n]));
148 sizer->SetItemMinSize(win, wxSize(minsize[n], -1));
149 }
150
151 } layoutTestData[] =
152 {
153 // some really simple cases (no need to permute those, they're
154 // symmetrical anyhow)
155 { { 1, 1, 1, }, { 50, 50, 50, }, 150, { 50, 50, 50, }, true },
156 { { 2, 2, 2, }, { 50, 50, 50, }, 600, { 200, 200, 200, }, true },
157
158 // items with different proportions and min sizes when there is enough
159 // space to lay them out
160 { { 1, 2, 3, }, { 0, 0, 0, }, 600, { 100, 200, 300, } },
161 { { 1, 2, 3, }, { 100, 100, 100, }, 600, { 100, 200, 300, } },
162 { { 1, 2, 3, }, { 100, 50, 50, }, 600, { 100, 200, 300, } },
163 { { 0, 1, 1, }, { 200, 100, 100, }, 600, { 200, 200, 200, } },
164 { { 0, 1, 2, }, { 300, 100, 100, }, 600, { 300, 100, 200, } },
165 { { 0, 1, 1, }, { 100, 50, 50, }, 300, { 100, 100, 100, } },
166 { { 0, 1, 2, }, { 100, 50, 50, }, 400, { 100, 100, 200, } },
167
168 // cases when there is not enough space to lay out the items correctly
169 // while still respecting their min sizes
170 { { 0, 1, 1, }, { 100, 150, 50, }, 300, { 100, 150, 50, } },
171 { { 1, 2, 3, }, { 100, 100, 100, }, 300, { 100, 100, 100, } },
172 { { 1, 2, 3, }, { 100, 50, 50, }, 300, { 100, 80, 120, } },
173 { { 1, 2, 3, }, { 100, 10, 10, }, 150, { 100, 20, 30, } },
174
175 // cases when there is not enough space even for the min sizes (don't
176 // permute in these cases as the layout does depend on the item order
177 // because the first ones have priority)
178 { { 1, 2, 3, }, { 100, 50, 50, }, 150, { 100, 50, 0, }, true },
179 { { 1, 2, 3, }, { 100, 100, 100, }, 200, { 100, 100, 0, }, true },
180 { { 1, 2, 3, }, { 100, 100, 100, }, 150, { 100, 50, 0, }, true },
181 { { 1, 2, 3, }, { 100, 100, 100, }, 50, { 50, 0, 0, }, true },
182 { { 1, 2, 3, }, { 100, 100, 100, }, 0, { 0, 0, 0, }, true },
183 };
184
185 wxWindow *child[3];
186 child[0] = new wxWindow(m_win, wxID_ANY);
187 child[1] = new wxWindow(m_win, wxID_ANY);
188 child[2] = new wxWindow(m_win, wxID_ANY);
189
190 for ( unsigned i = 0; i < WXSIZEOF(layoutTestData); i++ )
191 {
192 LayoutTestData ltd = layoutTestData[i];
193
194 // the results shouldn't depend on the order of items except in the
195 // case when there is not enough space for even the fixed width items
196 // (in which case the first ones might get enough of it but not the
197 // last ones) so test a couple of permutations of test data unless
198 // specifically disabled for this test case
199 for ( unsigned p = 0; p < 3; p++)
200 {
201 switch ( p )
202 {
203 case 0:
204 // nothing to do, use original data
205 break;
206
207 case 1:
208 // exchange first and last elements
209 wxSwap(ltd.prop[0], ltd.prop[2]);
210 wxSwap(ltd.minsize[0], ltd.minsize[2]);
211 wxSwap(ltd.sizes[0], ltd.sizes[2]);
212 break;
213
214 case 2:
215 // exchange the original third and second elements
216 wxSwap(ltd.prop[0], ltd.prop[1]);
217 wxSwap(ltd.minsize[0], ltd.minsize[1]);
218 wxSwap(ltd.sizes[0], ltd.sizes[1]);
219 break;
220 }
221
222 m_sizer->Clear();
223
224 unsigned j;
225 for ( j = 0; j < WXSIZEOF(child); j++ )
226 ltd.AddToSizer(m_sizer, child[j], j);
227
228 m_win->SetClientSize(ltd.x, -1);
229 m_win->Layout();
230
231 for ( j = 0; j < WXSIZEOF(child); j++ )
232 {
233 WX_ASSERT_EQUAL_MESSAGE
234 (
235 (
236 "test %lu, permutation #%lu: wrong size for child #%d "
237 "for total size %d",
238 static_cast<unsigned long>(i),
239 static_cast<unsigned long>(p),
240 j,
241 ltd.x
242 ),
243 ltd.sizes[j], child[j]->GetSize().x
244 );
245 }
246
247 // don't try other permutations if explicitly disabled
248 if ( ltd.dontPermute )
249 break;
250 }
251 }
252 }
253
254 void BoxSizerTestCase::CalcMin()
255 {
256 static const unsigned NUM_TEST_ITEM = 3;
257
258 static const struct CalcMinTestData
259 {
260 // proportions of the elements, if one of them is -1 it means to not
261 // use this window at all in this test
262 int prop[NUM_TEST_ITEM];
263
264 // minimal sizes of the elements in the sizer direction
265 int minsize[NUM_TEST_ITEM];
266
267 // the expected minimal sizer size
268 int total;
269 } calcMinTestData[] =
270 {
271 { { 1, 1, -1 }, { 30, 50, 0 }, 100 },
272 { { 1, 1, 0 }, { 30, 50, 20 }, 120 },
273 { { 10, 10, -1 }, { 30, 50, 0 }, 100 },
274 { { 1, 2, 2 }, { 50, 50, 80 }, 250 },
275 { { 1, 2, 2 }, { 100, 50, 80 }, 500 },
276 };
277
278 unsigned n;
279 wxWindow *child[NUM_TEST_ITEM];
280 for ( n = 0; n < NUM_TEST_ITEM; n++ )
281 child[n] = new wxWindow(m_win, wxID_ANY);
282
283 for ( unsigned i = 0; i < WXSIZEOF(calcMinTestData); i++ )
284 {
285 m_sizer->Clear();
286
287 const CalcMinTestData& cmtd = calcMinTestData[i];
288 for ( n = 0; n < NUM_TEST_ITEM; n++ )
289 {
290 if ( cmtd.prop[n] != -1 )
291 {
292 child[n]->SetInitialSize(wxSize(cmtd.minsize[n], -1));
293 m_sizer->Add(child[n], wxSizerFlags(cmtd.prop[n]));
294 }
295 }
296
297 WX_ASSERT_EQUAL_MESSAGE
298 (
299 ("In test #%u", i),
300 cmtd.total, m_sizer->CalcMin().x
301 );
302 }
303 }