1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     provide new wxSizer class for layout 
   4 // Author:      Robert Roebling and Robin Dunn, contributions by 
   5 //              Dirk Holtwick, Ron Lee 
   6 // Modified by: Ron Lee 
   9 // Copyright:   (c) Robin Dunn, Robert Roebling 
  10 // Licence:     wxWindows licence 
  11 ///////////////////////////////////////////////////////////////////////////// 
  13 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  14 #pragma implementation "sizer.h" 
  17 // For compilers that support precompilation, includes "wx.h". 
  18 #include "wx/wxprec.h" 
  26 #include "wx/statbox.h" 
  27 #include "wx/listimpl.cpp" 
  28 #if WXWIN_COMPATIBILITY_2_4 
  29     #include "wx/notebook.h" 
  33 #   include "wx/mac/uma.h" 
  36 //--------------------------------------------------------------------------- 
  38 IMPLEMENT_CLASS(wxSizerItem
, wxObject
) 
  39 IMPLEMENT_CLASS(wxSizer
, wxObject
) 
  40 IMPLEMENT_CLASS(wxGridSizer
, wxSizer
) 
  41 IMPLEMENT_CLASS(wxFlexGridSizer
, wxGridSizer
) 
  42 IMPLEMENT_CLASS(wxBoxSizer
, wxSizer
) 
  44 IMPLEMENT_CLASS(wxStaticBoxSizer
, wxBoxSizer
) 
  47 WX_DEFINE_EXPORTED_LIST( wxSizerItemList 
); 
  82 //--------------------------------------------------------------------------- 
  84 //--------------------------------------------------------------------------- 
  86 void wxSizerItem::Init() 
  94 void wxSizerItem::Init(const wxSizerFlags
& flags
) 
  98     m_proportion 
= flags
.GetProportion(); 
  99     m_flag 
= flags
.GetFlags(); 
 100     m_border 
= flags
.GetBorderInPixels(); 
 103 wxSizerItem::wxSizerItem( int width
, int height
, int proportion
, int flag
, int border
, wxObject
* userData 
) 
 106     , m_size( wxSize( width
, height 
) ) // size is set directly 
 107     , m_minSize( m_size 
)               // minimal size is the initial size 
 108     , m_proportion( proportion 
) 
 112     , m_userData( userData 
) 
 117 wxSizerItem::wxSizerItem( wxWindow 
*window
, int proportion
, int flag
, int border
, wxObject
* userData 
) 
 120     , m_proportion( proportion 
) 
 124     , m_userData( userData 
) 
 126     if (flag 
& wxFIXED_MINSIZE
) 
 127         window
->SetMinSize(window
->GetSize()); 
 128     m_minSize 
= window
->GetSize(); 
 130     // aspect ratio calculated from initial size 
 131     SetRatio( m_minSize 
); 
 133     // m_size is calculated later 
 136 wxSizerItem::wxSizerItem( wxSizer 
*sizer
, int proportion
, int flag
, int border
, wxObject
* userData 
) 
 139     , m_proportion( proportion 
) 
 144     , m_userData( userData 
) 
 146     // m_minSize is calculated later 
 147     // m_size is calculated later 
 150 wxSizerItem::wxSizerItem() 
 159 wxSizerItem::~wxSizerItem() 
 165         m_window
->SetContainingSizer(NULL
); 
 167     else // we must be a sizer 
 174 wxSize 
wxSizerItem::GetSize() const 
 178         ret 
= m_sizer
->GetSize(); 
 181         ret 
= m_window
->GetSize(); 
 188     if (m_flag 
& wxNORTH
) 
 190     if (m_flag 
& wxSOUTH
) 
 196 wxSize 
wxSizerItem::CalcMin() 
 200         m_minSize 
= m_sizer
->GetMinSize(); 
 202         // if we have to preserve aspect ratio _AND_ this is 
 203         // the first-time calculation, consider ret to be initial size 
 204         if ((m_flag 
& wxSHAPED
) && !m_ratio
) 
 207     else if ( IsWindow() ) 
 209         // Since the size of the window may change during runtime, we 
 210         // should use the current minimal/best size. 
 211         m_minSize 
= m_window
->GetBestFittingSize(); 
 214     return GetMinSizeWithBorder(); 
 217 wxSize 
wxSizerItem::GetMinSizeWithBorder() const 
 219     wxSize ret 
= m_minSize
; 
 225     if (m_flag 
& wxNORTH
) 
 227     if (m_flag 
& wxSOUTH
) 
 234 void wxSizerItem::SetDimension( wxPoint pos
, wxSize size 
) 
 236     if (m_flag 
& wxSHAPED
) 
 238         // adjust aspect ratio 
 239         int rwidth 
= (int) (size
.y 
* m_ratio
); 
 243             int rheight 
= (int) (size
.x 
/ m_ratio
); 
 244             // add vertical space 
 245             if (m_flag 
& wxALIGN_CENTER_VERTICAL
) 
 246                 pos
.y 
+= (size
.y 
- rheight
) / 2; 
 247             else if (m_flag 
& wxALIGN_BOTTOM
) 
 248                 pos
.y 
+= (size
.y 
- rheight
); 
 249             // use reduced dimensions 
 252         else if (rwidth 
< size
.x
) 
 254             // add horizontal space 
 255             if (m_flag 
& wxALIGN_CENTER_HORIZONTAL
) 
 256                 pos
.x 
+= (size
.x 
- rwidth
) / 2; 
 257             else if (m_flag 
& wxALIGN_RIGHT
) 
 258                 pos
.x 
+= (size
.x 
- rwidth
); 
 263     // This is what GetPosition() returns. Since we calculate 
 264     // borders afterwards, GetPosition() will be the left/top 
 265     // corner of the surrounding border. 
 277     if (m_flag 
& wxNORTH
) 
 282     if (m_flag 
& wxSOUTH
) 
 288         m_sizer
