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