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