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