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