->SetDimension( pos
.x
, pos
.y
, size
.x
, size
.y 
); 
 291         m_window
->SetSize( pos
.x
, pos
.y
, size
.x
, size
.y
, wxSIZE_ALLOW_MINUS_ONE 
); 
 296 void wxSizerItem::DeleteWindows() 
 305         m_sizer
->DeleteWindows(); 
 308 bool wxSizerItem::IsWindow() const 
 310     return (m_window 
!= NULL
); 
 313 bool wxSizerItem::IsSizer() const 
 315     return (m_sizer 
!= NULL
); 
 318 bool wxSizerItem::IsSpacer() const 
 320     return (m_window 
== NULL
) && (m_sizer 
== NULL
); 
 323 void wxSizerItem::Show( bool show 
) 
 328         m_window
->Show( show 
); 
 330         m_sizer
->ShowItems( show 
); 
 332     // ... nothing else to do to hide/show spacers 
 335 void wxSizerItem::SetOption( int option 
) 
 337     SetProportion( option 
); 
 340 int wxSizerItem::GetOption() const 
 342     return GetProportion(); 
 346 //--------------------------------------------------------------------------- 
 348 //--------------------------------------------------------------------------- 
 351     : m_minSize( wxSize( 0, 0 ) ) 
 357     WX_CLEAR_LIST(wxSizerItemList
, m_children
); 
 360 void wxSizer::Insert( size_t index
, wxSizerItem 
*item 
) 
 362     m_children
.Insert( index
, item 
); 
 364     if( item
->GetWindow() ) 
 365         item
->GetWindow()->SetContainingSizer( this ); 
 368 bool wxSizer::Remove( wxWindow 
*window 
) 
 370     return Detach( window 
); 
 373 bool wxSizer::Remove( wxSizer 
*sizer 
) 
 375     wxASSERT_MSG( sizer
, _T("Removing NULL sizer") ); 
 377     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 380         wxSizerItem     
*item 
= node
->GetData(); 
 382         if (item
->GetSizer() == sizer
) 
 385             m_children
.Erase( node 
); 
 389         node 
= node
->GetNext(); 
 395 bool wxSizer::Remove( int index 
) 
 397     wxCHECK_MSG( index 
>= 0 && (size_t)index 
< m_children
.GetCount(), 
 399                  _T("Remove index is out of range") ); 
 401     wxSizerItemList::compatibility_iterator node 
= m_children
.Item( index 
); 
 403     wxCHECK_MSG( node
, false, _T("Failed to find child node") ); 
 405     wxSizerItem 
*item 
= node
->GetData(); 
 407     if( item
->IsWindow() ) 
 408         item
->GetWindow()->SetContainingSizer( NULL 
); 
 411     m_children
.Erase( node 
); 
 415 bool wxSizer::Detach( wxSizer 
*sizer 
) 
 417     wxASSERT_MSG( sizer
, _T("Detaching NULL sizer") ); 
 419     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 422         wxSizerItem     
*item 
= node
->GetData(); 
 424         if (item
->GetSizer() == sizer
) 
 428             m_children
.Erase( node 
); 
 431         node 
= node
->GetNext(); 
 437 bool wxSizer::Detach( wxWindow 
*window 
) 
 439     wxASSERT_MSG( window
, _T("Detaching NULL window") ); 
 441     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 444         wxSizerItem     
*item 
= node
->GetData(); 
 446         if (item
->GetWindow() == window
) 
 448             item
->GetWindow()->SetContainingSizer( NULL 
); 
 450             m_children
.Erase( node 
); 
 453         node 
= node
->GetNext(); 
 459 bool wxSizer::Detach( int index 
) 
 461     wxCHECK_MSG( index 
>= 0 && (size_t)index 
< m_children
.GetCount(), 
 463                  _T("Detach index is out of range") ); 
 465     wxSizerItemList::compatibility_iterator node 
= m_children
.Item( index 
); 
 467     wxCHECK_MSG( node
, false, _T("Failed to find child node") ); 
 469     wxSizerItem 
*item 
= node
->GetData(); 
 471     if( item
->IsSizer() ) 
 473     else if( item
->IsWindow() ) 
 474         item
->GetWindow()->SetContainingSizer( NULL 
); 
 477     m_children
.Erase( node 
); 
 481 void wxSizer::Clear( bool delete_windows 
) 
 483     // First clear the ContainingSizer pointers 
 484     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 487         wxSizerItem     
*item 
= node
->GetData(); 
 489         if (item
->IsWindow()) 
 490             item
->GetWindow()->SetContainingSizer( NULL 
); 
 491         node 
= node
->GetNext(); 
 494     // Destroy the windows if needed 
 498     // Now empty the list 
 499     WX_CLEAR_LIST(wxSizerItemList
, m_children
); 
 502 void wxSizer::DeleteWindows() 
 504     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 507         wxSizerItem     
*item 
= node
->GetData(); 
 509         item
->DeleteWindows(); 
 510         node 
= node
->GetNext(); 
 514 wxSize 
wxSizer::Fit( wxWindow 
*window 
) 
 516     wxSize 
size(window
->IsTopLevel() ? FitSize(window
) 
 517                                      : GetMinWindowSize(window
)); 
 519     window
->SetSize( size 
); 
 524 void wxSizer::FitInside( wxWindow 
*window 
) 
 527     if (window
->IsTopLevel()) 
 528         size 
= VirtualFitSize( window 
); 
 530         size 
= GetMinClientSize( window 
); 
 532     window
->SetVirtualSize( size 
); 
 535 void wxSizer::Layout() 
 537     // (re)calculates minimums needed for each item and other preparations 
 541     // Applies the layout and repositions/resizes the items 
 545 void wxSizer::SetSizeHints( wxWindow 
*window 
) 
 547     // Preserve the window's max size hints, but set the 
 548     // lower bound according to the sizer calculations. 
 550     wxSize size 
