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