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