= Fit( window 
); 
 552     window
->SetSizeHints( size
.x
, 
 554                           window
->GetMaxWidth(), 
 555                           window
->GetMaxHeight() ); 
 558 void wxSizer::SetVirtualSizeHints( wxWindow 
*window 
) 
 560     // Preserve the window's max size hints, but set the 
 561     // lower bound according to the sizer calculations. 
 564     wxSize 
size( window
->GetVirtualSize() ); 
 565     window
->SetVirtualSizeHints( size
.x
, 
 567                                  window
->GetMaxWidth(), 
 568                                  window
->GetMaxHeight() ); 
 571 wxSize 
wxSizer::GetMaxWindowSize( wxWindow 
*window 
) const 
 573     return window
->GetMaxSize(); 
 576 wxSize 
wxSizer::GetMinWindowSize( wxWindow 
*window 
) 
 578     wxSize      
minSize( GetMinSize() ); 
 579     wxSize      
size( window
->GetSize() ); 
 580     wxSize      
client_size( window
->GetClientSize() ); 
 582     return wxSize( minSize
.x
+size
.x
-client_size
.x
, 
 583                    minSize
.y
+size
.y
-client_size
.y 
); 
 586 // TODO on mac we need a function that determines how much free space this 
 587 // min size contains, in order to make sure that we have 20 pixels of free 
 588 // space around the controls 
 590 // Return a window size that will fit within the screens dimensions 
 591 wxSize 
wxSizer::FitSize( wxWindow 
*window 
) 
 593     wxSize size     
= GetMinWindowSize( window 
); 
 594     wxSize sizeMax  
= GetMaxWindowSize( window 
); 
 596     // Limit the size if sizeMax != wxDefaultSize 
 598     if ( size
.x 
> sizeMax
.x 
&& sizeMax
.x 
!= wxDefaultCoord 
) 
 600     if ( size
.y 
> sizeMax
.y 
&& sizeMax
.y 
!= wxDefaultCoord 
) 
 606 wxSize 
wxSizer::GetMaxClientSize( wxWindow 
*window 
) const 
 608     wxSize 
maxSize( window
->GetMaxSize() ); 
 610     if( maxSize 
!= wxDefaultSize 
) 
 612         wxSize 
size( window
->GetSize() ); 
 613         wxSize 
client_size( window
->GetClientSize() ); 
 615         return wxSize( maxSize
.x 
+ client_size
.x 
- size
.x
, 
 616                        maxSize
.y 
+ client_size
.y 
- size
.y 
); 
 619         return wxDefaultSize
; 
 622 wxSize 
wxSizer::GetMinClientSize( wxWindow 
*WXUNUSED(window
) ) 
 624     return GetMinSize();  // Already returns client size. 
 627 wxSize 
wxSizer::VirtualFitSize( wxWindow 
*window 
) 
 629     wxSize size     
= GetMinClientSize( window 
); 
 630     wxSize sizeMax  
= GetMaxClientSize( window 
); 
 632     // Limit the size if sizeMax != wxDefaultSize 
 634     if ( size
.x 
> sizeMax
.x 
&& sizeMax
.x 
!= wxDefaultCoord 
) 
 636     if ( size
.y 
> sizeMax
.y 
&& sizeMax
.y 
!= wxDefaultCoord 
) 
 642 void wxSizer::SetDimension( int x
, int y
, int width
, int height 
) 
 651 wxSize 
wxSizer::GetMinSize() 
 653     wxSize 
ret( CalcMin() ); 
 654     if (ret
.x 
< m_minSize
.x
) ret
.x 
= m_minSize
.x
; 
 655     if (ret
.y 
< m_minSize
.y
) ret
.y 
= m_minSize
.y
; 
 659 void wxSizer::DoSetMinSize( int width
, int height 
) 
 662     m_minSize
.y 
= height
; 
 665 bool wxSizer::DoSetItemMinSize( wxWindow 
*window
, int width
, int height 
) 
 667     wxASSERT_MSG( window
, _T("SetMinSize for NULL window") ); 
 669     // Is it our immediate child? 
 671     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 674         wxSizerItem     
*item 
= node
->GetData(); 
 676         if (item
->GetWindow() == window
) 
 678             item
->SetMinSize( width
, height 
); 
 681         node 
= node
->GetNext(); 
 684     // No?  Search any subsizers we own then 
 686     node 
= m_children
.GetFirst(); 
 689         wxSizerItem     
*item 
= node
->GetData(); 
 691         if ( item
->GetSizer() && 
 692              item
->GetSizer()->DoSetItemMinSize( window
, width
, height 
) ) 
 694             // A child sizer found the requested windw, exit. 
 697         node 
= node
->GetNext(); 
 703 bool wxSizer::DoSetItemMinSize( wxSizer 
*sizer
, int width
, int height 
) 
 705     wxASSERT_MSG( sizer
, _T("SetMinSize for NULL sizer") ); 
 707     // Is it our immediate child? 
 709     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 712         wxSizerItem     
*item 
= node
->GetData(); 
 714         if (item
->GetSizer() == sizer
) 
 716             item
->GetSizer()->DoSetMinSize( width
, height 
); 
 719         node 
= node
->GetNext(); 
 722     // No?  Search any subsizers we own then 
 724     node 
= m_children
.GetFirst(); 
 727         wxSizerItem     
*item 
= node
->GetData(); 
 729         if ( item
->GetSizer() && 
 730              item
->GetSizer()->DoSetItemMinSize( sizer
, width
, height 
) ) 
 732             // A child found the requested sizer, exit. 
 735         node 
= node
->GetNext(); 
 741 bool wxSizer::DoSetItemMinSize( size_t index
, int width
, int height 
) 
 743     wxSizerItemList::compatibility_iterator node 
