]> git.saurik.com Git - wxWidgets.git/blame - src/common/sizer.cpp
macro naming changes, delegate api calls getting property info, object info exposed...
[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
3ca6a5f0 1291void wxFlexGridSizer::RemoveGrowableRow( size_t WXUNUSED(idx) )
f6bcfd97
BP
1292{
1293}
1294
e8800dcf 1295void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
f6bcfd97
BP
1296{
1297 m_growableCols.Add( idx );
e8800dcf 1298 m_growableColsProportions.Add( proportion );
f6bcfd97
BP
1299}
1300
3ca6a5f0 1301void wxFlexGridSizer::RemoveGrowableCol( size_t WXUNUSED(idx) )
f6bcfd97
BP
1302{
1303}
1304
c62ac5b6 1305//---------------------------------------------------------------------------
92afa2b1 1306// wxBoxSizer
61d514bb
RR
1307//---------------------------------------------------------------------------
1308
92afa2b1 1309wxBoxSizer::wxBoxSizer( int orient )
12a3f227 1310 : m_orient( orient )
61d514bb 1311{
61d514bb
RR
1312}
1313
92afa2b1 1314void wxBoxSizer::RecalcSizes()
61d514bb
RR
1315{
1316 if (m_children.GetCount() == 0)
61d514bb 1317 return;
0c0d686f 1318
61d514bb 1319 int delta = 0;
61d514bb
RR
1320 if (m_stretchable)
1321 {
1322 if (m_orient == wxHORIZONTAL)
85e5cfc9 1323 delta = m_size.x - m_fixedWidth;
3ca6a5f0 1324 else
85e5cfc9 1325 delta = m_size.y - m_fixedHeight;
61d514bb 1326 }
0c0d686f 1327
61d514bb 1328 wxPoint pt( m_position );
0c0d686f 1329
222ed1d6 1330 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
61d514bb
RR
1331 while (node)
1332 {
12a3f227
RL
1333 wxSizerItem *item = node->GetData();
1334
2b5f62a0 1335 if (item->IsShown())
3ca6a5f0 1336 {
2b5f62a0 1337 wxSize size( item->CalcMin() );
3ca6a5f0 1338
2b5f62a0 1339 if (m_orient == wxVERTICAL)
3ca6a5f0 1340 {
2b5f62a0 1341 wxCoord height = size.y;
12a3f227 1342 if (item->GetProportion())
2b5f62a0 1343 {
85e5cfc9
VZ
1344 // Because of at least one visible item has non-zero
1345 // proportion then m_stretchable is not zero
1346 height = (delta * item->GetProportion()) / m_stretchable;
2b5f62a0
VZ
1347 }
1348
1349 wxPoint child_pos( pt );
1350 wxSize child_size( wxSize( size.x, height) );
1351
1352 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1353 child_size.x = m_size.x;
1354 else if (item->GetFlag() & wxALIGN_RIGHT)
1355 child_pos.x += m_size.x - size.x;
1356 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
1357 // XXX wxCENTER is added for backward compatibility;
1358 // wxALIGN_CENTER should be used in new code
1359 child_pos.x += (m_size.x - size.x) / 2;
1360
1361 item->SetDimension( child_pos, child_size );
1362
1363 pt.y += height;
1364 }
1365 else
1366 {
1367 wxCoord width = size.x;
12a3f227 1368 if (item->GetProportion())
2b5f62a0 1369 {
85e5cfc9
VZ
1370 // Because of at least one visible item has non-zero
1371 // proportion then m_stretchable is not zero
1372 width = (delta * item->GetProportion()) / m_stretchable;
2b5f62a0
VZ
1373 }
1374
1375 wxPoint child_pos( pt );
1376 wxSize child_size( wxSize(width, size.y) );
1377
1378 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1379 child_size.y = m_size.y;
1380 else if (item->GetFlag() & wxALIGN_BOTTOM)
1381 child_pos.y += m_size.y - size.y;
1382 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
1383 // XXX wxCENTER is added for backward compatibility;
1384 // wxALIGN_CENTER should be used in new code
1385 child_pos.y += (m_size.y - size.y) / 2;
1386
1387 item->SetDimension( child_pos, child_size );
1388
1389 pt.x += width;
3ca6a5f0 1390 }
3ca6a5f0
BP
1391 }
1392
12a3f227 1393 node = node->GetNext();
61d514bb
RR
1394 }
1395}
1396
92afa2b1 1397wxSize wxBoxSizer::CalcMin()
61d514bb
RR
1398{
1399 if (m_children.GetCount() == 0)
c7a9fa36 1400 return wxSize(10,10);
0c0d686f 1401
61d514bb
RR
1402 m_stretchable = 0;
1403 m_minWidth = 0;
1404 m_minHeight = 0;
1405 m_fixedWidth = 0;
1406 m_fixedHeight = 0;
0c0d686f 1407
222ed1d6 1408 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
85e5cfc9
VZ
1409 while (node)
1410 {
1411 wxSizerItem *item = node->GetData();
12a3f227 1412
85e5cfc9
VZ
1413 if (item->IsShown() && item->GetProportion() != 0)
1414 m_stretchable += item->GetProportion();
1415
1416 node = node->GetNext();
1417 }
1418
1419 // Total minimum size (width or height) of sizer
1420 int maxMinSize = 0;
1421
1422 node = m_children.GetFirst();
61d514bb 1423 while (node)
f98de448 1424 {
85e5cfc9 1425 wxSizerItem *item = node->GetData();
12a3f227
RL
1426
1427 if (item->IsShown() && item->GetProportion() != 0)
f98de448 1428 {
12a3f227 1429 int stretch = item->GetProportion();
f98de448 1430 wxSize size( item->CalcMin() );
85e5cfc9
VZ
1431 int minSize;
1432
f98de448 1433 // Integer division rounded up is (a + b - 1) / b
85e5cfc9
VZ
1434 // Round up needed in order to guarantee that all
1435 // all items will have size not less then their min size
f98de448 1436 if (m_orient == wxHORIZONTAL)
85e5cfc9 1437 minSize = ( size.x*m_stretchable + stretch - 1)/stretch;
f98de448 1438 else
85e5cfc9
VZ
1439 minSize = ( size.y*m_stretchable + stretch - 1)/stretch;
1440
1441 if (minSize > maxMinSize)
1442 maxMinSize = minSize;
f98de448 1443 }
12a3f227 1444 node = node->GetNext();
f98de448 1445 }
12a3f227 1446
4f469fb5
RR
1447 // Calculate overall minimum size
1448 node = m_children.GetFirst();
f98de448 1449 while (node)
61d514bb 1450 {
85e5cfc9 1451 wxSizerItem *item = node->GetData();
12a3f227 1452
2b5f62a0 1453 if (item->IsShown())
f98de448 1454 {
2b5f62a0 1455 wxSize size( item->CalcMin() );
12a3f227 1456 if (item->GetProportion() != 0)
2b5f62a0
VZ
1457 {
1458 if (m_orient == wxHORIZONTAL)
85e5cfc9 1459 size.x = (maxMinSize*item->GetProportion())/m_stretchable;
2b5f62a0 1460 else
85e5cfc9 1461 size.y = (maxMinSize*item->GetProportion())/m_stretchable;
3ca6a5f0
BP
1462 }
1463 else
2b5f62a0
VZ
1464 {
1465 if (m_orient == wxVERTICAL)
1466 {
1467 m_fixedHeight += size.y;
1468 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1469 }
1470 else
1471 {
1472 m_fixedWidth += size.x;
1473 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1474 }
1475 }
85e5cfc9
VZ
1476
1477 if (m_orient == wxHORIZONTAL)
1478 {
1479 m_minWidth += size.x;
1480 m_minHeight = wxMax( m_minHeight, size.y );
1481 }
1482 else
1483 {
1484 m_minHeight += size.y;
1485 m_minWidth = wxMax( m_minWidth, size.x );
1486 }
2b5f62a0 1487 }
12a3f227 1488 node = node->GetNext();
61d514bb 1489 }
0c0d686f 1490
61d514bb
RR
1491 return wxSize( m_minWidth, m_minHeight );
1492}
27ea1d8a
RR
1493
1494//---------------------------------------------------------------------------
1495// wxStaticBoxSizer
1496//---------------------------------------------------------------------------
1497
1e6feb95
VZ
1498#if wxUSE_STATBOX
1499
27ea1d8a 1500wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
12a3f227
RL
1501 : wxBoxSizer( orient )
1502 , m_staticBox( box )
27ea1d8a 1503{
223d09f6 1504 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
27ea1d8a 1505}
0c0d686f 1506
12a3f227
RL
1507static void GetStaticBoxBorders( wxStaticBox *box,
1508 int *borderTop,
1509 int *borderOther)
84028727
VZ
1510{
1511 // this has to be done platform by platform as there is no way to
1512 // guess the thickness of a wxStaticBox border
ec4e4a14
DE
1513#ifdef __WXCOCOA__
1514 box->GetBordersForSizer(borderTop,borderOther);
1515#else // __WXCOCOA__
84028727
VZ
1516#ifdef __WXGTK__
1517 if ( box->GetLabel().IsEmpty() )
1518 *borderTop = 5;
1519 else
1520#endif // __WXGTK__
f2b99f63
JS
1521 *borderTop = box->GetCharHeight();
1522
84028727 1523 *borderOther = 5;
ec4e4a14 1524#endif // __WXCOCOA__
84028727
VZ
1525}
1526
27ea1d8a
RR
1527void wxStaticBoxSizer::RecalcSizes()
1528{
84028727
VZ
1529 int top_border, other_border;
1530 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
27ea1d8a
RR
1531
1532 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
0c0d686f 1533
27ea1d8a
RR
1534 wxPoint old_pos( m_position );
1535 m_position.x += other_border;
1536 m_position.y += top_border;
1537 wxSize old_size( m_size );
1538 m_size.x -= 2*other_border;
1539 m_size.y -= top_border + other_border;
0c0d686f 1540
27ea1d8a 1541 wxBoxSizer::RecalcSizes();
0c0d686f 1542
27ea1d8a
RR
1543 m_position = old_pos;
1544 m_size = old_size;
1545}
1546
1547wxSize wxStaticBoxSizer::CalcMin()
1548{
84028727
VZ
1549 int top_border, other_border;
1550 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
0c0d686f 1551
27ea1d8a 1552 wxSize ret( wxBoxSizer::CalcMin() );
cae31b8b 1553 ret.x += 2*other_border;
27ea1d8a 1554 ret.y += other_border + top_border;
0c0d686f 1555
27ea1d8a
RR
1556 return ret;
1557}
83edc0a5 1558
1e6feb95
VZ
1559#endif // wxUSE_STATBOX
1560
ade4eb65 1561// ----------------------------------------------------------------------------
83edc0a5 1562// wxNotebookSizer
ade4eb65 1563// ----------------------------------------------------------------------------
83edc0a5 1564
ade4eb65 1565#if wxUSE_BOOKCTRL
60be2f47 1566
ade4eb65
VZ
1567wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrl *bookctrl)
1568 : m_bookctrl(bookctrl)
83edc0a5 1569{
ade4eb65 1570 wxASSERT_MSG( bookctrl, wxT("wxBookCtrlSizer needs a control") );
83edc0a5
RR
1571}
1572
ade4eb65 1573void wxBookCtrlSizer::RecalcSizes()
83edc0a5 1574{
ade4eb65 1575 m_bookctrl->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
83edc0a5
RR
1576}
1577
ade4eb65 1578wxSize wxBookCtrlSizer::CalcMin()
83edc0a5 1579{
ade4eb65 1580 wxSize sizeBorder = m_bookctrl->CalcSizeFromPage(wxSize(0, 0));
1e6feb95
VZ
1581
1582 sizeBorder.x += 5;
1583 sizeBorder.y += 5;
3ca6a5f0 1584
ade4eb65 1585 if ( m_bookctrl->GetPageCount() == 0 )
1e6feb95
VZ
1586 {
1587 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
1588 }
83edc0a5
RR
1589
1590 int maxX = 0;
1591 int maxY = 0;
1592
ade4eb65
VZ
1593 wxWindowList::compatibility_iterator
1594 node = m_bookctrl->GetChildren().GetFirst();
83edc0a5
RR
1595 while (node)
1596 {
1597 wxWindow *item = node->GetData();
3ca6a5f0
BP
1598 wxSizer *itemsizer = item->GetSizer();
1599
1600 if (itemsizer)
1601 {
83edc0a5 1602 wxSize subsize( itemsizer->CalcMin() );
83edc0a5 1603
1e6feb95
VZ
1604 if (subsize.x > maxX)
1605 maxX = subsize.x;
1606 if (subsize.y > maxY)
1607 maxY = subsize.y;
3ca6a5f0
BP
1608 }
1609
1610 node = node->GetNext();
83edc0a5
RR
1611 }
1612
1e6feb95 1613 return wxSize( maxX, maxY ) + sizeBorder;
83edc0a5
RR
1614}
1615
2d480e40
RD
1616
1617#if wxUSE_NOTEBOOK
1618
1619wxNotebookSizer::wxNotebookSizer(wxNotebook *nb)
1620 : wxBookCtrlSizer(nb)
1621{
1622}
1623
1624#endif // wxUSE_NOTEBOOOK
ade4eb65 1625#endif // wxUSE_BOOKCTRL
34c3ffca 1626