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