]> git.saurik.com Git - wxWidgets.git/blame - src/common/sizer.cpp
serbase.cpp added to the list of files
[wxWidgets.git] / src / common / sizer.cpp
CommitLineData
5279a24d
RR
1/////////////////////////////////////////////////////////////////////////////
2// Name: sizer.cpp
1044a386 3// Purpose: provide new wxSizer class for layout
5279a24d
RR
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
5279a24d 12#ifdef __GNUG__
c62ac5b6 13#pragma implementation "sizer.h"
5279a24d
RR
14#endif
15
77671fd2
VZ
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20 #pragma hdrstop
21#endif
22
5279a24d 23#include "wx/sizer.h"
61d514bb 24#include "wx/utils.h"
27ea1d8a 25#include "wx/statbox.h"
5279a24d
RR
26
27//---------------------------------------------------------------------------
3417c2cd 28// wxSizerItem
5279a24d
RR
29//---------------------------------------------------------------------------
30
3417c2cd 31wxSizerItem::wxSizerItem( int width, int height, int option, int flag, int border )
5279a24d
RR
32{
33 m_window = (wxWindow *) NULL;
3417c2cd 34 m_sizer = (wxSizer *) NULL;
d597fcb7
RR
35 m_option = option;
36 m_border = border;
37 m_flag = flag;
38
39 // minimal size is the initial size
5279a24d 40 m_minSize.x = width;
c62ac5b6 41 m_minSize.y = height;
d597fcb7
RR
42
43 // size is set directly
44 m_size = m_minSize;
5279a24d
RR
45}
46
3417c2cd 47wxSizerItem::wxSizerItem( wxWindow *window, int option, int flag, int border )
5279a24d
RR
48{
49 m_window = window;
3417c2cd 50 m_sizer = (wxSizer *) NULL;
5279a24d 51 m_option = option;
d597fcb7
RR
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 = ...
5279a24d
RR
60}
61
3417c2cd 62wxSizerItem::wxSizerItem( wxSizer *sizer, int option, int flag, int border )
5279a24d
RR
63{
64 m_window = (wxWindow *) NULL;
65 m_sizer = sizer;
5279a24d 66 m_option = option;
d597fcb7
RR
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 = ...
5279a24d
RR
75}
76
3417c2cd 77wxSize wxSizerItem::GetSize()
5279a24d 78{
d597fcb7 79 wxSize ret;
3417c2cd 80 if (IsSizer())
d597fcb7
RR
81 ret = m_sizer->GetSize();
82 else
c62ac5b6 83 if (IsWindow())
d597fcb7
RR
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;
5279a24d
RR
97}
98
3417c2cd 99wxSize wxSizerItem::CalcMin()
c62ac5b6 100{
d597fcb7 101 wxSize ret;
3417c2cd 102 if (IsSizer())
d597fcb7
RR
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
c62ac5b6 110 if (IsWindow())
d597fcb7
RR
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;
c62ac5b6
RR
125}
126
3417c2cd 127void wxSizerItem::SetDimension( wxPoint pos, wxSize size )
c62ac5b6 128{
d597fcb7
RR
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
3417c2cd 148 if (IsSizer())
c62ac5b6
RR
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 );
d597fcb7
RR
153
154 m_size = size;
c62ac5b6
RR
155}
156
3417c2cd 157bool wxSizerItem::IsWindow()
5279a24d
RR
158{
159 return (m_window != NULL);
160}
161
3417c2cd 162bool wxSizerItem::IsSizer()
5279a24d
RR
163{
164 return (m_sizer != NULL);
165}
166
3417c2cd 167bool wxSizerItem::IsSpacer()
5279a24d
RR
168{
169 return (m_window == NULL) && (m_sizer == NULL);
170}
171
172//---------------------------------------------------------------------------
3417c2cd 173// wxSizer
5279a24d
RR
174//---------------------------------------------------------------------------
175
3417c2cd 176wxSizer::wxSizer()
5279a24d
RR
177{
178 m_children.DeleteContents( TRUE );
179}
180
3417c2cd 181wxSizer::~wxSizer()
5279a24d
RR
182{
183}
184
3417c2cd 185void wxSizer::Add( wxWindow *window, int option, int flag, int border )
5279a24d 186{
3417c2cd 187 m_children.Append( new wxSizerItem( window, option, flag, border ) );
5279a24d
RR
188}
189
3417c2cd 190void wxSizer::Add( wxSizer *sizer, int option, int flag, int border )
5279a24d 191{
3417c2cd 192 m_children.Append( new wxSizerItem( sizer, option, flag, border ) );
5279a24d
RR
193}
194
3417c2cd 195void wxSizer::Add( int width, int height, int option, int flag, int border )
5279a24d 196{
3417c2cd 197 m_children.Append( new wxSizerItem( width, height, option, flag, border ) );
5279a24d
RR
198}
199
42b4e99e
RR
200void wxSizer::Prepend( wxWindow *window, int option, int flag, int border )
201{
202 m_children.Insert( new wxSizerItem( window, option, flag, border ) );
203}
204
205void wxSizer::Prepend( wxSizer *sizer, int option, int flag, int border )
206{
207 m_children.Insert( new wxSizerItem( sizer, option, flag, border ) );
208}
209
210void wxSizer::Prepend( int width, int height, int option, int flag, int border )
211{
212 m_children.Insert( new wxSizerItem( width, height, option, flag, border ) );
213}
214
215bool wxSizer::Remove( wxWindow *window )
216{
217 wxASSERT( window );
218
219 wxNode *node = m_children.First();
220 while (node)
221 {
222 wxSizerItem *item = (wxSizerItem*)node->Data();
223 if (item->GetWindow() == window)
224 {
225 m_children.DeleteNode( node );
226 return TRUE;
227 }
228 node = node->Next();
229 }
230
231 return FALSE;
232}
233
234bool wxSizer::Remove( wxSizer *sizer )
235{
236 wxASSERT( sizer );
237
238 wxNode *node = m_children.First();
239 while (node)
240 {
241 wxSizerItem *item = (wxSizerItem*)node->Data();
242 if (item->GetSizer() == sizer)
243 {
244 m_children.DeleteNode( node );
245 return TRUE;
246 }
247 node = node->Next();
248 }
249
250 return FALSE;
251}
252
253bool wxSizer::Remove( int pos )
254{
255 wxNode *node = m_children.Nth( pos );
256 if (!node) return FALSE;
257
258 m_children.DeleteNode( node );
259
260 return TRUE;
261}
262
3417c2cd 263void wxSizer::Fit( wxWindow *window )
5279a24d
RR
264{
265 window->SetSize( GetMinWindowSize( window ) );
266}
267
3417c2cd 268void wxSizer::Layout()
c62ac5b6 269{
42b4e99e 270 CalcMin();
c62ac5b6
RR
271 RecalcSizes();
272}
273
3417c2cd 274void wxSizer::SetSizeHints( wxWindow *window )
5279a24d
RR
275{
276 wxSize size( GetMinWindowSize( window ) );
277 window->SetSizeHints( size.x, size.y );
278}
279
3417c2cd 280wxSize wxSizer::GetMinWindowSize( wxWindow *window )
5279a24d 281{
77671fd2 282 wxSize minSize( GetMinSize() );
5279a24d
RR
283 wxSize size( window->GetSize() );
284 wxSize client_size( window->GetClientSize() );
77671fd2
VZ
285 return wxSize( minSize.x+size.x-client_size.x,
286 minSize.y+size.y-client_size.y );
5279a24d
RR
287}
288
3417c2cd 289void wxSizer::SetDimension( int x, int y, int width, int height )
5279a24d
RR
290{
291 m_position.x = x;
292 m_position.y = y;
293 m_size.x = width;
294 m_size.y = height;
42b4e99e 295 CalcMin();
5279a24d
RR
296 RecalcSizes();
297}
298
c62ac5b6 299//---------------------------------------------------------------------------
92afa2b1 300// wxBoxSizer
61d514bb
RR
301//---------------------------------------------------------------------------
302
92afa2b1 303wxBoxSizer::wxBoxSizer( int orient )
61d514bb
RR
304{
305 m_orient = orient;
306}
307
92afa2b1 308void wxBoxSizer::RecalcSizes()
61d514bb
RR
309{
310 if (m_children.GetCount() == 0)
61d514bb 311 return;
61d514bb
RR
312
313 int delta = 0;
314 int extra = 0;
315 if (m_stretchable)
316 {
317 if (m_orient == wxHORIZONTAL)
318 {
319 delta = (m_size.x - m_fixedWidth) / m_stretchable;
320 extra = (m_size.x - m_fixedWidth) % m_stretchable;
321 }
322 else
323 {
324 delta = (m_size.y - m_fixedHeight) / m_stretchable;
325 extra = (m_size.y - m_fixedHeight) % m_stretchable;
326 }
327 }
328
329 wxPoint pt( m_position );
330
331 wxNode *node = m_children.GetFirst();
332 while (node)
333 {
3417c2cd 334 wxSizerItem *item = (wxSizerItem*) node->Data();
61d514bb
RR
335
336 int weight = 1;
337 if (item->GetOption())
338 weight = item->GetOption();
339
340 wxSize size( item->CalcMin() );
341
342 if (m_orient == wxVERTICAL)
343 {
344 long height = size.y;
345 if (item->GetOption())
346 {
347 height = (delta * weight) + extra;
348 extra = 0; // only the first item will get the remainder as extra size
349 }
d597fcb7
RR
350
351 wxPoint child_pos( pt );
352 wxSize child_size( wxSize( size.x, height) );
353
354 if (item->GetFlag() & wxALIGN_RIGHT)
355 child_pos.x += m_size.x - size.x;
356 else if (item->GetFlag() & wxCENTER)
357 child_pos.x += (m_size.x - size.x) / 2;
358 else if (item->GetFlag() & wxEXPAND)
359 child_size.x = m_size.x;
360
361 item->SetDimension( child_pos, child_size );
362
61d514bb
RR
363 pt.y += height;
364 }
365 else
366 {
367 long width = size.x;
368 if (item->GetOption())
369 {
370 width = (delta * weight) + extra;
371 extra = 0; // only the first item will get the remainder as extra size
372 }
d597fcb7
RR
373
374 wxPoint child_pos( pt );
375 wxSize child_size( wxSize(width, size.y) );
376
377 if (item->GetFlag() & wxALIGN_BOTTOM)
378 child_pos.y += m_size.y - size.y;
379 else if (item->GetFlag() & wxCENTER)
380 child_pos.y += (m_size.y - size.y) / 2;
381 else if (item->GetFlag() & wxEXPAND)
382 child_size.y = m_size.y;
383
384 item->SetDimension( child_pos, child_size );
385
61d514bb
RR
386 pt.x += width;
387 }
388
389 node = node->Next();
390 }
391}
392
92afa2b1 393wxSize wxBoxSizer::CalcMin()
61d514bb
RR
394{
395 if (m_children.GetCount() == 0)
396 return wxSize(2,2);
397
398 m_stretchable = 0;
399 m_minWidth = 0;
400 m_minHeight = 0;
401 m_fixedWidth = 0;
402 m_fixedHeight = 0;
403
404 wxNode *node = m_children.GetFirst();
405 while (node)
406 {
3417c2cd 407 wxSizerItem *item = (wxSizerItem*) node->Data();
61d514bb
RR
408
409 int weight = 1;
410 if (item->GetOption())
411 weight = item->GetOption();
412
413 wxSize size( item->CalcMin() );
414
415 if (m_orient == wxHORIZONTAL)
416 {
417 m_minWidth += (size.x * weight);
418 m_minHeight = wxMax( m_minHeight, size.y );
419 }
420 else
421 {
422 m_minHeight += (size.y * weight);
423 m_minWidth = wxMax( m_minWidth, size.x );
424 }
425
426 if (item->GetOption())
427 {
428 m_stretchable += weight;
429 }
430 else
431 {
432 if (m_orient == wxVERTICAL)
433 {
434 m_fixedHeight += size.y;
435 m_fixedWidth = wxMax( m_fixedWidth, size.x );
436 }
437 else
438 {
439 m_fixedWidth += size.x;
440 m_fixedHeight = wxMax( m_fixedHeight, size.y );
441 }
442 }
443
444 node = node->Next();
445 }
446
447 return wxSize( m_minWidth, m_minHeight );
448}
27ea1d8a
RR
449
450//---------------------------------------------------------------------------
451// wxStaticBoxSizer
452//---------------------------------------------------------------------------
453
454wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
455 : wxBoxSizer( orient )
456{
457 wxASSERT_MSG( box, _T("wxStaticBoxSizer needs a static box") );
458
459 m_staticBox = box;
460}
461
462void wxStaticBoxSizer::RecalcSizes()
463{
464 // this will have to be done platform by platform
465 // as there is no way to guess the thickness of
466 // a wxStaticBox border
467 int top_border = 15;
468 if (m_staticBox->GetLabel().IsEmpty()) top_border = 5;
469 int other_border = 5;
470
471 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
472
473 wxPoint old_pos( m_position );
474 m_position.x += other_border;
475 m_position.y += top_border;
476 wxSize old_size( m_size );
477 m_size.x -= 2*other_border;
478 m_size.y -= top_border + other_border;
479
480 wxBoxSizer::RecalcSizes();
481
482 m_position = old_pos;
483 m_size = old_size;
484}
485
486wxSize wxStaticBoxSizer::CalcMin()
487{
488 // this will have to be done platform by platform
489 // as there is no way to guess the thickness of
490 // a wxStaticBox border
491 int top_border = 15;
492 if (m_staticBox->GetLabel().IsEmpty()) top_border = 5;
493 int other_border = 5;
494
495 wxSize ret( wxBoxSizer::CalcMin() );
496 ret.x += 2*top_border;
497 ret.y += other_border + top_border;
498
499 return ret;
500}