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