]> git.saurik.com Git - wxWidgets.git/blame - src/common/sizer.cpp
bitmap button size was too small when uxtheme functions were used to get the margins
[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 )
0ca5105b 1156 return wxSize(10, 10);
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
VZ
1280 if ( !CalcRowsCols(nrows, ncols) )
1281 return wxSize(10, 10);
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
8d2474f4 1484void wxFlexGridSizer::RemoveGrowableRow( size_t idx )
f6bcfd97 1485{
8d2474f4 1486 m_growableRows.Remove( idx );
f6bcfd97
BP
1487}
1488
e8800dcf 1489void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
f6bcfd97
BP
1490{
1491 m_growableCols.Add( idx );
e8800dcf 1492 m_growableColsProportions.Add( proportion );
f6bcfd97
BP
1493}
1494
8d2474f4 1495void wxFlexGridSizer::RemoveGrowableCol( size_t idx )
f6bcfd97 1496{
8d2474f4 1497 m_growableCols.Remove( idx );
f6bcfd97
BP
1498}
1499
c62ac5b6 1500//---------------------------------------------------------------------------
92afa2b1 1501// wxBoxSizer
61d514bb
RR
1502//---------------------------------------------------------------------------
1503
92afa2b1 1504wxBoxSizer::wxBoxSizer( int orient )
12a3f227 1505 : m_orient( orient )
61d514bb 1506{
61d514bb
RR
1507}
1508
92afa2b1 1509void wxBoxSizer::RecalcSizes()
61d514bb
RR
1510{
1511 if (m_children.GetCount() == 0)
61d514bb 1512 return;
0c0d686f 1513
61d514bb 1514 int delta = 0;
61d514bb
RR
1515 if (m_stretchable)
1516 {
1517 if (m_orient == wxHORIZONTAL)
85e5cfc9 1518 delta = m_size.x - m_fixedWidth;
3ca6a5f0 1519 else
85e5cfc9 1520 delta = m_size.y - m_fixedHeight;
61d514bb 1521 }
0c0d686f 1522
61d514bb 1523 wxPoint pt( m_position );
0c0d686f 1524
222ed1d6 1525 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
61d514bb
RR
1526 while (node)
1527 {
12a3f227
RL
1528 wxSizerItem *item = node->GetData();
1529
2b5f62a0 1530 if (item->IsShown())
3ca6a5f0 1531 {
ba763a45 1532 wxSize size( item->GetMinSizeWithBorder() );
3ca6a5f0 1533
2b5f62a0 1534 if (m_orient == wxVERTICAL)
3ca6a5f0 1535 {
2b5f62a0 1536 wxCoord height = size.y;
12a3f227 1537 if (item->GetProportion())
2b5f62a0 1538 {
85e5cfc9
VZ
1539 // Because of at least one visible item has non-zero
1540 // proportion then m_stretchable is not zero
1541 height = (delta * item->GetProportion()) / m_stretchable;
2b5f62a0
VZ
1542 }
1543
1544 wxPoint child_pos( pt );
42841dfc 1545 wxSize child_size( size.x, height );
2b5f62a0
VZ
1546
1547 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1548 child_size.x = m_size.x;
1549 else if (item->GetFlag() & wxALIGN_RIGHT)
1550 child_pos.x += m_size.x - size.x;
1551 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
1552 // XXX wxCENTER is added for backward compatibility;
1553 // wxALIGN_CENTER should be used in new code
1554 child_pos.x += (m_size.x - size.x) / 2;
1555
1556 item->SetDimension( child_pos, child_size );
1557
1558 pt.y += height;
1559 }
1560 else
1561 {
1562 wxCoord width = size.x;
12a3f227 1563 if (item->GetProportion())
2b5f62a0 1564 {
85e5cfc9
VZ
1565 // Because of at least one visible item has non-zero
1566 // proportion then m_stretchable is not zero
1567 width = (delta * item->GetProportion()) / m_stretchable;
2b5f62a0
VZ
1568 }
1569
1570 wxPoint child_pos( pt );
42841dfc 1571 wxSize child_size( width, size.y );
2b5f62a0
VZ
1572
1573 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1574 child_size.y = m_size.y;
1575 else if (item->GetFlag() & wxALIGN_BOTTOM)
1576 child_pos.y += m_size.y - size.y;
1577 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
1578 // XXX wxCENTER is added for backward compatibility;
1579 // wxALIGN_CENTER should be used in new code
1580 child_pos.y += (m_size.y - size.y) / 2;
1581
1582 item->SetDimension( child_pos, child_size );
1583
1584 pt.x += width;
3ca6a5f0 1585 }
3ca6a5f0
BP
1586 }
1587
12a3f227 1588 node = node->GetNext();
61d514bb
RR
1589 }
1590}
1591
92afa2b1 1592wxSize wxBoxSizer::CalcMin()
61d514bb
RR
1593{
1594 if (m_children.GetCount() == 0)
c7a9fa36 1595 return wxSize(10,10);
0c0d686f 1596
61d514bb
RR
1597 m_stretchable = 0;
1598 m_minWidth = 0;
1599 m_minHeight = 0;
1600 m_fixedWidth = 0;
1601 m_fixedHeight = 0;
0c0d686f 1602
ba763a45 1603 // precalc item minsizes and count proportions
222ed1d6 1604 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
85e5cfc9
VZ
1605 while (node)
1606 {
1607 wxSizerItem *item = node->GetData();
12a3f227 1608
d4444410
VZ
1609 if ( item->IsShown() )
1610 {
ba763a45 1611 item->CalcMin(); // result is stored in the item
8b2bac62 1612
85e5cfc9 1613 m_stretchable += item->GetProportion();
d4444410 1614 }
85e5cfc9
VZ
1615
1616 node = node->GetNext();
1617 }
1618
1619 // Total minimum size (width or height) of sizer
1620 int maxMinSize = 0;
1621
1622 node = m_children.GetFirst();
61d514bb 1623 while (node)
f98de448 1624 {
85e5cfc9 1625 wxSizerItem *item = node->GetData();
12a3f227
RL
1626
1627 if (item->IsShown() && item->GetProportion() != 0)
f98de448 1628 {
12a3f227 1629 int stretch = item->GetProportion();
ba763a45 1630 wxSize size( item->GetMinSizeWithBorder() );
85e5cfc9 1631 int minSize;
8b2bac62 1632
f98de448 1633 // Integer division rounded up is (a + b - 1) / b
85e5cfc9
VZ
1634 // Round up needed in order to guarantee that all
1635 // all items will have size not less then their min size
f98de448 1636 if (m_orient == wxHORIZONTAL)
85e5cfc9 1637 minSize = ( size.x*m_stretchable + stretch - 1)/stretch;
f98de448 1638 else
85e5cfc9 1639 minSize = ( size.y*m_stretchable + stretch - 1)/stretch;
8b2bac62 1640
85e5cfc9
VZ
1641 if (minSize > maxMinSize)
1642 maxMinSize = minSize;
f98de448 1643 }
12a3f227 1644 node = node->GetNext();
f98de448 1645 }
12a3f227 1646
4f469fb5
RR
1647 // Calculate overall minimum size
1648 node = m_children.GetFirst();
f98de448 1649 while (node)
61d514bb 1650 {
85e5cfc9 1651 wxSizerItem *item = node->GetData();
12a3f227 1652
2b5f62a0 1653 if (item->IsShown())
f98de448 1654 {
ba763a45 1655 wxSize size( item->GetMinSizeWithBorder() );
12a3f227 1656 if (item->GetProportion() != 0)
2b5f62a0
VZ
1657 {
1658 if (m_orient == wxHORIZONTAL)
85e5cfc9 1659 size.x = (maxMinSize*item->GetProportion())/m_stretchable;
2b5f62a0 1660 else
85e5cfc9 1661 size.y = (maxMinSize*item->GetProportion())/m_stretchable;
3ca6a5f0
BP
1662 }
1663 else
2b5f62a0
VZ
1664 {
1665 if (m_orient == wxVERTICAL)
1666 {
1667 m_fixedHeight += size.y;
1668 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1669 }
1670 else
1671 {
1672 m_fixedWidth += size.x;
1673 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1674 }
1675 }
85e5cfc9
VZ
1676
1677 if (m_orient == wxHORIZONTAL)
1678 {
1679 m_minWidth += size.x;
1680 m_minHeight = wxMax( m_minHeight, size.y );
1681 }
1682 else
1683 {
1684 m_minHeight += size.y;
1685 m_minWidth = wxMax( m_minWidth, size.x );
1686 }
2b5f62a0 1687 }
12a3f227 1688 node = node->GetNext();
61d514bb 1689 }
0c0d686f 1690
61d514bb
RR
1691 return wxSize( m_minWidth, m_minHeight );
1692}
27ea1d8a
RR
1693
1694//---------------------------------------------------------------------------
1695// wxStaticBoxSizer
1696//---------------------------------------------------------------------------
1697
1e6feb95
VZ
1698#if wxUSE_STATBOX
1699
27ea1d8a 1700wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
e978011a
VZ
1701 : wxBoxSizer( orient ),
1702 m_staticBox( box )
27ea1d8a 1703{
223d09f6 1704 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
e978011a
VZ
1705
1706 // do this so that our Detach() is called if the static box is destroyed
1707 // before we are
1708 m_staticBox->SetContainingSizer(this);
27ea1d8a 1709}
0c0d686f 1710
6c1635b5
VZ
1711wxStaticBoxSizer::wxStaticBoxSizer(int orient, wxWindow *win, const wxString& s)
1712 : wxBoxSizer(orient),
1713 m_staticBox(new wxStaticBox(win, wxID_ANY, s))
1714{
e978011a
VZ
1715 // same as above
1716 m_staticBox->SetContainingSizer(this);
6c1635b5
VZ
1717}
1718
649cfca1
VZ
1719wxStaticBoxSizer::~wxStaticBoxSizer()
1720{
1721 delete m_staticBox;
1722}
1723
12a3f227
RL
1724static void GetStaticBoxBorders( wxStaticBox *box,
1725 int *borderTop,
1726 int *borderOther)
84028727
VZ
1727{
1728 // this has to be done platform by platform as there is no way to
1729 // guess the thickness of a wxStaticBox border
5dd070c2 1730 box->GetBordersForSizer(borderTop, borderOther);
84028727
VZ
1731}
1732
27ea1d8a
RR
1733void wxStaticBoxSizer::RecalcSizes()
1734{
84028727
VZ
1735 int top_border, other_border;
1736 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
27ea1d8a
RR
1737
1738 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
0c0d686f 1739
27ea1d8a
RR
1740 wxPoint old_pos( m_position );
1741 m_position.x += other_border;
1742 m_position.y += top_border;
1743 wxSize old_size( m_size );
1744 m_size.x -= 2*other_border;
1745 m_size.y -= top_border + other_border;
0c0d686f 1746
27ea1d8a 1747 wxBoxSizer::RecalcSizes();
0c0d686f 1748
27ea1d8a
RR
1749 m_position = old_pos;
1750 m_size = old_size;
1751}
1752
1753wxSize wxStaticBoxSizer::CalcMin()
1754{
84028727
VZ
1755 int top_border, other_border;
1756 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
0c0d686f 1757
27ea1d8a 1758 wxSize ret( wxBoxSizer::CalcMin() );
cae31b8b 1759 ret.x += 2*other_border;
27ea1d8a 1760 ret.y += other_border + top_border;
0c0d686f 1761
27ea1d8a
RR
1762 return ret;
1763}
83edc0a5 1764
eb2a7883
VZ
1765void wxStaticBoxSizer::ShowItems( bool show )
1766{
1767 m_staticBox->Show( show );
1768 wxBoxSizer::ShowItems( show );
1769}
1770
e978011a
VZ
1771bool wxStaticBoxSizer::Detach( wxWindow *window )
1772{
1773 // avoid deleting m_staticBox in our dtor if it's being detached from the
1774 // sizer (which can happen because it's being already destroyed for
1775 // example)
1776 if ( window == m_staticBox )
1777 {
1778 m_staticBox = NULL;
1779 return true;
1780 }
1781
1782 return wxSizer::Detach( window );
1783}
1784
1e6feb95
VZ
1785#endif // wxUSE_STATBOX
1786
974c2a59
WS
1787#if wxUSE_BUTTON
1788
acf2ac37
RR
1789wxStdDialogButtonSizer::wxStdDialogButtonSizer()
1790 : wxBoxSizer(wxHORIZONTAL)
1791{
94f53923
JS
1792 // Vertical buttons with lots of space on either side
1793 // looks rubbish on WinCE, so let's not do this for now.
1794 // If we are going to use vertical buttons, we should
1795 // put the sizer to the right of other controls in the dialog,
1796 // and that's beyond the scope of this sizer.
1797#ifndef __WXWINCE__
acf2ac37 1798 bool is_pda = (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA);
974c2a59 1799 // If we have a PDA screen, put yes/no button over
acf2ac37
RR
1800 // all other buttons, otherwise on the left side.
1801 if (is_pda)
1802 m_orient = wxVERTICAL;
94f53923 1803#endif
974c2a59 1804
acf2ac37
RR
1805 m_buttonAffirmative = NULL;
1806 m_buttonApply = NULL;
1807 m_buttonNegative = NULL;
1808 m_buttonCancel = NULL;
1809 m_buttonHelp = NULL;
1810}
1811
1812void wxStdDialogButtonSizer::AddButton(wxButton *mybutton)
1813{
1814 switch (mybutton->GetId())
1815 {
1816 case wxID_OK:
1817 case wxID_YES:
1818 case wxID_SAVE:
1819 m_buttonAffirmative = mybutton;
1820 break;
1821 case wxID_APPLY:
1822 m_buttonApply = mybutton;
1823 break;
1824 case wxID_NO:
1825 m_buttonNegative = mybutton;
1826 break;
1827 case wxID_CANCEL:
1828 m_buttonCancel = mybutton;
1829 break;
1830 case wxID_HELP:
2997ca30 1831 case wxID_CONTEXT_HELP:
acf2ac37
RR
1832 m_buttonHelp = mybutton;
1833 break;
1834 default:
1835 break;
1836 }
1837}
1838
b181a505
RR
1839void wxStdDialogButtonSizer::SetAffirmativeButton( wxButton *button )
1840{
1841 m_buttonAffirmative = button;
1842}
1843
1844void wxStdDialogButtonSizer::SetNegativeButton( wxButton *button )
1845{
1846 m_buttonNegative = button;
1847}
1848
1849void wxStdDialogButtonSizer::SetCancelButton( wxButton *button )
1850{
1851 m_buttonCancel = button;
1852}
1853
718903fe 1854void wxStdDialogButtonSizer::Realize()
acf2ac37
RR
1855{
1856#ifdef __WXMAC__
1857 Add(0, 0, 0, wxLEFT, 6);
1858 if (m_buttonHelp)
974c2a59
WS
1859 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 6);
1860
acf2ac37
RR
1861 if (m_buttonNegative){
1862 // HIG POLICE BULLETIN - destructive buttons need extra padding
1863 // 24 pixels on either side
1864 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 12);
1865 }
974c2a59 1866
acf2ac37 1867 // extra whitespace between help/negative and cancel/ok buttons
974c2a59
WS
1868 Add(0, 0, 1, wxEXPAND, 0);
1869
acf2ac37
RR
1870 if (m_buttonCancel){
1871 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 6);
1872 // Cancel or help should be default
1873 // m_buttonCancel->SetDefaultButton();
1874 }
974c2a59
WS
1875
1876 // Ugh, Mac doesn't really have apply dialogs, so I'll just
acf2ac37
RR
1877 // figure the best place is between Cancel and OK
1878 if (m_buttonApply)
1879 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 6);
974c2a59 1880
acf2ac37
RR
1881 if (m_buttonAffirmative){
1882 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT, 6);
974c2a59 1883
acf2ac37
RR
1884 if (m_buttonAffirmative->GetId() == wxID_SAVE){
1885 // these buttons have set labels under Mac so we should use them
1886 m_buttonAffirmative->SetLabel(_("Save"));
1887 m_buttonNegative->SetLabel(_("Don't Save"));
1888 }
1889 }
974c2a59 1890
acf2ac37
RR
1891 // Extra space around and at the right
1892 Add(12, 24);
1893#elif defined(__WXGTK20__)
1894 Add(0, 0, 0, wxLEFT, 9);
1895 if (m_buttonHelp)
974c2a59
WS
1896 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
1897
acf2ac37 1898 // extra whitespace between help and cancel/ok buttons
974c2a59
WS
1899 Add(0, 0, 1, wxEXPAND, 0);
1900
acf2ac37
RR
1901 if (m_buttonNegative){
1902 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
1903 }
974c2a59 1904
acf2ac37
RR
1905 if (m_buttonCancel){
1906 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
1907 // Cancel or help should be default
1908 // m_buttonCancel->SetDefaultButton();
1909 }
974c2a59 1910
acf2ac37
RR
1911 if (m_buttonApply)
1912 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
974c2a59 1913
acf2ac37
RR
1914 if (m_buttonAffirmative)
1915 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT, 6);
0f884515
JS
1916#elif defined(__WXMSW__)
1917 // Windows
1918
1919 // right-justify buttons
1920 Add(0, 0, 1, wxEXPAND, 0);
1921
1922 if (m_buttonAffirmative){
1923 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonAffirmative->ConvertDialogToPixels(wxSize(2, 0)).x);
1924 }
1925
1926 if (m_buttonNegative){
1927 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonNegative->ConvertDialogToPixels(wxSize(2, 0)).x);
1928 }
1929
1930 if (m_buttonCancel){
1931 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonCancel->ConvertDialogToPixels(wxSize(2, 0)).x);
1932 }
1933 if (m_buttonApply)
1934 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonApply->ConvertDialogToPixels(wxSize(2, 0)).x);
1935
1936 if (m_buttonHelp)
1937 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonHelp->ConvertDialogToPixels(wxSize(2, 0)).x);
acf2ac37 1938#else
0f884515 1939 // GTK+1 and any other platform
902725ee 1940
23b1018f 1941 // Add(0, 0, 0, wxLEFT, 5); // Not sure what this was for but it unbalances the dialog
acf2ac37 1942 if (m_buttonHelp)
974c2a59
WS
1943 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonHelp->ConvertDialogToPixels(wxSize(4, 0)).x);
1944
acf2ac37 1945 // extra whitespace between help and cancel/ok buttons
974c2a59 1946 Add(0, 0, 1, wxEXPAND, 0);
acf2ac37
RR
1947
1948 if (m_buttonApply)
1949 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonApply->ConvertDialogToPixels(wxSize(4, 0)).x);
974c2a59 1950
acf2ac37
RR
1951 if (m_buttonAffirmative){
1952 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonAffirmative->ConvertDialogToPixels(wxSize(4, 0)).x);
1953 }
974c2a59 1954
acf2ac37
RR
1955 if (m_buttonNegative){
1956 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonNegative->ConvertDialogToPixels(wxSize(4, 0)).x);
1957 }
974c2a59 1958
acf2ac37 1959 if (m_buttonCancel){
23b1018f 1960 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonCancel->ConvertDialogToPixels(wxSize(4, 0)).x);
acf2ac37
RR
1961 // Cancel or help should be default
1962 // m_buttonCancel->SetDefaultButton();
1963 }
974c2a59 1964
acf2ac37
RR
1965#endif
1966}
adbf2d73 1967
974c2a59
WS
1968#endif // wxUSE_BUTTON
1969
adbf2d73
VS
1970#if WXWIN_COMPATIBILITY_2_4
1971
ade4eb65 1972// ----------------------------------------------------------------------------
83edc0a5 1973// wxNotebookSizer
ade4eb65 1974// ----------------------------------------------------------------------------
83edc0a5 1975
adbf2d73
VS
1976#if wxUSE_BOOKCTRL
1977IMPLEMENT_CLASS(wxBookCtrlSizer, wxSizer)
1978#if wxUSE_NOTEBOOK
1979IMPLEMENT_CLASS(wxNotebookSizer, wxBookCtrlSizer)
1980#endif // wxUSE_NOTEBOOK
1981#endif // wxUSE_BOOKCTRL
1982
ade4eb65 1983#if wxUSE_BOOKCTRL
60be2f47 1984
3abb199d
VZ
1985#if WXWIN_COMPATIBILITY_2_6
1986
61c083e7 1987wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrlBase *bookctrl)
ade4eb65 1988 : m_bookctrl(bookctrl)
83edc0a5 1989{
ade4eb65 1990 wxASSERT_MSG( bookctrl, wxT("wxBookCtrlSizer needs a control") );
83edc0a5
RR
1991}
1992
3abb199d
VZ
1993#endif // WXWIN_COMPATIBILITY_2_6
1994
ade4eb65 1995void wxBookCtrlSizer::RecalcSizes()
83edc0a5 1996{
ade4eb65 1997 m_bookctrl->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
83edc0a5
RR
1998}
1999
ade4eb65 2000wxSize wxBookCtrlSizer::CalcMin()
83edc0a5 2001{
c47addef 2002 wxSize sizeBorder = m_bookctrl->CalcSizeFromPage(wxSize(0,0));
1e6feb95
VZ
2003
2004 sizeBorder.x += 5;
2005 sizeBorder.y += 5;
3ca6a5f0 2006
ade4eb65 2007 if ( m_bookctrl->GetPageCount() == 0 )
1e6feb95
VZ
2008 {
2009 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
2010 }
83edc0a5
RR
2011
2012 int maxX = 0;
2013 int maxY = 0;
2014
ade4eb65
VZ
2015 wxWindowList::compatibility_iterator
2016 node = m_bookctrl->GetChildren().GetFirst();
83edc0a5
RR
2017 while (node)
2018 {
2019 wxWindow *item = node->GetData();
3ca6a5f0
BP
2020 wxSizer *itemsizer = item->GetSizer();
2021
2022 if (itemsizer)
2023 {
83edc0a5 2024 wxSize subsize( itemsizer->CalcMin() );
83edc0a5 2025
1e6feb95
VZ
2026 if (subsize.x > maxX)
2027 maxX = subsize.x;
2028 if (subsize.y > maxY)
2029 maxY = subsize.y;
3ca6a5f0
BP
2030 }
2031
2032 node = node->GetNext();
83edc0a5
RR
2033 }
2034
1e6feb95 2035 return wxSize( maxX, maxY ) + sizeBorder;
83edc0a5
RR
2036}
2037
2d480e40
RD
2038#if wxUSE_NOTEBOOK
2039
f3190d1c
VZ
2040#if WXWIN_COMPATIBILITY_2_6
2041
2d480e40 2042wxNotebookSizer::wxNotebookSizer(wxNotebook *nb)
2d480e40 2043{
adbf2d73
VS
2044 wxASSERT_MSG( nb, wxT("wxNotebookSizer needs a control") );
2045 m_bookctrl = nb;
2d480e40
RD
2046}
2047
f3190d1c
VZ
2048#endif // WXWIN_COMPATIBILITY_2_6
2049
2d480e40 2050#endif // wxUSE_NOTEBOOOK
ade4eb65 2051#endif // wxUSE_BOOKCTRL
34c3ffca 2052
adbf2d73 2053#endif // WXWIN_COMPATIBILITY_2_4