]> git.saurik.com Git - wxWidgets.git/blame - src/common/sizer.cpp
if we return GetSize() from DoGetBestSize(), remember it as min size as well to preve...
[wxWidgets.git] / src / common / sizer.cpp
CommitLineData
5279a24d
RR
1/////////////////////////////////////////////////////////////////////////////
2// Name: sizer.cpp
1044a386 3// Purpose: provide new wxSizer class for layout
aa5973ee
JS
4// Author: Robert Roebling and Robin Dunn, contributions by
5// Dirk Holtwick, Ron Lee
566d84a7 6// Modified by: Ron Lee
0c0d686f 7// Created:
5279a24d 8// RCS-ID: $Id$
aa5973ee 9// Copyright: (c) Robin Dunn, Robert Roebling
65571936 10// Licence: wxWindows licence
5279a24d
RR
11/////////////////////////////////////////////////////////////////////////////
12
14f355c2 13#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
c62ac5b6 14#pragma implementation "sizer.h"
5279a24d
RR
15#endif
16
77671fd2
VZ
17// For compilers that support precompilation, includes "wx.h".
18#include "wx/wxprec.h"
19
20#ifdef __BORLANDC__
21 #pragma hdrstop
22#endif
23
0f769aab
WS
24#ifndef WX_PRECOMP
25 #include "wx/string.h"
26 #include "wx/intl.h"
27#endif // WX_PRECOMP
28
5279a24d 29#include "wx/sizer.h"
61d514bb 30#include "wx/utils.h"
27ea1d8a 31#include "wx/statbox.h"
acf2ac37 32#include "wx/settings.h"
c54b92d3 33#include "wx/listimpl.cpp"
efba61ba 34#include "wx/intl.h"
adbf2d73
VS
35#if WXWIN_COMPATIBILITY_2_4
36 #include "wx/notebook.h"
37#endif
5279a24d 38
0c0d686f
RD
39//---------------------------------------------------------------------------
40
9cbee2ce
RL
41IMPLEMENT_CLASS(wxSizerItem, wxObject)
42IMPLEMENT_CLASS(wxSizer, wxObject)
43IMPLEMENT_CLASS(wxGridSizer, wxSizer)
44IMPLEMENT_CLASS(wxFlexGridSizer, wxGridSizer)
45IMPLEMENT_CLASS(wxBoxSizer, wxSizer)
1e6feb95 46#if wxUSE_STATBOX
9cbee2ce 47IMPLEMENT_CLASS(wxStaticBoxSizer, wxBoxSizer)
1e6feb95 48#endif
974c2a59 49#if wxUSE_BUTTON
acf2ac37 50IMPLEMENT_CLASS(wxStdDialogButtonSizer, wxBoxSizer)
974c2a59 51#endif
0c0d686f 52
12a3f227
RL
53WX_DEFINE_EXPORTED_LIST( wxSizerItemList );
54
066f1b7a 55/*
8b2bac62
WS
56 TODO PROPERTIES
57 sizeritem
58 object
59 object_ref
60 minsize
61 option
62 flag
63 border
066f1b7a 64 spacer
8b2bac62
WS
65 option
66 flag
67 borfder
68 boxsizer
69 orient
066f1b7a 70 staticboxsizer
8b2bac62
WS
71 orient
72 label
73 gridsizer
74 rows
75 cols
76 vgap
77 hgap
78 flexgridsizer
79 rows
80 cols
81 vgap
82 hgap
83 growablerows
84 growablecols
066f1b7a
SC
85 minsize
86*/
ccbc8038 87
50c06297 88// ----------------------------------------------------------------------------
3417c2cd 89// wxSizerItem
50c06297 90// ----------------------------------------------------------------------------
ccbc8038
VZ
91
92void wxSizerItem::Init(const wxSizerFlags& flags)
93{
94 Init();
95
96 m_proportion = flags.GetProportion();
97 m_flag = flags.GetFlags();
98 m_border = flags.GetBorderInPixels();
99}
100
50c06297
VZ
101wxSizerItem::wxSizerItem()
102{
103 Init();
104
105 m_proportion = 0;
106 m_border = 0;
107 m_flag = 0;
108
109 m_kind = Item_None;
110}
111
112// window item
113void wxSizerItem::SetWindow(wxWindow *window)
114{
115 wxCHECK_RET( window, _T("NULL window in wxSizerItem::SetWindow()") );
116
117 m_kind = Item_Window;
118 m_window = window;
119
120 // window doesn't become smaller than its initial size, whatever happens
ba763a45 121 m_minSize = window->GetSize();
8b2bac62 122
50c06297
VZ
123 if ( m_flag & wxFIXED_MINSIZE )
124 window->SetMinSize(m_minSize);
125
36461f58 126 // aspect ratio calculated from initial size
50c06297
VZ
127 SetRatio(m_minSize);
128}
36461f58 129
50c06297
VZ
130wxSizerItem::wxSizerItem(wxWindow *window,
131 int proportion,
132 int flag,
133 int border,
134 wxObject* userData)
135 : m_proportion(proportion),
136 m_border(border),
137 m_flag(flag),
138 m_userData(userData)
139{
140 SetWindow(window);
5279a24d
RR
141}
142
50c06297
VZ
143// sizer item
144void wxSizerItem::SetSizer(wxSizer *sizer)
5279a24d 145{
50c06297
VZ
146 m_kind = Item_Sizer;
147 m_sizer = sizer;
5279a24d
RR
148}
149
50c06297
VZ
150wxSizerItem::wxSizerItem(wxSizer *sizer,
151 int proportion,
152 int flag,
153 int border,
154 wxObject* userData)
155 : m_proportion(proportion),
156 m_border(border),
157 m_flag(flag),
158 m_ratio(0.0),
159 m_userData(userData)
20b35a69 160{
50c06297 161 SetSizer(sizer);
ccbc8038 162
50c06297
VZ
163 // m_minSize is set later
164}
165
166// spacer item
167void wxSizerItem::SetSpacer(const wxSize& size)
168{
169 m_kind = Item_Spacer;
170 m_spacer = new wxSizerSpacer(size);
171 m_minSize = size;
172 SetRatio(size);
173}
174
175wxSizerItem::wxSizerItem(int width,
176 int height,
177 int proportion,
178 int flag,
179 int border,
180 wxObject* userData)
181 : m_minSize(width, height), // minimal size is the initial size
182 m_proportion(proportion),
183 m_border(border),
184 m_flag(flag),
185 m_userData(userData)
186{
187 SetSpacer(width, height);
20b35a69
RD
188}
189
0c0d686f
RD
190wxSizerItem::~wxSizerItem()
191{
f91e8382
VZ
192 delete m_userData;
193
50c06297 194 switch ( m_kind )
f91e8382 195 {
50c06297
VZ
196 case Item_None:
197 break;
198
199 case Item_Window:
200 m_window->SetContainingSizer(NULL);
201 break;
202
203 case Item_Sizer:
204 delete m_sizer;
205 break;
206
207 case Item_Spacer:
208 delete m_spacer;
209 break;
210
211 case Item_Max:
212 default:
213 wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
f91e8382 214 }
0c0d686f
RD
215}
216
50c06297
VZ
217wxSize wxSizerItem::GetSpacer() const
218{
219 wxSize size;
220 if ( m_kind == Item_Spacer )
221 size = m_spacer->GetSize();
222
223 return size;
224}
225
0c0d686f 226
9cbee2ce 227wxSize wxSizerItem::GetSize() const
5279a24d 228{
d597fcb7 229 wxSize ret;
50c06297
VZ
230 switch ( m_kind )
231 {
232 case Item_None:
233 break;
234
235 case Item_Window:
236 ret = m_window->GetSize();
237 break;
238
239 case Item_Sizer:
240 ret = m_sizer->GetSize();
241 break;
242
243 case Item_Spacer:
244 ret = m_spacer->GetSize();
245 break;
246
247 case Item_Max:
248 default:
249 wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
250 }
0c0d686f 251
d597fcb7
RR
252 if (m_flag & wxWEST)
253 ret.x += m_border;
254 if (m_flag & wxEAST)
255 ret.x += m_border;
256 if (m_flag & wxNORTH)
257 ret.y += m_border;
258 if (m_flag & wxSOUTH)
259 ret.y += m_border;
0c0d686f 260
d597fcb7 261 return ret;
5279a24d
RR
262}
263
3417c2cd 264wxSize wxSizerItem::CalcMin()
c62ac5b6 265{
3417c2cd 266 if (IsSizer())
be2577e4 267 {
ba763a45 268 m_minSize = m_sizer->GetMinSize();
d13d8d4e 269
be2577e4
RD
270 // if we have to preserve aspect ratio _AND_ this is
271 // the first-time calculation, consider ret to be initial size
d13d8d4e 272 if ((m_flag & wxSHAPED) && !m_ratio)
36461f58 273 SetRatio(m_minSize);
be2577e4 274 }
ba763a45 275 else if ( IsWindow() )
d13d8d4e 276 {
ba763a45
RD
277 // Since the size of the window may change during runtime, we
278 // should use the current minimal/best size.
279 m_minSize = m_window->GetBestFittingSize();
d13d8d4e 280 }
0c0d686f 281
ba763a45
RD
282 return GetMinSizeWithBorder();
283}
284
285wxSize wxSizerItem::GetMinSizeWithBorder() const
286{
287 wxSize ret = m_minSize;
288
d597fcb7
RR
289 if (m_flag & wxWEST)
290 ret.x += m_border;
291 if (m_flag & wxEAST)
292 ret.x += m_border;
293 if (m_flag & wxNORTH)
294 ret.y += m_border;
295 if (m_flag & wxSOUTH)
296 ret.y += m_border;
8b2bac62 297
d597fcb7 298 return ret;
c62ac5b6
RR
299}
300
ba763a45 301
3417c2cd 302void wxSizerItem::SetDimension( wxPoint pos, wxSize size )
c62ac5b6 303{
cdddaeea 304 if (m_flag & wxSHAPED)
d597fcb7 305 {
be2577e4
RD
306 // adjust aspect ratio
307 int rwidth = (int) (size.y * m_ratio);
cdddaeea
VZ
308 if (rwidth > size.x)
309 {
be2577e4
RD
310 // fit horizontally
311 int rheight = (int) (size.x / m_ratio);
312 // add vertical space
313 if (m_flag & wxALIGN_CENTER_VERTICAL)
314 pos.y += (size.y - rheight) / 2;
315 else if (m_flag & wxALIGN_BOTTOM)
316 pos.y += (size.y - rheight);
317 // use reduced dimensions
318 size.y =rheight;
cdddaeea
VZ
319 }
320 else if (rwidth < size.x)
321 {
be2577e4
RD
322 // add horizontal space
323 if (m_flag & wxALIGN_CENTER_HORIZONTAL)
324 pos.x += (size.x - rwidth) / 2;
325 else if (m_flag & wxALIGN_RIGHT)
326 pos.x += (size.x - rwidth);
327 size.x = rwidth;
328 }
329 }
33ac7e6f 330
cdddaeea
VZ
331 // This is what GetPosition() returns. Since we calculate
332 // borders afterwards, GetPosition() will be the left/top
333 // corner of the surrounding border.
334 m_pos = pos;
335
336 if (m_flag & wxWEST)
337 {
338 pos.x += m_border;
339 size.x -= m_border;
340 }
341 if (m_flag & wxEAST)
342 {
343 size.x -= m_border;
344 }
345 if (m_flag & wxNORTH)
346 {
347 pos.y += m_border;
348 size.y -= m_border;
349 }
350 if (m_flag & wxSOUTH)
351 {
352 size.y -= m_border;
353 }
0c0d686f 354
50c06297 355 m_rect = wxRect(pos, size);
0c0d686f 356
50c06297
VZ
357 switch ( m_kind )
358 {
359 case Item_None:
360 wxFAIL_MSG( _T("can't set size of uninitialized sizer item") );
361 break;
362
363 case Item_Window:
364 m_window->SetSize(pos.x, pos.y, size.x, size.y,
365 wxSIZE_ALLOW_MINUS_ONE);
366 break;
367
368 case Item_Sizer:
369 m_sizer->SetDimension(pos.x, pos.y, size.x, size.y);
370 break;
371
372 case Item_Spacer:
373 m_spacer->SetSize(size);
374 break;
375
376 case Item_Max:
377 default:
378 wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
379 }
c62ac5b6
RR
380}
381
84f7908b
RR
382void wxSizerItem::DeleteWindows()
383{
50c06297 384 switch ( m_kind )
77aa9abd 385 {
50c06297
VZ
386 case Item_None:
387 case Item_Spacer:
388 break;
389
390 case Item_Window:
caa2490c
RN
391 //We are deleting the window from this sizer - normally
392 //the window destroys the sizer associated with it,
393 //which might destroy this, which we don't want
394 m_window->SetContainingSizer(NULL);
50c06297 395 m_window->Destroy();
caa2490c
RN
396 //Putting this after the switch will result in a spacer
397 //not being deleted properly on destruction
398 m_kind = Item_None;
50c06297
VZ
399 break;
400
401 case Item_Sizer:
402 m_sizer->DeleteWindows();
403 break;
404
405 case Item_Max:
406 default:
407 wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
77aa9abd 408 }
be90c029 409
84f7908b
RR
410}
411
50c06297 412void wxSizerItem::Show( bool show )
5279a24d 413{
50c06297
VZ
414 switch ( m_kind )
415 {
416 case Item_None:
417 wxFAIL_MSG( _T("can't show uninitialized sizer item") );
418 break;
5279a24d 419
50c06297
VZ
420 case Item_Window:
421 m_window->Show(show);
422 break;
5279a24d 423
50c06297 424 case Item_Sizer:
3a5910cb 425 m_sizer->Show(show);
50c06297
VZ
426 break;
427
428 case Item_Spacer:
429 m_spacer->Show(show);
430 break;
431
432 case Item_Max:
433 default:
434 wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
435 }
5279a24d
RR
436}
437
50c06297 438bool wxSizerItem::IsShown() const
12a3f227 439{
50c06297
VZ
440 switch ( m_kind )
441 {
442 case Item_None:
443 wxFAIL_MSG( _T("uninitialized sizer item") );
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 )
12a3f227
RL
1056 : m_rows( rows )
1057 , m_cols( cols )
1058 , m_vgap( vgap )
1059 , m_hgap( hgap )
f6bcfd97 1060{
02319c24
RD
1061 if (m_rows == 0 && m_cols == 0)
1062 m_rows = 1;
f6bcfd97
BP
1063}
1064
1065wxGridSizer::wxGridSizer( int cols, int vgap, int hgap )
12a3f227
RL
1066 : m_rows( 0 )
1067 , m_cols( cols )
1068 , m_vgap( vgap )
1069 , m_hgap( hgap )
f6bcfd97 1070{
02319c24
RD
1071 if (m_rows == 0 && m_cols == 0)
1072 m_rows = 1;
f6bcfd97
BP
1073}
1074
0ca5105b 1075int wxGridSizer::CalcRowsCols(int& nrows, int& ncols) const
f6bcfd97 1076{
f6bcfd97 1077 int nitems = m_children.GetCount();
2b5f62a0 1078 if ( nitems)
0ca5105b
VZ
1079 {
1080 if ( m_cols )
1081 {
1082 ncols = m_cols;
1083 nrows = (nitems + m_cols - 1) / m_cols;
1084 }
1085 else if ( m_rows )
1086 {
1087 ncols = (nitems + m_rows - 1) / m_rows;
1088 nrows = m_rows;
1089 }
1090 else // 0 columns, 0 rows?
1091 {
1092 wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") );
f6bcfd97 1093
0ca5105b
VZ
1094 nrows = ncols = 0;
1095 }
1096 }
1097
1098 return nitems;
1099}
1100
1101void wxGridSizer::RecalcSizes()
1102{
1103 int nitems, nrows, ncols;
1104 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
1105 return;
f6bcfd97
BP
1106
1107 wxSize sz( GetSize() );
1108 wxPoint pt( GetPosition() );
3ca6a5f0
BP
1109
1110 int w = (sz.x - (ncols - 1) * m_hgap) / ncols;
1111 int h = (sz.y - (nrows - 1) * m_vgap) / nrows;
f6bcfd97
BP
1112
1113 int x = pt.x;
1114 for (int c = 0; c < ncols; c++)
1115 {
1116 int y = pt.y;
1117 for (int r = 0; r < nrows; r++)
1118 {
1119 int i = r * ncols + c;
1120 if (i < nitems)
1121 {
222ed1d6 1122 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
12a3f227
RL
1123
1124 wxASSERT_MSG( node, _T("Failed to find SizerItemList node") );
3ca6a5f0 1125
12a3f227 1126 SetItemBounds( node->GetData(), x, y, w, h);
f6bcfd97
BP
1127 }
1128 y = y + h + m_vgap;
1129 }
1130 x = x + w + m_hgap;
1131 }
1132}
1133
1134wxSize wxGridSizer::CalcMin()
1135{
196be0f1
JS
1136 int nrows, ncols;
1137 if ( CalcRowsCols(nrows, ncols) == 0 )
0ca5105b 1138 return wxSize(10, 10);
f6bcfd97 1139
4f469fb5 1140 // Find the max width and height for any component
f6bcfd97
BP
1141 int w = 0;
1142 int h = 0;
3ca6a5f0 1143
222ed1d6 1144 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
f6bcfd97
BP
1145 while (node)
1146 {
12a3f227
RL
1147 wxSizerItem *item = node->GetData();
1148 wxSize sz( item->CalcMin() );
1149
f6bcfd97
BP
1150 w = wxMax( w, sz.x );
1151 h = wxMax( h, sz.y );
3ca6a5f0 1152
12a3f227 1153 node = node->GetNext();
f6bcfd97 1154 }
3ca6a5f0 1155
12a3f227
RL
1156 return wxSize( ncols * w + (ncols-1) * m_hgap,
1157 nrows * h + (nrows-1) * m_vgap );
f6bcfd97
BP
1158}
1159
1160void wxGridSizer::SetItemBounds( wxSizerItem *item, int x, int y, int w, int h )
1161{
1162 wxPoint pt( x,y );
8b2bac62 1163 wxSize sz( item->GetMinSizeWithBorder() );
f6bcfd97
BP
1164 int flag = item->GetFlag();
1165
1166 if ((flag & wxEXPAND) || (flag & wxSHAPED))
1167 {
1168 sz = wxSize(w, h);
1169 }
1170 else
1171 {
1172 if (flag & wxALIGN_CENTER_HORIZONTAL)
1173 {
559b747d 1174 pt.x = x + (w - sz.x) / 2;
f6bcfd97
BP
1175 }
1176 else if (flag & wxALIGN_RIGHT)
1177 {
559b747d 1178 pt.x = x + (w - sz.x);
f6bcfd97 1179 }
3ca6a5f0 1180
f6bcfd97
BP
1181 if (flag & wxALIGN_CENTER_VERTICAL)
1182 {
559b747d 1183 pt.y = y + (h - sz.y) / 2;
f6bcfd97
BP
1184 }
1185 else if (flag & wxALIGN_BOTTOM)
1186 {
559b747d 1187 pt.y = y + (h - sz.y);
f6bcfd97
BP
1188 }
1189 }
3ca6a5f0 1190
f6bcfd97
BP
1191 item->SetDimension(pt, sz);
1192}
1193
1194//---------------------------------------------------------------------------
1195// wxFlexGridSizer
1196//---------------------------------------------------------------------------
1197
1198wxFlexGridSizer::wxFlexGridSizer( int rows, int cols, int vgap, int hgap )
5d76f462
VZ
1199 : wxGridSizer( rows, cols, vgap, hgap ),
1200 m_flexDirection(wxBOTH),
1201 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
3ca6a5f0 1202{
f6bcfd97
BP
1203}
1204
1205wxFlexGridSizer::wxFlexGridSizer( int cols, int vgap, int hgap )
5d76f462
VZ
1206 : wxGridSizer( cols, vgap, hgap ),
1207 m_flexDirection(wxBOTH),
1208 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
3ca6a5f0 1209{
f6bcfd97 1210}
3ca6a5f0 1211
f6bcfd97
BP
1212wxFlexGridSizer::~wxFlexGridSizer()
1213{
f6bcfd97
BP
1214}
1215
1216void wxFlexGridSizer::RecalcSizes()
1217{
0ca5105b
VZ
1218 int nitems, nrows, ncols;
1219 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
f6bcfd97
BP
1220 return;
1221
20b35a69 1222 wxPoint pt( GetPosition() );
f6bcfd97 1223 wxSize sz( GetSize() );
5d76f462 1224
ba763a45 1225 AdjustForGrowables(sz, m_calculatedMinSize, nrows, ncols);
3ca6a5f0 1226
f6bcfd97
BP
1227 sz = wxSize( pt.x + sz.x, pt.y + sz.y );
1228
1229 int x = pt.x;
1230 for (int c = 0; c < ncols; c++)
1231 {
1232 int y = pt.y;
1233 for (int r = 0; r < nrows; r++)
1234 {
1235 int i = r * ncols + c;
1236 if (i < nitems)
1237 {
222ed1d6 1238 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
12a3f227
RL
1239
1240 wxASSERT_MSG( node, _T("Failed to find node") );
3ca6a5f0 1241
f6bcfd97
BP
1242 int w = wxMax( 0, wxMin( m_colWidths[c], sz.x - x ) );
1243 int h = wxMax( 0, wxMin( m_rowHeights[r], sz.y - y ) );
3ca6a5f0 1244
12a3f227 1245 SetItemBounds( node->GetData(), x, y, w, h);
f6bcfd97 1246 }
53701799
RD
1247 if (m_rowHeights[r] != -1)
1248 y = y + m_rowHeights[r] + m_vgap;
f6bcfd97 1249 }
53701799
RD
1250 if (m_colWidths[c] != -1)
1251 x = x + m_colWidths[c] + m_hgap;
f6bcfd97
BP
1252 }
1253}
1254
1255wxSize wxFlexGridSizer::CalcMin()
1256{
150c8d89
RL
1257 int nrows,
1258 ncols;
1259 size_t i, s;
1260
55f9f0cb 1261 // Number of rows/columns can change as items are added or removed.
5d76f462
VZ
1262 if ( !CalcRowsCols(nrows, ncols) )
1263 return wxSize(10, 10);
f6bcfd97 1264
5d76f462
VZ
1265 m_rowHeights.SetCount(nrows);
1266 m_colWidths.SetCount(ncols);
3ca6a5f0 1267
395a82b1
VZ
1268 // We have to recalcuate the sizes in case the item minimum size has
1269 // changed since the previous layout, or the item has been hidden using
1270 // wxSizer::Show(). If all the items in a row/column are hidden, the final
1271 // dimension of the row/column will be -1, indicating that the column
1272 // itself is hidden.
55f9f0cb
VZ
1273 for( s = m_rowHeights.GetCount(), i = 0; i < s; ++i )
1274 m_rowHeights[ i ] = -1;
1275 for( s = m_colWidths.GetCount(), i = 0; i < s; ++i )
1276 m_colWidths[ i ] = -1;
1277
222ed1d6 1278 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
12a3f227 1279
150c8d89 1280 i = 0;
f6bcfd97
BP
1281 while (node)
1282 {
12a3f227 1283 wxSizerItem *item = node->GetData();
55f9f0cb
VZ
1284 if ( item->IsShown() )
1285 {
1286 wxSize sz( item->CalcMin() );
1287 int row = i / ncols;
1288 int col = i % ncols;
12a3f227 1289
55f9f0cb
VZ
1290 m_rowHeights[ row ] = wxMax( wxMax( 0, sz.y ), m_rowHeights[ row ] );
1291 m_colWidths[ col ] = wxMax( wxMax( 0, sz.x ), m_colWidths[ col ] );
1292 }
3ca6a5f0 1293
12a3f227 1294 node = node->GetNext();
f6bcfd97
BP
1295 i++;
1296 }
3ca6a5f0 1297
20b35a69 1298 AdjustForFlexDirection();
8b2bac62 1299
20b35a69
RD
1300 // Sum total minimum size, including gaps between rows/columns.
1301 // -1 is used as a magic number meaning empty column.
1302 int width = 0;
1303 for (int col = 0; col < ncols; col++)
1304 if ( m_colWidths[ col ] != -1 )
53701799
RD
1305 width += m_colWidths[ col ] + m_hgap;
1306 if (width > 0)
1307 width -= m_hgap;
20b35a69
RD
1308
1309 int height = 0;
1310 for (int row = 0; row < nrows; row++)
1311 if ( m_rowHeights[ row ] != -1 )
53701799
RD
1312 height += m_rowHeights[ row ] + m_vgap;
1313 if (height > 0)
1314 height -= m_vgap;
20b35a69 1315
ba763a45
RD
1316 m_calculatedMinSize = wxSize( width, height );
1317 return m_calculatedMinSize;
20b35a69
RD
1318}
1319
1320void wxFlexGridSizer::AdjustForFlexDirection()
1321{
1322 // the logic in CalcMin works when we resize flexibly in both directions
1323 // but maybe this is not the case
5d76f462
VZ
1324 if ( m_flexDirection != wxBOTH )
1325 {
1326 // select the array corresponding to the direction in which we do *not*
1327 // resize flexibly
1328 wxArrayInt& array = m_flexDirection == wxVERTICAL ? m_colWidths
1329 : m_rowHeights;
1330
1331 const int count = array.GetCount();
1332
1333 // find the largest value in this array
55f9f0cb 1334 int n, largest = 0;
5d76f462
VZ
1335 for ( n = 0; n < count; ++n )
1336 {
1337 if ( array[n] > largest )
1338 largest = array[n];
1339 }
1340
1341 // and now fill it with the largest value
1342 for ( n = 0; n < count; ++n )
1343 {
1344 array[n] = largest;
1345 }
1346 }
8b2bac62 1347}
5d76f462 1348
3ca6a5f0 1349
20b35a69
RD
1350void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz, const wxSize& minsz,
1351 int nrows, int ncols)
1352{
1353 // what to do with the rows? by default, resize them proportionally
1354 if ( sz.y > minsz.y && ( (m_flexDirection & wxVERTICAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1355 {
1356 int sum_proportions = 0;
1357 int growable_space = 0;
1358 int num = 0;
1359 size_t idx;
1360 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1361 {
1362 // Since the number of rows/columns can change as items are
1363 // inserted/deleted, we need to verify at runtime that the
1364 // requested growable rows/columns are still valid.
1365 if (m_growableRows[idx] >= nrows)
1366 continue;
8b2bac62 1367
20b35a69
RD
1368 // If all items in a row/column are hidden, that row/column will
1369 // have a dimension of -1. This causes the row/column to be
1370 // hidden completely.
1371 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1372 continue;
1373 sum_proportions += m_growableRowsProportions[idx];
1374 growable_space += m_rowHeights[ m_growableRows[idx] ];
1375 num++;
1376 }
3ca6a5f0 1377
20b35a69
RD
1378 if (num > 0)
1379 {
1380 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1381 {
1382 if (m_growableRows[idx] >= nrows )
1383 continue;
1384 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1385 m_rowHeights[ m_growableRows[idx] ] = 0;
1386 else
1387 {
1388 int delta = (sz.y - minsz.y);
1389 if (sum_proportions == 0)
1390 delta = (delta/num) + m_rowHeights[ m_growableRows[idx] ];
1391 else
1392 delta = ((delta+growable_space)*m_growableRowsProportions[idx]) / sum_proportions;
1393 m_rowHeights[ m_growableRows[idx] ] = delta;
1394 }
1395 }
1396 }
1397 }
1398 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.y > minsz.y) )
1399 {
1400 // rounding problem?
1401 for ( int row = 0; row < nrows; ++row )
1402 m_rowHeights[ row ] = sz.y / nrows;
1403 }
1404
1405 // the same logic as above but for the columns
1406 if ( sz.x > minsz.x && ( (m_flexDirection & wxHORIZONTAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1407 {
1408 int sum_proportions = 0;
1409 int growable_space = 0;
1410 int num = 0;
1411 size_t idx;
1412 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1413 {
1414 // Since the number of rows/columns can change as items are
1415 // inserted/deleted, we need to verify at runtime that the
1416 // requested growable rows/columns are still valid.
1417 if (m_growableCols[idx] >= ncols)
1418 continue;
8b2bac62 1419
20b35a69
RD
1420 // If all items in a row/column are hidden, that row/column will
1421 // have a dimension of -1. This causes the column to be hidden
1422 // completely.
1423 if (m_colWidths[ m_growableCols[idx] ] == -1)
1424 continue;
1425 sum_proportions += m_growableColsProportions[idx];
1426 growable_space += m_colWidths[ m_growableCols[idx] ];
1427 num++;
1428 }
1429
1430 if (num > 0)
1431 {
1432 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1433 {
1434 if (m_growableCols[idx] >= ncols )
1435 continue;
1436 if (m_colWidths[ m_growableCols[idx] ] == -1)
1437 m_colWidths[ m_growableCols[idx] ] = 0;
1438 else
1439 {
1440 int delta = (sz.x - minsz.x);
1441 if (sum_proportions == 0)
1442 delta = (delta/num) + m_colWidths[ m_growableCols[idx] ];
1443 else
1444 delta = ((delta+growable_space)*m_growableColsProportions[idx])/sum_proportions;
1445 m_colWidths[ m_growableCols[idx] ] = delta;
1446 }
1447 }
1448 }
1449 }
1450 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.x > minsz.x) )
1451 {
1452 for ( int col=0; col < ncols; ++col )
1453 m_colWidths[ col ] = sz.x / ncols;
1454 }
f6bcfd97
BP
1455}
1456
20b35a69 1457
e8800dcf 1458void wxFlexGridSizer::AddGrowableRow( size_t idx, int proportion )
f6bcfd97
BP
1459{
1460 m_growableRows.Add( idx );
e8800dcf 1461 m_growableRowsProportions.Add( proportion );
f6bcfd97
BP
1462}
1463
8d2474f4 1464void wxFlexGridSizer::RemoveGrowableRow( size_t idx )
f6bcfd97 1465{
8d2474f4 1466 m_growableRows.Remove( idx );
f6bcfd97
BP
1467}
1468
e8800dcf 1469void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
f6bcfd97
BP
1470{
1471 m_growableCols.Add( idx );
e8800dcf 1472 m_growableColsProportions.Add( proportion );
f6bcfd97
BP
1473}
1474
8d2474f4 1475void wxFlexGridSizer::RemoveGrowableCol( size_t idx )
f6bcfd97 1476{
8d2474f4 1477 m_growableCols.Remove( idx );
f6bcfd97
BP
1478}
1479
c62ac5b6 1480//---------------------------------------------------------------------------
92afa2b1 1481// wxBoxSizer
61d514bb
RR
1482//---------------------------------------------------------------------------
1483
92afa2b1 1484wxBoxSizer::wxBoxSizer( int orient )
12a3f227 1485 : m_orient( orient )
61d514bb 1486{
61d514bb
RR
1487}
1488
92afa2b1 1489void wxBoxSizer::RecalcSizes()
61d514bb
RR
1490{
1491 if (m_children.GetCount() == 0)
61d514bb 1492 return;
0c0d686f 1493
61d514bb 1494 int delta = 0;
61d514bb
RR
1495 if (m_stretchable)
1496 {
1497 if (m_orient == wxHORIZONTAL)
85e5cfc9 1498 delta = m_size.x - m_fixedWidth;
3ca6a5f0 1499 else
85e5cfc9 1500 delta = m_size.y - m_fixedHeight;
61d514bb 1501 }
0c0d686f 1502
61d514bb 1503 wxPoint pt( m_position );
0c0d686f 1504
222ed1d6 1505 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
61d514bb
RR
1506 while (node)
1507 {
12a3f227
RL
1508 wxSizerItem *item = node->GetData();
1509
2b5f62a0 1510 if (item->IsShown())
3ca6a5f0 1511 {
ba763a45 1512 wxSize size( item->GetMinSizeWithBorder() );
3ca6a5f0 1513
2b5f62a0 1514 if (m_orient == wxVERTICAL)
3ca6a5f0 1515 {
2b5f62a0 1516 wxCoord height = size.y;
12a3f227 1517 if (item->GetProportion())
2b5f62a0 1518 {
85e5cfc9
VZ
1519 // Because of at least one visible item has non-zero
1520 // proportion then m_stretchable is not zero
1521 height = (delta * item->GetProportion()) / m_stretchable;
2b5f62a0
VZ
1522 }
1523
1524 wxPoint child_pos( pt );
42841dfc 1525 wxSize child_size( size.x, height );
2b5f62a0
VZ
1526
1527 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1528 child_size.x = m_size.x;
1529 else if (item->GetFlag() & wxALIGN_RIGHT)
1530 child_pos.x += m_size.x - size.x;
1531 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
1532 // XXX wxCENTER is added for backward compatibility;
1533 // wxALIGN_CENTER should be used in new code
1534 child_pos.x += (m_size.x - size.x) / 2;
1535
1536 item->SetDimension( child_pos, child_size );
1537
1538 pt.y += height;
1539 }
1540 else
1541 {
1542 wxCoord width = size.x;
12a3f227 1543 if (item->GetProportion())
2b5f62a0 1544 {
85e5cfc9
VZ
1545 // Because of at least one visible item has non-zero
1546 // proportion then m_stretchable is not zero
1547 width = (delta * item->GetProportion()) / m_stretchable;
2b5f62a0
VZ
1548 }
1549
1550 wxPoint child_pos( pt );
42841dfc 1551 wxSize child_size( width, size.y );
2b5f62a0
VZ
1552
1553 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1554 child_size.y = m_size.y;
1555 else if (item->GetFlag() & wxALIGN_BOTTOM)
1556 child_pos.y += m_size.y - size.y;
1557 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
1558 // XXX wxCENTER is added for backward compatibility;
1559 // wxALIGN_CENTER should be used in new code
1560 child_pos.y += (m_size.y - size.y) / 2;
1561
1562 item->SetDimension( child_pos, child_size );
1563
1564 pt.x += width;
3ca6a5f0 1565 }
3ca6a5f0
BP
1566 }
1567
12a3f227 1568 node = node->GetNext();
61d514bb
RR
1569 }
1570}
1571
92afa2b1 1572wxSize wxBoxSizer::CalcMin()
61d514bb
RR
1573{
1574 if (m_children.GetCount() == 0)
c7a9fa36 1575 return wxSize(10,10);
0c0d686f 1576
61d514bb
RR
1577 m_stretchable = 0;
1578 m_minWidth = 0;
1579 m_minHeight = 0;
1580 m_fixedWidth = 0;
1581 m_fixedHeight = 0;
0c0d686f 1582
ba763a45 1583 // precalc item minsizes and count proportions
222ed1d6 1584 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
85e5cfc9
VZ
1585 while (node)
1586 {
1587 wxSizerItem *item = node->GetData();
12a3f227 1588
d4444410
VZ
1589 if ( item->IsShown() )
1590 {
ba763a45 1591 item->CalcMin(); // result is stored in the item
8b2bac62 1592
85e5cfc9 1593 m_stretchable += item->GetProportion();
d4444410 1594 }
85e5cfc9
VZ
1595
1596 node = node->GetNext();
1597 }
1598
1599 // Total minimum size (width or height) of sizer
1600 int maxMinSize = 0;
1601
1602 node = m_children.GetFirst();
61d514bb 1603 while (node)
f98de448 1604 {
85e5cfc9 1605 wxSizerItem *item = node->GetData();
12a3f227
RL
1606
1607 if (item->IsShown() && item->GetProportion() != 0)
f98de448 1608 {
12a3f227 1609 int stretch = item->GetProportion();
ba763a45 1610 wxSize size( item->GetMinSizeWithBorder() );
85e5cfc9 1611 int minSize;
8b2bac62 1612
f98de448 1613 // Integer division rounded up is (a + b - 1) / b
85e5cfc9
VZ
1614 // Round up needed in order to guarantee that all
1615 // all items will have size not less then their min size
f98de448 1616 if (m_orient == wxHORIZONTAL)
85e5cfc9 1617 minSize = ( size.x*m_stretchable + stretch - 1)/stretch;
f98de448 1618 else
85e5cfc9 1619 minSize = ( size.y*m_stretchable + stretch - 1)/stretch;
8b2bac62 1620
85e5cfc9
VZ
1621 if (minSize > maxMinSize)
1622 maxMinSize = minSize;
f98de448 1623 }
12a3f227 1624 node = node->GetNext();
f98de448 1625 }
12a3f227 1626
4f469fb5
RR
1627 // Calculate overall minimum size
1628 node = m_children.GetFirst();
f98de448 1629 while (node)
61d514bb 1630 {
85e5cfc9 1631 wxSizerItem *item = node->GetData();
12a3f227 1632
2b5f62a0 1633 if (item->IsShown())
f98de448 1634 {
ba763a45 1635 wxSize size( item->GetMinSizeWithBorder() );
12a3f227 1636 if (item->GetProportion() != 0)
2b5f62a0
VZ
1637 {
1638 if (m_orient == wxHORIZONTAL)
85e5cfc9 1639 size.x = (maxMinSize*item->GetProportion())/m_stretchable;
2b5f62a0 1640 else
85e5cfc9 1641 size.y = (maxMinSize*item->GetProportion())/m_stretchable;
3ca6a5f0
BP
1642 }
1643 else
2b5f62a0
VZ
1644 {
1645 if (m_orient == wxVERTICAL)
1646 {
1647 m_fixedHeight += size.y;
1648 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1649 }
1650 else
1651 {
1652 m_fixedWidth += size.x;
1653 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1654 }
1655 }
85e5cfc9
VZ
1656
1657 if (m_orient == wxHORIZONTAL)
1658 {
1659 m_minWidth += size.x;
1660 m_minHeight = wxMax( m_minHeight, size.y );
1661 }
1662 else
1663 {
1664 m_minHeight += size.y;
1665 m_minWidth = wxMax( m_minWidth, size.x );
1666 }
2b5f62a0 1667 }
12a3f227 1668 node = node->GetNext();
61d514bb 1669 }
0c0d686f 1670
61d514bb
RR
1671 return wxSize( m_minWidth, m_minHeight );
1672}
27ea1d8a
RR
1673
1674//---------------------------------------------------------------------------
1675// wxStaticBoxSizer
1676//---------------------------------------------------------------------------
1677
1e6feb95
VZ
1678#if wxUSE_STATBOX
1679
27ea1d8a 1680wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
12a3f227
RL
1681 : wxBoxSizer( orient )
1682 , m_staticBox( box )
27ea1d8a 1683{
223d09f6 1684 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
27ea1d8a 1685}
0c0d686f 1686
6c1635b5
VZ
1687wxStaticBoxSizer::wxStaticBoxSizer(int orient, wxWindow *win, const wxString& s)
1688 : wxBoxSizer(orient),
1689 m_staticBox(new wxStaticBox(win, wxID_ANY, s))
1690{
1691}
1692
12a3f227
RL
1693static void GetStaticBoxBorders( wxStaticBox *box,
1694 int *borderTop,
1695 int *borderOther)
84028727
VZ
1696{
1697 // this has to be done platform by platform as there is no way to
1698 // guess the thickness of a wxStaticBox border
5dd070c2 1699 box->GetBordersForSizer(borderTop, borderOther);
84028727
VZ
1700}
1701
27ea1d8a
RR
1702void wxStaticBoxSizer::RecalcSizes()
1703{
84028727
VZ
1704 int top_border, other_border;
1705 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
27ea1d8a
RR
1706
1707 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
0c0d686f 1708
27ea1d8a
RR
1709 wxPoint old_pos( m_position );
1710 m_position.x += other_border;
1711 m_position.y += top_border;
1712 wxSize old_size( m_size );
1713 m_size.x -= 2*other_border;
1714 m_size.y -= top_border + other_border;
0c0d686f 1715
27ea1d8a 1716 wxBoxSizer::RecalcSizes();
0c0d686f 1717
27ea1d8a
RR
1718 m_position = old_pos;
1719 m_size = old_size;
1720}
1721
1722wxSize wxStaticBoxSizer::CalcMin()
1723{
84028727
VZ
1724 int top_border, other_border;
1725 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
0c0d686f 1726
27ea1d8a 1727 wxSize ret( wxBoxSizer::CalcMin() );
cae31b8b 1728 ret.x += 2*other_border;
27ea1d8a 1729 ret.y += other_border + top_border;
0c0d686f 1730
27ea1d8a
RR
1731 return ret;
1732}
83edc0a5 1733
eb2a7883
VZ
1734void wxStaticBoxSizer::ShowItems( bool show )
1735{
1736 m_staticBox->Show( show );
1737 wxBoxSizer::ShowItems( show );
1738}
1739
1e6feb95
VZ
1740#endif // wxUSE_STATBOX
1741
974c2a59
WS
1742#if wxUSE_BUTTON
1743
acf2ac37
RR
1744wxStdDialogButtonSizer::wxStdDialogButtonSizer()
1745 : wxBoxSizer(wxHORIZONTAL)
1746{
94f53923
JS
1747 // Vertical buttons with lots of space on either side
1748 // looks rubbish on WinCE, so let's not do this for now.
1749 // If we are going to use vertical buttons, we should
1750 // put the sizer to the right of other controls in the dialog,
1751 // and that's beyond the scope of this sizer.
1752#ifndef __WXWINCE__
acf2ac37 1753 bool is_pda = (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA);
974c2a59 1754 // If we have a PDA screen, put yes/no button over
acf2ac37
RR
1755 // all other buttons, otherwise on the left side.
1756 if (is_pda)
1757 m_orient = wxVERTICAL;
94f53923 1758#endif
974c2a59 1759
acf2ac37
RR
1760 m_buttonAffirmative = NULL;
1761 m_buttonApply = NULL;
1762 m_buttonNegative = NULL;
1763 m_buttonCancel = NULL;
1764 m_buttonHelp = NULL;
1765}
1766
1767void wxStdDialogButtonSizer::AddButton(wxButton *mybutton)
1768{
1769 switch (mybutton->GetId())
1770 {
1771 case wxID_OK:
1772 case wxID_YES:
1773 case wxID_SAVE:
1774 m_buttonAffirmative = mybutton;
1775 break;
1776 case wxID_APPLY:
1777 m_buttonApply = mybutton;
1778 break;
1779 case wxID_NO:
1780 m_buttonNegative = mybutton;
1781 break;
1782 case wxID_CANCEL:
1783 m_buttonCancel = mybutton;
1784 break;
1785 case wxID_HELP:
2997ca30 1786 case wxID_CONTEXT_HELP:
acf2ac37
RR
1787 m_buttonHelp = mybutton;
1788 break;
1789 default:
1790 break;
1791 }
1792}
1793
b181a505
RR
1794void wxStdDialogButtonSizer::SetAffirmativeButton( wxButton *button )
1795{
1796 m_buttonAffirmative = button;
1797}
1798
1799void wxStdDialogButtonSizer::SetNegativeButton( wxButton *button )
1800{
1801 m_buttonNegative = button;
1802}
1803
1804void wxStdDialogButtonSizer::SetCancelButton( wxButton *button )
1805{
1806 m_buttonCancel = button;
1807}
1808
718903fe 1809void wxStdDialogButtonSizer::Realize()
acf2ac37
RR
1810{
1811#ifdef __WXMAC__
1812 Add(0, 0, 0, wxLEFT, 6);
1813 if (m_buttonHelp)
974c2a59
WS
1814 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 6);
1815
acf2ac37
RR
1816 if (m_buttonNegative){
1817 // HIG POLICE BULLETIN - destructive buttons need extra padding
1818 // 24 pixels on either side
1819 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 12);
1820 }
974c2a59 1821
acf2ac37 1822 // extra whitespace between help/negative and cancel/ok buttons
974c2a59
WS
1823 Add(0, 0, 1, wxEXPAND, 0);
1824
acf2ac37
RR
1825 if (m_buttonCancel){
1826 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 6);
1827 // Cancel or help should be default
1828 // m_buttonCancel->SetDefaultButton();
1829 }
974c2a59
WS
1830
1831 // Ugh, Mac doesn't really have apply dialogs, so I'll just
acf2ac37
RR
1832 // figure the best place is between Cancel and OK
1833 if (m_buttonApply)
1834 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 6);
974c2a59 1835
acf2ac37
RR
1836 if (m_buttonAffirmative){
1837 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT, 6);
974c2a59 1838
acf2ac37
RR
1839 if (m_buttonAffirmative->GetId() == wxID_SAVE){
1840 // these buttons have set labels under Mac so we should use them
1841 m_buttonAffirmative->SetLabel(_("Save"));
1842 m_buttonNegative->SetLabel(_("Don't Save"));
1843 }
1844 }
974c2a59 1845
acf2ac37
RR
1846 // Extra space around and at the right
1847 Add(12, 24);
1848#elif defined(__WXGTK20__)
1849 Add(0, 0, 0, wxLEFT, 9);
1850 if (m_buttonHelp)
974c2a59
WS
1851 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
1852
acf2ac37 1853 // extra whitespace between help and cancel/ok buttons
974c2a59
WS
1854 Add(0, 0, 1, wxEXPAND, 0);
1855
acf2ac37
RR
1856 if (m_buttonNegative){
1857 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
1858 }
974c2a59 1859
acf2ac37
RR
1860 if (m_buttonCancel){
1861 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
1862 // Cancel or help should be default
1863 // m_buttonCancel->SetDefaultButton();
1864 }
974c2a59 1865
acf2ac37
RR
1866 if (m_buttonApply)
1867 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
974c2a59 1868
acf2ac37
RR
1869 if (m_buttonAffirmative)
1870 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT, 6);
0f884515
JS
1871#elif defined(__WXMSW__)
1872 // Windows
1873
1874 // right-justify buttons
1875 Add(0, 0, 1, wxEXPAND, 0);
1876
1877 if (m_buttonAffirmative){
1878 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonAffirmative->ConvertDialogToPixels(wxSize(2, 0)).x);
1879 }
1880
1881 if (m_buttonNegative){
1882 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonNegative->ConvertDialogToPixels(wxSize(2, 0)).x);
1883 }
1884
1885 if (m_buttonCancel){
1886 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonCancel->ConvertDialogToPixels(wxSize(2, 0)).x);
1887 }
1888 if (m_buttonApply)
1889 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonApply->ConvertDialogToPixels(wxSize(2, 0)).x);
1890
1891 if (m_buttonHelp)
1892 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonHelp->ConvertDialogToPixels(wxSize(2, 0)).x);
acf2ac37 1893#else
0f884515
JS
1894 // GTK+1 and any other platform
1895
23b1018f 1896 // Add(0, 0, 0, wxLEFT, 5); // Not sure what this was for but it unbalances the dialog
acf2ac37 1897 if (m_buttonHelp)
974c2a59
WS
1898 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonHelp->ConvertDialogToPixels(wxSize(4, 0)).x);
1899
acf2ac37 1900 // extra whitespace between help and cancel/ok buttons
974c2a59 1901 Add(0, 0, 1, wxEXPAND, 0);
acf2ac37
RR
1902
1903 if (m_buttonApply)
1904 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonApply->ConvertDialogToPixels(wxSize(4, 0)).x);
974c2a59 1905
acf2ac37
RR
1906 if (m_buttonAffirmative){
1907 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonAffirmative->ConvertDialogToPixels(wxSize(4, 0)).x);
1908 }
974c2a59 1909
acf2ac37
RR
1910 if (m_buttonNegative){
1911 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonNegative->ConvertDialogToPixels(wxSize(4, 0)).x);
1912 }
974c2a59 1913
acf2ac37 1914 if (m_buttonCancel){
23b1018f 1915 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonCancel->ConvertDialogToPixels(wxSize(4, 0)).x);
acf2ac37
RR
1916 // Cancel or help should be default
1917 // m_buttonCancel->SetDefaultButton();
1918 }
974c2a59 1919
acf2ac37
RR
1920#endif
1921}
adbf2d73 1922
974c2a59
WS
1923#endif // wxUSE_BUTTON
1924
adbf2d73
VS
1925#if WXWIN_COMPATIBILITY_2_4
1926
ade4eb65 1927// ----------------------------------------------------------------------------
83edc0a5 1928// wxNotebookSizer
ade4eb65 1929// ----------------------------------------------------------------------------
83edc0a5 1930
adbf2d73
VS
1931#if wxUSE_BOOKCTRL
1932IMPLEMENT_CLASS(wxBookCtrlSizer, wxSizer)
1933#if wxUSE_NOTEBOOK
1934IMPLEMENT_CLASS(wxNotebookSizer, wxBookCtrlSizer)
1935#endif // wxUSE_NOTEBOOK
1936#endif // wxUSE_BOOKCTRL
1937
ade4eb65 1938#if wxUSE_BOOKCTRL
60be2f47 1939
61c083e7 1940wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrlBase *bookctrl)
ade4eb65 1941 : m_bookctrl(bookctrl)
83edc0a5 1942{
ade4eb65 1943 wxASSERT_MSG( bookctrl, wxT("wxBookCtrlSizer needs a control") );
83edc0a5
RR
1944}
1945
ade4eb65 1946void wxBookCtrlSizer::RecalcSizes()
83edc0a5 1947{
ade4eb65 1948 m_bookctrl->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
83edc0a5
RR
1949}
1950
ade4eb65 1951wxSize wxBookCtrlSizer::CalcMin()
83edc0a5 1952{
c47addef 1953 wxSize sizeBorder = m_bookctrl->CalcSizeFromPage(wxSize(0,0));
1e6feb95
VZ
1954
1955 sizeBorder.x += 5;
1956 sizeBorder.y += 5;
3ca6a5f0 1957
ade4eb65 1958 if ( m_bookctrl->GetPageCount() == 0 )
1e6feb95
VZ
1959 {
1960 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
1961 }
83edc0a5
RR
1962
1963 int maxX = 0;
1964 int maxY = 0;
1965
ade4eb65
VZ
1966 wxWindowList::compatibility_iterator
1967 node = m_bookctrl->GetChildren().GetFirst();
83edc0a5
RR
1968 while (node)
1969 {
1970 wxWindow *item = node->GetData();
3ca6a5f0
BP
1971 wxSizer *itemsizer = item->GetSizer();
1972
1973 if (itemsizer)
1974 {
83edc0a5 1975 wxSize subsize( itemsizer->CalcMin() );
83edc0a5 1976
1e6feb95
VZ
1977 if (subsize.x > maxX)
1978 maxX = subsize.x;
1979 if (subsize.y > maxY)
1980 maxY = subsize.y;
3ca6a5f0
BP
1981 }
1982
1983 node = node->GetNext();
83edc0a5
RR
1984 }
1985
1e6feb95 1986 return wxSize( maxX, maxY ) + sizeBorder;
83edc0a5
RR
1987}
1988
2d480e40
RD
1989#if wxUSE_NOTEBOOK
1990
1991wxNotebookSizer::wxNotebookSizer(wxNotebook *nb)
2d480e40 1992{
adbf2d73
VS
1993 wxASSERT_MSG( nb, wxT("wxNotebookSizer needs a control") );
1994 m_bookctrl = nb;
2d480e40
RD
1995}
1996
1997#endif // wxUSE_NOTEBOOOK
ade4eb65 1998#endif // wxUSE_BOOKCTRL
34c3ffca 1999
adbf2d73 2000#endif // WXWIN_COMPATIBILITY_2_4