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