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