]> git.saurik.com Git - wxWidgets.git/blob - src/common/sizer.cpp
Added wxStaticBoxSizer,
[wxWidgets.git] / src / common / sizer.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: sizer.cpp
3 // Purpose: provide new wxSizer class for layounting
4 // Author: Robert Roebling and Robin Dunn
5 // Modified by:
6 // Created:
7 // RCS-ID: $Id$
8 // Copyright: (c) Robin Dunn, Dirk Holtwick and Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "sizer.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #include "wx/sizer.h"
24 #include "wx/utils.h"
25 #include "wx/statbox.h"
26
27 //---------------------------------------------------------------------------
28 // wxSizerItem
29 //---------------------------------------------------------------------------
30
31 wxSizerItem::wxSizerItem( int width, int height, int option, int flag, int border )
32 {
33 m_window = (wxWindow *) NULL;
34 m_sizer = (wxSizer *) NULL;
35 m_option = option;
36 m_border = border;
37 m_flag = flag;
38
39 // minimal size is the initial size
40 m_minSize.x = width;
41 m_minSize.y = height;
42
43 // size is set directly
44 m_size = m_minSize;
45 }
46
47 wxSizerItem::wxSizerItem( wxWindow *window, int option, int flag, int border )
48 {
49 m_window = window;
50 m_sizer = (wxSizer *) NULL;
51 m_option = option;
52 m_border = border;
53 m_flag = flag;
54
55 // minimal size is the initial size
56 m_minSize = window->GetSize();
57
58 // size is calculated later
59 // m_size = ...
60 }
61
62 wxSizerItem::wxSizerItem( wxSizer *sizer, int option, int flag, int border )
63 {
64 m_window = (wxWindow *) NULL;
65 m_sizer = sizer;
66 m_option = option;
67 m_border = border;
68 m_flag = flag;
69
70 // minimal size is calculated later
71 // m_minSize = ...
72
73 // size is calculated later
74 // m_size = ...
75 }
76
77 wxSize wxSizerItem::GetSize()
78 {
79 wxSize ret;
80 if (IsSizer())
81 ret = m_sizer->GetSize();
82 else
83 if (IsWindow())
84 ret = m_window->GetSize();
85 else ret = m_size;
86
87 if (m_flag & wxWEST)
88 ret.x += m_border;
89 if (m_flag & wxEAST)
90 ret.x += m_border;
91 if (m_flag & wxNORTH)
92 ret.y += m_border;
93 if (m_flag & wxSOUTH)
94 ret.y += m_border;
95
96 return ret;
97 }
98
99 wxSize wxSizerItem::CalcMin()
100 {
101 wxSize ret;
102 if (IsSizer())
103 ret = m_sizer->CalcMin();
104 /*
105 The minimum size of a window should be the
106 initial size, as saved in m_minSize, not the
107 current size.
108
109 else
110 if (IsWindow())
111 ret = m_window->GetSize();
112 */
113 else ret = m_minSize;
114
115 if (m_flag & wxWEST)
116 ret.x += m_border;
117 if (m_flag & wxEAST)
118 ret.x += m_border;
119 if (m_flag & wxNORTH)
120 ret.y += m_border;
121 if (m_flag & wxSOUTH)
122 ret.y += m_border;
123
124 return ret;
125 }
126
127 void wxSizerItem::SetDimension( wxPoint pos, wxSize size )
128 {
129 if (m_flag & wxWEST)
130 {
131 pos.x += m_border;
132 size.x -= m_border;
133 }
134 if (m_flag & wxEAST)
135 {
136 size.x -= m_border;
137 }
138 if (m_flag & wxNORTH)
139 {
140 pos.y += m_border;
141 size.y -= m_border;
142 }
143 if (m_flag & wxSOUTH)
144 {
145 size.y -= m_border;
146 }
147
148 if (IsSizer())
149 m_sizer->SetDimension( pos.x, pos.y, size.x, size.y );
150
151 if (IsWindow())
152 m_window->SetSize( pos.x, pos.y, size.x, size.y );
153
154 m_size = size;
155 }
156
157 bool wxSizerItem::IsWindow()
158 {
159 return (m_window != NULL);
160 }
161
162 bool wxSizerItem::IsSizer()
163 {
164 return (m_sizer != NULL);
165 }
166
167 bool wxSizerItem::IsSpacer()
168 {
169 return (m_window == NULL) && (m_sizer == NULL);
170 }
171
172 //---------------------------------------------------------------------------
173 // wxSizer
174 //---------------------------------------------------------------------------
175
176 wxSizer::wxSizer()
177 {
178 m_children.DeleteContents( TRUE );
179 }
180
181 wxSizer::~wxSizer()
182 {
183 }
184
185 void wxSizer::Add( wxWindow *window, int option, int flag, int border )
186 {
187 m_children.Append( new wxSizerItem( window, option, flag, border ) );
188 }
189
190 void wxSizer::Add( wxSizer *sizer, int option, int flag, int border )
191 {
192 m_children.Append( new wxSizerItem( sizer, option, flag, border ) );
193 }
194
195 void wxSizer::Add( int width, int height, int option, int flag, int border )
196 {
197 m_children.Append( new wxSizerItem( width, height, option, flag, border ) );
198 }
199
200 void wxSizer::Fit( wxWindow *window )
201 {
202 window->SetSize( GetMinWindowSize( window ) );
203 }
204
205 void wxSizer::Layout()
206 {
207 m_size = CalcMin();
208 RecalcSizes();
209 }
210
211 void wxSizer::SetSizeHints( wxWindow *window )
212 {
213 wxSize size( GetMinWindowSize( window ) );
214 window->SetSizeHints( size.x, size.y );
215 }
216
217 wxSize wxSizer::GetMinWindowSize( wxWindow *window )
218 {
219 wxSize minSize( GetMinSize() );
220 wxSize size( window->GetSize() );
221 wxSize client_size( window->GetClientSize() );
222 return wxSize( minSize.x+size.x-client_size.x,
223 minSize.y+size.y-client_size.y );
224 }
225
226 void wxSizer::SetDimension( int x, int y, int width, int height )
227 {
228 m_position.x = x;
229 m_position.y = y;
230 m_size.x = width;
231 m_size.y = height;
232 RecalcSizes();
233 }
234
235 //---------------------------------------------------------------------------
236 // wxBoxSizer
237 //---------------------------------------------------------------------------
238
239 wxBoxSizer::wxBoxSizer( int orient )
240 {
241 m_orient = orient;
242 }
243
244 void wxBoxSizer::RecalcSizes()
245 {
246 if (m_children.GetCount() == 0)
247 {
248 SetDimension( m_position.x, m_position.y, 2, 2 );
249 return;
250 }
251
252 int delta = 0;
253 int extra = 0;
254 if (m_stretchable)
255 {
256 if (m_orient == wxHORIZONTAL)
257 {
258 delta = (m_size.x - m_fixedWidth) / m_stretchable;
259 extra = (m_size.x - m_fixedWidth) % m_stretchable;
260 }
261 else
262 {
263 delta = (m_size.y - m_fixedHeight) / m_stretchable;
264 extra = (m_size.y - m_fixedHeight) % m_stretchable;
265 }
266 }
267
268 wxPoint pt( m_position );
269
270 wxNode *node = m_children.GetFirst();
271 while (node)
272 {
273 wxSizerItem *item = (wxSizerItem*) node->Data();
274
275 int weight = 1;
276 if (item->GetOption())
277 weight = item->GetOption();
278
279 wxSize size( item->CalcMin() );
280
281 if (m_orient == wxVERTICAL)
282 {
283 long height = size.y;
284 if (item->GetOption())
285 {
286 height = (delta * weight) + extra;
287 extra = 0; // only the first item will get the remainder as extra size
288 }
289
290 wxPoint child_pos( pt );
291 wxSize child_size( wxSize( size.x, height) );
292
293 if (item->GetFlag() & wxALIGN_RIGHT)
294 child_pos.x += m_size.x - size.x;
295 else if (item->GetFlag() & wxCENTER)
296 child_pos.x += (m_size.x - size.x) / 2;
297 else if (item->GetFlag() & wxEXPAND)
298 child_size.x = m_size.x;
299
300 item->SetDimension( child_pos, child_size );
301
302 pt.y += height;
303 }
304 else
305 {
306 long width = size.x;
307 if (item->GetOption())
308 {
309 width = (delta * weight) + extra;
310 extra = 0; // only the first item will get the remainder as extra size
311 }
312
313 wxPoint child_pos( pt );
314 wxSize child_size( wxSize(width, size.y) );
315
316 if (item->GetFlag() & wxALIGN_BOTTOM)
317 child_pos.y += m_size.y - size.y;
318 else if (item->GetFlag() & wxCENTER)
319 child_pos.y += (m_size.y - size.y) / 2;
320 else if (item->GetFlag() & wxEXPAND)
321 child_size.y = m_size.y;
322
323 item->SetDimension( child_pos, child_size );
324
325 pt.x += width;
326 }
327
328 node = node->Next();
329 }
330 }
331
332 wxSize wxBoxSizer::CalcMin()
333 {
334 if (m_children.GetCount() == 0)
335 return wxSize(2,2);
336
337 m_stretchable = 0;
338 m_minWidth = 0;
339 m_minHeight = 0;
340 m_fixedWidth = 0;
341 m_fixedHeight = 0;
342
343 wxNode *node = m_children.GetFirst();
344 while (node)
345 {
346 wxSizerItem *item = (wxSizerItem*) node->Data();
347
348 int weight = 1;
349 if (item->GetOption())
350 weight = item->GetOption();
351
352 wxSize size( item->CalcMin() );
353
354 if (m_orient == wxHORIZONTAL)
355 {
356 m_minWidth += (size.x * weight);
357 m_minHeight = wxMax( m_minHeight, size.y );
358 }
359 else
360 {
361 m_minHeight += (size.y * weight);
362 m_minWidth = wxMax( m_minWidth, size.x );
363 }
364
365 if (item->GetOption())
366 {
367 m_stretchable += weight;
368 }
369 else
370 {
371 if (m_orient == wxVERTICAL)
372 {
373 m_fixedHeight += size.y;
374 m_fixedWidth = wxMax( m_fixedWidth, size.x );
375 }
376 else
377 {
378 m_fixedWidth += size.x;
379 m_fixedHeight = wxMax( m_fixedHeight, size.y );
380 }
381 }
382
383 node = node->Next();
384 }
385
386 return wxSize( m_minWidth, m_minHeight );
387 }
388
389 //---------------------------------------------------------------------------
390 // wxStaticBoxSizer
391 //---------------------------------------------------------------------------
392
393 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
394 : wxBoxSizer( orient )
395 {
396 wxASSERT_MSG( box, _T("wxStaticBoxSizer needs a static box") );
397
398 m_staticBox = box;
399 }
400
401 void wxStaticBoxSizer::RecalcSizes()
402 {
403 // this will have to be done platform by platform
404 // as there is no way to guess the thickness of
405 // a wxStaticBox border
406 int top_border = 15;
407 if (m_staticBox->GetLabel().IsEmpty()) top_border = 5;
408 int other_border = 5;
409
410 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
411
412 wxPoint old_pos( m_position );
413 m_position.x += other_border;
414 m_position.y += top_border;
415 wxSize old_size( m_size );
416 m_size.x -= 2*other_border;
417 m_size.y -= top_border + other_border;
418
419 wxBoxSizer::RecalcSizes();
420
421 m_position = old_pos;
422 m_size = old_size;
423 }
424
425 wxSize wxStaticBoxSizer::CalcMin()
426 {
427 // this will have to be done platform by platform
428 // as there is no way to guess the thickness of
429 // a wxStaticBox border
430 int top_border = 15;
431 if (m_staticBox->GetLabel().IsEmpty()) top_border = 5;
432 int other_border = 5;
433
434 wxSize ret( wxBoxSizer::CalcMin() );
435 ret.x += 2*top_border;
436 ret.y += other_border + top_border;
437
438 return ret;
439 }