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