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