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