]> git.saurik.com Git - wxWidgets.git/blame - src/common/sizer.cpp
Cleanup
[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
5279a24d
RR
10// Licence: wxWindows licence
11/////////////////////////////////////////////////////////////////////////////
12
14f355c2 13#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
c62ac5b6 14#pragma implementation "sizer.h"
5279a24d
RR
15#endif
16
77671fd2
VZ
17// For compilers that support precompilation, includes "wx.h".
18#include "wx/wxprec.h"
19
20#ifdef __BORLANDC__
21 #pragma hdrstop
22#endif
23
5279a24d 24#include "wx/sizer.h"
61d514bb 25#include "wx/utils.h"
27ea1d8a 26#include "wx/statbox.h"
83edc0a5 27#include "wx/notebook.h"
c54b92d3 28#include "wx/listimpl.cpp"
5279a24d 29
78ca5669
DS
30#ifdef __WXMAC__
31# include "wx/mac/uma.h"
32#endif
33
0c0d686f
RD
34//---------------------------------------------------------------------------
35
9cbee2ce
RL
36IMPLEMENT_CLASS(wxSizerItem, wxObject)
37IMPLEMENT_CLASS(wxSizer, wxObject)
38IMPLEMENT_CLASS(wxGridSizer, wxSizer)
39IMPLEMENT_CLASS(wxFlexGridSizer, wxGridSizer)
40IMPLEMENT_CLASS(wxBoxSizer, wxSizer)
1e6feb95 41#if wxUSE_STATBOX
9cbee2ce 42IMPLEMENT_CLASS(wxStaticBoxSizer, wxBoxSizer)
1e6feb95 43#endif
ade4eb65
VZ
44#if wxUSE_BOOKCTRL
45IMPLEMENT_CLASS(wxBookCtrlSizer, wxSizer)
60be2f47 46#if wxUSE_NOTEBOOK
ade4eb65
VZ
47IMPLEMENT_CLASS(wxNotebookSizer, wxBookCtrlSizer)
48#endif // wxUSE_NOTEBOOK
49#endif // wxUSE_BOOKCTRL
0c0d686f 50
12a3f227
RL
51WX_DEFINE_EXPORTED_LIST( wxSizerItemList );
52
066f1b7a
SC
53/*
54 TODO PROPERTIES
55 sizeritem
56 object
57 object_ref
58 minsize
59 option
60 flag
61 border
62 spacer
63 option
64 flag
65 borfder
66 boxsizer
67 orient
68 staticboxsizer
69 orient
70 label
71 gridsizer
72 rows
73 cols
74 vgap
75 hgap
76 flexgridsizer
77 rows
78 cols
79 vgap
80 hgap
81 growablerows
82 growablecols
83 minsize
84*/
5279a24d 85//---------------------------------------------------------------------------
3417c2cd 86// wxSizerItem
5279a24d
RR
87//---------------------------------------------------------------------------
88
12a3f227
RL
89wxSizerItem::wxSizerItem( int width, int height, int proportion, int flag, int border, wxObject* userData )
90 : m_window( NULL )
91 , m_sizer( NULL )
00976fe5
RL
92 , m_size( wxSize( width, height ) ) // size is set directly
93 , m_minSize( m_size ) // minimal size is the initial size
12a3f227 94 , m_proportion( proportion )
00976fe5
RL
95 , m_border( border )
96 , m_flag( flag )
e0d8fb45 97 , m_show( true )
00976fe5 98 , m_userData( userData )
5279a24d 99{
00976fe5 100 SetRatio( m_size );
5279a24d
RR
101}
102
12a3f227 103wxSizerItem::wxSizerItem( wxWindow *window, int proportion, int flag, int border, wxObject* userData )
00976fe5 104 : m_window( window )
12a3f227 105 , m_sizer( NULL )
00976fe5 106 , m_minSize( window->GetSize() ) // minimal size is the initial size
12a3f227 107 , m_proportion( proportion )
00976fe5
RL
108 , m_border( border )
109 , m_flag( flag )
e0d8fb45 110 , m_show( true )
00976fe5 111 , m_userData( userData )
5279a24d 112{
be2577e4 113 // aspect ratio calculated from initial size
00976fe5 114 SetRatio( m_minSize );
be2577e4 115
00976fe5 116 // m_size is calculated later
5279a24d
RR
117}
118
12a3f227
RL
119wxSizerItem::wxSizerItem( wxSizer *sizer, int proportion, int flag, int border, wxObject* userData )
120 : m_window( NULL )
00976fe5 121 , m_sizer( sizer )
12a3f227 122 , m_proportion( proportion )
00976fe5
RL
123 , m_border( border )
124 , m_flag( flag )
e0d8fb45 125 , m_show( true )
12a3f227 126 , m_ratio( 0.0 )
00976fe5 127 , m_userData( userData )
5279a24d 128{
00976fe5
RL
129 // m_minSize is calculated later
130 // m_size is calculated later
5279a24d
RR
131}
132
20b35a69
RD
133wxSizerItem::wxSizerItem()
134 : m_window( NULL )
135 , m_sizer( NULL )
136 , m_proportion( 0 )
137 , m_border( 0 )
138 , m_flag( 0 )
139 , m_show( true )
140 , m_ratio( 0.0 )
141 , m_userData( NULL )
142{
143}
144
0c0d686f
RD
145wxSizerItem::~wxSizerItem()
146{
f91e8382
VZ
147 delete m_userData;
148
149 if ( m_window )
150 {
151 m_window->SetContainingSizer(NULL);
152 }
153 else // we must be a sizer
154 {
0c0d686f 155 delete m_sizer;
f91e8382 156 }
0c0d686f
RD
157}
158
159
9cbee2ce 160wxSize wxSizerItem::GetSize() const
5279a24d 161{
d597fcb7 162 wxSize ret;
3417c2cd 163 if (IsSizer())
d597fcb7
RR
164 ret = m_sizer->GetSize();
165 else
c62ac5b6 166 if (IsWindow())
d597fcb7
RR
167 ret = m_window->GetSize();
168 else ret = m_size;
0c0d686f 169
d597fcb7
RR
170 if (m_flag & wxWEST)
171 ret.x += m_border;
172 if (m_flag & wxEAST)
173 ret.x += m_border;
174 if (m_flag & wxNORTH)
175 ret.y += m_border;
176 if (m_flag & wxSOUTH)
177 ret.y += m_border;
0c0d686f 178
d597fcb7 179 return ret;
5279a24d
RR
180}
181
3417c2cd 182wxSize wxSizerItem::CalcMin()
c62ac5b6 183{
d597fcb7 184 wxSize ret;
3417c2cd 185 if (IsSizer())
be2577e4 186 {
f6bcfd97 187 ret = m_sizer->GetMinSize();
d13d8d4e 188
be2577e4
RD
189 // if we have to preserve aspect ratio _AND_ this is
190 // the first-time calculation, consider ret to be initial size
d13d8d4e
VZ
191 if ((m_flag & wxSHAPED) && !m_ratio)
192 SetRatio(ret);
be2577e4 193 }
d597fcb7 194 else
d13d8d4e 195 {
395a82b1 196 if ( IsWindow() )
d13d8d4e 197 {
395a82b1
VZ
198 // the size of the window may change during run-time, we should
199 // use the current minimal size
2b5f62a0 200 m_minSize = m_window->GetAdjustedBestSize();
d13d8d4e
VZ
201 }
202
203 ret = m_minSize;
204 }
0c0d686f 205
d597fcb7
RR
206 if (m_flag & wxWEST)
207 ret.x += m_border;
208 if (m_flag & wxEAST)
209 ret.x += m_border;
210 if (m_flag & wxNORTH)
211 ret.y += m_border;
212 if (m_flag & wxSOUTH)
213 ret.y += m_border;
0c0d686f 214
d597fcb7 215 return ret;
c62ac5b6
RR
216}
217
3417c2cd 218void wxSizerItem::SetDimension( wxPoint pos, wxSize size )
c62ac5b6 219{
cdddaeea 220 if (m_flag & wxSHAPED)
d597fcb7 221 {
be2577e4
RD
222 // adjust aspect ratio
223 int rwidth = (int) (size.y * m_ratio);
cdddaeea
VZ
224 if (rwidth > size.x)
225 {
be2577e4
RD
226 // fit horizontally
227 int rheight = (int) (size.x / m_ratio);
228 // add vertical space
229 if (m_flag & wxALIGN_CENTER_VERTICAL)
230 pos.y += (size.y - rheight) / 2;
231 else if (m_flag & wxALIGN_BOTTOM)
232 pos.y += (size.y - rheight);
233 // use reduced dimensions
234 size.y =rheight;
cdddaeea
VZ
235 }
236 else if (rwidth < size.x)
237 {
be2577e4
RD
238 // add horizontal space
239 if (m_flag & wxALIGN_CENTER_HORIZONTAL)
240 pos.x += (size.x - rwidth) / 2;
241 else if (m_flag & wxALIGN_RIGHT)
242 pos.x += (size.x - rwidth);
243 size.x = rwidth;
244 }
245 }
33ac7e6f 246
cdddaeea
VZ
247 // This is what GetPosition() returns. Since we calculate
248 // borders afterwards, GetPosition() will be the left/top
249 // corner of the surrounding border.
250 m_pos = pos;
251
252 if (m_flag & wxWEST)
253 {
254 pos.x += m_border;
255 size.x -= m_border;
256 }
257 if (m_flag & wxEAST)
258 {
259 size.x -= m_border;
260 }
261 if (m_flag & wxNORTH)
262 {
263 pos.y += m_border;
264 size.y -= m_border;
265 }
266 if (m_flag & wxSOUTH)
267 {
268 size.y -= m_border;
269 }
0c0d686f 270
3417c2cd 271 if (IsSizer())
c62ac5b6 272 m_sizer->SetDimension( pos.x, pos.y, size.x, size.y );
0c0d686f 273
c62ac5b6 274 if (IsWindow())
b919f007 275 m_window->SetSize( pos.x, pos.y, size.x, size.y, wxSIZE_ALLOW_MINUS_ONE );
d597fcb7
RR
276
277 m_size = size;
c62ac5b6
RR
278}
279
84f7908b
RR
280void wxSizerItem::DeleteWindows()
281{
282 if (m_window)
283 m_window->Destroy();
be90c029 284
84f7908b
RR
285 if (m_sizer)
286 m_sizer->DeleteWindows();
287}
288
9cbee2ce 289bool wxSizerItem::IsWindow() const
5279a24d
RR
290{
291 return (m_window != NULL);
292}
293
9cbee2ce 294bool wxSizerItem::IsSizer() const
5279a24d
RR
295{
296 return (m_sizer != NULL);
297}
298
9cbee2ce 299bool wxSizerItem::IsSpacer() const
5279a24d
RR
300{
301 return (m_window == NULL) && (m_sizer == NULL);
302}
303
12a3f227
RL
304void wxSizerItem::Show( bool show )
305{
306 m_show = show;
307
308 if( IsWindow() )
309 m_window->Show( show );
310 else if( IsSizer() )
311 m_sizer->ShowItems( show );
312
313 // ... nothing else to do to hide/show spacers
314}
315
316void wxSizerItem::SetOption( int option )
317{
318 SetProportion( option );
319}
320
321int wxSizerItem::GetOption() const
322{
323 return GetProportion();
324}
325
326
5279a24d 327//---------------------------------------------------------------------------
3417c2cd 328// wxSizer
5279a24d
RR
329//---------------------------------------------------------------------------
330
3417c2cd 331wxSizer::wxSizer()
12a3f227 332 : m_minSize( wxSize( 0, 0 ) )
5279a24d 333{
5279a24d
RR
334}
335
3417c2cd 336wxSizer::~wxSizer()
5279a24d 337{
222ed1d6 338 WX_CLEAR_LIST(wxSizerItemList, m_children);
5279a24d 339}
0c0d686f 340
12a3f227 341void wxSizer::Add( wxWindow *window, int proportion, int flag, int border, wxObject* userData )
5279a24d 342{
12a3f227
RL
343 m_children.Append( new wxSizerItem( window, proportion, flag, border, userData ) );
344 window->SetContainingSizer( this );
5279a24d
RR
345}
346
12a3f227 347void wxSizer::Add( wxSizer *sizer, int proportion, int flag, int border, wxObject* userData )
5279a24d 348{
12a3f227 349 m_children.Append( new wxSizerItem( sizer, proportion, flag, border, userData ) );
5279a24d
RR
350}
351
12a3f227 352void wxSizer::Add( int width, int height, int proportion, int flag, int border, wxObject* userData )
5279a24d 353{
12a3f227 354 m_children.Append( new wxSizerItem( width, height, proportion, flag, border, userData ) );
5279a24d
RR
355}
356
12a3f227 357void wxSizer::Add( wxSizerItem *item )
42b4e99e 358{
12a3f227
RL
359 m_children.Append( item );
360
361 if( item->GetWindow() )
362 item->GetWindow()->SetContainingSizer( this );
42b4e99e
RR
363}
364
12a3f227 365void wxSizer::Prepend( wxWindow *window, int proportion, int flag, int border, wxObject* userData )
42b4e99e 366{
12a3f227
RL
367 m_children.Insert( new wxSizerItem( window, proportion, flag, border, userData ) );
368 window->SetContainingSizer( this );
42b4e99e
RR
369}
370
12a3f227 371void wxSizer::Prepend( wxSizer *sizer, int proportion, int flag, int border, wxObject* userData )
42b4e99e 372{
12a3f227 373 m_children.Insert( new wxSizerItem( sizer, proportion, flag, border, userData ) );
f35aa3da
RR
374}
375
12a3f227 376void wxSizer::Prepend( int width, int height, int proportion, int flag, int border, wxObject* userData )
f35aa3da 377{
12a3f227 378 m_children.Insert( new wxSizerItem( width, height, proportion, flag, border, userData ) );
f35aa3da
RR
379}
380
12a3f227 381void wxSizer::Prepend( wxSizerItem *item )
f35aa3da 382{
12a3f227
RL
383 m_children.Insert( item );
384
385 if( item->GetWindow() )
386 item->GetWindow()->SetContainingSizer( this );
f35aa3da
RR
387}
388
12a3f227
RL
389void wxSizer::Insert( size_t index,
390 wxWindow *window,
391 int proportion,
392 int flag,
393 int border,
394 wxObject* userData )
f35aa3da 395{
12a3f227
RL
396 m_children.Insert( index,
397 new wxSizerItem( window, proportion, flag, border, userData ) );
398 window->SetContainingSizer( this );
42b4e99e
RR
399}
400
12a3f227
RL
401void wxSizer::Insert( size_t index,
402 wxSizer *sizer,
403 int proportion,
404 int flag,
405 int border,
406 wxObject* userData )
42b4e99e 407{
12a3f227
RL
408 m_children.Insert( index,
409 new wxSizerItem( sizer, proportion, flag, border, userData ) );
410}
0c0d686f 411
12a3f227
RL
412void wxSizer::Insert( size_t index,
413 int width,
414 int height,
415 int proportion,
416 int flag,
417 int border,
418 wxObject* userData )
419{
420 m_children.Insert( index,
421 new wxSizerItem( width, height, proportion, flag, border, userData ) );
422}
423
424void wxSizer::Insert( size_t index, wxSizerItem *item )
425{
426 m_children.Insert( index, item );
0c0d686f 427
12a3f227
RL
428 if( item->GetWindow() )
429 item->GetWindow()->SetContainingSizer( this );
430}
431
432bool wxSizer::Remove( wxWindow *window )
433{
434 return Detach( window );
42b4e99e
RR
435}
436
437bool wxSizer::Remove( wxSizer *sizer )
438{
12a3f227 439 wxASSERT_MSG( sizer, _T("Removing NULL sizer") );
0c0d686f 440
222ed1d6 441 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
42b4e99e
RR
442 while (node)
443 {
12a3f227
RL
444 wxSizerItem *item = node->GetData();
445
3ca6a5f0 446 if (item->GetSizer() == sizer)
222ed1d6
MB
447 {
448 delete item;
449 m_children.Erase( node );
450 return true;
451 }
12a3f227
RL
452
453 node = node->GetNext();
42b4e99e 454 }
0c0d686f 455
e0d8fb45 456 return false;
42b4e99e
RR
457}
458
e0d8fb45 459bool wxSizer::Remove( int index )
42b4e99e 460{
e0d8fb45
VZ
461 wxCHECK_MSG( index >= 0 && (size_t)index < m_children.GetCount(),
462 false,
12a3f227 463 _T("Remove index is out of range") );
0c0d686f 464
222ed1d6 465 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
0c0d686f 466
e0d8fb45 467 wxCHECK_MSG( node, false, _T("Failed to find child node") );
12a3f227 468
e0d8fb45 469 wxSizerItem *item = node->GetData();
9cbee2ce
RL
470
471 if( item->IsWindow() )
472 item->GetWindow()->SetContainingSizer( NULL );
473
222ed1d6
MB
474 delete item;
475 m_children.Erase( node );
476 return true;
42b4e99e 477}
0c0d686f 478
00976fe5
RL
479bool wxSizer::Detach( wxSizer *sizer )
480{
12a3f227 481 wxASSERT_MSG( sizer, _T("Detaching NULL sizer") );
00976fe5 482
222ed1d6 483 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
00976fe5
RL
484 while (node)
485 {
12a3f227
RL
486 wxSizerItem *item = node->GetData();
487
00976fe5
RL
488 if (item->GetSizer() == sizer)
489 {
96fdbb60 490 item->DetachSizer();
89c20ac1 491 delete item;
222ed1d6
MB
492 m_children.Erase( node );
493 return true;
12a3f227
RL
494 }
495 node = node->GetNext();
496 }
497
e0d8fb45 498 return false;
12a3f227
RL
499}
500
501bool wxSizer::Detach( wxWindow *window )
502{
503 wxASSERT_MSG( window, _T("Detaching NULL window") );
504
222ed1d6 505 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
12a3f227
RL
506 while (node)
507 {
508 wxSizerItem *item = node->GetData();
509
510 if (item->GetWindow() == window)
511 {
512 item->GetWindow()->SetContainingSizer( NULL );
89c20ac1 513 delete item;
222ed1d6
MB
514 m_children.Erase( node );
515 return true;
00976fe5 516 }
12a3f227 517 node = node->GetNext();
00976fe5
RL
518 }
519
e0d8fb45 520 return false;
00976fe5
RL
521}
522
e0d8fb45 523bool wxSizer::Detach( int index )
00976fe5 524{
e0d8fb45
VZ
525 wxCHECK_MSG( index >= 0 && (size_t)index < m_children.GetCount(),
526 false,
12a3f227
RL
527 _T("Detach index is out of range") );
528
222ed1d6 529 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
00976fe5 530
e0d8fb45 531 wxCHECK_MSG( node, false, _T("Failed to find child node") );
00976fe5 532
e0d8fb45 533 wxSizerItem *item = node->GetData();
9cbee2ce
RL
534
535 if( item->IsSizer() )
536 item->DetachSizer();
537 else if( item->IsWindow() )
538 item->GetWindow()->SetContainingSizer( NULL );
12a3f227 539
89c20ac1 540 delete item;
222ed1d6
MB
541 m_children.Erase( node );
542 return true;
00976fe5
RL
543}
544
84f7908b
RR
545void wxSizer::Clear( bool delete_windows )
546{
be90c029 547 // First clear the ContainingSizer pointers
222ed1d6 548 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
be90c029
RD
549 while (node)
550 {
12a3f227
RL
551 wxSizerItem *item = node->GetData();
552
be90c029 553 if (item->IsWindow())
12a3f227
RL
554 item->GetWindow()->SetContainingSizer( NULL );
555 node = node->GetNext();
be90c029
RD
556 }
557
558 // Destroy the windows if needed
84f7908b
RR
559 if (delete_windows)
560 DeleteWindows();
be90c029
RD
561
562 // Now empty the list
222ed1d6 563 WX_CLEAR_LIST(wxSizerItemList, m_children);
84f7908b
RR
564}
565
566void wxSizer::DeleteWindows()
567{
222ed1d6 568 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
84f7908b
RR
569 while (node)
570 {
12a3f227
RL
571 wxSizerItem *item = node->GetData();
572
84f7908b 573 item->DeleteWindows();
12a3f227 574 node = node->GetNext();
84f7908b
RR
575 }
576}
577
e5251d4f 578wxSize wxSizer::Fit( wxWindow *window )
5279a24d 579{
f43c7771
VZ
580 wxSize size(window->IsTopLevel() ? FitSize(window)
581 : GetMinWindowSize(window));
9ef2e675 582
ccf5c8a8 583 window->SetSize( size );
e5251d4f
VZ
584
585 return size;
5279a24d
RR
586}
587
566d84a7
RL
588void wxSizer::FitInside( wxWindow *window )
589{
590 wxSize size;
591 if (window->IsTopLevel())
592 size = VirtualFitSize( window );
593 else
594 size = GetMinClientSize( window );
595
596 window->SetVirtualSize( size );
597}
598
3417c2cd 599void wxSizer::Layout()
c62ac5b6 600{
42b4e99e 601 CalcMin();
c62ac5b6
RR
602 RecalcSizes();
603}
604
3417c2cd 605void wxSizer::SetSizeHints( wxWindow *window )
5279a24d 606{
34c3ffca
RL
607 // Preserve the window's max size hints, but set the
608 // lower bound according to the sizer calculations.
609
e5251d4f
VZ
610 wxSize size = Fit( window );
611
34c3ffca
RL
612 window->SetSizeHints( size.x,
613 size.y,
614 window->GetMaxWidth(),
615 window->GetMaxHeight() );
5279a24d
RR
616}
617
566d84a7
RL
618void wxSizer::SetVirtualSizeHints( wxWindow *window )
619{
620 // Preserve the window's max size hints, but set the
621 // lower bound according to the sizer calculations.
622
623 FitInside( window );
624 wxSize size( window->GetVirtualSize() );
625 window->SetVirtualSizeHints( size.x,
626 size.y,
627 window->GetMaxWidth(),
628 window->GetMaxHeight() );
629}
630
9cbee2ce 631wxSize wxSizer::GetMaxWindowSize( wxWindow *window ) const
65ba4113 632{
34c3ffca 633 return window->GetMaxSize();
65ba4113
GT
634}
635
3417c2cd 636wxSize wxSizer::GetMinWindowSize( wxWindow *window )
5279a24d 637{
12a3f227
RL
638 wxSize minSize( GetMinSize() );
639 wxSize size( window->GetSize() );
640 wxSize client_size( window->GetClientSize() );
641
77671fd2 642 return wxSize( minSize.x+size.x-client_size.x,
0c0d686f 643 minSize.y+size.y-client_size.y );
5279a24d
RR
644}
645
e11d436b
SC
646// TODO on mac we need a function that determines how much free space this
647// min size contains, in order to make sure that we have 20 pixels of free
648// space around the controls
649
65ba4113
GT
650// Return a window size that will fit within the screens dimensions
651wxSize wxSizer::FitSize( wxWindow *window )
652{
653 wxSize size = GetMinWindowSize( window );
654 wxSize sizeMax = GetMaxWindowSize( window );
655
34c3ffca
RL
656 // Limit the size if sizeMax != wxDefaultSize
657
658 if ( size.x > sizeMax.x && sizeMax.x != -1 )
65ba4113 659 size.x = sizeMax.x;
34c3ffca 660 if ( size.y > sizeMax.y && sizeMax.y != -1 )
65ba4113
GT
661 size.y = sizeMax.y;
662
663 return size;
664}
665
9cbee2ce 666wxSize wxSizer::GetMaxClientSize( wxWindow *window ) const
566d84a7
RL
667{
668 wxSize maxSize( window->GetMaxSize() );
669
670 if( maxSize != wxDefaultSize )
671 {
672 wxSize size( window->GetSize() );
673 wxSize client_size( window->GetClientSize() );
674
675 return wxSize( maxSize.x + client_size.x - size.x,
676 maxSize.y + client_size.y - size.y );
677 }
678 else
679 return wxDefaultSize;
680}
681
1b0674f7 682wxSize wxSizer::GetMinClientSize( wxWindow *WXUNUSED(window) )
566d84a7
RL
683{
684 return GetMinSize(); // Already returns client size.
685}
686
687wxSize wxSizer::VirtualFitSize( wxWindow *window )
688{
689 wxSize size = GetMinClientSize( window );
690 wxSize sizeMax = GetMaxClientSize( window );
691
692 // Limit the size if sizeMax != wxDefaultSize
693
694 if ( size.x > sizeMax.x && sizeMax.x != -1 )
695 size.x = sizeMax.x;
696 if ( size.y > sizeMax.y && sizeMax.y != -1 )
697 size.y = sizeMax.y;
698
699 return size;
700}
701
3417c2cd 702void wxSizer::SetDimension( int x, int y, int width, int height )
5279a24d
RR
703{
704 m_position.x = x;
705 m_position.y = y;
706 m_size.x = width;
707 m_size.y = height;
2b5f62a0 708 Layout();
5279a24d
RR
709}
710
f6bcfd97 711wxSize wxSizer::GetMinSize()
3ca6a5f0 712{
f6bcfd97
BP
713 wxSize ret( CalcMin() );
714 if (ret.x < m_minSize.x) ret.x = m_minSize.x;
715 if (ret.y < m_minSize.y) ret.y = m_minSize.y;
3ca6a5f0 716 return ret;
f6bcfd97
BP
717}
718
719void wxSizer::DoSetMinSize( int width, int height )
720{
721 m_minSize.x = width;
722 m_minSize.y = height;
723}
724
725bool wxSizer::DoSetItemMinSize( wxWindow *window, int width, int height )
726{
12a3f227
RL
727 wxASSERT_MSG( window, _T("SetMinSize for NULL window") );
728
729 // Is it our immediate child?
f6bcfd97 730
222ed1d6 731 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
f6bcfd97
BP
732 while (node)
733 {
12a3f227
RL
734 wxSizerItem *item = node->GetData();
735
3ca6a5f0
BP
736 if (item->GetWindow() == window)
737 {
f6bcfd97 738 item->SetInitSize( width, height );
e0d8fb45 739 return true;
3ca6a5f0 740 }
12a3f227 741 node = node->GetNext();
f6bcfd97
BP
742 }
743
12a3f227
RL
744 // No? Search any subsizers we own then
745
746 node = m_children.GetFirst();
f6bcfd97
BP
747 while (node)
748 {
12a3f227
RL
749 wxSizerItem *item = node->GetData();
750
751 if ( item->GetSizer() &&
752 item->GetSizer()->DoSetItemMinSize( window, width, height ) )
3ca6a5f0 753 {
12a3f227 754 // A child sizer found the requested windw, exit.
e0d8fb45 755 return true;
3ca6a5f0 756 }
12a3f227 757 node = node->GetNext();
f6bcfd97
BP
758 }
759
e0d8fb45 760 return false;
f6bcfd97
BP
761}
762
763bool wxSizer::DoSetItemMinSize( wxSizer *sizer, int width, int height )
764{
12a3f227 765 wxASSERT_MSG( sizer, _T("SetMinSize for NULL sizer") );
f6bcfd97 766
12a3f227
RL
767 // Is it our immediate child?
768
222ed1d6 769 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
f6bcfd97
BP
770 while (node)
771 {
12a3f227
RL
772 wxSizerItem *item = node->GetData();
773
3ca6a5f0
BP
774 if (item->GetSizer() == sizer)
775 {
f6bcfd97 776 item->GetSizer()->DoSetMinSize( width, height );
e0d8fb45 777 return true;
3ca6a5f0 778 }
12a3f227 779 node = node->GetNext();
f6bcfd97
BP
780 }
781
12a3f227
RL
782 // No? Search any subsizers we own then
783
784 node = m_children.GetFirst();
f6bcfd97
BP
785 while (node)
786 {
12a3f227
RL
787 wxSizerItem *item = node->GetData();
788
789 if ( item->GetSizer() &&
790 item->GetSizer()->DoSetItemMinSize( sizer, width, height ) )
3ca6a5f0 791 {
12a3f227 792 // A child found the requested sizer, exit.
e0d8fb45 793 return true;
3ca6a5f0 794 }
12a3f227 795 node = node->GetNext();
f6bcfd97
BP
796 }
797
e0d8fb45 798 return false;
f6bcfd97
BP
799}
800
12a3f227 801bool wxSizer::DoSetItemMinSize( size_t index, int width, int height )
f6bcfd97 802{
222ed1d6 803 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
12a3f227 804
e0d8fb45 805 wxCHECK_MSG( node, false, _T("Failed to find child node") );
12a3f227
RL
806
807 wxSizerItem *item = node->GetData();
f6bcfd97 808
f6bcfd97
BP
809 if (item->GetSizer())
810 {
0ca5105b 811 // Sizers contains the minimal size in them, if not calculated ...
f6bcfd97
BP
812 item->GetSizer()->DoSetMinSize( width, height );
813 }
814 else
815 {
0ca5105b 816 // ... but the minimal size of spacers and windows in stored in them
f6bcfd97
BP
817 item->SetInitSize( width, height );
818 }
819
e0d8fb45 820 return true;
f6bcfd97
BP
821}
822
12a3f227 823void wxSizer::Show( wxWindow *window, bool show )
2b5f62a0 824{
12a3f227
RL
825 wxASSERT_MSG( window, _T("Show for NULL window") );
826
222ed1d6 827 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
2b5f62a0
VZ
828 while (node)
829 {
12a3f227 830 wxSizerItem *item = node->GetData();
2b5f62a0 831
12a3f227 832 if (item->GetWindow() == window)
2b5f62a0 833 {
12a3f227
RL
834 item->Show( show );
835 break;
2b5f62a0 836 }
12a3f227 837 node = node->GetNext();
2b5f62a0
VZ
838 }
839}
840
12a3f227 841void wxSizer::Show( wxSizer *sizer, bool show )
2b5f62a0 842{
12a3f227
RL
843 wxASSERT_MSG( sizer, _T("Show for NULL sizer") );
844
222ed1d6 845 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
2b5f62a0
VZ
846 while (node)
847 {
12a3f227 848 wxSizerItem *item = node->GetData();
2b5f62a0 849
12a3f227 850 if (item->GetSizer() == sizer)
2b5f62a0 851 {
12a3f227
RL
852 item->Show( show );
853 break;
2b5f62a0 854 }
12a3f227 855 node = node->GetNext();
2b5f62a0
VZ
856 }
857}
858
12a3f227 859void wxSizer::Show( size_t index, bool show )
2b5f62a0 860{
12a3f227
RL
861 wxCHECK_RET( index < m_children.GetCount(),
862 _T("Show index is out of range") );
2b5f62a0 863
12a3f227
RL
864 m_children.Item( index )->GetData()->Show( show );
865}
2b5f62a0 866
12a3f227
RL
867void wxSizer::ShowItems( bool show )
868{
222ed1d6 869 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
12a3f227
RL
870 while (node)
871 {
872 node->GetData()->Show( show );
873 node = node->GetNext();
2b5f62a0
VZ
874 }
875}
876
9cbee2ce 877bool wxSizer::IsShown( wxWindow *window ) const
2b5f62a0 878{
222ed1d6 879 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
2b5f62a0
VZ
880 while (node)
881 {
12a3f227 882 wxSizerItem *item = node->GetData();
dc259b79 883
12a3f227 884 if (item->GetWindow() == window)
2b5f62a0
VZ
885 {
886 return item->IsShown();
887 }
12a3f227 888 node = node->GetNext();
2b5f62a0
VZ
889 }
890
12a3f227
RL
891 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
892
e0d8fb45 893 return false;
2b5f62a0
VZ
894}
895
9cbee2ce 896bool wxSizer::IsShown( wxSizer *sizer ) const
2b5f62a0 897{
222ed1d6 898 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
2b5f62a0
VZ
899 while (node)
900 {
12a3f227 901 wxSizerItem *item = node->GetData();
2b5f62a0 902
12a3f227 903 if (item->GetSizer() == sizer)
2b5f62a0
VZ
904 {
905 return item->IsShown();
906 }
12a3f227 907 node = node->GetNext();
2b5f62a0
VZ
908 }
909
12a3f227
RL
910 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
911
e0d8fb45 912 return false;
2b5f62a0
VZ
913}
914
9cbee2ce 915bool wxSizer::IsShown( size_t index ) const
12a3f227
RL
916{
917 wxCHECK_MSG( index < m_children.GetCount(),
e0d8fb45 918 false,
12a3f227
RL
919 _T("IsShown index is out of range") );
920
921 return m_children.Item( index )->GetData()->IsShown();
922}
923
924
f6bcfd97
BP
925//---------------------------------------------------------------------------
926// wxGridSizer
927//---------------------------------------------------------------------------
928
929wxGridSizer::wxGridSizer( int rows, int cols, int vgap, int hgap )
12a3f227
RL
930 : m_rows( rows )
931 , m_cols( cols )
932 , m_vgap( vgap )
933 , m_hgap( hgap )
f6bcfd97 934{
02319c24
RD
935 if (m_rows == 0 && m_cols == 0)
936 m_rows = 1;
f6bcfd97
BP
937}
938
939wxGridSizer::wxGridSizer( int cols, int vgap, int hgap )
12a3f227
RL
940 : m_rows( 0 )
941 , m_cols( cols )
942 , m_vgap( vgap )
943 , m_hgap( hgap )
f6bcfd97 944{
02319c24
RD
945 if (m_rows == 0 && m_cols == 0)
946 m_rows = 1;
f6bcfd97
BP
947}
948
0ca5105b 949int wxGridSizer::CalcRowsCols(int& nrows, int& ncols) const
f6bcfd97 950{
f6bcfd97 951 int nitems = m_children.GetCount();
2b5f62a0 952 if ( nitems)
0ca5105b
VZ
953 {
954 if ( m_cols )
955 {
956 ncols = m_cols;
957 nrows = (nitems + m_cols - 1) / m_cols;
958 }
959 else if ( m_rows )
960 {
961 ncols = (nitems + m_rows - 1) / m_rows;
962 nrows = m_rows;
963 }
964 else // 0 columns, 0 rows?
965 {
966 wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") );
f6bcfd97 967
0ca5105b
VZ
968 nrows = ncols = 0;
969 }
970 }
971
972 return nitems;
973}
974
975void wxGridSizer::RecalcSizes()
976{
977 int nitems, nrows, ncols;
978 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
979 return;
f6bcfd97
BP
980
981 wxSize sz( GetSize() );
982 wxPoint pt( GetPosition() );
3ca6a5f0
BP
983
984 int w = (sz.x - (ncols - 1) * m_hgap) / ncols;
985 int h = (sz.y - (nrows - 1) * m_vgap) / nrows;
f6bcfd97
BP
986
987 int x = pt.x;
988 for (int c = 0; c < ncols; c++)
989 {
990 int y = pt.y;
991 for (int r = 0; r < nrows; r++)
992 {
993 int i = r * ncols + c;
994 if (i < nitems)
995 {
222ed1d6 996 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
12a3f227
RL
997
998 wxASSERT_MSG( node, _T("Failed to find SizerItemList node") );
3ca6a5f0 999
12a3f227 1000 SetItemBounds( node->GetData(), x, y, w, h);
f6bcfd97
BP
1001 }
1002 y = y + h + m_vgap;
1003 }
1004 x = x + w + m_hgap;
1005 }
1006}
1007
1008wxSize wxGridSizer::CalcMin()
1009{
196be0f1
JS
1010 int nrows, ncols;
1011 if ( CalcRowsCols(nrows, ncols) == 0 )
0ca5105b 1012 return wxSize(10, 10);
f6bcfd97 1013
4f469fb5 1014 // Find the max width and height for any component
f6bcfd97
BP
1015 int w = 0;
1016 int h = 0;
3ca6a5f0 1017
222ed1d6 1018 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
f6bcfd97
BP
1019 while (node)
1020 {
12a3f227
RL
1021 wxSizerItem *item = node->GetData();
1022 wxSize sz( item->CalcMin() );
1023
f6bcfd97
BP
1024 w = wxMax( w, sz.x );
1025 h = wxMax( h, sz.y );
3ca6a5f0 1026
12a3f227 1027 node = node->GetNext();
f6bcfd97 1028 }
3ca6a5f0 1029
12a3f227
RL
1030 return wxSize( ncols * w + (ncols-1) * m_hgap,
1031 nrows * h + (nrows-1) * m_vgap );
f6bcfd97
BP
1032}
1033
1034void wxGridSizer::SetItemBounds( wxSizerItem *item, int x, int y, int w, int h )
1035{
1036 wxPoint pt( x,y );
1037 wxSize sz( item->CalcMin() );
1038 int flag = item->GetFlag();
1039
1040 if ((flag & wxEXPAND) || (flag & wxSHAPED))
1041 {
1042 sz = wxSize(w, h);
1043 }
1044 else
1045 {
1046 if (flag & wxALIGN_CENTER_HORIZONTAL)
1047 {
1048 pt.x = x + (w - sz.x) / 2;
1049 }
1050 else if (flag & wxALIGN_RIGHT)
1051 {
1052 pt.x = x + (w - sz.x);
1053 }
3ca6a5f0 1054
f6bcfd97
BP
1055 if (flag & wxALIGN_CENTER_VERTICAL)
1056 {
1057 pt.y = y + (h - sz.y) / 2;
1058 }
1059 else if (flag & wxALIGN_BOTTOM)
1060 {
1061 pt.y = y + (h - sz.y);
1062 }
1063 }
3ca6a5f0 1064
f6bcfd97
BP
1065 item->SetDimension(pt, sz);
1066}
1067
1068//---------------------------------------------------------------------------
1069// wxFlexGridSizer
1070//---------------------------------------------------------------------------
1071
1072wxFlexGridSizer::wxFlexGridSizer( int rows, int cols, int vgap, int hgap )
5d76f462
VZ
1073 : wxGridSizer( rows, cols, vgap, hgap ),
1074 m_flexDirection(wxBOTH),
1075 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
3ca6a5f0 1076{
f6bcfd97
BP
1077}
1078
1079wxFlexGridSizer::wxFlexGridSizer( int cols, int vgap, int hgap )
5d76f462
VZ
1080 : wxGridSizer( cols, vgap, hgap ),
1081 m_flexDirection(wxBOTH),
1082 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
3ca6a5f0 1083{
f6bcfd97 1084}
3ca6a5f0 1085
f6bcfd97
BP
1086wxFlexGridSizer::~wxFlexGridSizer()
1087{
f6bcfd97
BP
1088}
1089
1090void wxFlexGridSizer::RecalcSizes()
1091{
0ca5105b
VZ
1092 int nitems, nrows, ncols;
1093 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
f6bcfd97
BP
1094 return;
1095
20b35a69 1096 wxPoint pt( GetPosition() );
f6bcfd97
BP
1097 wxSize sz( GetSize() );
1098 wxSize minsz( CalcMin() );
5d76f462 1099
20b35a69 1100 AdjustForGrowables(sz, minsz, nrows, ncols);
3ca6a5f0 1101
f6bcfd97
BP
1102 sz = wxSize( pt.x + sz.x, pt.y + sz.y );
1103
1104 int x = pt.x;
1105 for (int c = 0; c < ncols; c++)
1106 {
1107 int y = pt.y;
1108 for (int r = 0; r < nrows; r++)
1109 {
1110 int i = r * ncols + c;
1111 if (i < nitems)
1112 {
222ed1d6 1113 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
12a3f227
RL
1114
1115 wxASSERT_MSG( node, _T("Failed to find node") );
3ca6a5f0 1116
f6bcfd97
BP
1117 int w = wxMax( 0, wxMin( m_colWidths[c], sz.x - x ) );
1118 int h = wxMax( 0, wxMin( m_rowHeights[r], sz.y - y ) );
3ca6a5f0 1119
12a3f227 1120 SetItemBounds( node->GetData(), x, y, w, h);
f6bcfd97
BP
1121 }
1122 y = y + m_rowHeights[r] + m_vgap;
1123 }
1124 x = x + m_colWidths[c] + m_hgap;
1125 }
1126}
1127
1128wxSize wxFlexGridSizer::CalcMin()
1129{
150c8d89
RL
1130 int nrows,
1131 ncols;
1132 size_t i, s;
1133
55f9f0cb 1134 // Number of rows/columns can change as items are added or removed.
5d76f462
VZ
1135 if ( !CalcRowsCols(nrows, ncols) )
1136 return wxSize(10, 10);
f6bcfd97 1137
5d76f462
VZ
1138 m_rowHeights.SetCount(nrows);
1139 m_colWidths.SetCount(ncols);
3ca6a5f0 1140
395a82b1
VZ
1141 // We have to recalcuate the sizes in case the item minimum size has
1142 // changed since the previous layout, or the item has been hidden using
1143 // wxSizer::Show(). If all the items in a row/column are hidden, the final
1144 // dimension of the row/column will be -1, indicating that the column
1145 // itself is hidden.
55f9f0cb
VZ
1146 for( s = m_rowHeights.GetCount(), i = 0; i < s; ++i )
1147 m_rowHeights[ i ] = -1;
1148 for( s = m_colWidths.GetCount(), i = 0; i < s; ++i )
1149 m_colWidths[ i ] = -1;
1150
222ed1d6 1151 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
12a3f227 1152
150c8d89 1153 i = 0;
f6bcfd97
BP
1154 while (node)
1155 {
12a3f227 1156 wxSizerItem *item = node->GetData();
55f9f0cb
VZ
1157 if ( item->IsShown() )
1158 {
1159 wxSize sz( item->CalcMin() );
1160 int row = i / ncols;
1161 int col = i % ncols;
12a3f227 1162
55f9f0cb
VZ
1163 m_rowHeights[ row ] = wxMax( wxMax( 0, sz.y ), m_rowHeights[ row ] );
1164 m_colWidths[ col ] = wxMax( wxMax( 0, sz.x ), m_colWidths[ col ] );
1165 }
3ca6a5f0 1166
12a3f227 1167 node = node->GetNext();
f6bcfd97
BP
1168 i++;
1169 }
3ca6a5f0 1170
20b35a69
RD
1171 AdjustForFlexDirection();
1172
1173 // Sum total minimum size, including gaps between rows/columns.
1174 // -1 is used as a magic number meaning empty column.
1175 int width = 0;
1176 for (int col = 0; col < ncols; col++)
1177 if ( m_colWidths[ col ] != -1 )
1178 width += m_colWidths[ col ] + ( col == ncols-1 ? 0 : m_hgap );
1179
1180 int height = 0;
1181 for (int row = 0; row < nrows; row++)
1182 if ( m_rowHeights[ row ] != -1 )
1183 height += m_rowHeights[ row ] + ( row == nrows-1 ? 0 : m_vgap );
1184
1185 return wxSize( width, height );
1186}
1187
1188void wxFlexGridSizer::AdjustForFlexDirection()
1189{
1190 // the logic in CalcMin works when we resize flexibly in both directions
1191 // but maybe this is not the case
5d76f462
VZ
1192 if ( m_flexDirection != wxBOTH )
1193 {
1194 // select the array corresponding to the direction in which we do *not*
1195 // resize flexibly
1196 wxArrayInt& array = m_flexDirection == wxVERTICAL ? m_colWidths
1197 : m_rowHeights;
1198
1199 const int count = array.GetCount();
1200
1201 // find the largest value in this array
55f9f0cb 1202 int n, largest = 0;
5d76f462
VZ
1203 for ( n = 0; n < count; ++n )
1204 {
1205 if ( array[n] > largest )
1206 largest = array[n];
1207 }
1208
1209 // and now fill it with the largest value
1210 for ( n = 0; n < count; ++n )
1211 {
1212 array[n] = largest;
1213 }
1214 }
20b35a69 1215}
5d76f462 1216
3ca6a5f0 1217
20b35a69
RD
1218void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz, const wxSize& minsz,
1219 int nrows, int ncols)
1220{
1221 // what to do with the rows? by default, resize them proportionally
1222 if ( sz.y > minsz.y && ( (m_flexDirection & wxVERTICAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1223 {
1224 int sum_proportions = 0;
1225 int growable_space = 0;
1226 int num = 0;
1227 size_t idx;
1228 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1229 {
1230 // Since the number of rows/columns can change as items are
1231 // inserted/deleted, we need to verify at runtime that the
1232 // requested growable rows/columns are still valid.
1233 if (m_growableRows[idx] >= nrows)
1234 continue;
1235
1236 // If all items in a row/column are hidden, that row/column will
1237 // have a dimension of -1. This causes the row/column to be
1238 // hidden completely.
1239 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1240 continue;
1241 sum_proportions += m_growableRowsProportions[idx];
1242 growable_space += m_rowHeights[ m_growableRows[idx] ];
1243 num++;
1244 }
3ca6a5f0 1245
20b35a69
RD
1246 if (num > 0)
1247 {
1248 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1249 {
1250 if (m_growableRows[idx] >= nrows )
1251 continue;
1252 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1253 m_rowHeights[ m_growableRows[idx] ] = 0;
1254 else
1255 {
1256 int delta = (sz.y - minsz.y);
1257 if (sum_proportions == 0)
1258 delta = (delta/num) + m_rowHeights[ m_growableRows[idx] ];
1259 else
1260 delta = ((delta+growable_space)*m_growableRowsProportions[idx]) / sum_proportions;
1261 m_rowHeights[ m_growableRows[idx] ] = delta;
1262 }
1263 }
1264 }
1265 }
1266 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.y > minsz.y) )
1267 {
1268 // rounding problem?
1269 for ( int row = 0; row < nrows; ++row )
1270 m_rowHeights[ row ] = sz.y / nrows;
1271 }
1272
1273 // the same logic as above but for the columns
1274 if ( sz.x > minsz.x && ( (m_flexDirection & wxHORIZONTAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1275 {
1276 int sum_proportions = 0;
1277 int growable_space = 0;
1278 int num = 0;
1279 size_t idx;
1280 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1281 {
1282 // Since the number of rows/columns can change as items are
1283 // inserted/deleted, we need to verify at runtime that the
1284 // requested growable rows/columns are still valid.
1285 if (m_growableCols[idx] >= ncols)
1286 continue;
1287
1288 // If all items in a row/column are hidden, that row/column will
1289 // have a dimension of -1. This causes the column to be hidden
1290 // completely.
1291 if (m_colWidths[ m_growableCols[idx] ] == -1)
1292 continue;
1293 sum_proportions += m_growableColsProportions[idx];
1294 growable_space += m_colWidths[ m_growableCols[idx] ];
1295 num++;
1296 }
1297
1298 if (num > 0)
1299 {
1300 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1301 {
1302 if (m_growableCols[idx] >= ncols )
1303 continue;
1304 if (m_colWidths[ m_growableCols[idx] ] == -1)
1305 m_colWidths[ m_growableCols[idx] ] = 0;
1306 else
1307 {
1308 int delta = (sz.x - minsz.x);
1309 if (sum_proportions == 0)
1310 delta = (delta/num) + m_colWidths[ m_growableCols[idx] ];
1311 else
1312 delta = ((delta+growable_space)*m_growableColsProportions[idx])/sum_proportions;
1313 m_colWidths[ m_growableCols[idx] ] = delta;
1314 }
1315 }
1316 }
1317 }
1318 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.x > minsz.x) )
1319 {
1320 for ( int col=0; col < ncols; ++col )
1321 m_colWidths[ col ] = sz.x / ncols;
1322 }
f6bcfd97
BP
1323}
1324
20b35a69 1325
e8800dcf 1326void wxFlexGridSizer::AddGrowableRow( size_t idx, int proportion )
f6bcfd97
BP
1327{
1328 m_growableRows.Add( idx );
e8800dcf 1329 m_growableRowsProportions.Add( proportion );
f6bcfd97
BP
1330}
1331
8d2474f4 1332void wxFlexGridSizer::RemoveGrowableRow( size_t idx )
f6bcfd97 1333{
8d2474f4 1334 m_growableRows.Remove( idx );
f6bcfd97
BP
1335}
1336
e8800dcf 1337void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
f6bcfd97
BP
1338{
1339 m_growableCols.Add( idx );
e8800dcf 1340 m_growableColsProportions.Add( proportion );
f6bcfd97
BP
1341}
1342
8d2474f4 1343void wxFlexGridSizer::RemoveGrowableCol( size_t idx )
f6bcfd97 1344{
8d2474f4 1345 m_growableCols.Remove( idx );
f6bcfd97
BP
1346}
1347
c62ac5b6 1348//---------------------------------------------------------------------------
92afa2b1 1349// wxBoxSizer
61d514bb
RR
1350//---------------------------------------------------------------------------
1351
92afa2b1 1352wxBoxSizer::wxBoxSizer( int orient )
12a3f227 1353 : m_orient( orient )
61d514bb 1354{
61d514bb
RR
1355}
1356
92afa2b1 1357void wxBoxSizer::RecalcSizes()
61d514bb
RR
1358{
1359 if (m_children.GetCount() == 0)
61d514bb 1360 return;
0c0d686f 1361
61d514bb 1362 int delta = 0;
61d514bb
RR
1363 if (m_stretchable)
1364 {
1365 if (m_orient == wxHORIZONTAL)
85e5cfc9 1366 delta = m_size.x - m_fixedWidth;
3ca6a5f0 1367 else
85e5cfc9 1368 delta = m_size.y - m_fixedHeight;
61d514bb 1369 }
0c0d686f 1370
61d514bb 1371 wxPoint pt( m_position );
0c0d686f 1372
222ed1d6 1373 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
61d514bb
RR
1374 while (node)
1375 {
12a3f227
RL
1376 wxSizerItem *item = node->GetData();
1377
2b5f62a0 1378 if (item->IsShown())
3ca6a5f0 1379 {
2b5f62a0 1380 wxSize size( item->CalcMin() );
3ca6a5f0 1381
2b5f62a0 1382 if (m_orient == wxVERTICAL)
3ca6a5f0 1383 {
2b5f62a0 1384 wxCoord height = size.y;
12a3f227 1385 if (item->GetProportion())
2b5f62a0 1386 {
85e5cfc9
VZ
1387 // Because of at least one visible item has non-zero
1388 // proportion then m_stretchable is not zero
1389 height = (delta * item->GetProportion()) / m_stretchable;
2b5f62a0
VZ
1390 }
1391
1392 wxPoint child_pos( pt );
1393 wxSize child_size( wxSize( size.x, height) );
1394
1395 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1396 child_size.x = m_size.x;
1397 else if (item->GetFlag() & wxALIGN_RIGHT)
1398 child_pos.x += m_size.x - size.x;
1399 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
1400 // XXX wxCENTER is added for backward compatibility;
1401 // wxALIGN_CENTER should be used in new code
1402 child_pos.x += (m_size.x - size.x) / 2;
1403
1404 item->SetDimension( child_pos, child_size );
1405
1406 pt.y += height;
1407 }
1408 else
1409 {
1410 wxCoord width = size.x;
12a3f227 1411 if (item->GetProportion())
2b5f62a0 1412 {
85e5cfc9
VZ
1413 // Because of at least one visible item has non-zero
1414 // proportion then m_stretchable is not zero
1415 width = (delta * item->GetProportion()) / m_stretchable;
2b5f62a0
VZ
1416 }
1417
1418 wxPoint child_pos( pt );
1419 wxSize child_size( wxSize(width, size.y) );
1420
1421 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1422 child_size.y = m_size.y;
1423 else if (item->GetFlag() & wxALIGN_BOTTOM)
1424 child_pos.y += m_size.y - size.y;
1425 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
1426 // XXX wxCENTER is added for backward compatibility;
1427 // wxALIGN_CENTER should be used in new code
1428 child_pos.y += (m_size.y - size.y) / 2;
1429
1430 item->SetDimension( child_pos, child_size );
1431
1432 pt.x += width;
3ca6a5f0 1433 }
3ca6a5f0
BP
1434 }
1435
12a3f227 1436 node = node->GetNext();
61d514bb
RR
1437 }
1438}
1439
92afa2b1 1440wxSize wxBoxSizer::CalcMin()
61d514bb
RR
1441{
1442 if (m_children.GetCount() == 0)
c7a9fa36 1443 return wxSize(10,10);
0c0d686f 1444
61d514bb
RR
1445 m_stretchable = 0;
1446 m_minWidth = 0;
1447 m_minHeight = 0;
1448 m_fixedWidth = 0;
1449 m_fixedHeight = 0;
0c0d686f 1450
222ed1d6 1451 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
85e5cfc9
VZ
1452 while (node)
1453 {
1454 wxSizerItem *item = node->GetData();
12a3f227 1455
85e5cfc9
VZ
1456 if (item->IsShown() && item->GetProportion() != 0)
1457 m_stretchable += item->GetProportion();
1458
1459 node = node->GetNext();
1460 }
1461
1462 // Total minimum size (width or height) of sizer
1463 int maxMinSize = 0;
1464
1465 node = m_children.GetFirst();
61d514bb 1466 while (node)
f98de448 1467 {
85e5cfc9 1468 wxSizerItem *item = node->GetData();
12a3f227
RL
1469
1470 if (item->IsShown() && item->GetProportion() != 0)
f98de448 1471 {
12a3f227 1472 int stretch = item->GetProportion();
f98de448 1473 wxSize size( item->CalcMin() );
85e5cfc9
VZ
1474 int minSize;
1475
f98de448 1476 // Integer division rounded up is (a + b - 1) / b
85e5cfc9
VZ
1477 // Round up needed in order to guarantee that all
1478 // all items will have size not less then their min size
f98de448 1479 if (m_orient == wxHORIZONTAL)
85e5cfc9 1480 minSize = ( size.x*m_stretchable + stretch - 1)/stretch;
f98de448 1481 else
85e5cfc9
VZ
1482 minSize = ( size.y*m_stretchable + stretch - 1)/stretch;
1483
1484 if (minSize > maxMinSize)
1485 maxMinSize = minSize;
f98de448 1486 }
12a3f227 1487 node = node->GetNext();
f98de448 1488 }
12a3f227 1489
4f469fb5
RR
1490 // Calculate overall minimum size
1491 node = m_children.GetFirst();
f98de448 1492 while (node)
61d514bb 1493 {
85e5cfc9 1494 wxSizerItem *item = node->GetData();
12a3f227 1495
2b5f62a0 1496 if (item->IsShown())
f98de448 1497 {
2b5f62a0 1498 wxSize size( item->CalcMin() );
12a3f227 1499 if (item->GetProportion() != 0)
2b5f62a0
VZ
1500 {
1501 if (m_orient == wxHORIZONTAL)
85e5cfc9 1502 size.x = (maxMinSize*item->GetProportion())/m_stretchable;
2b5f62a0 1503 else
85e5cfc9 1504 size.y = (maxMinSize*item->GetProportion())/m_stretchable;
3ca6a5f0
BP
1505 }
1506 else
2b5f62a0
VZ
1507 {
1508 if (m_orient == wxVERTICAL)
1509 {
1510 m_fixedHeight += size.y;
1511 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1512 }
1513 else
1514 {
1515 m_fixedWidth += size.x;
1516 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1517 }
1518 }
85e5cfc9
VZ
1519
1520 if (m_orient == wxHORIZONTAL)
1521 {
1522 m_minWidth += size.x;
1523 m_minHeight = wxMax( m_minHeight, size.y );
1524 }
1525 else
1526 {
1527 m_minHeight += size.y;
1528 m_minWidth = wxMax( m_minWidth, size.x );
1529 }
2b5f62a0 1530 }
12a3f227 1531 node = node->GetNext();
61d514bb 1532 }
0c0d686f 1533
61d514bb
RR
1534 return wxSize( m_minWidth, m_minHeight );
1535}
27ea1d8a
RR
1536
1537//---------------------------------------------------------------------------
1538// wxStaticBoxSizer
1539//---------------------------------------------------------------------------
1540
1e6feb95
VZ
1541#if wxUSE_STATBOX
1542
27ea1d8a 1543wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
12a3f227
RL
1544 : wxBoxSizer( orient )
1545 , m_staticBox( box )
27ea1d8a 1546{
223d09f6 1547 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
27ea1d8a 1548}
0c0d686f 1549
12a3f227
RL
1550static void GetStaticBoxBorders( wxStaticBox *box,
1551 int *borderTop,
1552 int *borderOther)
84028727
VZ
1553{
1554 // this has to be done platform by platform as there is no way to
1555 // guess the thickness of a wxStaticBox border
ec4e4a14
DE
1556#ifdef __WXCOCOA__
1557 box->GetBordersForSizer(borderTop,borderOther);
67021102
DS
1558#elif defined(__WXMAC__)
1559
1560 static int extraTop = -1; // Uninitted
1561 static int other = 5;
1562
1563 if ( extraTop == -1 )
1564 {
67021102
DS
1565 // The minimal border used for the top. Later on the staticbox'
1566 // font height is added to this.
1567 extraTop = 0;
1568
78ca5669 1569 if ( UMAGetSystemVersion() >= 0x1030 /*Panther*/ )
67021102
DS
1570 {
1571 // As indicated by the HIG, Panther needs an extra border of 11
1572 // pixels (otherwise overlapping occurs at the top). The "other"
1573 // border has to be 11.
1574 extraTop = 11;
1575 other = 11;
1576 }
1577
1578 }
1579
1580 *borderTop = extraTop + box->GetCharHeight();
1581 *borderOther = other;
1582
1583#else
84028727
VZ
1584#ifdef __WXGTK__
1585 if ( box->GetLabel().IsEmpty() )
1586 *borderTop = 5;
1587 else
1588#endif // __WXGTK__
f2b99f63
JS
1589 *borderTop = box->GetCharHeight();
1590
84028727 1591 *borderOther = 5;
ec4e4a14 1592#endif // __WXCOCOA__
84028727
VZ
1593}
1594
27ea1d8a
RR
1595void wxStaticBoxSizer::RecalcSizes()
1596{
84028727
VZ
1597 int top_border, other_border;
1598 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
27ea1d8a
RR
1599
1600 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
0c0d686f 1601
27ea1d8a
RR
1602 wxPoint old_pos( m_position );
1603 m_position.x += other_border;
1604 m_position.y += top_border;
1605 wxSize old_size( m_size );
1606 m_size.x -= 2*other_border;
1607 m_size.y -= top_border + other_border;
0c0d686f 1608
27ea1d8a 1609 wxBoxSizer::RecalcSizes();
0c0d686f 1610
27ea1d8a
RR
1611 m_position = old_pos;
1612 m_size = old_size;
1613}
1614
1615wxSize wxStaticBoxSizer::CalcMin()
1616{
84028727
VZ
1617 int top_border, other_border;
1618 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
0c0d686f 1619
27ea1d8a 1620 wxSize ret( wxBoxSizer::CalcMin() );
cae31b8b 1621 ret.x += 2*other_border;
27ea1d8a 1622 ret.y += other_border + top_border;
0c0d686f 1623
27ea1d8a
RR
1624 return ret;
1625}
83edc0a5 1626
1e6feb95
VZ
1627#endif // wxUSE_STATBOX
1628
ade4eb65 1629// ----------------------------------------------------------------------------
83edc0a5 1630// wxNotebookSizer
ade4eb65 1631// ----------------------------------------------------------------------------
83edc0a5 1632
ade4eb65 1633#if wxUSE_BOOKCTRL
60be2f47 1634
ade4eb65
VZ
1635wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrl *bookctrl)
1636 : m_bookctrl(bookctrl)
83edc0a5 1637{
ade4eb65 1638 wxASSERT_MSG( bookctrl, wxT("wxBookCtrlSizer needs a control") );
83edc0a5
RR
1639}
1640
ade4eb65 1641void wxBookCtrlSizer::RecalcSizes()
83edc0a5 1642{
ade4eb65 1643 m_bookctrl->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
83edc0a5
RR
1644}
1645
ade4eb65 1646wxSize wxBookCtrlSizer::CalcMin()
83edc0a5 1647{
ade4eb65 1648 wxSize sizeBorder = m_bookctrl->CalcSizeFromPage(wxSize(0, 0));
1e6feb95
VZ
1649
1650 sizeBorder.x += 5;
1651 sizeBorder.y += 5;
3ca6a5f0 1652
ade4eb65 1653 if ( m_bookctrl->GetPageCount() == 0 )
1e6feb95
VZ
1654 {
1655 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
1656 }
83edc0a5
RR
1657
1658 int maxX = 0;
1659 int maxY = 0;
1660
ade4eb65
VZ
1661 wxWindowList::compatibility_iterator
1662 node = m_bookctrl->GetChildren().GetFirst();
83edc0a5
RR
1663 while (node)
1664 {
1665 wxWindow *item = node->GetData();
3ca6a5f0
BP
1666 wxSizer *itemsizer = item->GetSizer();
1667
1668 if (itemsizer)
1669 {
83edc0a5 1670 wxSize subsize( itemsizer->CalcMin() );
83edc0a5 1671
1e6feb95
VZ
1672 if (subsize.x > maxX)
1673 maxX = subsize.x;
1674 if (subsize.y > maxY)
1675 maxY = subsize.y;
3ca6a5f0
BP
1676 }
1677
1678 node = node->GetNext();
83edc0a5
RR
1679 }
1680
1e6feb95 1681 return wxSize( maxX, maxY ) + sizeBorder;
83edc0a5
RR
1682}
1683
2d480e40
RD
1684
1685#if wxUSE_NOTEBOOK
1686
1687wxNotebookSizer::wxNotebookSizer(wxNotebook *nb)
1688 : wxBookCtrlSizer(nb)
1689{
1690}
1691
1692#endif // wxUSE_NOTEBOOOK
ade4eb65 1693#endif // wxUSE_BOOKCTRL
34c3ffca 1694