]> git.saurik.com Git - wxWidgets.git/blame - src/common/sizer.cpp
fixed header include guard position (patch 992443)
[wxWidgets.git] / src / common / sizer.cpp
CommitLineData
5279a24d
RR
1/////////////////////////////////////////////////////////////////////////////
2// Name: sizer.cpp
1044a386 3// Purpose: provide new wxSizer class for layout
aa5973ee
JS
4// Author: Robert Roebling and Robin Dunn, contributions by
5// Dirk Holtwick, Ron Lee
566d84a7 6// Modified by: Ron Lee
0c0d686f 7// Created:
5279a24d 8// RCS-ID: $Id$
aa5973ee 9// Copyright: (c) Robin Dunn, Robert Roebling
65571936 10// Licence: wxWindows licence
5279a24d
RR
11/////////////////////////////////////////////////////////////////////////////
12
14f355c2 13#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
c62ac5b6 14#pragma implementation "sizer.h"
5279a24d
RR
15#endif
16
77671fd2
VZ
17// For compilers that support precompilation, includes "wx.h".
18#include "wx/wxprec.h"
19
20#ifdef __BORLANDC__
21 #pragma hdrstop
22#endif
23
5279a24d 24#include "wx/sizer.h"
61d514bb 25#include "wx/utils.h"
27ea1d8a 26#include "wx/statbox.h"
c54b92d3 27#include "wx/listimpl.cpp"
adbf2d73
VS
28#if WXWIN_COMPATIBILITY_2_4
29 #include "wx/notebook.h"
30#endif
5279a24d 31
78ca5669
DS
32#ifdef __WXMAC__
33# include "wx/mac/uma.h"
34#endif
35
0c0d686f
RD
36//---------------------------------------------------------------------------
37
9cbee2ce
RL
38IMPLEMENT_CLASS(wxSizerItem, wxObject)
39IMPLEMENT_CLASS(wxSizer, wxObject)
40IMPLEMENT_CLASS(wxGridSizer, wxSizer)
41IMPLEMENT_CLASS(wxFlexGridSizer, wxGridSizer)
42IMPLEMENT_CLASS(wxBoxSizer, wxSizer)
1e6feb95 43#if wxUSE_STATBOX
9cbee2ce 44IMPLEMENT_CLASS(wxStaticBoxSizer, wxBoxSizer)
1e6feb95 45#endif
0c0d686f 46
12a3f227
RL
47WX_DEFINE_EXPORTED_LIST( wxSizerItemList );
48
066f1b7a
SC
49/*
50 TODO PROPERTIES
51 sizeritem
52 object
53 object_ref
54 minsize
55 option
56 flag
57 border
58 spacer
59 option
60 flag
61 borfder
62 boxsizer
63 orient
64 staticboxsizer
65 orient
66 label
67 gridsizer
68 rows
69 cols
70 vgap
71 hgap
72 flexgridsizer
73 rows
74 cols
75 vgap
76 hgap
77 growablerows
78 growablecols
79 minsize
80*/
5279a24d 81//---------------------------------------------------------------------------
3417c2cd 82// wxSizerItem
5279a24d
RR
83//---------------------------------------------------------------------------
84
12a3f227
RL
85wxSizerItem::wxSizerItem( int width, int height, int proportion, int flag, int border, wxObject* userData )
86 : m_window( NULL )
87 , m_sizer( NULL )
00976fe5
RL
88 , m_size( wxSize( width, height ) ) // size is set directly
89 , m_minSize( m_size ) // minimal size is the initial size
12a3f227 90 , m_proportion( proportion )
00976fe5
RL
91 , m_border( border )
92 , m_flag( flag )
e0d8fb45 93 , m_show( true )
00976fe5 94 , m_userData( userData )
5279a24d 95{
00976fe5 96 SetRatio( m_size );
5279a24d
RR
97}
98
12a3f227 99wxSizerItem::wxSizerItem( wxWindow *window, int proportion, int flag, int border, wxObject* userData )
00976fe5 100 : m_window( window )
12a3f227 101 , m_sizer( NULL )
12a3f227 102 , m_proportion( proportion )
00976fe5
RL
103 , m_border( border )
104 , m_flag( flag )
e0d8fb45 105 , m_show( true )
00976fe5 106 , m_userData( userData )
5279a24d 107{
ba763a45
RD
108 if (flag & wxFIXED_MINSIZE)
109 window->SetMinSize(window->GetSize());
110 m_minSize = window->GetSize();
111
36461f58
RD
112 // aspect ratio calculated from initial size
113 SetRatio( m_minSize );
114
00976fe5 115 // m_size is calculated later
5279a24d
RR
116}
117
12a3f227
RL
118wxSizerItem::wxSizerItem( wxSizer *sizer, int proportion, int flag, int border, wxObject* userData )
119 : m_window( NULL )
00976fe5 120 , m_sizer( sizer )
12a3f227 121 , m_proportion( proportion )
00976fe5
RL
122 , m_border( border )
123 , m_flag( flag )
e0d8fb45 124 , m_show( true )
12a3f227 125 , m_ratio( 0.0 )
00976fe5 126 , m_userData( userData )
5279a24d 127{
00976fe5
RL
128 // m_minSize is calculated later
129 // m_size is calculated later
5279a24d
RR
130}
131
20b35a69
RD
132wxSizerItem::wxSizerItem()
133 : m_window( NULL )
134 , m_sizer( NULL )
135 , m_proportion( 0 )
136 , m_border( 0 )
137 , m_flag( 0 )
138 , m_show( true )
139 , m_ratio( 0.0 )
140 , m_userData( NULL )
141{
142}
143
0c0d686f
RD
144wxSizerItem::~wxSizerItem()
145{
f91e8382
VZ
146 delete m_userData;
147
148 if ( m_window )
149 {
150 m_window->SetContainingSizer(NULL);
151 }
152 else // we must be a sizer
153 {
0c0d686f 154 delete m_sizer;
f91e8382 155 }
0c0d686f
RD
156}
157
158
9cbee2ce 159wxSize wxSizerItem::GetSize() const
5279a24d 160{
d597fcb7 161 wxSize ret;
3417c2cd 162 if (IsSizer())
d597fcb7
RR
163 ret = m_sizer->GetSize();
164 else
c62ac5b6 165 if (IsWindow())
d597fcb7
RR
166 ret = m_window->GetSize();
167 else ret = m_size;
0c0d686f 168
d597fcb7
RR
169 if (m_flag & wxWEST)
170 ret.x += m_border;
171 if (m_flag & wxEAST)
172 ret.x += m_border;
173 if (m_flag & wxNORTH)
174 ret.y += m_border;
175 if (m_flag & wxSOUTH)
176 ret.y += m_border;
0c0d686f 177
d597fcb7 178 return ret;
5279a24d
RR
179}
180
3417c2cd 181wxSize wxSizerItem::CalcMin()
c62ac5b6 182{
3417c2cd 183 if (IsSizer())
be2577e4 184 {
ba763a45 185 m_minSize = m_sizer->GetMinSize();
d13d8d4e 186
be2577e4
RD
187 // if we have to preserve aspect ratio _AND_ this is
188 // the first-time calculation, consider ret to be initial size
d13d8d4e 189 if ((m_flag & wxSHAPED) && !m_ratio)
36461f58 190 SetRatio(m_minSize);
be2577e4 191 }
ba763a45 192 else if ( IsWindow() )
d13d8d4e 193 {
ba763a45
RD
194 // Since the size of the window may change during runtime, we
195 // should use the current minimal/best size.
196 m_minSize = m_window->GetBestFittingSize();
d13d8d4e 197 }
0c0d686f 198
ba763a45
RD
199 return GetMinSizeWithBorder();
200}
201
202wxSize wxSizerItem::GetMinSizeWithBorder() const
203{
204 wxSize ret = m_minSize;
205
d597fcb7
RR
206 if (m_flag & wxWEST)
207 ret.x += m_border;
208 if (m_flag & wxEAST)
209 ret.x += m_border;
210 if (m_flag & wxNORTH)
211 ret.y += m_border;
212 if (m_flag & wxSOUTH)
213 ret.y += m_border;
ba763a45 214
d597fcb7 215 return ret;
c62ac5b6
RR
216}
217
ba763a45 218
3417c2cd 219void wxSizerItem::SetDimension( wxPoint pos, wxSize size )
c62ac5b6 220{
cdddaeea 221 if (m_flag & wxSHAPED)
d597fcb7 222 {
be2577e4
RD
223 // adjust aspect ratio
224 int rwidth = (int) (size.y * m_ratio);
cdddaeea
VZ
225 if (rwidth > size.x)
226 {
be2577e4
RD
227 // fit horizontally
228 int rheight = (int) (size.x / m_ratio);
229 // add vertical space
230 if (m_flag & wxALIGN_CENTER_VERTICAL)
231 pos.y += (size.y - rheight) / 2;
232 else if (m_flag & wxALIGN_BOTTOM)
233 pos.y += (size.y - rheight);
234 // use reduced dimensions
235 size.y =rheight;
cdddaeea
VZ
236 }
237 else if (rwidth < size.x)
238 {
be2577e4
RD
239 // add horizontal space
240 if (m_flag & wxALIGN_CENTER_HORIZONTAL)
241 pos.x += (size.x - rwidth) / 2;
242 else if (m_flag & wxALIGN_RIGHT)
243 pos.x += (size.x - rwidth);
244 size.x = rwidth;
245 }
246 }
33ac7e6f 247
cdddaeea
VZ
248 // This is what GetPosition() returns. Since we calculate
249 // borders afterwards, GetPosition() will be the left/top
250 // corner of the surrounding border.
251 m_pos = pos;
252
253 if (m_flag & wxWEST)
254 {
255 pos.x += m_border;
256 size.x -= m_border;
257 }
258 if (m_flag & wxEAST)
259 {
260 size.x -= m_border;
261 }
262 if (m_flag & wxNORTH)
263 {
264 pos.y += m_border;
265 size.y -= m_border;
266 }
267 if (m_flag & wxSOUTH)
268 {
269 size.y -= m_border;
270 }
0c0d686f 271
3417c2cd 272 if (IsSizer())
c62ac5b6 273 m_sizer->SetDimension( pos.x, pos.y, size.x, size.y );
0c0d686f 274
c62ac5b6 275 if (IsWindow())
b919f007 276 m_window->SetSize( pos.x, pos.y, size.x, size.y, wxSIZE_ALLOW_MINUS_ONE );
d597fcb7
RR
277
278 m_size = size;
c62ac5b6
RR
279}
280
84f7908b
RR
281void wxSizerItem::DeleteWindows()
282{
283 if (m_window)
77aa9abd 284 {
84f7908b 285 m_window->Destroy();
77aa9abd
RD
286 m_window = NULL;
287 }
be90c029 288
84f7908b
RR
289 if (m_sizer)
290 m_sizer->DeleteWindows();
291}
292
9cbee2ce 293bool wxSizerItem::IsWindow() const
5279a24d
RR
294{
295 return (m_window != NULL);
296}
297
9cbee2ce 298bool wxSizerItem::IsSizer() const
5279a24d
RR
299{
300 return (m_sizer != NULL);
301}
302
9cbee2ce 303bool wxSizerItem::IsSpacer() const
5279a24d
RR
304{
305 return (m_window == NULL) && (m_sizer == NULL);
306}
307
12a3f227
RL
308void wxSizerItem::Show( bool show )
309{
310 m_show = show;
311
312 if( IsWindow() )
313 m_window->Show( show );
314 else if( IsSizer() )
315 m_sizer->ShowItems( show );
316
317 // ... nothing else to do to hide/show spacers
318}
319
320void wxSizerItem::SetOption( int option )
321{
322 SetProportion( option );
323}
324
325int wxSizerItem::GetOption() const
326{
327 return GetProportion();
328}
329
330
5279a24d 331//---------------------------------------------------------------------------
3417c2cd 332// wxSizer
5279a24d
RR
333//---------------------------------------------------------------------------
334
3417c2cd 335wxSizer::wxSizer()
12a3f227 336 : m_minSize( wxSize( 0, 0 ) )
5279a24d 337{
5279a24d
RR
338}
339
3417c2cd 340wxSizer::~wxSizer()
5279a24d 341{
222ed1d6 342 WX_CLEAR_LIST(wxSizerItemList, m_children);
5279a24d 343}
0c0d686f 344
12a3f227 345void wxSizer::Add( wxWindow *window, int proportion, int flag, int border, wxObject* userData )
5279a24d 346{
12a3f227
RL
347 m_children.Append( new wxSizerItem( window, proportion, flag, border, userData ) );
348 window->SetContainingSizer( this );
5279a24d
RR
349}
350
12a3f227 351void wxSizer::Add( wxSizer *sizer, int proportion, int flag, int border, wxObject* userData )
5279a24d 352{
12a3f227 353 m_children.Append( new wxSizerItem( sizer, proportion, flag, border, userData ) );
5279a24d
RR
354}
355
12a3f227 356void wxSizer::Add( int width, int height, int proportion, int flag, int border, wxObject* userData )
5279a24d 357{
12a3f227 358 m_children.Append( new wxSizerItem( width, height, proportion, flag, border, userData ) );
5279a24d
RR
359}
360
12a3f227 361void wxSizer::Add( wxSizerItem *item )
42b4e99e 362{
12a3f227
RL
363 m_children.Append( item );
364
365 if( item->GetWindow() )
366 item->GetWindow()->SetContainingSizer( this );
42b4e99e
RR
367}
368
12a3f227 369void wxSizer::Prepend( wxWindow *window, int proportion, int flag, int border, wxObject* userData )
42b4e99e 370{
12a3f227
RL
371 m_children.Insert( new wxSizerItem( window, proportion, flag, border, userData ) );
372 window->SetContainingSizer( this );
42b4e99e
RR
373}
374
12a3f227 375void wxSizer::Prepend( wxSizer *sizer, int proportion, int flag, int border, wxObject* userData )
42b4e99e 376{
12a3f227 377 m_children.Insert( new wxSizerItem( sizer, proportion, flag, border, userData ) );
f35aa3da
RR
378}
379
12a3f227 380void wxSizer::Prepend( int width, int height, int proportion, int flag, int border, wxObject* userData )
f35aa3da 381{
12a3f227 382 m_children.Insert( new wxSizerItem( width, height, proportion, flag, border, userData ) );
f35aa3da
RR
383}
384
12a3f227 385void wxSizer::Prepend( wxSizerItem *item )
f35aa3da 386{
12a3f227
RL
387 m_children.Insert( item );
388
389 if( item->GetWindow() )
390 item->GetWindow()->SetContainingSizer( this );
f35aa3da
RR
391}
392
12a3f227
RL
393void wxSizer::Insert( size_t index,
394 wxWindow *window,
395 int proportion,
396 int flag,
397 int border,
398 wxObject* userData )
f35aa3da 399{
12a3f227
RL
400 m_children.Insert( index,
401 new wxSizerItem( window, proportion, flag, border, userData ) );
402 window->SetContainingSizer( this );
42b4e99e
RR
403}
404
12a3f227
RL
405void wxSizer::Insert( size_t index,
406 wxSizer *sizer,
407 int proportion,
408 int flag,
409 int border,
410 wxObject* userData )
42b4e99e 411{
12a3f227
RL
412 m_children.Insert( index,
413 new wxSizerItem( sizer, proportion, flag, border, userData ) );
414}
0c0d686f 415
12a3f227
RL
416void wxSizer::Insert( size_t index,
417 int width,
418 int height,
419 int proportion,
420 int flag,
421 int border,
422 wxObject* userData )
423{
424 m_children.Insert( index,
425 new wxSizerItem( width, height, proportion, flag, border, userData ) );
426}
427
428void wxSizer::Insert( size_t index, wxSizerItem *item )
429{
430 m_children.Insert( index, item );
0c0d686f 431
12a3f227
RL
432 if( item->GetWindow() )
433 item->GetWindow()->SetContainingSizer( this );
434}
435
436bool wxSizer::Remove( wxWindow *window )
437{
438 return Detach( window );
42b4e99e
RR
439}
440
441bool wxSizer::Remove( wxSizer *sizer )
442{
12a3f227 443 wxASSERT_MSG( sizer, _T("Removing NULL sizer") );
0c0d686f 444
222ed1d6 445 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
42b4e99e
RR
446 while (node)
447 {
12a3f227
RL
448 wxSizerItem *item = node->GetData();
449
3ca6a5f0 450 if (item->GetSizer() == sizer)
222ed1d6
MB
451 {
452 delete item;
453 m_children.Erase( node );
454 return true;
455 }
12a3f227
RL
456
457 node = node->GetNext();
42b4e99e 458 }
0c0d686f 459
e0d8fb45 460 return false;
42b4e99e
RR
461}
462
e0d8fb45 463bool wxSizer::Remove( int index )
42b4e99e 464{
e0d8fb45
VZ
465 wxCHECK_MSG( index >= 0 && (size_t)index < m_children.GetCount(),
466 false,
12a3f227 467 _T("Remove index is out of range") );
0c0d686f 468
222ed1d6 469 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
0c0d686f 470
e0d8fb45 471 wxCHECK_MSG( node, false, _T("Failed to find child node") );
12a3f227 472
e0d8fb45 473 wxSizerItem *item = node->GetData();
9cbee2ce
RL
474
475 if( item->IsWindow() )
476 item->GetWindow()->SetContainingSizer( NULL );
477
222ed1d6
MB
478 delete item;
479 m_children.Erase( node );
480 return true;
42b4e99e 481}
0c0d686f 482
00976fe5
RL
483bool wxSizer::Detach( wxSizer *sizer )
484{
12a3f227 485 wxASSERT_MSG( sizer, _T("Detaching NULL sizer") );
00976fe5 486
222ed1d6 487 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
00976fe5
RL
488 while (node)
489 {
12a3f227
RL
490 wxSizerItem *item = node->GetData();
491
00976fe5
RL
492 if (item->GetSizer() == sizer)
493 {
96fdbb60 494 item->DetachSizer();
89c20ac1 495 delete item;
222ed1d6
MB
496 m_children.Erase( node );
497 return true;
12a3f227
RL
498 }
499 node = node->GetNext();
500 }
501
e0d8fb45 502 return false;
12a3f227
RL
503}
504
505bool wxSizer::Detach( wxWindow *window )
506{
507 wxASSERT_MSG( window, _T("Detaching NULL window") );
508
222ed1d6 509 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
12a3f227
RL
510 while (node)
511 {
512 wxSizerItem *item = node->GetData();
513
514 if (item->GetWindow() == window)
515 {
516 item->GetWindow()->SetContainingSizer( NULL );
89c20ac1 517 delete item;
222ed1d6
MB
518 m_children.Erase( node );
519 return true;
00976fe5 520 }
12a3f227 521 node = node->GetNext();
00976fe5
RL
522 }
523
e0d8fb45 524 return false;
00976fe5
RL
525}
526
e0d8fb45 527bool wxSizer::Detach( int index )
00976fe5 528{
e0d8fb45
VZ
529 wxCHECK_MSG( index >= 0 && (size_t)index < m_children.GetCount(),
530 false,
12a3f227
RL
531 _T("Detach index is out of range") );
532
222ed1d6 533 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
00976fe5 534
e0d8fb45 535 wxCHECK_MSG( node, false, _T("Failed to find child node") );
00976fe5 536
e0d8fb45 537 wxSizerItem *item = node->GetData();
9cbee2ce
RL
538
539 if( item->IsSizer() )
540 item->DetachSizer();
541 else if( item->IsWindow() )
542 item->GetWindow()->SetContainingSizer( NULL );
12a3f227 543
89c20ac1 544 delete item;
222ed1d6
MB
545 m_children.Erase( node );
546 return true;
00976fe5
RL
547}
548
84f7908b
RR
549void wxSizer::Clear( bool delete_windows )
550{
be90c029 551 // First clear the ContainingSizer pointers
222ed1d6 552 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
be90c029
RD
553 while (node)
554 {
12a3f227
RL
555 wxSizerItem *item = node->GetData();
556
be90c029 557 if (item->IsWindow())
12a3f227
RL
558 item->GetWindow()->SetContainingSizer( NULL );
559 node = node->GetNext();
be90c029
RD
560 }
561
562 // Destroy the windows if needed
84f7908b
RR
563 if (delete_windows)
564 DeleteWindows();
be90c029
RD
565
566 // Now empty the list
222ed1d6 567 WX_CLEAR_LIST(wxSizerItemList, m_children);
84f7908b
RR
568}
569
570void wxSizer::DeleteWindows()
571{
222ed1d6 572 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
84f7908b
RR
573 while (node)
574 {
12a3f227
RL
575 wxSizerItem *item = node->GetData();
576
84f7908b 577 item->DeleteWindows();
12a3f227 578 node = node->GetNext();
84f7908b
RR
579 }
580}
581
e5251d4f 582wxSize wxSizer::Fit( wxWindow *window )
5279a24d 583{
f43c7771
VZ
584 wxSize size(window->IsTopLevel() ? FitSize(window)
585 : GetMinWindowSize(window));
9ef2e675 586
ccf5c8a8 587 window->SetSize( size );
e5251d4f
VZ
588
589 return size;
5279a24d
RR
590}
591
566d84a7
RL
592void wxSizer::FitInside( wxWindow *window )
593{
594 wxSize size;
595 if (window->IsTopLevel())
596 size = VirtualFitSize( window );
597 else
598 size = GetMinClientSize( window );
599
600 window->SetVirtualSize( size );
601}
602
3417c2cd 603void wxSizer::Layout()
c62ac5b6 604{
ba763a45
RD
605 // (re)calculates minimums needed for each item and other preparations
606 // for layout
42b4e99e 607 CalcMin();
ba763a45
RD
608
609 // Applies the layout and repositions/resizes the items
c62ac5b6
RR
610 RecalcSizes();
611}
612
3417c2cd 613void wxSizer::SetSizeHints( wxWindow *window )
5279a24d 614{
34c3ffca
RL
615 // Preserve the window's max size hints, but set the
616 // lower bound according to the sizer calculations.
617
e5251d4f
VZ
618 wxSize size = Fit( window );
619
34c3ffca
RL
620 window->SetSizeHints( size.x,
621 size.y,
622 window->GetMaxWidth(),
623 window->GetMaxHeight() );
5279a24d
RR
624}
625
566d84a7
RL
626void wxSizer::SetVirtualSizeHints( wxWindow *window )
627{
628 // Preserve the window's max size hints, but set the
629 // lower bound according to the sizer calculations.
630
631 FitInside( window );
632 wxSize size( window->GetVirtualSize() );
633 window->SetVirtualSizeHints( size.x,
634 size.y,
635 window->GetMaxWidth(),
636 window->GetMaxHeight() );
637}
638
9cbee2ce 639wxSize wxSizer::GetMaxWindowSize( wxWindow *window ) const
65ba4113 640{
34c3ffca 641 return window->GetMaxSize();
65ba4113
GT
642}
643
3417c2cd 644wxSize wxSizer::GetMinWindowSize( wxWindow *window )
5279a24d 645{
12a3f227
RL
646 wxSize minSize( GetMinSize() );
647 wxSize size( window->GetSize() );
648 wxSize client_size( window->GetClientSize() );
649
77671fd2 650 return wxSize( minSize.x+size.x-client_size.x,
0c0d686f 651 minSize.y+size.y-client_size.y );
5279a24d
RR
652}
653
e11d436b
SC
654// TODO on mac we need a function that determines how much free space this
655// min size contains, in order to make sure that we have 20 pixels of free
656// space around the controls
657
65ba4113
GT
658// Return a window size that will fit within the screens dimensions
659wxSize wxSizer::FitSize( wxWindow *window )
660{
661 wxSize size = GetMinWindowSize( window );
662 wxSize sizeMax = GetMaxWindowSize( window );
663
34c3ffca
RL
664 // Limit the size if sizeMax != wxDefaultSize
665
666 if ( size.x > sizeMax.x && sizeMax.x != -1 )
65ba4113 667 size.x = sizeMax.x;
34c3ffca 668 if ( size.y > sizeMax.y && sizeMax.y != -1 )
65ba4113
GT
669 size.y = sizeMax.y;
670
671 return size;
672}
673
9cbee2ce 674wxSize wxSizer::GetMaxClientSize( wxWindow *window ) const
566d84a7
RL
675{
676 wxSize maxSize( window->GetMaxSize() );
677
678 if( maxSize != wxDefaultSize )
679 {
680 wxSize size( window->GetSize() );
681 wxSize client_size( window->GetClientSize() );
682
683 return wxSize( maxSize.x + client_size.x - size.x,
684 maxSize.y + client_size.y - size.y );
685 }
686 else
687 return wxDefaultSize;
688}
689
1b0674f7 690wxSize wxSizer::GetMinClientSize( wxWindow *WXUNUSED(window) )
566d84a7
RL
691{
692 return GetMinSize(); // Already returns client size.
693}
694
695wxSize wxSizer::VirtualFitSize( wxWindow *window )
696{
697 wxSize size = GetMinClientSize( window );
698 wxSize sizeMax = GetMaxClientSize( window );
699
700 // Limit the size if sizeMax != wxDefaultSize
701
702 if ( size.x > sizeMax.x && sizeMax.x != -1 )
703 size.x = sizeMax.x;
704 if ( size.y > sizeMax.y && sizeMax.y != -1 )
705 size.y = sizeMax.y;
706
707 return size;
708}
709
3417c2cd 710void wxSizer::SetDimension( int x, int y, int width, int height )
5279a24d
RR
711{
712 m_position.x = x;
713 m_position.y = y;
714 m_size.x = width;
715 m_size.y = height;
2b5f62a0 716 Layout();
5279a24d
RR
717}
718
f6bcfd97 719wxSize wxSizer::GetMinSize()
3ca6a5f0 720{
f6bcfd97
BP
721 wxSize ret( CalcMin() );
722 if (ret.x < m_minSize.x) ret.x = m_minSize.x;
723 if (ret.y < m_minSize.y) ret.y = m_minSize.y;
3ca6a5f0 724 return ret;
f6bcfd97
BP
725}
726
727void wxSizer::DoSetMinSize( int width, int height )
728{
729 m_minSize.x = width;
730 m_minSize.y = height;
731}
732
733bool wxSizer::DoSetItemMinSize( wxWindow *window, int width, int height )
734{
12a3f227
RL
735 wxASSERT_MSG( window, _T("SetMinSize for NULL window") );
736
737 // Is it our immediate child?
f6bcfd97 738
222ed1d6 739 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
f6bcfd97
BP
740 while (node)
741 {
12a3f227
RL
742 wxSizerItem *item = node->GetData();
743
3ca6a5f0
BP
744 if (item->GetWindow() == window)
745 {
1eba2193 746 item->SetMinSize( width, height );
e0d8fb45 747 return true;
3ca6a5f0 748 }
12a3f227 749 node = node->GetNext();
f6bcfd97
BP
750 }
751
12a3f227
RL
752 // No? Search any subsizers we own then
753
754 node = m_children.GetFirst();
f6bcfd97
BP
755 while (node)
756 {
12a3f227
RL
757 wxSizerItem *item = node->GetData();
758
759 if ( item->GetSizer() &&
760 item->GetSizer()->DoSetItemMinSize( window, width, height ) )
3ca6a5f0 761 {
12a3f227 762 // A child sizer found the requested windw, exit.
e0d8fb45 763 return true;
3ca6a5f0 764 }
12a3f227 765 node = node->GetNext();
f6bcfd97
BP
766 }
767
e0d8fb45 768 return false;
f6bcfd97
BP
769}
770
771bool wxSizer::DoSetItemMinSize( wxSizer *sizer, int width, int height )
772{
12a3f227 773 wxASSERT_MSG( sizer, _T("SetMinSize for NULL sizer") );
f6bcfd97 774
12a3f227
RL
775 // Is it our immediate child?
776
222ed1d6 777 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
f6bcfd97
BP
778 while (node)
779 {
12a3f227
RL
780 wxSizerItem *item = node->GetData();
781
3ca6a5f0
BP
782 if (item->GetSizer() == sizer)
783 {
f6bcfd97 784 item->GetSizer()->DoSetMinSize( width, height );
e0d8fb45 785 return true;
3ca6a5f0 786 }
12a3f227 787 node = node->GetNext();
f6bcfd97
BP
788 }
789
12a3f227
RL
790 // No? Search any subsizers we own then
791
792 node = m_children.GetFirst();
f6bcfd97
BP
793 while (node)
794 {
12a3f227
RL
795 wxSizerItem *item = node->GetData();
796
797 if ( item->GetSizer() &&
798 item->GetSizer()->DoSetItemMinSize( sizer, width, height ) )
3ca6a5f0 799 {
12a3f227 800 // A child found the requested sizer, exit.
e0d8fb45 801 return true;
3ca6a5f0 802 }
12a3f227 803 node = node->GetNext();
f6bcfd97
BP
804 }
805
e0d8fb45 806 return false;
f6bcfd97
BP
807}
808
12a3f227 809bool wxSizer::DoSetItemMinSize( size_t index, int width, int height )
f6bcfd97 810{
222ed1d6 811 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
12a3f227 812
e0d8fb45 813 wxCHECK_MSG( node, false, _T("Failed to find child node") );
12a3f227
RL
814
815 wxSizerItem *item = node->GetData();
f6bcfd97 816
f6bcfd97
BP
817 if (item->GetSizer())
818 {
0ca5105b 819 // Sizers contains the minimal size in them, if not calculated ...
f6bcfd97
BP
820 item->GetSizer()->DoSetMinSize( width, height );
821 }
822 else
823 {
ba763a45 824 // ... but the minimal size of spacers and windows is stored via the item
1eba2193 825 item->SetMinSize( width, height );
f6bcfd97
BP
826 }
827
e0d8fb45 828 return true;
f6bcfd97
BP
829}
830
12a3f227 831void wxSizer::Show( wxWindow *window, bool show )
2b5f62a0 832{
12a3f227
RL
833 wxASSERT_MSG( window, _T("Show for NULL window") );
834
222ed1d6 835 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
2b5f62a0
VZ
836 while (node)
837 {
12a3f227 838 wxSizerItem *item = node->GetData();
2b5f62a0 839
12a3f227 840 if (item->GetWindow() == window)
2b5f62a0 841 {
12a3f227
RL
842 item->Show( show );
843 break;
2b5f62a0 844 }
12a3f227 845 node = node->GetNext();
2b5f62a0
VZ
846 }
847}
848
12a3f227 849void wxSizer::Show( wxSizer *sizer, bool show )
2b5f62a0 850{
12a3f227
RL
851 wxASSERT_MSG( sizer, _T("Show for NULL sizer") );
852
222ed1d6 853 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
2b5f62a0
VZ
854 while (node)
855 {
12a3f227 856 wxSizerItem *item = node->GetData();
2b5f62a0 857
12a3f227 858 if (item->GetSizer() == sizer)
2b5f62a0 859 {
12a3f227
RL
860 item->Show( show );
861 break;
2b5f62a0 862 }
12a3f227 863 node = node->GetNext();
2b5f62a0
VZ
864 }
865}
866
12a3f227 867void wxSizer::Show( size_t index, bool show )
2b5f62a0 868{
12a3f227
RL
869 wxCHECK_RET( index < m_children.GetCount(),
870 _T("Show index is out of range") );
2b5f62a0 871
12a3f227
RL
872 m_children.Item( index )->GetData()->Show( show );
873}
2b5f62a0 874
12a3f227
RL
875void wxSizer::ShowItems( bool show )
876{
222ed1d6 877 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
12a3f227
RL
878 while (node)
879 {
880 node->GetData()->Show( show );
881 node = node->GetNext();
2b5f62a0
VZ
882 }
883}
884
9cbee2ce 885bool wxSizer::IsShown( wxWindow *window ) const
2b5f62a0 886{
222ed1d6 887 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
2b5f62a0
VZ
888 while (node)
889 {
12a3f227 890 wxSizerItem *item = node->GetData();
dc259b79 891
12a3f227 892 if (item->GetWindow() == window)
2b5f62a0
VZ
893 {
894 return item->IsShown();
895 }
12a3f227 896 node = node->GetNext();
2b5f62a0
VZ
897 }
898
12a3f227
RL
899 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
900
e0d8fb45 901 return false;
2b5f62a0
VZ
902}
903
9cbee2ce 904bool wxSizer::IsShown( wxSizer *sizer ) const
2b5f62a0 905{
222ed1d6 906 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
2b5f62a0
VZ
907 while (node)
908 {
12a3f227 909 wxSizerItem *item = node->GetData();
2b5f62a0 910
12a3f227 911 if (item->GetSizer() == sizer)
2b5f62a0
VZ
912 {
913 return item->IsShown();
914 }
12a3f227 915 node = node->GetNext();
2b5f62a0
VZ
916 }
917
12a3f227
RL
918 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
919
e0d8fb45 920 return false;
2b5f62a0
VZ
921}
922
9cbee2ce 923bool wxSizer::IsShown( size_t index ) const
12a3f227
RL
924{
925 wxCHECK_MSG( index < m_children.GetCount(),
e0d8fb45 926 false,
12a3f227
RL
927 _T("IsShown index is out of range") );
928
929 return m_children.Item( index )->GetData()->IsShown();
930}
931
932
f6bcfd97
BP
933//---------------------------------------------------------------------------
934// wxGridSizer
935//---------------------------------------------------------------------------
936
937wxGridSizer::wxGridSizer( int rows, int cols, int vgap, int hgap )
12a3f227
RL
938 : m_rows( rows )
939 , m_cols( cols )
940 , m_vgap( vgap )
941 , m_hgap( hgap )
f6bcfd97 942{
02319c24
RD
943 if (m_rows == 0 && m_cols == 0)
944 m_rows = 1;
f6bcfd97
BP
945}
946
947wxGridSizer::wxGridSizer( int cols, int vgap, int hgap )
12a3f227
RL
948 : m_rows( 0 )
949 , m_cols( cols )
950 , m_vgap( vgap )
951 , m_hgap( hgap )
f6bcfd97 952{
02319c24
RD
953 if (m_rows == 0 && m_cols == 0)
954 m_rows = 1;
f6bcfd97
BP
955}
956
0ca5105b 957int wxGridSizer::CalcRowsCols(int& nrows, int& ncols) const
f6bcfd97 958{
f6bcfd97 959 int nitems = m_children.GetCount();
2b5f62a0 960 if ( nitems)
0ca5105b
VZ
961 {
962 if ( m_cols )
963 {
964 ncols = m_cols;
965 nrows = (nitems + m_cols - 1) / m_cols;
966 }
967 else if ( m_rows )
968 {
969 ncols = (nitems + m_rows - 1) / m_rows;
970 nrows = m_rows;
971 }
972 else // 0 columns, 0 rows?
973 {
974 wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") );
f6bcfd97 975
0ca5105b
VZ
976 nrows = ncols = 0;
977 }
978 }
979
980 return nitems;
981}
982
983void wxGridSizer::RecalcSizes()
984{
985 int nitems, nrows, ncols;
986 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
987 return;
f6bcfd97
BP
988
989 wxSize sz( GetSize() );
990 wxPoint pt( GetPosition() );
3ca6a5f0
BP
991
992 int w = (sz.x - (ncols - 1) * m_hgap) / ncols;
993 int h = (sz.y - (nrows - 1) * m_vgap) / nrows;
f6bcfd97
BP
994
995 int x = pt.x;
996 for (int c = 0; c < ncols; c++)
997 {
998 int y = pt.y;
999 for (int r = 0; r < nrows; r++)
1000 {
1001 int i = r * ncols + c;
1002 if (i < nitems)
1003 {
222ed1d6 1004 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
12a3f227
RL
1005
1006 wxASSERT_MSG( node, _T("Failed to find SizerItemList node") );
3ca6a5f0 1007
12a3f227 1008 SetItemBounds( node->GetData(), x, y, w, h);
f6bcfd97
BP
1009 }
1010 y = y + h + m_vgap;
1011 }
1012 x = x + w + m_hgap;
1013 }
1014}
1015
1016wxSize wxGridSizer::CalcMin()
1017{
196be0f1
JS
1018 int nrows, ncols;
1019 if ( CalcRowsCols(nrows, ncols) == 0 )
0ca5105b 1020 return wxSize(10, 10);
f6bcfd97 1021
4f469fb5 1022 // Find the max width and height for any component
f6bcfd97
BP
1023 int w = 0;
1024 int h = 0;
3ca6a5f0 1025
222ed1d6 1026 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
f6bcfd97
BP
1027 while (node)
1028 {
12a3f227
RL
1029 wxSizerItem *item = node->GetData();
1030 wxSize sz( item->CalcMin() );
1031
f6bcfd97
BP
1032 w = wxMax( w, sz.x );
1033 h = wxMax( h, sz.y );
3ca6a5f0 1034
12a3f227 1035 node = node->GetNext();
f6bcfd97 1036 }
3ca6a5f0 1037
12a3f227
RL
1038 return wxSize( ncols * w + (ncols-1) * m_hgap,
1039 nrows * h + (nrows-1) * m_vgap );
f6bcfd97
BP
1040}
1041
1042void wxGridSizer::SetItemBounds( wxSizerItem *item, int x, int y, int w, int h )
1043{
1044 wxPoint pt( x,y );
559b747d 1045 wxSize sz( item->GetMinSizeWithBorder() );
f6bcfd97
BP
1046 int flag = item->GetFlag();
1047
1048 if ((flag & wxEXPAND) || (flag & wxSHAPED))
1049 {
1050 sz = wxSize(w, h);
1051 }
1052 else
1053 {
1054 if (flag & wxALIGN_CENTER_HORIZONTAL)
1055 {
559b747d 1056 pt.x = x + (w - sz.x) / 2;
f6bcfd97
BP
1057 }
1058 else if (flag & wxALIGN_RIGHT)
1059 {
559b747d 1060 pt.x = x + (w - sz.x);
f6bcfd97 1061 }
3ca6a5f0 1062
f6bcfd97
BP
1063 if (flag & wxALIGN_CENTER_VERTICAL)
1064 {
559b747d 1065 pt.y = y + (h - sz.y) / 2;
f6bcfd97
BP
1066 }
1067 else if (flag & wxALIGN_BOTTOM)
1068 {
559b747d 1069 pt.y = y + (h - sz.y);
f6bcfd97
BP
1070 }
1071 }
3ca6a5f0 1072
f6bcfd97
BP
1073 item->SetDimension(pt, sz);
1074}
1075
1076//---------------------------------------------------------------------------
1077// wxFlexGridSizer
1078//---------------------------------------------------------------------------
1079
1080wxFlexGridSizer::wxFlexGridSizer( int rows, int cols, int vgap, int hgap )
5d76f462
VZ
1081 : wxGridSizer( rows, cols, vgap, hgap ),
1082 m_flexDirection(wxBOTH),
1083 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
3ca6a5f0 1084{
f6bcfd97
BP
1085}
1086
1087wxFlexGridSizer::wxFlexGridSizer( int cols, int vgap, int hgap )
5d76f462
VZ
1088 : wxGridSizer( cols, vgap, hgap ),
1089 m_flexDirection(wxBOTH),
1090 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
3ca6a5f0 1091{
f6bcfd97 1092}
3ca6a5f0 1093
f6bcfd97
BP
1094wxFlexGridSizer::~wxFlexGridSizer()
1095{
f6bcfd97
BP
1096}
1097
1098void wxFlexGridSizer::RecalcSizes()
1099{
0ca5105b
VZ
1100 int nitems, nrows, ncols;
1101 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
f6bcfd97
BP
1102 return;
1103
20b35a69 1104 wxPoint pt( GetPosition() );
f6bcfd97 1105 wxSize sz( GetSize() );
5d76f462 1106
ba763a45 1107 AdjustForGrowables(sz, m_calculatedMinSize, nrows, ncols);
3ca6a5f0 1108
f6bcfd97
BP
1109 sz = wxSize( pt.x + sz.x, pt.y + sz.y );
1110
1111 int x = pt.x;
1112 for (int c = 0; c < ncols; c++)
1113 {
1114 int y = pt.y;
1115 for (int r = 0; r < nrows; r++)
1116 {
1117 int i = r * ncols + c;
1118 if (i < nitems)
1119 {
222ed1d6 1120 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
12a3f227
RL
1121
1122 wxASSERT_MSG( node, _T("Failed to find node") );
3ca6a5f0 1123
f6bcfd97
BP
1124 int w = wxMax( 0, wxMin( m_colWidths[c], sz.x - x ) );
1125 int h = wxMax( 0, wxMin( m_rowHeights[r], sz.y - y ) );
3ca6a5f0 1126
12a3f227 1127 SetItemBounds( node->GetData(), x, y, w, h);
f6bcfd97
BP
1128 }
1129 y = y + m_rowHeights[r] + m_vgap;
1130 }
1131 x = x + m_colWidths[c] + m_hgap;
1132 }
1133}
1134
1135wxSize wxFlexGridSizer::CalcMin()
1136{
150c8d89
RL
1137 int nrows,
1138 ncols;
1139 size_t i, s;
1140
55f9f0cb 1141 // Number of rows/columns can change as items are added or removed.
5d76f462
VZ
1142 if ( !CalcRowsCols(nrows, ncols) )
1143 return wxSize(10, 10);
f6bcfd97 1144
5d76f462
VZ
1145 m_rowHeights.SetCount(nrows);
1146 m_colWidths.SetCount(ncols);
3ca6a5f0 1147
395a82b1
VZ
1148 // We have to recalcuate the sizes in case the item minimum size has
1149 // changed since the previous layout, or the item has been hidden using
1150 // wxSizer::Show(). If all the items in a row/column are hidden, the final
1151 // dimension of the row/column will be -1, indicating that the column
1152 // itself is hidden.
55f9f0cb
VZ
1153 for( s = m_rowHeights.GetCount(), i = 0; i < s; ++i )
1154 m_rowHeights[ i ] = -1;
1155 for( s = m_colWidths.GetCount(), i = 0; i < s; ++i )
1156 m_colWidths[ i ] = -1;
1157
222ed1d6 1158 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
12a3f227 1159
150c8d89 1160 i = 0;
f6bcfd97
BP
1161 while (node)
1162 {
12a3f227 1163 wxSizerItem *item = node->GetData();
55f9f0cb
VZ
1164 if ( item->IsShown() )
1165 {
1166 wxSize sz( item->CalcMin() );
1167 int row = i / ncols;
1168 int col = i % ncols;
12a3f227 1169
55f9f0cb
VZ
1170 m_rowHeights[ row ] = wxMax( wxMax( 0, sz.y ), m_rowHeights[ row ] );
1171 m_colWidths[ col ] = wxMax( wxMax( 0, sz.x ), m_colWidths[ col ] );
1172 }
3ca6a5f0 1173
12a3f227 1174 node = node->GetNext();
f6bcfd97
BP
1175 i++;
1176 }
3ca6a5f0 1177
20b35a69
RD
1178 AdjustForFlexDirection();
1179
1180 // Sum total minimum size, including gaps between rows/columns.
1181 // -1 is used as a magic number meaning empty column.
1182 int width = 0;
1183 for (int col = 0; col < ncols; col++)
1184 if ( m_colWidths[ col ] != -1 )
1185 width += m_colWidths[ col ] + ( col == ncols-1 ? 0 : m_hgap );
1186
1187 int height = 0;
1188 for (int row = 0; row < nrows; row++)
1189 if ( m_rowHeights[ row ] != -1 )
1190 height += m_rowHeights[ row ] + ( row == nrows-1 ? 0 : m_vgap );
1191
ba763a45
RD
1192 m_calculatedMinSize = wxSize( width, height );
1193 return m_calculatedMinSize;
20b35a69
RD
1194}
1195
1196void wxFlexGridSizer::AdjustForFlexDirection()
1197{
1198 // the logic in CalcMin works when we resize flexibly in both directions
1199 // but maybe this is not the case
5d76f462
VZ
1200 if ( m_flexDirection != wxBOTH )
1201 {
1202 // select the array corresponding to the direction in which we do *not*
1203 // resize flexibly
1204 wxArrayInt& array = m_flexDirection == wxVERTICAL ? m_colWidths
1205 : m_rowHeights;
1206
1207 const int count = array.GetCount();
1208
1209 // find the largest value in this array
55f9f0cb 1210 int n, largest = 0;
5d76f462
VZ
1211 for ( n = 0; n < count; ++n )
1212 {
1213 if ( array[n] > largest )
1214 largest = array[n];
1215 }
1216
1217 // and now fill it with the largest value
1218 for ( n = 0; n < count; ++n )
1219 {
1220 array[n] = largest;
1221 }
1222 }
20b35a69 1223}
5d76f462 1224
3ca6a5f0 1225
20b35a69
RD
1226void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz, const wxSize& minsz,
1227 int nrows, int ncols)
1228{
1229 // what to do with the rows? by default, resize them proportionally
1230 if ( sz.y > minsz.y && ( (m_flexDirection & wxVERTICAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1231 {
1232 int sum_proportions = 0;
1233 int growable_space = 0;
1234 int num = 0;
1235 size_t idx;
1236 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1237 {
1238 // Since the number of rows/columns can change as items are
1239 // inserted/deleted, we need to verify at runtime that the
1240 // requested growable rows/columns are still valid.
1241 if (m_growableRows[idx] >= nrows)
1242 continue;
1243
1244 // If all items in a row/column are hidden, that row/column will
1245 // have a dimension of -1. This causes the row/column to be
1246 // hidden completely.
1247 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1248 continue;
1249 sum_proportions += m_growableRowsProportions[idx];
1250 growable_space += m_rowHeights[ m_growableRows[idx] ];
1251 num++;
1252 }
3ca6a5f0 1253
20b35a69
RD
1254 if (num > 0)
1255 {
1256 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1257 {
1258 if (m_growableRows[idx] >= nrows )
1259 continue;
1260 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1261 m_rowHeights[ m_growableRows[idx] ] = 0;
1262 else
1263 {
1264 int delta = (sz.y - minsz.y);
1265 if (sum_proportions == 0)
1266 delta = (delta/num) + m_rowHeights[ m_growableRows[idx] ];
1267 else
1268 delta = ((delta+growable_space)*m_growableRowsProportions[idx]) / sum_proportions;
1269 m_rowHeights[ m_growableRows[idx] ] = delta;
1270 }
1271 }
1272 }
1273 }
1274 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.y > minsz.y) )
1275 {
1276 // rounding problem?
1277 for ( int row = 0; row < nrows; ++row )
1278 m_rowHeights[ row ] = sz.y / nrows;
1279 }
1280
1281 // the same logic as above but for the columns
1282 if ( sz.x > minsz.x && ( (m_flexDirection & wxHORIZONTAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1283 {
1284 int sum_proportions = 0;
1285 int growable_space = 0;
1286 int num = 0;
1287 size_t idx;
1288 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1289 {
1290 // Since the number of rows/columns can change as items are
1291 // inserted/deleted, we need to verify at runtime that the
1292 // requested growable rows/columns are still valid.
1293 if (m_growableCols[idx] >= ncols)
1294 continue;
1295
1296 // If all items in a row/column are hidden, that row/column will
1297 // have a dimension of -1. This causes the column to be hidden
1298 // completely.
1299 if (m_colWidths[ m_growableCols[idx] ] == -1)
1300 continue;
1301 sum_proportions += m_growableColsProportions[idx];
1302 growable_space += m_colWidths[ m_growableCols[idx] ];
1303 num++;
1304 }
1305
1306 if (num > 0)
1307 {
1308 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1309 {
1310 if (m_growableCols[idx] >= ncols )
1311 continue;
1312 if (m_colWidths[ m_growableCols[idx] ] == -1)
1313 m_colWidths[ m_growableCols[idx] ] = 0;
1314 else
1315 {
1316 int delta = (sz.x - minsz.x);
1317 if (sum_proportions == 0)
1318 delta = (delta/num) + m_colWidths[ m_growableCols[idx] ];
1319 else
1320 delta = ((delta+growable_space)*m_growableColsProportions[idx])/sum_proportions;
1321 m_colWidths[ m_growableCols[idx] ] = delta;
1322 }
1323 }
1324 }
1325 }
1326 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.x > minsz.x) )
1327 {
1328 for ( int col=0; col < ncols; ++col )
1329 m_colWidths[ col ] = sz.x / ncols;
1330 }
f6bcfd97
BP
1331}
1332
20b35a69 1333
e8800dcf 1334void wxFlexGridSizer::AddGrowableRow( size_t idx, int proportion )
f6bcfd97
BP
1335{
1336 m_growableRows.Add( idx );
e8800dcf 1337 m_growableRowsProportions.Add( proportion );
f6bcfd97
BP
1338}
1339
8d2474f4 1340void wxFlexGridSizer::RemoveGrowableRow( size_t idx )
f6bcfd97 1341{
8d2474f4 1342 m_growableRows.Remove( idx );
f6bcfd97
BP
1343}
1344
e8800dcf 1345void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
f6bcfd97
BP
1346{
1347 m_growableCols.Add( idx );
e8800dcf 1348 m_growableColsProportions.Add( proportion );
f6bcfd97
BP
1349}
1350
8d2474f4 1351void wxFlexGridSizer::RemoveGrowableCol( size_t idx )
f6bcfd97 1352{
8d2474f4 1353 m_growableCols.Remove( idx );
f6bcfd97
BP
1354}
1355
c62ac5b6 1356//---------------------------------------------------------------------------
92afa2b1 1357// wxBoxSizer
61d514bb
RR
1358//---------------------------------------------------------------------------
1359
92afa2b1 1360wxBoxSizer::wxBoxSizer( int orient )
12a3f227 1361 : m_orient( orient )
61d514bb 1362{
61d514bb
RR
1363}
1364
92afa2b1 1365void wxBoxSizer::RecalcSizes()
61d514bb
RR
1366{
1367 if (m_children.GetCount() == 0)
61d514bb 1368 return;
0c0d686f 1369
61d514bb 1370 int delta = 0;
61d514bb
RR
1371 if (m_stretchable)
1372 {
1373 if (m_orient == wxHORIZONTAL)
85e5cfc9 1374 delta = m_size.x - m_fixedWidth;
3ca6a5f0 1375 else
85e5cfc9 1376 delta = m_size.y - m_fixedHeight;
61d514bb 1377 }
0c0d686f 1378
61d514bb 1379 wxPoint pt( m_position );
0c0d686f 1380
222ed1d6 1381 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
61d514bb
RR
1382 while (node)
1383 {
12a3f227
RL
1384 wxSizerItem *item = node->GetData();
1385
2b5f62a0 1386 if (item->IsShown())
3ca6a5f0 1387 {
ba763a45 1388 wxSize size( item->GetMinSizeWithBorder() );
3ca6a5f0 1389
2b5f62a0 1390 if (m_orient == wxVERTICAL)
3ca6a5f0 1391 {
2b5f62a0 1392 wxCoord height = size.y;
12a3f227 1393 if (item->GetProportion())
2b5f62a0 1394 {
85e5cfc9
VZ
1395 // Because of at least one visible item has non-zero
1396 // proportion then m_stretchable is not zero
1397 height = (delta * item->GetProportion()) / m_stretchable;
2b5f62a0
VZ
1398 }
1399
1400 wxPoint child_pos( pt );
1401 wxSize child_size( wxSize( size.x, height) );
1402
1403 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1404 child_size.x = m_size.x;
1405 else if (item->GetFlag() & wxALIGN_RIGHT)
1406 child_pos.x += m_size.x - size.x;
1407 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
1408 // XXX wxCENTER is added for backward compatibility;
1409 // wxALIGN_CENTER should be used in new code
1410 child_pos.x += (m_size.x - size.x) / 2;
1411
1412 item->SetDimension( child_pos, child_size );
1413
1414 pt.y += height;
1415 }
1416 else
1417 {
1418 wxCoord width = size.x;
12a3f227 1419 if (item->GetProportion())
2b5f62a0 1420 {
85e5cfc9
VZ
1421 // Because of at least one visible item has non-zero
1422 // proportion then m_stretchable is not zero
1423 width = (delta * item->GetProportion()) / m_stretchable;
2b5f62a0
VZ
1424 }
1425
1426 wxPoint child_pos( pt );
1427 wxSize child_size( wxSize(width, size.y) );
1428
1429 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1430 child_size.y = m_size.y;
1431 else if (item->GetFlag() & wxALIGN_BOTTOM)
1432 child_pos.y += m_size.y - size.y;
1433 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
1434 // XXX wxCENTER is added for backward compatibility;
1435 // wxALIGN_CENTER should be used in new code
1436 child_pos.y += (m_size.y - size.y) / 2;
1437
1438 item->SetDimension( child_pos, child_size );
1439
1440 pt.x += width;
3ca6a5f0 1441 }
3ca6a5f0
BP
1442 }
1443
12a3f227 1444 node = node->GetNext();
61d514bb
RR
1445 }
1446}
1447
92afa2b1 1448wxSize wxBoxSizer::CalcMin()
61d514bb
RR
1449{
1450 if (m_children.GetCount() == 0)
c7a9fa36 1451 return wxSize(10,10);
0c0d686f 1452
61d514bb
RR
1453 m_stretchable = 0;
1454 m_minWidth = 0;
1455 m_minHeight = 0;
1456 m_fixedWidth = 0;
1457 m_fixedHeight = 0;
0c0d686f 1458
ba763a45 1459 // precalc item minsizes and count proportions
222ed1d6 1460 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
85e5cfc9
VZ
1461 while (node)
1462 {
1463 wxSizerItem *item = node->GetData();
12a3f227 1464
ba763a45
RD
1465 if (item->IsShown())
1466 item->CalcMin(); // result is stored in the item
1467
85e5cfc9
VZ
1468 if (item->IsShown() && item->GetProportion() != 0)
1469 m_stretchable += item->GetProportion();
1470
1471 node = node->GetNext();
1472 }
1473
1474 // Total minimum size (width or height) of sizer
1475 int maxMinSize = 0;
1476
1477 node = m_children.GetFirst();
61d514bb 1478 while (node)
f98de448 1479 {
85e5cfc9 1480 wxSizerItem *item = node->GetData();
12a3f227
RL
1481
1482 if (item->IsShown() && item->GetProportion() != 0)
f98de448 1483 {
12a3f227 1484 int stretch = item->GetProportion();
ba763a45 1485 wxSize size( item->GetMinSizeWithBorder() );
85e5cfc9
VZ
1486 int minSize;
1487
f98de448 1488 // Integer division rounded up is (a + b - 1) / b
85e5cfc9
VZ
1489 // Round up needed in order to guarantee that all
1490 // all items will have size not less then their min size
f98de448 1491 if (m_orient == wxHORIZONTAL)
85e5cfc9 1492 minSize = ( size.x*m_stretchable + stretch - 1)/stretch;
f98de448 1493 else
85e5cfc9
VZ
1494 minSize = ( size.y*m_stretchable + stretch - 1)/stretch;
1495
1496 if (minSize > maxMinSize)
1497 maxMinSize = minSize;
f98de448 1498 }
12a3f227 1499 node = node->GetNext();
f98de448 1500 }
12a3f227 1501
4f469fb5
RR
1502 // Calculate overall minimum size
1503 node = m_children.GetFirst();
f98de448 1504 while (node)
61d514bb 1505 {
85e5cfc9 1506 wxSizerItem *item = node->GetData();
12a3f227 1507
2b5f62a0 1508 if (item->IsShown())
f98de448 1509 {
ba763a45 1510 wxSize size( item->GetMinSizeWithBorder() );
12a3f227 1511 if (item->GetProportion() != 0)
2b5f62a0
VZ
1512 {
1513 if (m_orient == wxHORIZONTAL)
85e5cfc9 1514 size.x = (maxMinSize*item->GetProportion())/m_stretchable;
2b5f62a0 1515 else
85e5cfc9 1516 size.y = (maxMinSize*item->GetProportion())/m_stretchable;
3ca6a5f0
BP
1517 }
1518 else
2b5f62a0
VZ
1519 {
1520 if (m_orient == wxVERTICAL)
1521 {
1522 m_fixedHeight += size.y;
1523 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1524 }
1525 else
1526 {
1527 m_fixedWidth += size.x;
1528 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1529 }
1530 }
85e5cfc9
VZ
1531
1532 if (m_orient == wxHORIZONTAL)
1533 {
1534 m_minWidth += size.x;
1535 m_minHeight = wxMax( m_minHeight, size.y );
1536 }
1537 else
1538 {
1539 m_minHeight += size.y;
1540 m_minWidth = wxMax( m_minWidth, size.x );
1541 }
2b5f62a0 1542 }
12a3f227 1543 node = node->GetNext();
61d514bb 1544 }
0c0d686f 1545
61d514bb
RR
1546 return wxSize( m_minWidth, m_minHeight );
1547}
27ea1d8a
RR
1548
1549//---------------------------------------------------------------------------
1550// wxStaticBoxSizer
1551//---------------------------------------------------------------------------
1552
1e6feb95
VZ
1553#if wxUSE_STATBOX
1554
27ea1d8a 1555wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
12a3f227
RL
1556 : wxBoxSizer( orient )
1557 , m_staticBox( box )
27ea1d8a 1558{
223d09f6 1559 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
27ea1d8a 1560}
0c0d686f 1561
12a3f227
RL
1562static void GetStaticBoxBorders( wxStaticBox *box,
1563 int *borderTop,
1564 int *borderOther)
84028727
VZ
1565{
1566 // this has to be done platform by platform as there is no way to
1567 // guess the thickness of a wxStaticBox border
ec4e4a14
DE
1568#ifdef __WXCOCOA__
1569 box->GetBordersForSizer(borderTop,borderOther);
67021102
DS
1570#elif defined(__WXMAC__)
1571
1572 static int extraTop = -1; // Uninitted
1573 static int other = 5;
1574
1575 if ( extraTop == -1 )
1576 {
67021102
DS
1577 // The minimal border used for the top. Later on the staticbox'
1578 // font height is added to this.
1579 extraTop = 0;
1580
78ca5669 1581 if ( UMAGetSystemVersion() >= 0x1030 /*Panther*/ )
67021102
DS
1582 {
1583 // As indicated by the HIG, Panther needs an extra border of 11
1584 // pixels (otherwise overlapping occurs at the top). The "other"
1585 // border has to be 11.
1586 extraTop = 11;
1587 other = 11;
1588 }
1589
1590 }
1591
1592 *borderTop = extraTop + box->GetCharHeight();
1593 *borderOther = other;
1594
1595#else
84028727
VZ
1596#ifdef __WXGTK__
1597 if ( box->GetLabel().IsEmpty() )
1598 *borderTop = 5;
1599 else
1600#endif // __WXGTK__
f2b99f63
JS
1601 *borderTop = box->GetCharHeight();
1602
84028727 1603 *borderOther = 5;
ec4e4a14 1604#endif // __WXCOCOA__
84028727
VZ
1605}
1606
27ea1d8a
RR
1607void wxStaticBoxSizer::RecalcSizes()
1608{
84028727
VZ
1609 int top_border, other_border;
1610 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
27ea1d8a
RR
1611
1612 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
0c0d686f 1613
27ea1d8a
RR
1614 wxPoint old_pos( m_position );
1615 m_position.x += other_border;
1616 m_position.y += top_border;
1617 wxSize old_size( m_size );
1618 m_size.x -= 2*other_border;
1619 m_size.y -= top_border + other_border;
0c0d686f 1620
27ea1d8a 1621 wxBoxSizer::RecalcSizes();
0c0d686f 1622
27ea1d8a
RR
1623 m_position = old_pos;
1624 m_size = old_size;
1625}
1626
1627wxSize wxStaticBoxSizer::CalcMin()
1628{
84028727
VZ
1629 int top_border, other_border;
1630 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
0c0d686f 1631
27ea1d8a 1632 wxSize ret( wxBoxSizer::CalcMin() );
cae31b8b 1633 ret.x += 2*other_border;
27ea1d8a 1634 ret.y += other_border + top_border;
0c0d686f 1635
27ea1d8a
RR
1636 return ret;
1637}
83edc0a5 1638
eb2a7883
VZ
1639void wxStaticBoxSizer::ShowItems( bool show )
1640{
1641 m_staticBox->Show( show );
1642 wxBoxSizer::ShowItems( show );
1643}
1644
1e6feb95
VZ
1645#endif // wxUSE_STATBOX
1646
adbf2d73
VS
1647
1648#if WXWIN_COMPATIBILITY_2_4
1649
ade4eb65 1650// ----------------------------------------------------------------------------
83edc0a5 1651// wxNotebookSizer
ade4eb65 1652// ----------------------------------------------------------------------------
83edc0a5 1653
adbf2d73
VS
1654#if wxUSE_BOOKCTRL
1655IMPLEMENT_CLASS(wxBookCtrlSizer, wxSizer)
1656#if wxUSE_NOTEBOOK
1657IMPLEMENT_CLASS(wxNotebookSizer, wxBookCtrlSizer)
1658#endif // wxUSE_NOTEBOOK
1659#endif // wxUSE_BOOKCTRL
1660
ade4eb65 1661#if wxUSE_BOOKCTRL
60be2f47 1662
ade4eb65
VZ
1663wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrl *bookctrl)
1664 : m_bookctrl(bookctrl)
83edc0a5 1665{
ade4eb65 1666 wxASSERT_MSG( bookctrl, wxT("wxBookCtrlSizer needs a control") );
83edc0a5
RR
1667}
1668
ade4eb65 1669void wxBookCtrlSizer::RecalcSizes()
83edc0a5 1670{
ade4eb65 1671 m_bookctrl->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
83edc0a5
RR
1672}
1673
ade4eb65 1674wxSize wxBookCtrlSizer::CalcMin()
83edc0a5 1675{
ade4eb65 1676 wxSize sizeBorder = m_bookctrl->CalcSizeFromPage(wxSize(0, 0));
1e6feb95
VZ
1677
1678 sizeBorder.x += 5;
1679 sizeBorder.y += 5;
3ca6a5f0 1680
ade4eb65 1681 if ( m_bookctrl->GetPageCount() == 0 )
1e6feb95
VZ
1682 {
1683 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
1684 }
83edc0a5
RR
1685
1686 int maxX = 0;
1687 int maxY = 0;
1688
ade4eb65
VZ
1689 wxWindowList::compatibility_iterator
1690 node = m_bookctrl->GetChildren().GetFirst();
83edc0a5
RR
1691 while (node)
1692 {
1693 wxWindow *item = node->GetData();
3ca6a5f0
BP
1694 wxSizer *itemsizer = item->GetSizer();
1695
1696 if (itemsizer)
1697 {
83edc0a5 1698 wxSize subsize( itemsizer->CalcMin() );
83edc0a5 1699
1e6feb95
VZ
1700 if (subsize.x > maxX)
1701 maxX = subsize.x;
1702 if (subsize.y > maxY)
1703 maxY = subsize.y;
3ca6a5f0
BP
1704 }
1705
1706 node = node->GetNext();
83edc0a5
RR
1707 }
1708
1e6feb95 1709 return wxSize( maxX, maxY ) + sizeBorder;
83edc0a5
RR
1710}
1711
2d480e40
RD
1712#if wxUSE_NOTEBOOK
1713
1714wxNotebookSizer::wxNotebookSizer(wxNotebook *nb)
2d480e40 1715{
adbf2d73
VS
1716 wxASSERT_MSG( nb, wxT("wxNotebookSizer needs a control") );
1717 m_bookctrl = nb;
2d480e40
RD
1718}
1719
1720#endif // wxUSE_NOTEBOOOK
ade4eb65 1721#endif // wxUSE_BOOKCTRL
34c3ffca 1722
adbf2d73 1723#endif // WXWIN_COMPATIBILITY_2_4