= m_children
.Item( index 
); 
 745     wxCHECK_MSG( node
, false, _T("Failed to find child node") ); 
 747     wxSizerItem     
*item 
= node
->GetData(); 
 749     if (item
->GetSizer()) 
 751         // Sizers contains the minimal size in them, if not calculated ... 
 752         item
->GetSizer()->DoSetMinSize( width
, height 
); 
 756         // ... but the minimal size of spacers and windows is stored via the item 
 757         item
->SetMinSize( width
, height 
); 
 763 wxSizerItem
* wxSizer::GetItem( wxWindow 
*window
, bool recursive 
) 
 765     wxASSERT_MSG( window
, _T("GetItem for NULL window") ); 
 767     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 770         wxSizerItem     
*item 
= node
->GetData(); 
 772         if (item
->GetWindow() == window
) 
 776         else if (recursive 
&& item
->IsSizer()) 
 778             wxSizerItem 
*subitem 
= item
->GetSizer()->GetItem( window
, true ); 
 783         node 
= node
->GetNext(); 
 789 wxSizerItem
* wxSizer::GetItem( wxSizer 
*sizer
, bool recursive 
) 
 791     wxASSERT_MSG( sizer
, _T("GetItem for NULL sizer") ); 
 793     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 796         wxSizerItem 
*item 
= node
->GetData(); 
 798         if (item
->GetSizer() == sizer
) 
 802         else if (recursive 
&& item
->IsSizer()) 
 804             wxSizerItem 
*subitem 
= item
->GetSizer()->GetItem( sizer
, true ); 
 809         node 
= node
->GetNext(); 
 815 wxSizerItem
* wxSizer::GetItem( size_t index 
) 
 817     wxCHECK_MSG( index 
< m_children
.GetCount(), 
 819                  _T("GetItem index is out of range") ); 
 821     return m_children
.Item( index 
)->GetData(); 
 824 bool wxSizer::Show( wxWindow 
*window
, bool show
, bool recursive 
) 
 826     wxSizerItem 
*item 
= GetItem( window
, recursive 
); 
 837 bool wxSizer::Show( wxSizer 
*sizer
, bool show
, bool recursive 
) 
 839     wxSizerItem 
*item 
= GetItem( sizer
, recursive 
); 
 850 bool wxSizer::Show( size_t index
, bool show
) 
 852     wxSizerItem 
*item 
= GetItem( index 
); 
 863 void wxSizer::ShowItems( bool show 
) 
 865     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 868         node
->GetData()->Show( show 
); 
 869         node 
= node
->GetNext(); 
 873 bool wxSizer::IsShown( wxWindow 
*window 
) const 
 875     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 878         wxSizerItem     
*item 
= node
->GetData(); 
 880         if (item
->GetWindow() == window
) 
 882             return item
->IsShown(); 
 884         node 
= node
->GetNext(); 
 887     wxFAIL_MSG( _T("IsShown failed to find sizer item") ); 
 892 bool wxSizer::IsShown( wxSizer 
*sizer 
) const 
 894     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 897         wxSizerItem     
*item 
= node
->GetData(); 
 899         if (item
->GetSizer() == sizer
) 
 901             return item
->IsShown(); 
 903         node 
= node
->GetNext(); 
 906     wxFAIL_MSG( _T("IsShown failed to find sizer item") ); 
 911 bool wxSizer::IsShown( size_t index 
) const 
 913     wxCHECK_MSG( index 
< m_children
.GetCount(), 
 915                  _T("IsShown index is out of range") ); 
 917     return m_children
.Item( index 
)->GetData()->IsShown(); 
 921 //--------------------------------------------------------------------------- 
 923 //--------------------------------------------------------------------------- 
 925 wxGridSizer::wxGridSizer( int rows
, int cols
, int vgap
, int hgap 
) 
 931     if (m_rows 
== 0 && m_cols 
== 0) 
 935 wxGridSizer::wxGridSizer( int cols
, int vgap
, int hgap 
) 
 941     if (m_rows 
== 0 && m_cols 
== 0) 
 945 int wxGridSizer::CalcRowsCols(int& nrows
, int& ncols
) const 
 947     int nitems 
= m_children
.GetCount(); 
 953             nrows 
= (nitems 
+ m_cols 
- 1) / m_cols
; 
 957             ncols 
= (nitems 
+ m_rows 
- 1) / m_rows
; 
 960         else // 0 columns, 0 rows? 
 962             wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") ); 
 971 void wxGridSizer::RecalcSizes() 
 973     int nitems
, nrows
, ncols
; 
 974     if ( (nitems 
= CalcRowsCols(nrows
, ncols
)) == 0 ) 
 977     wxSize 
sz( GetSize() ); 
 978     wxPoint 
pt( GetPosition() ); 
 980     int w 
= (sz
.x 
- (ncols 
- 1) * m_hgap
) / ncols
; 
 981     int h 
= (sz
.y 
- (nrows 
- 1) * m_vgap
) / nrows
; 
 984     for (int c 
= 0; c 
< ncols
; c
++) 
 987         for (int r 
= 0; r 
< nrows
; r
++) 
 989             int i 
= r 
* ncols 
+ c
; 
 992                 wxSizerItemList::compatibility_iterator node 
