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