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