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