]> git.saurik.com Git - wxWidgets.git/blame - src/common/sizer.cpp
Only call Select within SetString when internal data has been restored,
[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 {
f52e0cf4 196 if ( IsWindow() && !(m_flag & wxFIXED_MINSIZE) )
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 );
caa251e0 739 item->GetWindow()->SetSizeHints(width, height);
e0d8fb45 740 return true;
3ca6a5f0 741 }
12a3f227 742 node = node->GetNext();
f6bcfd97
BP
743 }
744
12a3f227
RL
745 // No? Search any subsizers we own then
746
747 node = m_children.GetFirst();
f6bcfd97
BP
748 while (node)
749 {
12a3f227
RL
750 wxSizerItem *item = node->GetData();
751
752 if ( item->GetSizer() &&
753 item->GetSizer()->DoSetItemMinSize( window, width, height ) )
3ca6a5f0 754 {
12a3f227 755 // A child sizer found the requested windw, exit.
e0d8fb45 756 return true;
3ca6a5f0 757 }
12a3f227 758 node = node->GetNext();
f6bcfd97
BP
759 }
760
e0d8fb45 761 return false;
f6bcfd97
BP
762}
763
764bool wxSizer::DoSetItemMinSize( wxSizer *sizer, int width, int height )
765{
12a3f227 766 wxASSERT_MSG( sizer, _T("SetMinSize for NULL sizer") );
f6bcfd97 767
12a3f227
RL
768 // Is it our immediate child?
769
222ed1d6 770 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
f6bcfd97
BP
771 while (node)
772 {
12a3f227
RL
773 wxSizerItem *item = node->GetData();
774
3ca6a5f0
BP
775 if (item->GetSizer() == sizer)
776 {
f6bcfd97 777 item->GetSizer()->DoSetMinSize( width, height );
e0d8fb45 778 return true;
3ca6a5f0 779 }
12a3f227 780 node = node->GetNext();
f6bcfd97
BP
781 }
782
12a3f227
RL
783 // No? Search any subsizers we own then
784
785 node = m_children.GetFirst();
f6bcfd97
BP
786 while (node)
787 {
12a3f227
RL
788 wxSizerItem *item = node->GetData();
789
790 if ( item->GetSizer() &&
791 item->GetSizer()->DoSetItemMinSize( sizer, width, height ) )
3ca6a5f0 792 {
12a3f227 793 // A child found the requested sizer, exit.
e0d8fb45 794 return true;
3ca6a5f0 795 }
12a3f227 796 node = node->GetNext();
f6bcfd97
BP
797 }
798
e0d8fb45 799 return false;
f6bcfd97
BP
800}
801
12a3f227 802bool wxSizer::DoSetItemMinSize( size_t index, int width, int height )
f6bcfd97 803{
222ed1d6 804 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
12a3f227 805
e0d8fb45 806 wxCHECK_MSG( node, false, _T("Failed to find child node") );
12a3f227
RL
807
808 wxSizerItem *item = node->GetData();
f6bcfd97 809
f6bcfd97
BP
810 if (item->GetSizer())
811 {
0ca5105b 812 // Sizers contains the minimal size in them, if not calculated ...
f6bcfd97
BP
813 item->GetSizer()->DoSetMinSize( width, height );
814 }
815 else
816 {
0ca5105b 817 // ... but the minimal size of spacers and windows in stored in them
f6bcfd97 818 item->SetInitSize( width, height );
caa251e0
RD
819 if (item->GetWindow())
820 item->GetWindow()->SetSizeHints(width, height);
f6bcfd97
BP
821 }
822
e0d8fb45 823 return true;
f6bcfd97
BP
824}
825
12a3f227 826void wxSizer::Show( wxWindow *window, bool show )
2b5f62a0 827{
12a3f227
RL
828 wxASSERT_MSG( window, _T("Show for NULL window") );
829
222ed1d6 830 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
2b5f62a0
VZ
831 while (node)
832 {
12a3f227 833 wxSizerItem *item = node->GetData();
2b5f62a0 834
12a3f227 835 if (item->GetWindow() == window)
2b5f62a0 836 {
12a3f227
RL
837 item->Show( show );
838 break;
2b5f62a0 839 }
12a3f227 840 node = node->GetNext();
2b5f62a0
VZ
841 }
842}
843
12a3f227 844void wxSizer::Show( wxSizer *sizer, bool show )
2b5f62a0 845{
12a3f227
RL
846 wxASSERT_MSG( sizer, _T("Show for NULL sizer") );
847
222ed1d6 848 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
2b5f62a0
VZ
849 while (node)
850 {
12a3f227 851 wxSizerItem *item = node->GetData();
2b5f62a0 852
12a3f227 853 if (item->GetSizer() == sizer)
2b5f62a0 854 {
12a3f227
RL
855 item->Show( show );
856 break;
2b5f62a0 857 }
12a3f227 858 node = node->GetNext();
2b5f62a0
VZ
859 }
860}
861
12a3f227 862void wxSizer::Show( size_t index, bool show )
2b5f62a0 863{
12a3f227
RL
864 wxCHECK_RET( index < m_children.GetCount(),
865 _T("Show index is out of range") );
2b5f62a0 866
12a3f227
RL
867 m_children.Item( index )->GetData()->Show( show );
868}
2b5f62a0 869
12a3f227
RL
870void wxSizer::ShowItems( bool show )
871{
222ed1d6 872 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
12a3f227
RL
873 while (node)
874 {
875 node->GetData()->Show( show );
876 node = node->GetNext();
2b5f62a0
VZ
877 }
878}
879
9cbee2ce 880bool wxSizer::IsShown( wxWindow *window ) const
2b5f62a0 881{
222ed1d6 882 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
2b5f62a0
VZ
883 while (node)
884 {
12a3f227 885 wxSizerItem *item = node->GetData();
dc259b79 886
12a3f227 887 if (item->GetWindow() == window)
2b5f62a0
VZ
888 {
889 return item->IsShown();
890 }
12a3f227 891 node = node->GetNext();
2b5f62a0
VZ
892 }
893
12a3f227
RL
894 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
895
e0d8fb45 896 return false;
2b5f62a0
VZ
897}
898
9cbee2ce 899bool wxSizer::IsShown( wxSizer *sizer ) const
2b5f62a0 900{
222ed1d6 901 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
2b5f62a0
VZ
902 while (node)
903 {
12a3f227 904 wxSizerItem *item = node->GetData();
2b5f62a0 905
12a3f227 906 if (item->GetSizer() == sizer)
2b5f62a0
VZ
907 {
908 return item->IsShown();
909 }
12a3f227 910 node = node->GetNext();
2b5f62a0
VZ
911 }
912
12a3f227
RL
913 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
914
e0d8fb45 915 return false;
2b5f62a0
VZ
916}
917
9cbee2ce 918bool wxSizer::IsShown( size_t index ) const
12a3f227
RL
919{
920 wxCHECK_MSG( index < m_children.GetCount(),
e0d8fb45 921 false,
12a3f227
RL
922 _T("IsShown index is out of range") );
923
924 return m_children.Item( index )->GetData()->IsShown();
925}
926
927
f6bcfd97
BP
928//---------------------------------------------------------------------------
929// wxGridSizer
930//---------------------------------------------------------------------------
931
932wxGridSizer::wxGridSizer( int rows, int cols, int vgap, int hgap )
12a3f227
RL
933 : m_rows( rows )
934 , m_cols( cols )
935 , m_vgap( vgap )
936 , m_hgap( hgap )
f6bcfd97 937{
02319c24
RD
938 if (m_rows == 0 && m_cols == 0)
939 m_rows = 1;
f6bcfd97
BP
940}
941
942wxGridSizer::wxGridSizer( int cols, int vgap, int hgap )
12a3f227
RL
943 : m_rows( 0 )
944 , m_cols( cols )
945 , m_vgap( vgap )
946 , m_hgap( hgap )
f6bcfd97 947{
02319c24
RD
948 if (m_rows == 0 && m_cols == 0)
949 m_rows = 1;
f6bcfd97
BP
950}
951
0ca5105b 952int wxGridSizer::CalcRowsCols(int& nrows, int& ncols) const
f6bcfd97 953{
f6bcfd97 954 int nitems = m_children.GetCount();
2b5f62a0 955 if ( nitems)
0ca5105b
VZ
956 {
957 if ( m_cols )
958 {
959 ncols = m_cols;
960 nrows = (nitems + m_cols - 1) / m_cols;
961 }
962 else if ( m_rows )
963 {
964 ncols = (nitems + m_rows - 1) / m_rows;
965 nrows = m_rows;
966 }
967 else // 0 columns, 0 rows?
968 {
969 wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") );
f6bcfd97 970
0ca5105b
VZ
971 nrows = ncols = 0;
972 }
973 }
974
975 return nitems;
976}
977
978void wxGridSizer::RecalcSizes()
979{
980 int nitems, nrows, ncols;
981 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
982 return;
f6bcfd97
BP
983
984 wxSize sz( GetSize() );
985 wxPoint pt( GetPosition() );
3ca6a5f0
BP
986
987 int w = (sz.x - (ncols - 1) * m_hgap) / ncols;
988 int h = (sz.y - (nrows - 1) * m_vgap) / nrows;
f6bcfd97
BP
989
990 int x = pt.x;
991 for (int c = 0; c < ncols; c++)
992 {
993 int y = pt.y;
994 for (int r = 0; r < nrows; r++)
995 {
996 int i = r * ncols + c;
997 if (i < nitems)
998 {
222ed1d6 999 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
12a3f227
RL
1000
1001 wxASSERT_MSG( node, _T("Failed to find SizerItemList node") );
3ca6a5f0 1002
12a3f227 1003 SetItemBounds( node->GetData(), x, y, w, h);
f6bcfd97
BP
1004 }
1005 y = y + h + m_vgap;
1006 }
1007 x = x + w + m_hgap;
1008 }
1009}
1010
1011wxSize wxGridSizer::CalcMin()
1012{
196be0f1
JS
1013 int nrows, ncols;
1014 if ( CalcRowsCols(nrows, ncols) == 0 )
0ca5105b 1015 return wxSize(10, 10);
f6bcfd97 1016
4f469fb5 1017 // Find the max width and height for any component
f6bcfd97
BP
1018 int w = 0;
1019 int h = 0;
3ca6a5f0 1020
222ed1d6 1021 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
f6bcfd97
BP
1022 while (node)
1023 {
12a3f227
RL
1024 wxSizerItem *item = node->GetData();
1025 wxSize sz( item->CalcMin() );
1026
f6bcfd97
BP
1027 w = wxMax( w, sz.x );
1028 h = wxMax( h, sz.y );
3ca6a5f0 1029
12a3f227 1030 node = node->GetNext();
f6bcfd97 1031 }
3ca6a5f0 1032
12a3f227
RL
1033 return wxSize( ncols * w + (ncols-1) * m_hgap,
1034 nrows * h + (nrows-1) * m_vgap );
f6bcfd97
BP
1035}
1036
1037void wxGridSizer::SetItemBounds( wxSizerItem *item, int x, int y, int w, int h )
1038{
1039 wxPoint pt( x,y );
1040 wxSize sz( item->CalcMin() );
1041 int flag = item->GetFlag();
1042
1043 if ((flag & wxEXPAND) || (flag & wxSHAPED))
1044 {
1045 sz = wxSize(w, h);
1046 }
1047 else
1048 {
1049 if (flag & wxALIGN_CENTER_HORIZONTAL)
1050 {
1051 pt.x = x + (w - sz.x) / 2;
1052 }
1053 else if (flag & wxALIGN_RIGHT)
1054 {
1055 pt.x = x + (w - sz.x);
1056 }
3ca6a5f0 1057
f6bcfd97
BP
1058 if (flag & wxALIGN_CENTER_VERTICAL)
1059 {
1060 pt.y = y + (h - sz.y) / 2;
1061 }
1062 else if (flag & wxALIGN_BOTTOM)
1063 {
1064 pt.y = y + (h - sz.y);
1065 }
1066 }
3ca6a5f0 1067
f6bcfd97
BP
1068 item->SetDimension(pt, sz);
1069}
1070
1071//---------------------------------------------------------------------------
1072// wxFlexGridSizer
1073//---------------------------------------------------------------------------
1074
1075wxFlexGridSizer::wxFlexGridSizer( int rows, int cols, int vgap, int hgap )
5d76f462
VZ
1076 : wxGridSizer( rows, cols, vgap, hgap ),
1077 m_flexDirection(wxBOTH),
1078 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
3ca6a5f0 1079{
f6bcfd97
BP
1080}
1081
1082wxFlexGridSizer::wxFlexGridSizer( int cols, int vgap, int hgap )
5d76f462
VZ
1083 : wxGridSizer( cols, vgap, hgap ),
1084 m_flexDirection(wxBOTH),
1085 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
3ca6a5f0 1086{
f6bcfd97 1087}
3ca6a5f0 1088
f6bcfd97
BP
1089wxFlexGridSizer::~wxFlexGridSizer()
1090{
f6bcfd97
BP
1091}
1092
1093void wxFlexGridSizer::RecalcSizes()
1094{
0ca5105b
VZ
1095 int nitems, nrows, ncols;
1096 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
f6bcfd97
BP
1097 return;
1098
20b35a69 1099 wxPoint pt( GetPosition() );
f6bcfd97
BP
1100 wxSize sz( GetSize() );
1101 wxSize minsz( CalcMin() );
5d76f462 1102
20b35a69 1103 AdjustForGrowables(sz, minsz, nrows, ncols);
3ca6a5f0 1104
f6bcfd97
BP
1105 sz = wxSize( pt.x + sz.x, pt.y + sz.y );
1106
1107 int x = pt.x;
1108 for (int c = 0; c < ncols; c++)
1109 {
1110 int y = pt.y;
1111 for (int r = 0; r < nrows; r++)
1112 {
1113 int i = r * ncols + c;
1114 if (i < nitems)
1115 {
222ed1d6 1116 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
12a3f227
RL
1117
1118 wxASSERT_MSG( node, _T("Failed to find node") );
3ca6a5f0 1119
f6bcfd97
BP
1120 int w = wxMax( 0, wxMin( m_colWidths[c], sz.x - x ) );
1121 int h = wxMax( 0, wxMin( m_rowHeights[r], sz.y - y ) );
3ca6a5f0 1122
12a3f227 1123 SetItemBounds( node->GetData(), x, y, w, h);
f6bcfd97
BP
1124 }
1125 y = y + m_rowHeights[r] + m_vgap;
1126 }
1127 x = x + m_colWidths[c] + m_hgap;
1128 }
1129}
1130
1131wxSize wxFlexGridSizer::CalcMin()
1132{
150c8d89
RL
1133 int nrows,
1134 ncols;
1135 size_t i, s;
1136
55f9f0cb 1137 // Number of rows/columns can change as items are added or removed.
5d76f462
VZ
1138 if ( !CalcRowsCols(nrows, ncols) )
1139 return wxSize(10, 10);
f6bcfd97 1140
5d76f462
VZ
1141 m_rowHeights.SetCount(nrows);
1142 m_colWidths.SetCount(ncols);
3ca6a5f0 1143
395a82b1
VZ
1144 // We have to recalcuate the sizes in case the item minimum size has
1145 // changed since the previous layout, or the item has been hidden using
1146 // wxSizer::Show(). If all the items in a row/column are hidden, the final
1147 // dimension of the row/column will be -1, indicating that the column
1148 // itself is hidden.
55f9f0cb
VZ
1149 for( s = m_rowHeights.GetCount(), i = 0; i < s; ++i )
1150 m_rowHeights[ i ] = -1;
1151 for( s = m_colWidths.GetCount(), i = 0; i < s; ++i )
1152 m_colWidths[ i ] = -1;
1153
222ed1d6 1154 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
12a3f227 1155
150c8d89 1156 i = 0;
f6bcfd97
BP
1157 while (node)
1158 {
12a3f227 1159 wxSizerItem *item = node->GetData();
55f9f0cb
VZ
1160 if ( item->IsShown() )
1161 {
1162 wxSize sz( item->CalcMin() );
1163 int row = i / ncols;
1164 int col = i % ncols;
12a3f227 1165
55f9f0cb
VZ
1166 m_rowHeights[ row ] = wxMax( wxMax( 0, sz.y ), m_rowHeights[ row ] );
1167 m_colWidths[ col ] = wxMax( wxMax( 0, sz.x ), m_colWidths[ col ] );
1168 }
3ca6a5f0 1169
12a3f227 1170 node = node->GetNext();
f6bcfd97
BP
1171 i++;
1172 }
3ca6a5f0 1173
20b35a69
RD
1174 AdjustForFlexDirection();
1175
1176 // Sum total minimum size, including gaps between rows/columns.
1177 // -1 is used as a magic number meaning empty column.
1178 int width = 0;
1179 for (int col = 0; col < ncols; col++)
1180 if ( m_colWidths[ col ] != -1 )
1181 width += m_colWidths[ col ] + ( col == ncols-1 ? 0 : m_hgap );
1182
1183 int height = 0;
1184 for (int row = 0; row < nrows; row++)
1185 if ( m_rowHeights[ row ] != -1 )
1186 height += m_rowHeights[ row ] + ( row == nrows-1 ? 0 : m_vgap );
1187
1188 return wxSize( width, height );
1189}
1190
1191void wxFlexGridSizer::AdjustForFlexDirection()
1192{
1193 // the logic in CalcMin works when we resize flexibly in both directions
1194 // but maybe this is not the case
5d76f462
VZ
1195 if ( m_flexDirection != wxBOTH )
1196 {
1197 // select the array corresponding to the direction in which we do *not*
1198 // resize flexibly
1199 wxArrayInt& array = m_flexDirection == wxVERTICAL ? m_colWidths
1200 : m_rowHeights;
1201
1202 const int count = array.GetCount();
1203
1204 // find the largest value in this array
55f9f0cb 1205 int n, largest = 0;
5d76f462
VZ
1206 for ( n = 0; n < count; ++n )
1207 {
1208 if ( array[n] > largest )
1209 largest = array[n];
1210 }
1211
1212 // and now fill it with the largest value
1213 for ( n = 0; n < count; ++n )
1214 {
1215 array[n] = largest;
1216 }
1217 }
20b35a69 1218}
5d76f462 1219
3ca6a5f0 1220
20b35a69
RD
1221void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz, const wxSize& minsz,
1222 int nrows, int ncols)
1223{
1224 // what to do with the rows? by default, resize them proportionally
1225 if ( sz.y > minsz.y && ( (m_flexDirection & wxVERTICAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1226 {
1227 int sum_proportions = 0;
1228 int growable_space = 0;
1229 int num = 0;
1230 size_t idx;
1231 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1232 {
1233 // Since the number of rows/columns can change as items are
1234 // inserted/deleted, we need to verify at runtime that the
1235 // requested growable rows/columns are still valid.
1236 if (m_growableRows[idx] >= nrows)
1237 continue;
1238
1239 // If all items in a row/column are hidden, that row/column will
1240 // have a dimension of -1. This causes the row/column to be
1241 // hidden completely.
1242 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1243 continue;
1244 sum_proportions += m_growableRowsProportions[idx];
1245 growable_space += m_rowHeights[ m_growableRows[idx] ];
1246 num++;
1247 }
3ca6a5f0 1248
20b35a69
RD
1249 if (num > 0)
1250 {
1251 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1252 {
1253 if (m_growableRows[idx] >= nrows )
1254 continue;
1255 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1256 m_rowHeights[ m_growableRows[idx] ] = 0;
1257 else
1258 {
1259 int delta = (sz.y - minsz.y);
1260 if (sum_proportions == 0)
1261 delta = (delta/num) + m_rowHeights[ m_growableRows[idx] ];
1262 else
1263 delta = ((delta+growable_space)*m_growableRowsProportions[idx]) / sum_proportions;
1264 m_rowHeights[ m_growableRows[idx] ] = delta;
1265 }
1266 }
1267 }
1268 }
1269 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.y > minsz.y) )
1270 {
1271 // rounding problem?
1272 for ( int row = 0; row < nrows; ++row )
1273 m_rowHeights[ row ] = sz.y / nrows;
1274 }
1275
1276 // the same logic as above but for the columns
1277 if ( sz.x > minsz.x && ( (m_flexDirection & wxHORIZONTAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1278 {
1279 int sum_proportions = 0;
1280 int growable_space = 0;
1281 int num = 0;
1282 size_t idx;
1283 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1284 {
1285 // Since the number of rows/columns can change as items are
1286 // inserted/deleted, we need to verify at runtime that the
1287 // requested growable rows/columns are still valid.
1288 if (m_growableCols[idx] >= ncols)
1289 continue;
1290
1291 // If all items in a row/column are hidden, that row/column will
1292 // have a dimension of -1. This causes the column to be hidden
1293 // completely.
1294 if (m_colWidths[ m_growableCols[idx] ] == -1)
1295 continue;
1296 sum_proportions += m_growableColsProportions[idx];
1297 growable_space += m_colWidths[ m_growableCols[idx] ];
1298 num++;
1299 }
1300
1301 if (num > 0)
1302 {
1303 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1304 {
1305 if (m_growableCols[idx] >= ncols )
1306 continue;
1307 if (m_colWidths[ m_growableCols[idx] ] == -1)
1308 m_colWidths[ m_growableCols[idx] ] = 0;
1309 else
1310 {
1311 int delta = (sz.x - minsz.x);
1312 if (sum_proportions == 0)
1313 delta = (delta/num) + m_colWidths[ m_growableCols[idx] ];
1314 else
1315 delta = ((delta+growable_space)*m_growableColsProportions[idx])/sum_proportions;
1316 m_colWidths[ m_growableCols[idx] ] = delta;
1317 }
1318 }
1319 }
1320 }
1321 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.x > minsz.x) )
1322 {
1323 for ( int col=0; col < ncols; ++col )
1324 m_colWidths[ col ] = sz.x / ncols;
1325 }
f6bcfd97
BP
1326}
1327
20b35a69 1328
e8800dcf 1329void wxFlexGridSizer::AddGrowableRow( size_t idx, int proportion )
f6bcfd97
BP
1330{
1331 m_growableRows.Add( idx );
e8800dcf 1332 m_growableRowsProportions.Add( proportion );
f6bcfd97
BP
1333}
1334
8d2474f4 1335void wxFlexGridSizer::RemoveGrowableRow( size_t idx )
f6bcfd97 1336{
8d2474f4 1337 m_growableRows.Remove( idx );
f6bcfd97
BP
1338}
1339
e8800dcf 1340void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
f6bcfd97
BP
1341{
1342 m_growableCols.Add( idx );
e8800dcf 1343 m_growableColsProportions.Add( proportion );
f6bcfd97
BP
1344}
1345
8d2474f4 1346void wxFlexGridSizer::RemoveGrowableCol( size_t idx )
f6bcfd97 1347{
8d2474f4 1348 m_growableCols.Remove( idx );
f6bcfd97
BP
1349}
1350
c62ac5b6 1351//---------------------------------------------------------------------------
92afa2b1 1352// wxBoxSizer
61d514bb
RR
1353//---------------------------------------------------------------------------
1354
92afa2b1 1355wxBoxSizer::wxBoxSizer( int orient )
12a3f227 1356 : m_orient( orient )
61d514bb 1357{
61d514bb
RR
1358}
1359
92afa2b1 1360void wxBoxSizer::RecalcSizes()
61d514bb
RR
1361{
1362 if (m_children.GetCount() == 0)
61d514bb 1363 return;
0c0d686f 1364
61d514bb 1365 int delta = 0;
61d514bb
RR
1366 if (m_stretchable)
1367 {
1368 if (m_orient == wxHORIZONTAL)
85e5cfc9 1369 delta = m_size.x - m_fixedWidth;
3ca6a5f0 1370 else
85e5cfc9 1371 delta = m_size.y - m_fixedHeight;
61d514bb 1372 }
0c0d686f 1373
61d514bb 1374 wxPoint pt( m_position );
0c0d686f 1375
222ed1d6 1376 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
61d514bb
RR
1377 while (node)
1378 {
12a3f227
RL
1379 wxSizerItem *item = node->GetData();
1380
2b5f62a0 1381 if (item->IsShown())
3ca6a5f0 1382 {
2b5f62a0 1383 wxSize size( item->CalcMin() );
3ca6a5f0 1384
2b5f62a0 1385 if (m_orient == wxVERTICAL)
3ca6a5f0 1386 {
2b5f62a0 1387 wxCoord height = size.y;
12a3f227 1388 if (item->GetProportion())
2b5f62a0 1389 {
85e5cfc9
VZ
1390 // Because of at least one visible item has non-zero
1391 // proportion then m_stretchable is not zero
1392 height = (delta * item->GetProportion()) / m_stretchable;
2b5f62a0
VZ
1393 }
1394
1395 wxPoint child_pos( pt );
1396 wxSize child_size( wxSize( size.x, height) );
1397
1398 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1399 child_size.x = m_size.x;
1400 else if (item->GetFlag() & wxALIGN_RIGHT)
1401 child_pos.x += m_size.x - size.x;
1402 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
1403 // XXX wxCENTER is added for backward compatibility;
1404 // wxALIGN_CENTER should be used in new code
1405 child_pos.x += (m_size.x - size.x) / 2;
1406
1407 item->SetDimension( child_pos, child_size );
1408
1409 pt.y += height;
1410 }
1411 else
1412 {
1413 wxCoord width = size.x;
12a3f227 1414 if (item->GetProportion())
2b5f62a0 1415 {
85e5cfc9
VZ
1416 // Because of at least one visible item has non-zero
1417 // proportion then m_stretchable is not zero
1418 width = (delta * item->GetProportion()) / m_stretchable;
2b5f62a0
VZ
1419 }
1420
1421 wxPoint child_pos( pt );
1422 wxSize child_size( wxSize(width, size.y) );
1423
1424 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1425 child_size.y = m_size.y;
1426 else if (item->GetFlag() & wxALIGN_BOTTOM)
1427 child_pos.y += m_size.y - size.y;
1428 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
1429 // XXX wxCENTER is added for backward compatibility;
1430 // wxALIGN_CENTER should be used in new code
1431 child_pos.y += (m_size.y - size.y) / 2;
1432
1433 item->SetDimension( child_pos, child_size );
1434
1435 pt.x += width;
3ca6a5f0 1436 }
3ca6a5f0
BP
1437 }
1438
12a3f227 1439 node = node->GetNext();
61d514bb
RR
1440 }
1441}
1442
92afa2b1 1443wxSize wxBoxSizer::CalcMin()
61d514bb
RR
1444{
1445 if (m_children.GetCount() == 0)
c7a9fa36 1446 return wxSize(10,10);
0c0d686f 1447
61d514bb
RR
1448 m_stretchable = 0;
1449 m_minWidth = 0;
1450 m_minHeight = 0;
1451 m_fixedWidth = 0;
1452 m_fixedHeight = 0;
0c0d686f 1453
222ed1d6 1454 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
85e5cfc9
VZ
1455 while (node)
1456 {
1457 wxSizerItem *item = node->GetData();
12a3f227 1458
85e5cfc9
VZ
1459 if (item->IsShown() && item->GetProportion() != 0)
1460 m_stretchable += item->GetProportion();
1461
1462 node = node->GetNext();
1463 }
1464
1465 // Total minimum size (width or height) of sizer
1466 int maxMinSize = 0;
1467
1468 node = m_children.GetFirst();
61d514bb 1469 while (node)
f98de448 1470 {
85e5cfc9 1471 wxSizerItem *item = node->GetData();
12a3f227
RL
1472
1473 if (item->IsShown() && item->GetProportion() != 0)
f98de448 1474 {
12a3f227 1475 int stretch = item->GetProportion();
f98de448 1476 wxSize size( item->CalcMin() );
85e5cfc9
VZ
1477 int minSize;
1478
f98de448 1479 // Integer division rounded up is (a + b - 1) / b
85e5cfc9
VZ
1480 // Round up needed in order to guarantee that all
1481 // all items will have size not less then their min size
f98de448 1482 if (m_orient == wxHORIZONTAL)
85e5cfc9 1483 minSize = ( size.x*m_stretchable + stretch - 1)/stretch;
f98de448 1484 else
85e5cfc9
VZ
1485 minSize = ( size.y*m_stretchable + stretch - 1)/stretch;
1486
1487 if (minSize > maxMinSize)
1488 maxMinSize = minSize;
f98de448 1489 }
12a3f227 1490 node = node->GetNext();
f98de448 1491 }
12a3f227 1492
4f469fb5
RR
1493 // Calculate overall minimum size
1494 node = m_children.GetFirst();
f98de448 1495 while (node)
61d514bb 1496 {
85e5cfc9 1497 wxSizerItem *item = node->GetData();
12a3f227 1498
2b5f62a0 1499 if (item->IsShown())
f98de448 1500 {
2b5f62a0 1501 wxSize size( item->CalcMin() );
12a3f227 1502 if (item->GetProportion() != 0)
2b5f62a0
VZ
1503 {
1504 if (m_orient == wxHORIZONTAL)
85e5cfc9 1505 size.x = (maxMinSize*item->GetProportion())/m_stretchable;
2b5f62a0 1506 else
85e5cfc9 1507 size.y = (maxMinSize*item->GetProportion())/m_stretchable;
3ca6a5f0
BP
1508 }
1509 else
2b5f62a0
VZ
1510 {
1511 if (m_orient == wxVERTICAL)
1512 {
1513 m_fixedHeight += size.y;
1514 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1515 }
1516 else
1517 {
1518 m_fixedWidth += size.x;
1519 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1520 }
1521 }
85e5cfc9
VZ
1522
1523 if (m_orient == wxHORIZONTAL)
1524 {
1525 m_minWidth += size.x;
1526 m_minHeight = wxMax( m_minHeight, size.y );
1527 }
1528 else
1529 {
1530 m_minHeight += size.y;
1531 m_minWidth = wxMax( m_minWidth, size.x );
1532 }
2b5f62a0 1533 }
12a3f227 1534 node = node->GetNext();
61d514bb 1535 }
0c0d686f 1536
61d514bb
RR
1537 return wxSize( m_minWidth, m_minHeight );
1538}
27ea1d8a
RR
1539
1540//---------------------------------------------------------------------------
1541// wxStaticBoxSizer
1542//---------------------------------------------------------------------------
1543
1e6feb95
VZ
1544#if wxUSE_STATBOX
1545
27ea1d8a 1546wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
12a3f227
RL
1547 : wxBoxSizer( orient )
1548 , m_staticBox( box )
27ea1d8a 1549{
223d09f6 1550 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
27ea1d8a 1551}
0c0d686f 1552
12a3f227
RL
1553static void GetStaticBoxBorders( wxStaticBox *box,
1554 int *borderTop,
1555 int *borderOther)
84028727
VZ
1556{
1557 // this has to be done platform by platform as there is no way to
1558 // guess the thickness of a wxStaticBox border
ec4e4a14
DE
1559#ifdef __WXCOCOA__
1560 box->GetBordersForSizer(borderTop,borderOther);
67021102
DS
1561#elif defined(__WXMAC__)
1562
1563 static int extraTop = -1; // Uninitted
1564 static int other = 5;
1565
1566 if ( extraTop == -1 )
1567 {
67021102
DS
1568 // The minimal border used for the top. Later on the staticbox'
1569 // font height is added to this.
1570 extraTop = 0;
1571
78ca5669 1572 if ( UMAGetSystemVersion() >= 0x1030 /*Panther*/ )
67021102
DS
1573 {
1574 // As indicated by the HIG, Panther needs an extra border of 11
1575 // pixels (otherwise overlapping occurs at the top). The "other"
1576 // border has to be 11.
1577 extraTop = 11;
1578 other = 11;
1579 }
1580
1581 }
1582
1583 *borderTop = extraTop + box->GetCharHeight();
1584 *borderOther = other;
1585
1586#else
84028727
VZ
1587#ifdef __WXGTK__
1588 if ( box->GetLabel().IsEmpty() )
1589 *borderTop = 5;
1590 else
1591#endif // __WXGTK__
f2b99f63
JS
1592 *borderTop = box->GetCharHeight();
1593
84028727 1594 *borderOther = 5;
ec4e4a14 1595#endif // __WXCOCOA__
84028727
VZ
1596}
1597
27ea1d8a
RR
1598void wxStaticBoxSizer::RecalcSizes()
1599{
84028727
VZ
1600 int top_border, other_border;
1601 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
27ea1d8a
RR
1602
1603 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
0c0d686f 1604
27ea1d8a
RR
1605 wxPoint old_pos( m_position );
1606 m_position.x += other_border;
1607 m_position.y += top_border;
1608 wxSize old_size( m_size );
1609 m_size.x -= 2*other_border;
1610 m_size.y -= top_border + other_border;
0c0d686f 1611
27ea1d8a 1612 wxBoxSizer::RecalcSizes();
0c0d686f 1613
27ea1d8a
RR
1614 m_position = old_pos;
1615 m_size = old_size;
1616}
1617
1618wxSize wxStaticBoxSizer::CalcMin()
1619{
84028727
VZ
1620 int top_border, other_border;
1621 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
0c0d686f 1622
27ea1d8a 1623 wxSize ret( wxBoxSizer::CalcMin() );
cae31b8b 1624 ret.x += 2*other_border;
27ea1d8a 1625 ret.y += other_border + top_border;
0c0d686f 1626
27ea1d8a
RR
1627 return ret;
1628}
83edc0a5 1629
1e6feb95
VZ
1630#endif // wxUSE_STATBOX
1631
ade4eb65 1632// ----------------------------------------------------------------------------
83edc0a5 1633// wxNotebookSizer
ade4eb65 1634// ----------------------------------------------------------------------------
83edc0a5 1635
ade4eb65 1636#if wxUSE_BOOKCTRL
60be2f47 1637
ade4eb65
VZ
1638wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrl *bookctrl)
1639 : m_bookctrl(bookctrl)
83edc0a5 1640{
ade4eb65 1641 wxASSERT_MSG( bookctrl, wxT("wxBookCtrlSizer needs a control") );
83edc0a5
RR
1642}
1643
ade4eb65 1644void wxBookCtrlSizer::RecalcSizes()
83edc0a5 1645{
ade4eb65 1646 m_bookctrl->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
83edc0a5
RR
1647}
1648
ade4eb65 1649wxSize wxBookCtrlSizer::CalcMin()
83edc0a5 1650{
ade4eb65 1651 wxSize sizeBorder = m_bookctrl->CalcSizeFromPage(wxSize(0, 0));
1e6feb95
VZ
1652
1653 sizeBorder.x += 5;
1654 sizeBorder.y += 5;
3ca6a5f0 1655
ade4eb65 1656 if ( m_bookctrl->GetPageCount() == 0 )
1e6feb95
VZ
1657 {
1658 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
1659 }
83edc0a5
RR
1660
1661 int maxX = 0;
1662 int maxY = 0;
1663
ade4eb65
VZ
1664 wxWindowList::compatibility_iterator
1665 node = m_bookctrl->GetChildren().GetFirst();
83edc0a5
RR
1666 while (node)
1667 {
1668 wxWindow *item = node->GetData();
3ca6a5f0
BP
1669 wxSizer *itemsizer = item->GetSizer();
1670
1671 if (itemsizer)
1672 {
83edc0a5 1673 wxSize subsize( itemsizer->CalcMin() );
83edc0a5 1674
1e6feb95
VZ
1675 if (subsize.x > maxX)
1676 maxX = subsize.x;
1677 if (subsize.y > maxY)
1678 maxY = subsize.y;
3ca6a5f0
BP
1679 }
1680
1681 node = node->GetNext();
83edc0a5
RR
1682 }
1683
1e6feb95 1684 return wxSize( maxX, maxY ) + sizeBorder;
83edc0a5
RR
1685}
1686
2d480e40
RD
1687
1688#if wxUSE_NOTEBOOK
1689
1690wxNotebookSizer::wxNotebookSizer(wxNotebook *nb)
1691 : wxBookCtrlSizer(nb)
1692{
1693}
1694
1695#endif // wxUSE_NOTEBOOOK
ade4eb65 1696#endif // wxUSE_BOOKCTRL
34c3ffca 1697