= m_children
.Item( i 
); 
 994                 wxASSERT_MSG( node
, _T("Failed to find SizerItemList node") ); 
 996                 SetItemBounds( node
->GetData(), x
, y
, w
, h
); 
1004 wxSize 
wxGridSizer::CalcMin() 
1007     if ( CalcRowsCols(nrows
, ncols
) == 0 ) 
1008         return wxSize(10, 10); 
1010     // Find the max width and height for any component 
1014     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1017         wxSizerItem     
*item 
= node
->GetData(); 
1018         wxSize           
sz( item
->CalcMin() ); 
1020         w 
= wxMax( w
, sz
.x 
); 
1021         h 
= wxMax( h
, sz
.y 
); 
1023         node 
= node
->GetNext(); 
1026     return wxSize( ncols 
* w 
+ (ncols
-1) * m_hgap
, 
1027                    nrows 
* h 
+ (nrows
-1) * m_vgap 
); 
1030 void wxGridSizer::SetItemBounds( wxSizerItem 
*item
, int x
, int y
, int w
, int h 
) 
1033     wxSize 
sz( item
->GetMinSizeWithBorder() ); 
1034     int flag 
= item
->GetFlag(); 
1036     if ((flag 
& wxEXPAND
) || (flag 
& wxSHAPED
)) 
1042         if (flag 
& wxALIGN_CENTER_HORIZONTAL
) 
1044             pt
.x 
= x 
+ (w 
- sz
.x
) / 2; 
1046         else if (flag 
& wxALIGN_RIGHT
) 
1048             pt
.x 
= x 
+ (w 
- sz
.x
); 
1051         if (flag 
& wxALIGN_CENTER_VERTICAL
) 
1053             pt
.y 
= y 
+ (h 
- sz
.y
) / 2; 
1055         else if (flag 
& wxALIGN_BOTTOM
) 
1057             pt
.y 
= y 
+ (h 
- sz
.y
); 
1061     item
->SetDimension(pt
, sz
); 
1064 //--------------------------------------------------------------------------- 
1066 //--------------------------------------------------------------------------- 
1068 wxFlexGridSizer::wxFlexGridSizer( int rows
, int cols
, int vgap
, int hgap 
) 
1069                : wxGridSizer( rows
, cols
, vgap
, hgap 
), 
1070                  m_flexDirection(wxBOTH
), 
1071                  m_growMode(wxFLEX_GROWMODE_SPECIFIED
) 
1075 wxFlexGridSizer::wxFlexGridSizer( int cols
, int vgap
, int hgap 
) 
1076                : wxGridSizer( cols
, vgap
, hgap 
), 
1077                  m_flexDirection(wxBOTH
), 
1078                  m_growMode(wxFLEX_GROWMODE_SPECIFIED
) 
1082 wxFlexGridSizer::~wxFlexGridSizer() 
1086 void wxFlexGridSizer::RecalcSizes() 
1088     int nitems
, nrows
, ncols
; 
1089     if ( (nitems 
= CalcRowsCols(nrows
, ncols
)) == 0 ) 
1092     wxPoint 
pt( GetPosition() ); 
1093     wxSize 
sz( GetSize() ); 
1095     AdjustForGrowables(sz
, m_calculatedMinSize
, nrows
, ncols
); 
1097     sz 
= wxSize( pt
.x 
+ sz
.x
, pt
.y 
+ sz
.y 
); 
1100     for (int c 
= 0; c 
< ncols
; c
++) 
1103         for (int r 
= 0; r 
< nrows
; r
++) 
1105             int i 
= r 
* ncols 
+ c
; 
1108                 wxSizerItemList::compatibility_iterator node 
= m_children
.Item( i 
); 
1110                 wxASSERT_MSG( node
, _T("Failed to find node") ); 
1112                 int w 
= wxMax( 0, wxMin( m_colWidths
[c
], sz
.x 
- x 
) ); 
1113                 int h 
= wxMax( 0, wxMin( m_rowHeights
[r
], sz
.y 
- y 
) ); 
1115                 SetItemBounds( node
->GetData(), x
, y
, w
, h
); 
1117             y 
= y 
+ m_rowHeights
[r
] + m_vgap
; 
1119         x 
= x 
+ m_colWidths
[c
] + m_hgap
; 
1123 wxSize 
wxFlexGridSizer::CalcMin() 
1129     // Number of rows/columns can change as items are added or removed. 
1130     if ( !CalcRowsCols(nrows
, ncols
) ) 
1131         return wxSize(10, 10); 
1133     m_rowHeights
.SetCount(nrows
); 
1134     m_colWidths
.SetCount(ncols
); 
1136     // We have to recalcuate the sizes in case the item minimum size has 
1137     // changed since the previous layout, or the item has been hidden using 
1138     // wxSizer::Show(). If all the items in a row/column are hidden, the final 
1139     // dimension of the row/column will be -1, indicating that the column 
1140     // itself is hidden. 
1141     for( s 
= m_rowHeights
.GetCount(), i 
= 0; i 
< s
; ++i 
) 
1142         m_rowHeights
[ i 
] = -1; 
1143     for( s 
= m_colWidths
.GetCount(), i 
= 0; i 
< s
; ++i 
) 
1144         m_colWidths
[ i 
] = -1; 
1146     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1151         wxSizerItem    
*item 
= node
->GetData(); 
1152         if ( item
->IsShown() ) 
1154             wxSize 
sz( item
->CalcMin() ); 
1155             int row 
= i 
/ ncols
; 
1156             int col 
= i 
% ncols
; 
1158             m_rowHeights
[ row 
] = wxMax( wxMax( 0, sz
.y 
), m_rowHeights
[ row 
] ); 
1159             m_colWidths
[ col 
] = wxMax( wxMax( 0, sz
.x 
), m_colWidths
[ col 
] ); 
1162         node 
= node
->GetNext(); 
1166     AdjustForFlexDirection(); 
1168     // Sum total minimum size, including gaps between rows/columns. 
1169     // -1 is used as a magic number meaning empty column. 
1171     for (int col 
= 0; col 
< ncols
; col
++) 
1172         if ( m_colWidths
[ col 
] != -1 ) 
1173             width 
+= m_colWidths
[ col 
] + ( col 
== ncols
-1 ? 0 : m_hgap 
); 
1176     for (int row 
= 0; row 
< nrows
; row
++) 
1177         if ( m_rowHeights
[ row 
] != -1 ) 
1178             height 
+= m_rowHeights
[ row 
] + ( row 
== nrows
-1 ? 0 : m_vgap 
); 
1180     m_calculatedMinSize 
= wxSize( width
, height 
); 
1181     return m_calculatedMinSize
; 
1184 void wxFlexGridSizer::AdjustForFlexDirection() 
1186     // the logic in CalcMin works when we resize flexibly in both directions 
1187     // but maybe this is not the case 
1188     if ( m_flexDirection 
!= wxBOTH 
) 
1190         // select the array corresponding to the direction in which we do *not* 
1192         wxArrayInt
& array 
= m_flexDirection 
== wxVERTICAL 
? m_colWidths
 
