]> git.saurik.com Git - wxWidgets.git/blame - src/common/sizer.cpp
don't try to subclass tab control using the same window proc for our class, this...
[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
902725ee 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 )
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
1327 const int count = array.GetCount();
1328
1329 // find the largest value in this array
55f9f0cb 1330 int n, largest = 0;
5d76f462
VZ
1331 for ( n = 0; n < count; ++n )
1332 {
1333 if ( array[n] > largest )
1334 largest = array[n];
1335 }
1336
1337 // and now fill it with the largest value
1338 for ( n = 0; n < count; ++n )
1339 {
1340 array[n] = largest;
1341 }
1342 }
8b2bac62 1343}
5d76f462 1344
3ca6a5f0 1345
20b35a69
RD
1346void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz, const wxSize& minsz,
1347 int nrows, int ncols)
1348{
1349 // what to do with the rows? by default, resize them proportionally
1350 if ( sz.y > minsz.y && ( (m_flexDirection & wxVERTICAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1351 {
1352 int sum_proportions = 0;
1353 int growable_space = 0;
1354 int num = 0;
1355 size_t idx;
1356 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1357 {
1358 // Since the number of rows/columns can change as items are
1359 // inserted/deleted, we need to verify at runtime that the
1360 // requested growable rows/columns are still valid.
1361 if (m_growableRows[idx] >= nrows)
1362 continue;
8b2bac62 1363
20b35a69
RD
1364 // If all items in a row/column are hidden, that row/column will
1365 // have a dimension of -1. This causes the row/column to be
1366 // hidden completely.
1367 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1368 continue;
1369 sum_proportions += m_growableRowsProportions[idx];
1370 growable_space += m_rowHeights[ m_growableRows[idx] ];
1371 num++;
1372 }
3ca6a5f0 1373
20b35a69
RD
1374 if (num > 0)
1375 {
1376 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1377 {
1378 if (m_growableRows[idx] >= nrows )
1379 continue;
1380 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1381 m_rowHeights[ m_growableRows[idx] ] = 0;
1382 else
1383 {
1384 int delta = (sz.y - minsz.y);
1385 if (sum_proportions == 0)
1386 delta = (delta/num) + m_rowHeights[ m_growableRows[idx] ];
1387 else
1388 delta = ((delta+growable_space)*m_growableRowsProportions[idx]) / sum_proportions;
1389 m_rowHeights[ m_growableRows[idx] ] = delta;
1390 }
1391 }
1392 }
1393 }
1394 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.y > minsz.y) )
1395 {
1396 // rounding problem?
1397 for ( int row = 0; row < nrows; ++row )
1398 m_rowHeights[ row ] = sz.y / nrows;
1399 }
1400
1401 // the same logic as above but for the columns
1402 if ( sz.x > minsz.x && ( (m_flexDirection & wxHORIZONTAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1403 {
1404 int sum_proportions = 0;
1405 int growable_space = 0;
1406 int num = 0;
1407 size_t idx;
1408 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1409 {
1410 // Since the number of rows/columns can change as items are
1411 // inserted/deleted, we need to verify at runtime that the
1412 // requested growable rows/columns are still valid.
1413 if (m_growableCols[idx] >= ncols)
1414 continue;
8b2bac62 1415
20b35a69
RD
1416 // If all items in a row/column are hidden, that row/column will
1417 // have a dimension of -1. This causes the column to be hidden
1418 // completely.
1419 if (m_colWidths[ m_growableCols[idx] ] == -1)
1420 continue;
1421 sum_proportions += m_growableColsProportions[idx];
1422 growable_space += m_colWidths[ m_growableCols[idx] ];
1423 num++;
1424 }
1425
1426 if (num > 0)
1427 {
1428 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1429 {
1430 if (m_growableCols[idx] >= ncols )
1431 continue;
1432 if (m_colWidths[ m_growableCols[idx] ] == -1)
1433 m_colWidths[ m_growableCols[idx] ] = 0;
1434 else
1435 {
1436 int delta = (sz.x - minsz.x);
1437 if (sum_proportions == 0)
1438 delta = (delta/num) + m_colWidths[ m_growableCols[idx] ];
1439 else
1440 delta = ((delta+growable_space)*m_growableColsProportions[idx])/sum_proportions;
1441 m_colWidths[ m_growableCols[idx] ] = delta;
1442 }
1443 }
1444 }
1445 }
1446 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.x > minsz.x) )
1447 {
1448 for ( int col=0; col < ncols; ++col )
1449 m_colWidths[ col ] = sz.x / ncols;
1450 }
f6bcfd97
BP
1451}
1452
20b35a69 1453
e8800dcf 1454void wxFlexGridSizer::AddGrowableRow( size_t idx, int proportion )
f6bcfd97
BP
1455{
1456 m_growableRows.Add( idx );
e8800dcf 1457 m_growableRowsProportions.Add( proportion );
f6bcfd97
BP
1458}
1459
8d2474f4 1460void wxFlexGridSizer::RemoveGrowableRow( size_t idx )
f6bcfd97 1461{
8d2474f4 1462 m_growableRows.Remove( idx );
f6bcfd97
BP
1463}
1464
e8800dcf 1465void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
f6bcfd97
BP
1466{
1467 m_growableCols.Add( idx );
e8800dcf 1468 m_growableColsProportions.Add( proportion );
f6bcfd97
BP
1469}
1470
8d2474f4 1471void wxFlexGridSizer::RemoveGrowableCol( size_t idx )
f6bcfd97 1472{
8d2474f4 1473 m_growableCols.Remove( idx );
f6bcfd97
BP
1474}
1475
c62ac5b6 1476//---------------------------------------------------------------------------
92afa2b1 1477// wxBoxSizer
61d514bb
RR
1478//---------------------------------------------------------------------------
1479
92afa2b1 1480wxBoxSizer::wxBoxSizer( int orient )
12a3f227 1481 : m_orient( orient )
61d514bb 1482{
61d514bb
RR
1483}
1484
92afa2b1 1485void wxBoxSizer::RecalcSizes()
61d514bb
RR
1486{
1487 if (m_children.GetCount() == 0)
61d514bb 1488 return;
0c0d686f 1489
61d514bb 1490 int delta = 0;
61d514bb
RR
1491 if (m_stretchable)
1492 {
1493 if (m_orient == wxHORIZONTAL)
85e5cfc9 1494 delta = m_size.x - m_fixedWidth;
3ca6a5f0 1495 else
85e5cfc9 1496 delta = m_size.y - m_fixedHeight;
61d514bb 1497 }
0c0d686f 1498
61d514bb 1499 wxPoint pt( m_position );
0c0d686f 1500
222ed1d6 1501 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
61d514bb
RR
1502 while (node)
1503 {
12a3f227
RL
1504 wxSizerItem *item = node->GetData();
1505
2b5f62a0 1506 if (item->IsShown())
3ca6a5f0 1507 {
ba763a45 1508 wxSize size( item->GetMinSizeWithBorder() );
3ca6a5f0 1509
2b5f62a0 1510 if (m_orient == wxVERTICAL)
3ca6a5f0 1511 {
2b5f62a0 1512 wxCoord height = size.y;
12a3f227 1513 if (item->GetProportion())
2b5f62a0 1514 {
85e5cfc9
VZ
1515 // Because of at least one visible item has non-zero
1516 // proportion then m_stretchable is not zero
1517 height = (delta * item->GetProportion()) / m_stretchable;
2b5f62a0
VZ
1518 }
1519
1520 wxPoint child_pos( pt );
42841dfc 1521 wxSize child_size( size.x, height );
2b5f62a0
VZ
1522
1523 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1524 child_size.x = m_size.x;
1525 else if (item->GetFlag() & wxALIGN_RIGHT)
1526 child_pos.x += m_size.x - size.x;
1527 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
1528 // XXX wxCENTER is added for backward compatibility;
1529 // wxALIGN_CENTER should be used in new code
1530 child_pos.x += (m_size.x - size.x) / 2;
1531
1532 item->SetDimension( child_pos, child_size );
1533
1534 pt.y += height;
1535 }
1536 else
1537 {
1538 wxCoord width = size.x;
12a3f227 1539 if (item->GetProportion())
2b5f62a0 1540 {
85e5cfc9
VZ
1541 // Because of at least one visible item has non-zero
1542 // proportion then m_stretchable is not zero
1543 width = (delta * item->GetProportion()) / m_stretchable;
2b5f62a0
VZ
1544 }
1545
1546 wxPoint child_pos( pt );
42841dfc 1547 wxSize child_size( width, size.y );
2b5f62a0
VZ
1548
1549 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1550 child_size.y = m_size.y;
1551 else if (item->GetFlag() & wxALIGN_BOTTOM)
1552 child_pos.y += m_size.y - size.y;
1553 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
1554 // XXX wxCENTER is added for backward compatibility;
1555 // wxALIGN_CENTER should be used in new code
1556 child_pos.y += (m_size.y - size.y) / 2;
1557
1558 item->SetDimension( child_pos, child_size );
1559
1560 pt.x += width;
3ca6a5f0 1561 }
3ca6a5f0
BP
1562 }
1563
12a3f227 1564 node = node->GetNext();
61d514bb
RR
1565 }
1566}
1567
92afa2b1 1568wxSize wxBoxSizer::CalcMin()
61d514bb
RR
1569{
1570 if (m_children.GetCount() == 0)
c7a9fa36 1571 return wxSize(10,10);
0c0d686f 1572
61d514bb
RR
1573 m_stretchable = 0;
1574 m_minWidth = 0;
1575 m_minHeight = 0;
1576 m_fixedWidth = 0;
1577 m_fixedHeight = 0;
0c0d686f 1578
ba763a45 1579 // precalc item minsizes and count proportions
222ed1d6 1580 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
85e5cfc9
VZ
1581 while (node)
1582 {
1583 wxSizerItem *item = node->GetData();
12a3f227 1584
d4444410
VZ
1585 if ( item->IsShown() )
1586 {
ba763a45 1587 item->CalcMin(); // result is stored in the item
8b2bac62 1588
85e5cfc9 1589 m_stretchable += item->GetProportion();
d4444410 1590 }
85e5cfc9
VZ
1591
1592 node = node->GetNext();
1593 }
1594
1595 // Total minimum size (width or height) of sizer
1596 int maxMinSize = 0;
1597
1598 node = m_children.GetFirst();
61d514bb 1599 while (node)
f98de448 1600 {
85e5cfc9 1601 wxSizerItem *item = node->GetData();
12a3f227
RL
1602
1603 if (item->IsShown() && item->GetProportion() != 0)
f98de448 1604 {
12a3f227 1605 int stretch = item->GetProportion();
ba763a45 1606 wxSize size( item->GetMinSizeWithBorder() );
85e5cfc9 1607 int minSize;
8b2bac62 1608
f98de448 1609 // Integer division rounded up is (a + b - 1) / b
85e5cfc9
VZ
1610 // Round up needed in order to guarantee that all
1611 // all items will have size not less then their min size
f98de448 1612 if (m_orient == wxHORIZONTAL)
85e5cfc9 1613 minSize = ( size.x*m_stretchable + stretch - 1)/stretch;
f98de448 1614 else
85e5cfc9 1615 minSize = ( size.y*m_stretchable + stretch - 1)/stretch;
8b2bac62 1616
85e5cfc9
VZ
1617 if (minSize > maxMinSize)
1618 maxMinSize = minSize;
f98de448 1619 }
12a3f227 1620 node = node->GetNext();
f98de448 1621 }
12a3f227 1622
4f469fb5
RR
1623 // Calculate overall minimum size
1624 node = m_children.GetFirst();
f98de448 1625 while (node)
61d514bb 1626 {
85e5cfc9 1627 wxSizerItem *item = node->GetData();
12a3f227 1628
2b5f62a0 1629 if (item->IsShown())
f98de448 1630 {
ba763a45 1631 wxSize size( item->GetMinSizeWithBorder() );
12a3f227 1632 if (item->GetProportion() != 0)
2b5f62a0
VZ
1633 {
1634 if (m_orient == wxHORIZONTAL)
85e5cfc9 1635 size.x = (maxMinSize*item->GetProportion())/m_stretchable;
2b5f62a0 1636 else
85e5cfc9 1637 size.y = (maxMinSize*item->GetProportion())/m_stretchable;
3ca6a5f0
BP
1638 }
1639 else
2b5f62a0
VZ
1640 {
1641 if (m_orient == wxVERTICAL)
1642 {
1643 m_fixedHeight += size.y;
1644 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1645 }
1646 else
1647 {
1648 m_fixedWidth += size.x;
1649 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1650 }
1651 }
85e5cfc9
VZ
1652
1653 if (m_orient == wxHORIZONTAL)
1654 {
1655 m_minWidth += size.x;
1656 m_minHeight = wxMax( m_minHeight, size.y );
1657 }
1658 else
1659 {
1660 m_minHeight += size.y;
1661 m_minWidth = wxMax( m_minWidth, size.x );
1662 }
2b5f62a0 1663 }
12a3f227 1664 node = node->GetNext();
61d514bb 1665 }
0c0d686f 1666
61d514bb
RR
1667 return wxSize( m_minWidth, m_minHeight );
1668}
27ea1d8a
RR
1669
1670//---------------------------------------------------------------------------
1671// wxStaticBoxSizer
1672//---------------------------------------------------------------------------
1673
1e6feb95
VZ
1674#if wxUSE_STATBOX
1675
27ea1d8a 1676wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
12a3f227
RL
1677 : wxBoxSizer( orient )
1678 , m_staticBox( box )
27ea1d8a 1679{
223d09f6 1680 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
27ea1d8a 1681}
0c0d686f 1682
6c1635b5
VZ
1683wxStaticBoxSizer::wxStaticBoxSizer(int orient, wxWindow *win, const wxString& s)
1684 : wxBoxSizer(orient),
1685 m_staticBox(new wxStaticBox(win, wxID_ANY, s))
1686{
1687}
1688
12a3f227
RL
1689static void GetStaticBoxBorders( wxStaticBox *box,
1690 int *borderTop,
1691 int *borderOther)
84028727
VZ
1692{
1693 // this has to be done platform by platform as there is no way to
1694 // guess the thickness of a wxStaticBox border
5dd070c2 1695 box->GetBordersForSizer(borderTop, borderOther);
84028727
VZ
1696}
1697
27ea1d8a
RR
1698void wxStaticBoxSizer::RecalcSizes()
1699{
84028727
VZ
1700 int top_border, other_border;
1701 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
27ea1d8a
RR
1702
1703 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
0c0d686f 1704
27ea1d8a
RR
1705 wxPoint old_pos( m_position );
1706 m_position.x += other_border;
1707 m_position.y += top_border;
1708 wxSize old_size( m_size );
1709 m_size.x -= 2*other_border;
1710 m_size.y -= top_border + other_border;
0c0d686f 1711
27ea1d8a 1712 wxBoxSizer::RecalcSizes();
0c0d686f 1713
27ea1d8a
RR
1714 m_position = old_pos;
1715 m_size = old_size;
1716}
1717
1718wxSize wxStaticBoxSizer::CalcMin()
1719{
84028727
VZ
1720 int top_border, other_border;
1721 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
0c0d686f 1722
27ea1d8a 1723 wxSize ret( wxBoxSizer::CalcMin() );
cae31b8b 1724 ret.x += 2*other_border;
27ea1d8a 1725 ret.y += other_border + top_border;
0c0d686f 1726
27ea1d8a
RR
1727 return ret;
1728}
83edc0a5 1729
eb2a7883
VZ
1730void wxStaticBoxSizer::ShowItems( bool show )
1731{
1732 m_staticBox->Show( show );
1733 wxBoxSizer::ShowItems( show );
1734}
1735
1e6feb95
VZ
1736#endif // wxUSE_STATBOX
1737
974c2a59
WS
1738#if wxUSE_BUTTON
1739
acf2ac37
RR
1740wxStdDialogButtonSizer::wxStdDialogButtonSizer()
1741 : wxBoxSizer(wxHORIZONTAL)
1742{
94f53923
JS
1743 // Vertical buttons with lots of space on either side
1744 // looks rubbish on WinCE, so let's not do this for now.
1745 // If we are going to use vertical buttons, we should
1746 // put the sizer to the right of other controls in the dialog,
1747 // and that's beyond the scope of this sizer.
1748#ifndef __WXWINCE__
acf2ac37 1749 bool is_pda = (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA);
974c2a59 1750 // If we have a PDA screen, put yes/no button over
acf2ac37
RR
1751 // all other buttons, otherwise on the left side.
1752 if (is_pda)
1753 m_orient = wxVERTICAL;
94f53923 1754#endif
974c2a59 1755
acf2ac37
RR
1756 m_buttonAffirmative = NULL;
1757 m_buttonApply = NULL;
1758 m_buttonNegative = NULL;
1759 m_buttonCancel = NULL;
1760 m_buttonHelp = NULL;
1761}
1762
1763void wxStdDialogButtonSizer::AddButton(wxButton *mybutton)
1764{
1765 switch (mybutton->GetId())
1766 {
1767 case wxID_OK:
1768 case wxID_YES:
1769 case wxID_SAVE:
1770 m_buttonAffirmative = mybutton;
1771 break;
1772 case wxID_APPLY:
1773 m_buttonApply = mybutton;
1774 break;
1775 case wxID_NO:
1776 m_buttonNegative = mybutton;
1777 break;
1778 case wxID_CANCEL:
1779 m_buttonCancel = mybutton;
1780 break;
1781 case wxID_HELP:
2997ca30 1782 case wxID_CONTEXT_HELP:
acf2ac37
RR
1783 m_buttonHelp = mybutton;
1784 break;
1785 default:
1786 break;
1787 }
1788}
1789
b181a505
RR
1790void wxStdDialogButtonSizer::SetAffirmativeButton( wxButton *button )
1791{
1792 m_buttonAffirmative = button;
1793}
1794
1795void wxStdDialogButtonSizer::SetNegativeButton( wxButton *button )
1796{
1797 m_buttonNegative = button;
1798}
1799
1800void wxStdDialogButtonSizer::SetCancelButton( wxButton *button )
1801{
1802 m_buttonCancel = button;
1803}
1804
718903fe 1805void wxStdDialogButtonSizer::Realize()
acf2ac37
RR
1806{
1807#ifdef __WXMAC__
1808 Add(0, 0, 0, wxLEFT, 6);
1809 if (m_buttonHelp)
974c2a59
WS
1810 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 6);
1811
acf2ac37
RR
1812 if (m_buttonNegative){
1813 // HIG POLICE BULLETIN - destructive buttons need extra padding
1814 // 24 pixels on either side
1815 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 12);
1816 }
974c2a59 1817
acf2ac37 1818 // extra whitespace between help/negative and cancel/ok buttons
974c2a59
WS
1819 Add(0, 0, 1, wxEXPAND, 0);
1820
acf2ac37
RR
1821 if (m_buttonCancel){
1822 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 6);
1823 // Cancel or help should be default
1824 // m_buttonCancel->SetDefaultButton();
1825 }
974c2a59
WS
1826
1827 // Ugh, Mac doesn't really have apply dialogs, so I'll just
acf2ac37
RR
1828 // figure the best place is between Cancel and OK
1829 if (m_buttonApply)
1830 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 6);
974c2a59 1831
acf2ac37
RR
1832 if (m_buttonAffirmative){
1833 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT, 6);
974c2a59 1834
acf2ac37
RR
1835 if (m_buttonAffirmative->GetId() == wxID_SAVE){
1836 // these buttons have set labels under Mac so we should use them
1837 m_buttonAffirmative->SetLabel(_("Save"));
1838 m_buttonNegative->SetLabel(_("Don't Save"));
1839 }
1840 }
974c2a59 1841
acf2ac37
RR
1842 // Extra space around and at the right
1843 Add(12, 24);
1844#elif defined(__WXGTK20__)
1845 Add(0, 0, 0, wxLEFT, 9);
1846 if (m_buttonHelp)
974c2a59
WS
1847 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
1848
acf2ac37 1849 // extra whitespace between help and cancel/ok buttons
974c2a59
WS
1850 Add(0, 0, 1, wxEXPAND, 0);
1851
acf2ac37
RR
1852 if (m_buttonNegative){
1853 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
1854 }
974c2a59 1855
acf2ac37
RR
1856 if (m_buttonCancel){
1857 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
1858 // Cancel or help should be default
1859 // m_buttonCancel->SetDefaultButton();
1860 }
974c2a59 1861
acf2ac37
RR
1862 if (m_buttonApply)
1863 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
974c2a59 1864
acf2ac37
RR
1865 if (m_buttonAffirmative)
1866 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT, 6);
0f884515
JS
1867#elif defined(__WXMSW__)
1868 // Windows
1869
1870 // right-justify buttons
1871 Add(0, 0, 1, wxEXPAND, 0);
1872
1873 if (m_buttonAffirmative){
1874 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonAffirmative->ConvertDialogToPixels(wxSize(2, 0)).x);
1875 }
1876
1877 if (m_buttonNegative){
1878 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonNegative->ConvertDialogToPixels(wxSize(2, 0)).x);
1879 }
1880
1881 if (m_buttonCancel){
1882 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonCancel->ConvertDialogToPixels(wxSize(2, 0)).x);
1883 }
1884 if (m_buttonApply)
1885 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonApply->ConvertDialogToPixels(wxSize(2, 0)).x);
1886
1887 if (m_buttonHelp)
1888 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonHelp->ConvertDialogToPixels(wxSize(2, 0)).x);
acf2ac37 1889#else
0f884515 1890 // GTK+1 and any other platform
902725ee 1891
23b1018f 1892 // Add(0, 0, 0, wxLEFT, 5); // Not sure what this was for but it unbalances the dialog
acf2ac37 1893 if (m_buttonHelp)
974c2a59
WS
1894 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonHelp->ConvertDialogToPixels(wxSize(4, 0)).x);
1895
acf2ac37 1896 // extra whitespace between help and cancel/ok buttons
974c2a59 1897 Add(0, 0, 1, wxEXPAND, 0);
acf2ac37
RR
1898
1899 if (m_buttonApply)
1900 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonApply->ConvertDialogToPixels(wxSize(4, 0)).x);
974c2a59 1901
acf2ac37
RR
1902 if (m_buttonAffirmative){
1903 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonAffirmative->ConvertDialogToPixels(wxSize(4, 0)).x);
1904 }
974c2a59 1905
acf2ac37
RR
1906 if (m_buttonNegative){
1907 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonNegative->ConvertDialogToPixels(wxSize(4, 0)).x);
1908 }
974c2a59 1909
acf2ac37 1910 if (m_buttonCancel){
23b1018f 1911 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonCancel->ConvertDialogToPixels(wxSize(4, 0)).x);
acf2ac37
RR
1912 // Cancel or help should be default
1913 // m_buttonCancel->SetDefaultButton();
1914 }
974c2a59 1915
acf2ac37
RR
1916#endif
1917}
adbf2d73 1918
974c2a59
WS
1919#endif // wxUSE_BUTTON
1920
adbf2d73
VS
1921#if WXWIN_COMPATIBILITY_2_4
1922
ade4eb65 1923// ----------------------------------------------------------------------------
83edc0a5 1924// wxNotebookSizer
ade4eb65 1925// ----------------------------------------------------------------------------
83edc0a5 1926
adbf2d73
VS
1927#if wxUSE_BOOKCTRL
1928IMPLEMENT_CLASS(wxBookCtrlSizer, wxSizer)
1929#if wxUSE_NOTEBOOK
1930IMPLEMENT_CLASS(wxNotebookSizer, wxBookCtrlSizer)
1931#endif // wxUSE_NOTEBOOK
1932#endif // wxUSE_BOOKCTRL
1933
ade4eb65 1934#if wxUSE_BOOKCTRL
60be2f47 1935
61c083e7 1936wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrlBase *bookctrl)
ade4eb65 1937 : m_bookctrl(bookctrl)
83edc0a5 1938{
ade4eb65 1939 wxASSERT_MSG( bookctrl, wxT("wxBookCtrlSizer needs a control") );
83edc0a5
RR
1940}
1941
ade4eb65 1942void wxBookCtrlSizer::RecalcSizes()
83edc0a5 1943{
ade4eb65 1944 m_bookctrl->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
83edc0a5
RR
1945}
1946
ade4eb65 1947wxSize wxBookCtrlSizer::CalcMin()
83edc0a5 1948{
c47addef 1949 wxSize sizeBorder = m_bookctrl->CalcSizeFromPage(wxSize(0,0));
1e6feb95
VZ
1950
1951 sizeBorder.x += 5;
1952 sizeBorder.y += 5;
3ca6a5f0 1953
ade4eb65 1954 if ( m_bookctrl->GetPageCount() == 0 )
1e6feb95
VZ
1955 {
1956 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
1957 }
83edc0a5
RR
1958
1959 int maxX = 0;
1960 int maxY = 0;
1961
ade4eb65
VZ
1962 wxWindowList::compatibility_iterator
1963 node = m_bookctrl->GetChildren().GetFirst();
83edc0a5
RR
1964 while (node)
1965 {
1966 wxWindow *item = node->GetData();
3ca6a5f0
BP
1967 wxSizer *itemsizer = item->GetSizer();
1968
1969 if (itemsizer)
1970 {
83edc0a5 1971 wxSize subsize( itemsizer->CalcMin() );
83edc0a5 1972
1e6feb95
VZ
1973 if (subsize.x > maxX)
1974 maxX = subsize.x;
1975 if (subsize.y > maxY)
1976 maxY = subsize.y;
3ca6a5f0
BP
1977 }
1978
1979 node = node->GetNext();
83edc0a5
RR
1980 }
1981
1e6feb95 1982 return wxSize( maxX, maxY ) + sizeBorder;
83edc0a5
RR
1983}
1984
2d480e40
RD
1985#if wxUSE_NOTEBOOK
1986
1987wxNotebookSizer::wxNotebookSizer(wxNotebook *nb)
2d480e40 1988{
adbf2d73
VS
1989 wxASSERT_MSG( nb, wxT("wxNotebookSizer needs a control") );
1990 m_bookctrl = nb;
2d480e40
RD
1991}
1992
1993#endif // wxUSE_NOTEBOOOK
ade4eb65 1994#endif // wxUSE_BOOKCTRL
34c3ffca 1995
adbf2d73 1996#endif // WXWIN_COMPATIBILITY_2_4