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