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