1195         const int count 
= array
.GetCount(); 
1197         // find the largest value in this array 
1199         for ( n 
= 0; n 
< count
; ++n 
) 
1201             if ( array
[n
] > largest 
) 
1205         // and now fill it with the largest value 
1206         for ( n 
= 0; n 
< count
; ++n 
) 
1214 void wxFlexGridSizer::AdjustForGrowables(const wxSize
& sz
, const wxSize
& minsz
, 
1215                                          int nrows
, int ncols
) 
1217     // what to do with the rows? by default, resize them proportionally 
1218     if ( sz
.y 
> minsz
.y 
&& ( (m_flexDirection 
& wxVERTICAL
) || (m_growMode 
== wxFLEX_GROWMODE_SPECIFIED
) ) ) 
1220         int sum_proportions 
= 0; 
1221         int growable_space 
= 0; 
1224         for (idx 
= 0; idx 
< m_growableRows
.GetCount(); idx
++) 
1226             // Since the number of rows/columns can change as items are 
1227             // inserted/deleted, we need to verify at runtime that the 
1228             // requested growable rows/columns are still valid. 
1229             if (m_growableRows
[idx
] >= nrows
) 
1232             // If all items in a row/column are hidden, that row/column will 
1233             // have a dimension of -1.  This causes the row/column to be 
1234             // hidden completely. 
1235             if (m_rowHeights
[ m_growableRows
[idx
] ] == -1) 
1237             sum_proportions 
+= m_growableRowsProportions
[idx
]; 
1238             growable_space 
+= m_rowHeights
[ m_growableRows
[idx
] ]; 
1244             for (idx 
= 0; idx 
< m_growableRows
.GetCount(); idx
++) 
1246                 if (m_growableRows
[idx
] >= nrows 
) 
1248                 if (m_rowHeights
[ m_growableRows
[idx
] ] == -1) 
1249                     m_rowHeights
[ m_growableRows
[idx
] ] = 0; 
1252                     int delta 
= (sz
.y 
- minsz
.y
); 
1253                     if (sum_proportions 
== 0) 
1254                         delta 
= (delta
/num
) + m_rowHeights
[ m_growableRows
[idx
] ]; 
1256                         delta 
= ((delta
+growable_space
)*m_growableRowsProportions
[idx
]) / sum_proportions
; 
1257                     m_rowHeights
[ m_growableRows
[idx
] ] = delta
; 
1262     else if ( (m_growMode 
== wxFLEX_GROWMODE_ALL
) && (sz
.y 
> minsz
.y
) ) 
1264         // rounding problem? 
1265         for ( int row 
= 0; row 
< nrows
; ++row 
) 
1266             m_rowHeights
[ row 
] = sz
.y 
/ nrows
; 
1269     // the same logic as above but for the columns 
1270     if ( sz
.x 
> minsz
.x 
&& ( (m_flexDirection 
& wxHORIZONTAL
) || (m_growMode 
== wxFLEX_GROWMODE_SPECIFIED
) ) ) 
1272         int sum_proportions 
= 0; 
1273         int growable_space 
= 0; 
1276         for (idx 
= 0; idx 
< m_growableCols
.GetCount(); idx
++) 
1278             // Since the number of rows/columns can change as items are 
1279             // inserted/deleted, we need to verify at runtime that the 
1280             // requested growable rows/columns are still valid. 
1281             if (m_growableCols
[idx
] >= ncols
) 
1284             // If all items in a row/column are hidden, that row/column will 
1285             // have a dimension of -1.  This causes the column to be hidden 
1287             if (m_colWidths
[ m_growableCols
[idx
] ] == -1) 
1289             sum_proportions 
+= m_growableColsProportions
[idx
]; 
1290             growable_space 
+= m_colWidths
[ m_growableCols
[idx
] ]; 
1296             for (idx 
= 0; idx 
< m_growableCols
.GetCount(); idx
++) 
1298                 if (m_growableCols
[idx
] >= ncols 
) 
1300                 if (m_colWidths
[ m_growableCols
[idx
] ] == -1) 
1301                     m_colWidths
[ m_growableCols
[idx
] ] = 0; 
1304                     int delta 
= (sz
.x 
- minsz
.x
); 
1305                     if (sum_proportions 
== 0) 
1306                         delta 
= (delta
/num
) + m_colWidths
[ m_growableCols
[idx
] ]; 
1308                         delta 
= ((delta
+growable_space
)*m_growableColsProportions
[idx
])/sum_proportions
; 
1309                     m_colWidths
[ m_growableCols
[idx
] ] = delta
; 
1314     else if ( (m_growMode 
== wxFLEX_GROWMODE_ALL
) && (sz
.x 
> minsz
.x
) ) 
1316         for ( int col
=0; col 
< ncols
; ++col 
) 
1317             m_colWidths
[ col 
] = sz
.x 
/ ncols
; 
1322 void wxFlexGridSizer::AddGrowableRow( size_t idx
, int proportion 
) 
1324     m_growableRows
.Add( idx 
); 
1325     m_growableRowsProportions
.Add( proportion 
); 
1328 void wxFlexGridSizer::RemoveGrowableRow( size_t idx 
) 
1330     m_growableRows
.Remove( idx 
); 
1333 void wxFlexGridSizer::AddGrowableCol( size_t idx
, int proportion 
) 
1335     m_growableCols
.Add( idx 
); 
1336     m_growableColsProportions
.Add( proportion 
); 
1339 void wxFlexGridSizer::RemoveGrowableCol( size_t idx 
) 
1341     m_growableCols
.Remove( idx 
); 
1344 //--------------------------------------------------------------------------- 
1346 //--------------------------------------------------------------------------- 
1348 wxBoxSizer::wxBoxSizer( int orient 
) 
1349     : m_orient( orient 
) 
1353 void wxBoxSizer::RecalcSizes() 
1355     if (m_children
.GetCount() == 0) 
1361         if (m_orient 
== wxHORIZONTAL
) 
1362             delta 
= m_size
.x 
- m_fixedWidth
; 
1364             delta 
= m_size
.y 
- m_fixedHeight
; 
1367     wxPoint 
pt( m_position 
); 
1369     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1372         wxSizerItem     
*item 
= node
->GetData(); 
1374         if (item
->IsShown()) 
1376             wxSize 
size( item
->GetMinSizeWithBorder() ); 
1378             if (m_orient 
== wxVERTICAL
) 
1380                 wxCoord height 
= size
.y
; 
1381                 if (item
->GetProportion()) 
1383                     // Because of at least one visible item has non-zero 
1384                     // proportion then m_stretchable is not zero 
1385                     height 
= (delta 
* item
->GetProportion()) / m_stretchable
; 
1388                 wxPoint 
child_pos( pt 
); 
1389                 wxSize  
child_size( size
.x
, height 
); 
1391                 if (item
->GetFlag() & (wxEXPAND 
| wxSHAPED
)) 
1392                     child_size
.x 
= m_size
.x
; 
1393                 else if (item
->GetFlag() & wxALIGN_RIGHT
) 
1394                     child_pos
.x 
+= m_size
.x 
- size
.x
; 
1395                 else if (item
->GetFlag() & (wxCENTER 
| wxALIGN_CENTER_HORIZONTAL
)) 
1396                 // XXX wxCENTER is added for backward compatibility; 
1397                 //     wxALIGN_CENTER should be used in new code 
1398                     child_pos
.x 
+= (m_size
.x 
- size
.x
) / 2; 
1400                 item
->SetDimension( child_pos
, child_size 
); 
1406                 wxCoord width 
= size
.x
; 
1407                 if (item
->GetProportion()) 
1409                     // Because of at least one visible item has non-zero 
1410                     // proportion then m_stretchable is not zero 
1411                     width 
= (delta 
* item
->GetProportion()) / m_stretchable
; 
1414                 wxPoint 
child_pos( pt 
); 
1415                 wxSize  
child_size( width
, size
.y 
); 
1417                 if (item
->GetFlag() & (wxEXPAND 
| wxSHAPED
)) 
1418                     child_size
.y 
= m_size
.y
; 
1419                 else if (item
->GetFlag() & wxALIGN_BOTTOM
) 
1420                     child_pos
.y 
+= m_size
.y 
- size
.y
; 
1421                 else if (item
->GetFlag() & (wxCENTER 
| wxALIGN_CENTER_VERTICAL
)) 
1422                 // XXX wxCENTER is added for backward compatibility; 
1423                 //     wxALIGN_CENTER should be used in new code 
1424                     child_pos
.y 
+= (m_size
.y 
- size
.y
) / 2; 
1426                 item
->SetDimension( child_pos
, child_size 
); 
1432         node 
= node
->GetNext(); 
1436 wxSize 
wxBoxSizer::CalcMin() 
1438     if (m_children
.GetCount() == 0) 
1439         return wxSize(10,10); 
1447     // precalc item minsizes and count proportions 
1448     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1451         wxSizerItem 
*item 
= node
->GetData(); 
1453         if (item
->IsShown()) 
1454             item
->CalcMin();  // result is stored in the item 
1456         if (item
->IsShown() && item
->GetProportion() != 0) 
1457             m_stretchable 
+= item
->GetProportion(); 
1459         node 
= node
->GetNext(); 
1462     // Total minimum size (width or height) of sizer 
1465     node 
= m_children
.GetFirst(); 
1468         wxSizerItem 
*item 
= node
->GetData(); 
1470         if (item
->IsShown() && item
->GetProportion() != 0) 
1472             int stretch 
= item
->GetProportion(); 
1473             wxSize 
size( item
->GetMinSizeWithBorder() ); 
1476             // Integer division rounded up is (a + b - 1) / b 
1477             // Round up needed in order to guarantee that all 
1478             // all items will have size not less then their min size 
1479             if (m_orient 
== wxHORIZONTAL
) 
1480                 minSize 
= ( size
.x
*m_stretchable 
+ stretch 
- 1)/stretch
; 
1482                 minSize 
= ( size
.y
*m_stretchable 
+ stretch 
- 1)/stretch
; 
1484             if (minSize 
> maxMinSize
) 
1485                 maxMinSize 
= minSize
; 
1487         node 
= node
->GetNext(); 
1490     // Calculate overall minimum size 
1491     node 
= m_children
.GetFirst(); 
1494         wxSizerItem 
*item 
= node
->GetData(); 
1496         if (item
->IsShown()) 
1498             wxSize 
size( item
->GetMinSizeWithBorder() ); 
1499             if (item
->GetProportion() != 0) 
1501                 if (m_orient 
== wxHORIZONTAL
) 
1502                     size
.x 
= (maxMinSize
*item
->GetProportion())/m_stretchable
; 
1504                     size
.y 
= (maxMinSize
*item
->GetProportion())/m_stretchable
; 
1508                 if (m_orient 
== wxVERTICAL
) 
1510                     m_fixedHeight 
+= size
.y
; 
1511                     m_fixedWidth 
= wxMax( m_fixedWidth
, size
.x 
); 
1515                     m_fixedWidth 
+= size
.x
; 
1516                     m_fixedHeight 
= wxMax( m_fixedHeight
, size
.y 
); 
1520             if (m_orient 
== wxHORIZONTAL
) 
1522                 m_minWidth 
+= size
.x
; 
1523                 m_minHeight 
= wxMax( m_minHeight
, size
.y 
); 
1527                 m_minHeight 
+= size
.y
; 
1528                 m_minWidth 
= wxMax( m_minWidth
, size
.x 
); 
1531         node 
= node
->GetNext(); 
1534     return wxSize( m_minWidth
, m_minHeight 
); 
1537 //--------------------------------------------------------------------------- 
1539 //--------------------------------------------------------------------------- 
1543 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox 
*box
, int orient 
) 
1544     : wxBoxSizer( orient 
) 
1545     , m_staticBox( box 
) 
1547     wxASSERT_MSG( box
, wxT("wxStaticBoxSizer needs a static box") ); 
1550 static void GetStaticBoxBorders( wxStaticBox 
*box
, 
1554     // this has to be done platform by platform as there is no way to 
1555     // guess the thickness of a wxStaticBox border 
1557     box
->GetBordersForSizer(borderTop
,borderOther
); 
1558 #elif defined(__WXMAC__) 
1560     static int extraTop 
= -1; // Uninitted 
1561     static int other 
= 5; 
1563     if ( extraTop 
== -1 ) 
1565         // The minimal border used for the top. Later on the staticbox' 
1566         // font height is added to this. 
1569         if ( UMAGetSystemVersion() >= 0x1030 /*Panther*/ ) 
1571             // As indicated by the HIG, Panther needs an extra border of 11 
1572             // pixels (otherwise overlapping occurs at the top). The "other" 
1573             // border has to be 11. 
1580     *borderTop 
= extraTop 
+ box
->GetCharHeight(); 
1581     *borderOther 
= other
; 
1585     if ( box
->GetLabel().IsEmpty() ) 
1589         *borderTop 
= box
->GetCharHeight(); 
1592 #endif // __WXCOCOA__ 
1595 void wxStaticBoxSizer::RecalcSizes() 
1597     int top_border
, other_border
; 
1598     GetStaticBoxBorders(m_staticBox
, &top_border
, &other_border
); 
1600     m_staticBox
->SetSize( m_position
.x
, m_position
.y
, m_size
.x
, m_size
.y 
); 
1602     wxPoint 
old_pos( m_position 
); 
1603     m_position
.x 
+= other_border
; 
1604     m_position
.y 
+= top_border
; 
1605     wxSize 
old_size( m_size 
); 
1606     m_size
.x 
-= 2*other_border
; 
1607     m_size
.y 
-= top_border 
+ other_border
; 
1609     wxBoxSizer::RecalcSizes(); 
1611     m_position 
= old_pos
; 
1615 wxSize 
wxStaticBoxSizer::CalcMin() 
1617     int top_border
, other_border
; 
1618     GetStaticBoxBorders(m_staticBox
, &top_border
, &other_border
); 
1620     wxSize 
ret( wxBoxSizer::CalcMin() ); 
1621     ret
.x 
+= 2*other_border
; 
1622     ret
.y 
+= other_border 
+ top_border
; 
1627 void wxStaticBoxSizer::ShowItems( bool show 
) 
1629     m_staticBox
->Show( show 
); 
1630     wxBoxSizer::ShowItems( show 
); 
1633 #endif // wxUSE_STATBOX 
1636 #if WXWIN_COMPATIBILITY_2_4 
1638 // ---------------------------------------------------------------------------- 
1640 // ---------------------------------------------------------------------------- 
1643 IMPLEMENT_CLASS(wxBookCtrlSizer
, wxSizer
) 
1645 IMPLEMENT_CLASS(wxNotebookSizer
, wxBookCtrlSizer
) 
1646 #endif // wxUSE_NOTEBOOK 
1647 #endif // wxUSE_BOOKCTRL 
1651 wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrl 
*bookctrl
) 
1652                : m_bookctrl(bookctrl
) 
1654     wxASSERT_MSG( bookctrl
, wxT("wxBookCtrlSizer needs a control") ); 
1657 void wxBookCtrlSizer::RecalcSizes() 
1659     m_bookctrl
->SetSize( m_position
.x
, m_position
.y
, m_size
.x
, m_size
.y 
); 
1662 wxSize 
wxBookCtrlSizer::CalcMin() 
1664     wxSize sizeBorder 
= m_bookctrl
->CalcSizeFromPage(wxSize(0, 0)); 
1669     if ( m_bookctrl
->GetPageCount() == 0 ) 
1671         return wxSize(sizeBorder
.x 
+ 10, sizeBorder
.y 
+ 10); 
1677     wxWindowList::compatibility_iterator
 
1678         node 
= m_bookctrl
->GetChildren().GetFirst(); 
1681         wxWindow 
*item 
= node
->GetData(); 
1682         wxSizer 
*itemsizer 
= item
->GetSizer(); 
1686             wxSize 
subsize( itemsizer
->CalcMin() ); 
1688             if (subsize
.x 
> maxX
) 
1690             if (subsize
.y 
> maxY
) 
1694         node 
= node
->GetNext(); 
1697     return wxSize( maxX
, maxY 
) + sizeBorder
; 
1702 wxNotebookSizer::wxNotebookSizer(wxNotebook 
*nb
) 
1704     wxASSERT_MSG( nb
, wxT("wxNotebookSizer needs a control") ); 
1708 #endif // wxUSE_NOTEBOOOK 
1709 #endif // wxUSE_BOOKCTRL 
1711 #endif // WXWIN_COMPATIBILITY_2_4