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