]> git.saurik.com Git - wxWidgets.git/blame - src/common/sizer.cpp
correcting dangling refs / reuse
[wxWidgets.git] / src / common / sizer.cpp
CommitLineData
5279a24d
RR
1/////////////////////////////////////////////////////////////////////////////
2// Name: sizer.cpp
1044a386 3// Purpose: provide new wxSizer class for layout
aa5973ee
JS
4// Author: Robert Roebling and Robin Dunn, contributions by
5// Dirk Holtwick, Ron Lee
566d84a7 6// Modified by: Ron Lee
0c0d686f 7// Created:
5279a24d 8// RCS-ID: $Id$
aa5973ee 9// Copyright: (c) Robin Dunn, Robert Roebling
65571936 10// Licence: wxWindows licence
5279a24d
RR
11/////////////////////////////////////////////////////////////////////////////
12
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"
c54b92d3 27#include "wx/listimpl.cpp"
adbf2d73
VS
28#if WXWIN_COMPATIBILITY_2_4
29 #include "wx/notebook.h"
30#endif
5279a24d 31
78ca5669
DS
32#ifdef __WXMAC__
33# include "wx/mac/uma.h"
34#endif
35
0c0d686f
RD
36//---------------------------------------------------------------------------
37
9cbee2ce
RL
38IMPLEMENT_CLASS(wxSizerItem, wxObject)
39IMPLEMENT_CLASS(wxSizer, wxObject)
40IMPLEMENT_CLASS(wxGridSizer, wxSizer)
41IMPLEMENT_CLASS(wxFlexGridSizer, wxGridSizer)
42IMPLEMENT_CLASS(wxBoxSizer, wxSizer)
1e6feb95 43#if wxUSE_STATBOX
9cbee2ce 44IMPLEMENT_CLASS(wxStaticBoxSizer, wxBoxSizer)
1e6feb95 45#endif
0c0d686f 46
12a3f227
RL
47WX_DEFINE_EXPORTED_LIST( wxSizerItemList );
48
066f1b7a 49/*
8b2bac62
WS
50 TODO PROPERTIES
51 sizeritem
52 object
53 object_ref
54 minsize
55 option
56 flag
57 border
066f1b7a 58 spacer
8b2bac62
WS
59 option
60 flag
61 borfder
62 boxsizer
63 orient
066f1b7a 64 staticboxsizer
8b2bac62
WS
65 orient
66 label
67 gridsizer
68 rows
69 cols
70 vgap
71 hgap
72 flexgridsizer
73 rows
74 cols
75 vgap
76 hgap
77 growablerows
78 growablecols
066f1b7a
SC
79 minsize
80*/
ccbc8038 81
5279a24d 82//---------------------------------------------------------------------------
3417c2cd 83// wxSizerItem
5279a24d
RR
84//---------------------------------------------------------------------------
85
ccbc8038
VZ
86void wxSizerItem::Init()
87{
88 m_window = NULL;
89 m_sizer = NULL;
90 m_show = true;
91 m_userData = NULL;
56eee37f 92 m_zoneRect = wxRect( 0, 0, 0, 0 );
ccbc8038
VZ
93}
94
95void wxSizerItem::Init(const wxSizerFlags& flags)
96{
97 Init();
98
99 m_proportion = flags.GetProportion();
100 m_flag = flags.GetFlags();
101 m_border = flags.GetBorderInPixels();
102}
103
12a3f227
RL
104wxSizerItem::wxSizerItem( int width, int height, int proportion, int flag, int border, wxObject* userData )
105 : m_window( NULL )
106 , m_sizer( NULL )
00976fe5
RL
107 , m_size( wxSize( width, height ) ) // size is set directly
108 , m_minSize( m_size ) // minimal size is the initial size
12a3f227 109 , m_proportion( proportion )
00976fe5
RL
110 , m_border( border )
111 , m_flag( flag )
56eee37f 112 , m_zoneRect( 0, 0, 0, 0 )
e0d8fb45 113 , m_show( true )
00976fe5 114 , m_userData( userData )
5279a24d 115{
00976fe5 116 SetRatio( m_size );
5279a24d
RR
117}
118
12a3f227 119wxSizerItem::wxSizerItem( wxWindow *window, int proportion, int flag, int border, wxObject* userData )
00976fe5 120 : m_window( window )
12a3f227 121 , m_sizer( NULL )
12a3f227 122 , m_proportion( proportion )
00976fe5
RL
123 , m_border( border )
124 , m_flag( flag )
56eee37f 125 , m_zoneRect( 0, 0, 0, 0 )
e0d8fb45 126 , m_show( true )
00976fe5 127 , m_userData( userData )
5279a24d 128{
ba763a45
RD
129 if (flag & wxFIXED_MINSIZE)
130 window->SetMinSize(window->GetSize());
131 m_minSize = window->GetSize();
8b2bac62 132
36461f58
RD
133 // aspect ratio calculated from initial size
134 SetRatio( m_minSize );
135
00976fe5 136 // m_size is calculated later
5279a24d
RR
137}
138
12a3f227
RL
139wxSizerItem::wxSizerItem( wxSizer *sizer, int proportion, int flag, int border, wxObject* userData )
140 : m_window( NULL )
00976fe5 141 , m_sizer( sizer )
12a3f227 142 , m_proportion( proportion )
00976fe5
RL
143 , m_border( border )
144 , m_flag( flag )
56eee37f 145 , m_zoneRect( 0, 0, 0, 0 )
e0d8fb45 146 , m_show( true )
12a3f227 147 , m_ratio( 0.0 )
00976fe5 148 , m_userData( userData )
5279a24d 149{
00976fe5
RL
150 // m_minSize is calculated later
151 // m_size is calculated later
5279a24d
RR
152}
153
20b35a69 154wxSizerItem::wxSizerItem()
20b35a69 155{
ccbc8038
VZ
156 Init();
157
158 m_proportion = 0;
159 m_border = 0;
160 m_flag = 0;
20b35a69
RD
161}
162
0c0d686f
RD
163wxSizerItem::~wxSizerItem()
164{
f91e8382
VZ
165 delete m_userData;
166
167 if ( m_window )
168 {
169 m_window->SetContainingSizer(NULL);
170 }
171 else // we must be a sizer
172 {
0c0d686f 173 delete m_sizer;
f91e8382 174 }
0c0d686f
RD
175}
176
177
9cbee2ce 178wxSize wxSizerItem::GetSize() const
5279a24d 179{
d597fcb7 180 wxSize ret;
3417c2cd 181 if (IsSizer())
d597fcb7
RR
182 ret = m_sizer->GetSize();
183 else
c62ac5b6 184 if (IsWindow())
d597fcb7
RR
185 ret = m_window->GetSize();
186 else ret = m_size;
0c0d686f 187
d597fcb7
RR
188 if (m_flag & wxWEST)
189 ret.x += m_border;
190 if (m_flag & wxEAST)
191 ret.x += m_border;
192 if (m_flag & wxNORTH)
193 ret.y += m_border;
194 if (m_flag & wxSOUTH)
195 ret.y += m_border;
0c0d686f 196
d597fcb7 197 return ret;
5279a24d
RR
198}
199
3417c2cd 200wxSize wxSizerItem::CalcMin()
c62ac5b6 201{
3417c2cd 202 if (IsSizer())
be2577e4 203 {
ba763a45 204 m_minSize = m_sizer->GetMinSize();
d13d8d4e 205
be2577e4
RD
206 // if we have to preserve aspect ratio _AND_ this is
207 // the first-time calculation, consider ret to be initial size
d13d8d4e 208 if ((m_flag & wxSHAPED) && !m_ratio)
36461f58 209 SetRatio(m_minSize);
be2577e4 210 }
ba763a45 211 else if ( IsWindow() )
d13d8d4e 212 {
ba763a45
RD
213 // Since the size of the window may change during runtime, we
214 // should use the current minimal/best size.
215 m_minSize = m_window->GetBestFittingSize();
d13d8d4e 216 }
0c0d686f 217
ba763a45
RD
218 return GetMinSizeWithBorder();
219}
220
221wxSize wxSizerItem::GetMinSizeWithBorder() const
222{
223 wxSize ret = m_minSize;
224
d597fcb7
RR
225 if (m_flag & wxWEST)
226 ret.x += m_border;
227 if (m_flag & wxEAST)
228 ret.x += m_border;
229 if (m_flag & wxNORTH)
230 ret.y += m_border;
231 if (m_flag & wxSOUTH)
232 ret.y += m_border;
8b2bac62 233
d597fcb7 234 return ret;
c62ac5b6
RR
235}
236
ba763a45 237
3417c2cd 238void wxSizerItem::SetDimension( wxPoint pos, wxSize size )
c62ac5b6 239{
cdddaeea 240 if (m_flag & wxSHAPED)
d597fcb7 241 {
be2577e4
RD
242 // adjust aspect ratio
243 int rwidth = (int) (size.y * m_ratio);
cdddaeea
VZ
244 if (rwidth > size.x)
245 {
be2577e4
RD
246 // fit horizontally
247 int rheight = (int) (size.x / m_ratio);
248 // add vertical space
249 if (m_flag & wxALIGN_CENTER_VERTICAL)
250 pos.y += (size.y - rheight) / 2;
251 else if (m_flag & wxALIGN_BOTTOM)
252 pos.y += (size.y - rheight);
253 // use reduced dimensions
254 size.y =rheight;
cdddaeea
VZ
255 }
256 else if (rwidth < size.x)
257 {
be2577e4
RD
258 // add horizontal space
259 if (m_flag & wxALIGN_CENTER_HORIZONTAL)
260 pos.x += (size.x - rwidth) / 2;
261 else if (m_flag & wxALIGN_RIGHT)
262 pos.x += (size.x - rwidth);
263 size.x = rwidth;
264 }
265 }
33ac7e6f 266
cdddaeea
VZ
267 // This is what GetPosition() returns. Since we calculate
268 // borders afterwards, GetPosition() will be the left/top
269 // corner of the surrounding border.
270 m_pos = pos;
271
272 if (m_flag & wxWEST)
273 {
274 pos.x += m_border;
275 size.x -= m_border;
276 }
277 if (m_flag & wxEAST)
278 {
279 size.x -= m_border;
280 }
281 if (m_flag & wxNORTH)
282 {
283 pos.y += m_border;
284 size.y -= m_border;
285 }
286 if (m_flag & wxSOUTH)
287 {
288 size.y -= m_border;
289 }
0c0d686f 290
3417c2cd 291 if (IsSizer())
c62ac5b6 292 m_sizer->SetDimension( pos.x, pos.y, size.x, size.y );
0c0d686f 293
56eee37f 294 m_zoneRect = wxRect(pos, size);
c62ac5b6 295 if (IsWindow())
b919f007 296 m_window->SetSize( pos.x, pos.y, size.x, size.y, wxSIZE_ALLOW_MINUS_ONE );
d597fcb7
RR
297
298 m_size = size;
c62ac5b6
RR
299}
300
84f7908b
RR
301void wxSizerItem::DeleteWindows()
302{
303 if (m_window)
77aa9abd 304 {
84f7908b 305 m_window->Destroy();
77aa9abd
RD
306 m_window = NULL;
307 }
be90c029 308
84f7908b
RR
309 if (m_sizer)
310 m_sizer->DeleteWindows();
311}
312
9cbee2ce 313bool wxSizerItem::IsWindow() const
5279a24d
RR
314{
315 return (m_window != NULL);
316}
317
9cbee2ce 318bool wxSizerItem::IsSizer() const
5279a24d
RR
319{
320 return (m_sizer != NULL);
321}
322
9cbee2ce 323bool wxSizerItem::IsSpacer() const
5279a24d
RR
324{
325 return (m_window == NULL) && (m_sizer == NULL);
326}
327
12a3f227
RL
328void wxSizerItem::Show( bool show )
329{
330 m_show = show;
331
332 if( IsWindow() )
333 m_window->Show( show );
334 else if( IsSizer() )
335 m_sizer->ShowItems( show );
336
337 // ... nothing else to do to hide/show spacers
338}
339
340void wxSizerItem::SetOption( int option )
341{
342 SetProportion( option );
343}
344
345int wxSizerItem::GetOption() const
346{
347 return GetProportion();
348}
349
350
5279a24d 351//---------------------------------------------------------------------------
3417c2cd 352// wxSizer
5279a24d
RR
353//---------------------------------------------------------------------------
354
3417c2cd 355wxSizer::wxSizer()
12a3f227 356 : m_minSize( wxSize( 0, 0 ) )
5279a24d 357{
5279a24d
RR
358}
359
3417c2cd 360wxSizer::~wxSizer()
5279a24d 361{
222ed1d6 362 WX_CLEAR_LIST(wxSizerItemList, m_children);
5279a24d 363}
0c0d686f 364
56eee37f 365wxSizerItem* wxSizer::Insert( size_t index, wxSizerItem *item )
12a3f227
RL
366{
367 m_children.Insert( index, item );
0c0d686f 368
12a3f227
RL
369 if( item->GetWindow() )
370 item->GetWindow()->SetContainingSizer( this );
56eee37f
WS
371
372 return item;
12a3f227
RL
373}
374
375bool wxSizer::Remove( wxWindow *window )
376{
377 return Detach( window );
42b4e99e
RR
378}
379
380bool wxSizer::Remove( wxSizer *sizer )
381{
12a3f227 382 wxASSERT_MSG( sizer, _T("Removing NULL sizer") );
0c0d686f 383
222ed1d6 384 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
42b4e99e
RR
385 while (node)
386 {
12a3f227
RL
387 wxSizerItem *item = node->GetData();
388
3ca6a5f0 389 if (item->GetSizer() == sizer)
222ed1d6
MB
390 {
391 delete item;
392 m_children.Erase( node );
393 return true;
394 }
12a3f227
RL
395
396 node = node->GetNext();
42b4e99e 397 }
0c0d686f 398
e0d8fb45 399 return false;
42b4e99e
RR
400}
401
e0d8fb45 402bool wxSizer::Remove( int index )
42b4e99e 403{
e0d8fb45
VZ
404 wxCHECK_MSG( index >= 0 && (size_t)index < m_children.GetCount(),
405 false,
12a3f227 406 _T("Remove index is out of range") );
0c0d686f 407
222ed1d6 408 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
0c0d686f 409
e0d8fb45 410 wxCHECK_MSG( node, false, _T("Failed to find child node") );
12a3f227 411
e0d8fb45 412 wxSizerItem *item = node->GetData();
9cbee2ce
RL
413
414 if( item->IsWindow() )
415 item->GetWindow()->SetContainingSizer( NULL );
416
222ed1d6
MB
417 delete item;
418 m_children.Erase( node );
419 return true;
42b4e99e 420}
0c0d686f 421
00976fe5
RL
422bool wxSizer::Detach( wxSizer *sizer )
423{
12a3f227 424 wxASSERT_MSG( sizer, _T("Detaching NULL sizer") );
00976fe5 425
222ed1d6 426 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
00976fe5
RL
427 while (node)
428 {
12a3f227
RL
429 wxSizerItem *item = node->GetData();
430
00976fe5
RL
431 if (item->GetSizer() == sizer)
432 {
96fdbb60 433 item->DetachSizer();
89c20ac1 434 delete item;
222ed1d6
MB
435 m_children.Erase( node );
436 return true;
12a3f227
RL
437 }
438 node = node->GetNext();
439 }
440
e0d8fb45 441 return false;
12a3f227
RL
442}
443
444bool wxSizer::Detach( wxWindow *window )
445{
446 wxASSERT_MSG( window, _T("Detaching NULL window") );
447
222ed1d6 448 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
12a3f227
RL
449 while (node)
450 {
451 wxSizerItem *item = node->GetData();
452
453 if (item->GetWindow() == window)
454 {
455 item->GetWindow()->SetContainingSizer( NULL );
89c20ac1 456 delete item;
222ed1d6
MB
457 m_children.Erase( node );
458 return true;
00976fe5 459 }
12a3f227 460 node = node->GetNext();
00976fe5
RL
461 }
462
e0d8fb45 463 return false;
00976fe5
RL
464}
465
e0d8fb45 466bool wxSizer::Detach( int index )
00976fe5 467{
e0d8fb45
VZ
468 wxCHECK_MSG( index >= 0 && (size_t)index < m_children.GetCount(),
469 false,
12a3f227
RL
470 _T("Detach index is out of range") );
471
222ed1d6 472 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
00976fe5 473
e0d8fb45 474 wxCHECK_MSG( node, false, _T("Failed to find child node") );
00976fe5 475
e0d8fb45 476 wxSizerItem *item = node->GetData();
9cbee2ce
RL
477
478 if( item->IsSizer() )
479 item->DetachSizer();
480 else if( item->IsWindow() )
481 item->GetWindow()->SetContainingSizer( NULL );
12a3f227 482
89c20ac1 483 delete item;
222ed1d6
MB
484 m_children.Erase( node );
485 return true;
00976fe5
RL
486}
487
84f7908b
RR
488void wxSizer::Clear( bool delete_windows )
489{
be90c029 490 // First clear the ContainingSizer pointers
222ed1d6 491 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
be90c029
RD
492 while (node)
493 {
12a3f227
RL
494 wxSizerItem *item = node->GetData();
495
be90c029 496 if (item->IsWindow())
12a3f227
RL
497 item->GetWindow()->SetContainingSizer( NULL );
498 node = node->GetNext();
be90c029
RD
499 }
500
501 // Destroy the windows if needed
84f7908b
RR
502 if (delete_windows)
503 DeleteWindows();
be90c029
RD
504
505 // Now empty the list
222ed1d6 506 WX_CLEAR_LIST(wxSizerItemList, m_children);
84f7908b
RR
507}
508
509void wxSizer::DeleteWindows()
510{
222ed1d6 511 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
84f7908b
RR
512 while (node)
513 {
12a3f227
RL
514 wxSizerItem *item = node->GetData();
515
84f7908b 516 item->DeleteWindows();
12a3f227 517 node = node->GetNext();
84f7908b
RR
518 }
519}
520
e5251d4f 521wxSize wxSizer::Fit( wxWindow *window )
5279a24d 522{
f43c7771
VZ
523 wxSize size(window->IsTopLevel() ? FitSize(window)
524 : GetMinWindowSize(window));
9ef2e675 525
ccf5c8a8 526 window->SetSize( size );
e5251d4f
VZ
527
528 return size;
5279a24d
RR
529}
530
566d84a7
RL
531void wxSizer::FitInside( wxWindow *window )
532{
533 wxSize size;
534 if (window->IsTopLevel())
535 size = VirtualFitSize( window );
536 else
537 size = GetMinClientSize( window );
538
539 window->SetVirtualSize( size );
540}
541
3417c2cd 542void wxSizer::Layout()
c62ac5b6 543{
ba763a45
RD
544 // (re)calculates minimums needed for each item and other preparations
545 // for layout
42b4e99e 546 CalcMin();
ba763a45
RD
547
548 // Applies the layout and repositions/resizes the items
c62ac5b6
RR
549 RecalcSizes();
550}
551
3417c2cd 552void wxSizer::SetSizeHints( wxWindow *window )
5279a24d 553{
34c3ffca
RL
554 // Preserve the window's max size hints, but set the
555 // lower bound according to the sizer calculations.
556
e5251d4f
VZ
557 wxSize size = Fit( window );
558
34c3ffca
RL
559 window->SetSizeHints( size.x,
560 size.y,
561 window->GetMaxWidth(),
562 window->GetMaxHeight() );
5279a24d
RR
563}
564
566d84a7
RL
565void wxSizer::SetVirtualSizeHints( wxWindow *window )
566{
567 // Preserve the window's max size hints, but set the
568 // lower bound according to the sizer calculations.
569
570 FitInside( window );
571 wxSize size( window->GetVirtualSize() );
572 window->SetVirtualSizeHints( size.x,
573 size.y,
574 window->GetMaxWidth(),
575 window->GetMaxHeight() );
576}
577
9cbee2ce 578wxSize wxSizer::GetMaxWindowSize( wxWindow *window ) const
65ba4113 579{
34c3ffca 580 return window->GetMaxSize();
65ba4113
GT
581}
582
3417c2cd 583wxSize wxSizer::GetMinWindowSize( wxWindow *window )
5279a24d 584{
12a3f227
RL
585 wxSize minSize( GetMinSize() );
586 wxSize size( window->GetSize() );
587 wxSize client_size( window->GetClientSize() );
588
77671fd2 589 return wxSize( minSize.x+size.x-client_size.x,
0c0d686f 590 minSize.y+size.y-client_size.y );
5279a24d
RR
591}
592
e11d436b
SC
593// TODO on mac we need a function that determines how much free space this
594// min size contains, in order to make sure that we have 20 pixels of free
595// space around the controls
596
65ba4113
GT
597// Return a window size that will fit within the screens dimensions
598wxSize wxSizer::FitSize( wxWindow *window )
599{
600 wxSize size = GetMinWindowSize( window );
601 wxSize sizeMax = GetMaxWindowSize( window );
602
34c3ffca
RL
603 // Limit the size if sizeMax != wxDefaultSize
604
d775fa82 605 if ( size.x > sizeMax.x && sizeMax.x != wxDefaultCoord )
65ba4113 606 size.x = sizeMax.x;
d775fa82 607 if ( size.y > sizeMax.y && sizeMax.y != wxDefaultCoord )
65ba4113
GT
608 size.y = sizeMax.y;
609
610 return size;
611}
612
9cbee2ce 613wxSize wxSizer::GetMaxClientSize( wxWindow *window ) const
566d84a7
RL
614{
615 wxSize maxSize( window->GetMaxSize() );
616
617 if( maxSize != wxDefaultSize )
618 {
619 wxSize size( window->GetSize() );
620 wxSize client_size( window->GetClientSize() );
621
622 return wxSize( maxSize.x + client_size.x - size.x,
623 maxSize.y + client_size.y - size.y );
624 }
625 else
626 return wxDefaultSize;
627}
628
1b0674f7 629wxSize wxSizer::GetMinClientSize( wxWindow *WXUNUSED(window) )
566d84a7
RL
630{
631 return GetMinSize(); // Already returns client size.
632}
633
634wxSize wxSizer::VirtualFitSize( wxWindow *window )
635{
636 wxSize size = GetMinClientSize( window );
637 wxSize sizeMax = GetMaxClientSize( window );
638
639 // Limit the size if sizeMax != wxDefaultSize
640
d775fa82 641 if ( size.x > sizeMax.x && sizeMax.x != wxDefaultCoord )
566d84a7 642 size.x = sizeMax.x;
d775fa82 643 if ( size.y > sizeMax.y && sizeMax.y != wxDefaultCoord )
566d84a7
RL
644 size.y = sizeMax.y;
645
646 return size;
647}
648
3417c2cd 649void wxSizer::SetDimension( int x, int y, int width, int height )
5279a24d
RR
650{
651 m_position.x = x;
652 m_position.y = y;
653 m_size.x = width;
654 m_size.y = height;
2b5f62a0 655 Layout();
5279a24d
RR
656}
657
f6bcfd97 658wxSize wxSizer::GetMinSize()
3ca6a5f0 659{
f6bcfd97
BP
660 wxSize ret( CalcMin() );
661 if (ret.x < m_minSize.x) ret.x = m_minSize.x;
662 if (ret.y < m_minSize.y) ret.y = m_minSize.y;
3ca6a5f0 663 return ret;
f6bcfd97
BP
664}
665
666void wxSizer::DoSetMinSize( int width, int height )
667{
668 m_minSize.x = width;
669 m_minSize.y = height;
670}
671
672bool wxSizer::DoSetItemMinSize( wxWindow *window, int width, int height )
673{
12a3f227
RL
674 wxASSERT_MSG( window, _T("SetMinSize for NULL window") );
675
676 // Is it our immediate child?
f6bcfd97 677
222ed1d6 678 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
f6bcfd97
BP
679 while (node)
680 {
12a3f227
RL
681 wxSizerItem *item = node->GetData();
682
3ca6a5f0
BP
683 if (item->GetWindow() == window)
684 {
1eba2193 685 item->SetMinSize( width, height );
e0d8fb45 686 return true;
3ca6a5f0 687 }
12a3f227 688 node = node->GetNext();
f6bcfd97
BP
689 }
690
12a3f227
RL
691 // No? Search any subsizers we own then
692
693 node = m_children.GetFirst();
f6bcfd97
BP
694 while (node)
695 {
12a3f227
RL
696 wxSizerItem *item = node->GetData();
697
698 if ( item->GetSizer() &&
699 item->GetSizer()->DoSetItemMinSize( window, width, height ) )
3ca6a5f0 700 {
12a3f227 701 // A child sizer found the requested windw, exit.
e0d8fb45 702 return true;
3ca6a5f0 703 }
12a3f227 704 node = node->GetNext();
f6bcfd97
BP
705 }
706
e0d8fb45 707 return false;
f6bcfd97
BP
708}
709
710bool wxSizer::DoSetItemMinSize( wxSizer *sizer, int width, int height )
711{
12a3f227 712 wxASSERT_MSG( sizer, _T("SetMinSize for NULL sizer") );
f6bcfd97 713
12a3f227
RL
714 // Is it our immediate child?
715
222ed1d6 716 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
f6bcfd97
BP
717 while (node)
718 {
12a3f227
RL
719 wxSizerItem *item = node->GetData();
720
3ca6a5f0
BP
721 if (item->GetSizer() == sizer)
722 {
f6bcfd97 723 item->GetSizer()->DoSetMinSize( width, height );
e0d8fb45 724 return true;
3ca6a5f0 725 }
12a3f227 726 node = node->GetNext();
f6bcfd97
BP
727 }
728
12a3f227
RL
729 // No? Search any subsizers we own then
730
731 node = m_children.GetFirst();
f6bcfd97
BP
732 while (node)
733 {
12a3f227
RL
734 wxSizerItem *item = node->GetData();
735
736 if ( item->GetSizer() &&
737 item->GetSizer()->DoSetItemMinSize( sizer, width, height ) )
3ca6a5f0 738 {
12a3f227 739 // A child found the requested sizer, exit.
e0d8fb45 740 return true;
3ca6a5f0 741 }
12a3f227 742 node = node->GetNext();
f6bcfd97
BP
743 }
744
e0d8fb45 745 return false;
f6bcfd97
BP
746}
747
12a3f227 748bool wxSizer::DoSetItemMinSize( size_t index, int width, int height )
f6bcfd97 749{
222ed1d6 750 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
12a3f227 751
e0d8fb45 752 wxCHECK_MSG( node, false, _T("Failed to find child node") );
12a3f227
RL
753
754 wxSizerItem *item = node->GetData();
f6bcfd97 755
f6bcfd97
BP
756 if (item->GetSizer())
757 {
0ca5105b 758 // Sizers contains the minimal size in them, if not calculated ...
f6bcfd97
BP
759 item->GetSizer()->DoSetMinSize( width, height );
760 }
761 else
762 {
ba763a45 763 // ... but the minimal size of spacers and windows is stored via the item
1eba2193 764 item->SetMinSize( width, height );
f6bcfd97
BP
765 }
766
e0d8fb45 767 return true;
f6bcfd97
BP
768}
769
9f13661f 770wxSizerItem* wxSizer::GetItem( wxWindow *window, bool recursive )
2b5f62a0 771{
9f13661f 772 wxASSERT_MSG( window, _T("GetItem for NULL window") );
12a3f227 773
222ed1d6 774 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
2b5f62a0
VZ
775 while (node)
776 {
12a3f227 777 wxSizerItem *item = node->GetData();
2b5f62a0 778
12a3f227 779 if (item->GetWindow() == window)
2b5f62a0 780 {
9f13661f 781 return item;
2b5f62a0 782 }
8b2bac62
WS
783 else if (recursive && item->IsSizer())
784 {
9f13661f
WS
785 wxSizerItem *subitem = item->GetSizer()->GetItem( window, true );
786 if (subitem)
787 return subitem;
8b2bac62
WS
788 }
789
12a3f227 790 node = node->GetNext();
2b5f62a0 791 }
8b2bac62 792
9f13661f 793 return NULL;
2b5f62a0
VZ
794}
795
9f13661f 796wxSizerItem* wxSizer::GetItem( wxSizer *sizer, bool recursive )
2b5f62a0 797{
9f13661f 798 wxASSERT_MSG( sizer, _T("GetItem for NULL sizer") );
12a3f227 799
222ed1d6 800 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
2b5f62a0
VZ
801 while (node)
802 {
9f13661f 803 wxSizerItem *item = node->GetData();
2b5f62a0 804
12a3f227 805 if (item->GetSizer() == sizer)
2b5f62a0 806 {
9f13661f 807 return item;
2b5f62a0 808 }
8b2bac62
WS
809 else if (recursive && item->IsSizer())
810 {
9f13661f
WS
811 wxSizerItem *subitem = item->GetSizer()->GetItem( sizer, true );
812 if (subitem)
813 return subitem;
8b2bac62
WS
814 }
815
12a3f227 816 node = node->GetNext();
2b5f62a0 817 }
8b2bac62 818
9f13661f
WS
819 return NULL;
820}
821
822wxSizerItem* wxSizer::GetItem( size_t index )
823{
824 wxCHECK_MSG( index < m_children.GetCount(),
825 NULL,
826 _T("GetItem index is out of range") );
827
828 return m_children.Item( index )->GetData();
829}
830
831bool wxSizer::Show( wxWindow *window, bool show, bool recursive )
832{
833 wxSizerItem *item = GetItem( window, recursive );
834
835 if ( item )
836 {
837 item->Show( show );
838 return true;
839 }
840
841 return false;
842}
843
844bool wxSizer::Show( wxSizer *sizer, bool show, bool recursive )
845{
846 wxSizerItem *item = GetItem( sizer, recursive );
847
848 if ( item )
849 {
850 item->Show( show );
851 return true;
852 }
853
8b2bac62 854 return false;
2b5f62a0
VZ
855}
856
8b2bac62 857bool wxSizer::Show( size_t index, bool show)
2b5f62a0 858{
9f13661f 859 wxSizerItem *item = GetItem( index );
2b5f62a0 860
9f13661f
WS
861 if ( item )
862 {
863 item->Show( show );
864 return true;
865 }
8b2bac62 866
9f13661f 867 return false;
12a3f227 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 );
8b2bac62 1040 wxSize sz( item->GetMinSizeWithBorder() );
f6bcfd97
BP
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 {
559b747d 1051 pt.x = x + (w - sz.x) / 2;
f6bcfd97
BP
1052 }
1053 else if (flag & wxALIGN_RIGHT)
1054 {
559b747d 1055 pt.x = x + (w - sz.x);
f6bcfd97 1056 }
3ca6a5f0 1057
f6bcfd97
BP
1058 if (flag & wxALIGN_CENTER_VERTICAL)
1059 {
559b747d 1060 pt.y = y + (h - sz.y) / 2;
f6bcfd97
BP
1061 }
1062 else if (flag & wxALIGN_BOTTOM)
1063 {
559b747d 1064 pt.y = y + (h - sz.y);
f6bcfd97
BP
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 1100 wxSize sz( GetSize() );
5d76f462 1101
ba763a45 1102 AdjustForGrowables(sz, m_calculatedMinSize, nrows, ncols);
3ca6a5f0 1103
f6bcfd97
BP
1104 sz = wxSize( pt.x + sz.x, pt.y + sz.y );
1105
1106 int x = pt.x;
1107 for (int c = 0; c < ncols; c++)
1108 {
1109 int y = pt.y;
1110 for (int r = 0; r < nrows; r++)
1111 {
1112 int i = r * ncols + c;
1113 if (i < nitems)
1114 {
222ed1d6 1115 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
12a3f227
RL
1116
1117 wxASSERT_MSG( node, _T("Failed to find node") );
3ca6a5f0 1118
f6bcfd97
BP
1119 int w = wxMax( 0, wxMin( m_colWidths[c], sz.x - x ) );
1120 int h = wxMax( 0, wxMin( m_rowHeights[r], sz.y - y ) );
3ca6a5f0 1121
12a3f227 1122 SetItemBounds( node->GetData(), x, y, w, h);
f6bcfd97
BP
1123 }
1124 y = y + m_rowHeights[r] + m_vgap;
1125 }
1126 x = x + m_colWidths[c] + m_hgap;
1127 }
1128}
1129
1130wxSize wxFlexGridSizer::CalcMin()
1131{
150c8d89
RL
1132 int nrows,
1133 ncols;
1134 size_t i, s;
1135
55f9f0cb 1136 // Number of rows/columns can change as items are added or removed.
5d76f462
VZ
1137 if ( !CalcRowsCols(nrows, ncols) )
1138 return wxSize(10, 10);
f6bcfd97 1139
5d76f462
VZ
1140 m_rowHeights.SetCount(nrows);
1141 m_colWidths.SetCount(ncols);
3ca6a5f0 1142
395a82b1
VZ
1143 // We have to recalcuate the sizes in case the item minimum size has
1144 // changed since the previous layout, or the item has been hidden using
1145 // wxSizer::Show(). If all the items in a row/column are hidden, the final
1146 // dimension of the row/column will be -1, indicating that the column
1147 // itself is hidden.
55f9f0cb
VZ
1148 for( s = m_rowHeights.GetCount(), i = 0; i < s; ++i )
1149 m_rowHeights[ i ] = -1;
1150 for( s = m_colWidths.GetCount(), i = 0; i < s; ++i )
1151 m_colWidths[ i ] = -1;
1152
222ed1d6 1153 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
12a3f227 1154
150c8d89 1155 i = 0;
f6bcfd97
BP
1156 while (node)
1157 {
12a3f227 1158 wxSizerItem *item = node->GetData();
55f9f0cb
VZ
1159 if ( item->IsShown() )
1160 {
1161 wxSize sz( item->CalcMin() );
1162 int row = i / ncols;
1163 int col = i % ncols;
12a3f227 1164
55f9f0cb
VZ
1165 m_rowHeights[ row ] = wxMax( wxMax( 0, sz.y ), m_rowHeights[ row ] );
1166 m_colWidths[ col ] = wxMax( wxMax( 0, sz.x ), m_colWidths[ col ] );
1167 }
3ca6a5f0 1168
12a3f227 1169 node = node->GetNext();
f6bcfd97
BP
1170 i++;
1171 }
3ca6a5f0 1172
20b35a69 1173 AdjustForFlexDirection();
8b2bac62 1174
20b35a69
RD
1175 // Sum total minimum size, including gaps between rows/columns.
1176 // -1 is used as a magic number meaning empty column.
1177 int width = 0;
1178 for (int col = 0; col < ncols; col++)
1179 if ( m_colWidths[ col ] != -1 )
1180 width += m_colWidths[ col ] + ( col == ncols-1 ? 0 : m_hgap );
1181
1182 int height = 0;
1183 for (int row = 0; row < nrows; row++)
1184 if ( m_rowHeights[ row ] != -1 )
1185 height += m_rowHeights[ row ] + ( row == nrows-1 ? 0 : m_vgap );
1186
ba763a45
RD
1187 m_calculatedMinSize = wxSize( width, height );
1188 return m_calculatedMinSize;
20b35a69
RD
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 }
8b2bac62 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;
8b2bac62 1238
20b35a69
RD
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;
8b2bac62 1290
20b35a69
RD
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 {
ba763a45 1383 wxSize size( item->GetMinSizeWithBorder() );
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 );
42841dfc 1396 wxSize child_size( size.x, height );
2b5f62a0
VZ
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 );
42841dfc 1422 wxSize child_size( width, size.y );
2b5f62a0
VZ
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
ba763a45 1454 // precalc item minsizes and count proportions
222ed1d6 1455 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
85e5cfc9
VZ
1456 while (node)
1457 {
1458 wxSizerItem *item = node->GetData();
12a3f227 1459
ba763a45
RD
1460 if (item->IsShown())
1461 item->CalcMin(); // result is stored in the item
8b2bac62 1462
85e5cfc9
VZ
1463 if (item->IsShown() && item->GetProportion() != 0)
1464 m_stretchable += item->GetProportion();
1465
1466 node = node->GetNext();
1467 }
1468
1469 // Total minimum size (width or height) of sizer
1470 int maxMinSize = 0;
1471
1472 node = m_children.GetFirst();
61d514bb 1473 while (node)
f98de448 1474 {
85e5cfc9 1475 wxSizerItem *item = node->GetData();
12a3f227
RL
1476
1477 if (item->IsShown() && item->GetProportion() != 0)
f98de448 1478 {
12a3f227 1479 int stretch = item->GetProportion();
ba763a45 1480 wxSize size( item->GetMinSizeWithBorder() );
85e5cfc9 1481 int minSize;
8b2bac62 1482
f98de448 1483 // Integer division rounded up is (a + b - 1) / b
85e5cfc9
VZ
1484 // Round up needed in order to guarantee that all
1485 // all items will have size not less then their min size
f98de448 1486 if (m_orient == wxHORIZONTAL)
85e5cfc9 1487 minSize = ( size.x*m_stretchable + stretch - 1)/stretch;
f98de448 1488 else
85e5cfc9 1489 minSize = ( size.y*m_stretchable + stretch - 1)/stretch;
8b2bac62 1490
85e5cfc9
VZ
1491 if (minSize > maxMinSize)
1492 maxMinSize = minSize;
f98de448 1493 }
12a3f227 1494 node = node->GetNext();
f98de448 1495 }
12a3f227 1496
4f469fb5
RR
1497 // Calculate overall minimum size
1498 node = m_children.GetFirst();
f98de448 1499 while (node)
61d514bb 1500 {
85e5cfc9 1501 wxSizerItem *item = node->GetData();
12a3f227 1502
2b5f62a0 1503 if (item->IsShown())
f98de448 1504 {
ba763a45 1505 wxSize size( item->GetMinSizeWithBorder() );
12a3f227 1506 if (item->GetProportion() != 0)
2b5f62a0
VZ
1507 {
1508 if (m_orient == wxHORIZONTAL)
85e5cfc9 1509 size.x = (maxMinSize*item->GetProportion())/m_stretchable;
2b5f62a0 1510 else
85e5cfc9 1511 size.y = (maxMinSize*item->GetProportion())/m_stretchable;
3ca6a5f0
BP
1512 }
1513 else
2b5f62a0
VZ
1514 {
1515 if (m_orient == wxVERTICAL)
1516 {
1517 m_fixedHeight += size.y;
1518 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1519 }
1520 else
1521 {
1522 m_fixedWidth += size.x;
1523 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1524 }
1525 }
85e5cfc9
VZ
1526
1527 if (m_orient == wxHORIZONTAL)
1528 {
1529 m_minWidth += size.x;
1530 m_minHeight = wxMax( m_minHeight, size.y );
1531 }
1532 else
1533 {
1534 m_minHeight += size.y;
1535 m_minWidth = wxMax( m_minWidth, size.x );
1536 }
2b5f62a0 1537 }
12a3f227 1538 node = node->GetNext();
61d514bb 1539 }
0c0d686f 1540
61d514bb
RR
1541 return wxSize( m_minWidth, m_minHeight );
1542}
27ea1d8a
RR
1543
1544//---------------------------------------------------------------------------
1545// wxStaticBoxSizer
1546//---------------------------------------------------------------------------
1547
1e6feb95
VZ
1548#if wxUSE_STATBOX
1549
27ea1d8a 1550wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
12a3f227
RL
1551 : wxBoxSizer( orient )
1552 , m_staticBox( box )
27ea1d8a 1553{
223d09f6 1554 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
27ea1d8a 1555}
0c0d686f 1556
12a3f227
RL
1557static void GetStaticBoxBorders( wxStaticBox *box,
1558 int *borderTop,
1559 int *borderOther)
84028727
VZ
1560{
1561 // this has to be done platform by platform as there is no way to
1562 // guess the thickness of a wxStaticBox border
ec4e4a14
DE
1563#ifdef __WXCOCOA__
1564 box->GetBordersForSizer(borderTop,borderOther);
67021102
DS
1565#elif defined(__WXMAC__)
1566
1567 static int extraTop = -1; // Uninitted
1568 static int other = 5;
1569
1570 if ( extraTop == -1 )
1571 {
67021102
DS
1572 // The minimal border used for the top. Later on the staticbox'
1573 // font height is added to this.
1574 extraTop = 0;
1575
78ca5669 1576 if ( UMAGetSystemVersion() >= 0x1030 /*Panther*/ )
67021102
DS
1577 {
1578 // As indicated by the HIG, Panther needs an extra border of 11
1579 // pixels (otherwise overlapping occurs at the top). The "other"
1580 // border has to be 11.
1581 extraTop = 11;
8b2bac62 1582 other = 11;
67021102
DS
1583 }
1584
1585 }
1586
1587 *borderTop = extraTop + box->GetCharHeight();
1588 *borderOther = other;
1589
1590#else
84028727 1591#ifdef __WXGTK__
56eee37f 1592 if ( box->GetLabel().empty() )
84028727
VZ
1593 *borderTop = 5;
1594 else
1595#endif // __WXGTK__
f2b99f63
JS
1596 *borderTop = box->GetCharHeight();
1597
84028727 1598 *borderOther = 5;
ec4e4a14 1599#endif // __WXCOCOA__
84028727
VZ
1600}
1601
27ea1d8a
RR
1602void wxStaticBoxSizer::RecalcSizes()
1603{
84028727
VZ
1604 int top_border, other_border;
1605 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
27ea1d8a
RR
1606
1607 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
0c0d686f 1608
27ea1d8a
RR
1609 wxPoint old_pos( m_position );
1610 m_position.x += other_border;
1611 m_position.y += top_border;
1612 wxSize old_size( m_size );
1613 m_size.x -= 2*other_border;
1614 m_size.y -= top_border + other_border;
0c0d686f 1615
27ea1d8a 1616 wxBoxSizer::RecalcSizes();
0c0d686f 1617
27ea1d8a
RR
1618 m_position = old_pos;
1619 m_size = old_size;
1620}
1621
1622wxSize wxStaticBoxSizer::CalcMin()
1623{
84028727
VZ
1624 int top_border, other_border;
1625 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
0c0d686f 1626
27ea1d8a 1627 wxSize ret( wxBoxSizer::CalcMin() );
cae31b8b 1628 ret.x += 2*other_border;
27ea1d8a 1629 ret.y += other_border + top_border;
0c0d686f 1630
27ea1d8a
RR
1631 return ret;
1632}
83edc0a5 1633
eb2a7883
VZ
1634void wxStaticBoxSizer::ShowItems( bool show )
1635{
1636 m_staticBox->Show( show );
1637 wxBoxSizer::ShowItems( show );
1638}
1639
1e6feb95
VZ
1640#endif // wxUSE_STATBOX
1641
adbf2d73
VS
1642
1643#if WXWIN_COMPATIBILITY_2_4
1644
ade4eb65 1645// ----------------------------------------------------------------------------
83edc0a5 1646// wxNotebookSizer
ade4eb65 1647// ----------------------------------------------------------------------------
83edc0a5 1648
adbf2d73
VS
1649#if wxUSE_BOOKCTRL
1650IMPLEMENT_CLASS(wxBookCtrlSizer, wxSizer)
1651#if wxUSE_NOTEBOOK
1652IMPLEMENT_CLASS(wxNotebookSizer, wxBookCtrlSizer)
1653#endif // wxUSE_NOTEBOOK
1654#endif // wxUSE_BOOKCTRL
1655
ade4eb65 1656#if wxUSE_BOOKCTRL
60be2f47 1657
61c083e7 1658wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrlBase *bookctrl)
ade4eb65 1659 : m_bookctrl(bookctrl)
83edc0a5 1660{
ade4eb65 1661 wxASSERT_MSG( bookctrl, wxT("wxBookCtrlSizer needs a control") );
83edc0a5
RR
1662}
1663
ade4eb65 1664void wxBookCtrlSizer::RecalcSizes()
83edc0a5 1665{
ade4eb65 1666 m_bookctrl->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
83edc0a5
RR
1667}
1668
ade4eb65 1669wxSize wxBookCtrlSizer::CalcMin()
83edc0a5 1670{
ade4eb65 1671 wxSize sizeBorder = m_bookctrl->CalcSizeFromPage(wxSize(0, 0));
1e6feb95
VZ
1672
1673 sizeBorder.x += 5;
1674 sizeBorder.y += 5;
3ca6a5f0 1675
ade4eb65 1676 if ( m_bookctrl->GetPageCount() == 0 )
1e6feb95
VZ
1677 {
1678 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
1679 }
83edc0a5
RR
1680
1681 int maxX = 0;
1682 int maxY = 0;
1683
ade4eb65
VZ
1684 wxWindowList::compatibility_iterator
1685 node = m_bookctrl->GetChildren().GetFirst();
83edc0a5
RR
1686 while (node)
1687 {
1688 wxWindow *item = node->GetData();
3ca6a5f0
BP
1689 wxSizer *itemsizer = item->GetSizer();
1690
1691 if (itemsizer)
1692 {
83edc0a5 1693 wxSize subsize( itemsizer->CalcMin() );
83edc0a5 1694
1e6feb95
VZ
1695 if (subsize.x > maxX)
1696 maxX = subsize.x;
1697 if (subsize.y > maxY)
1698 maxY = subsize.y;
3ca6a5f0
BP
1699 }
1700
1701 node = node->GetNext();
83edc0a5
RR
1702 }
1703
1e6feb95 1704 return wxSize( maxX, maxY ) + sizeBorder;
83edc0a5
RR
1705}
1706
2d480e40
RD
1707#if wxUSE_NOTEBOOK
1708
1709wxNotebookSizer::wxNotebookSizer(wxNotebook *nb)
2d480e40 1710{
adbf2d73
VS
1711 wxASSERT_MSG( nb, wxT("wxNotebookSizer needs a control") );
1712 m_bookctrl = nb;
2d480e40
RD
1713}
1714
1715#endif // wxUSE_NOTEBOOOK
ade4eb65 1716#endif // wxUSE_BOOKCTRL
34c3ffca 1717
adbf2d73 1718#endif // WXWIN_COMPATIBILITY_2_4