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