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