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