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 // For compilers that support precompilation, includes "wx.h". 
  14 #include "wx/wxprec.h" 
  21     #include "wx/string.h" 
  28 #include "wx/statbox.h" 
  29 #include "wx/settings.h" 
  30 #include "wx/listimpl.cpp" 
  32 #if WXWIN_COMPATIBILITY_2_4 
  33     #include "wx/notebook.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 IMPLEMENT_CLASS(wxStdDialogButtonSizer
, wxBoxSizer
) 
  50 WX_DEFINE_EXPORTED_LIST( wxSizerItemList 
) 
  85 // ---------------------------------------------------------------------------- 
  87 // ---------------------------------------------------------------------------- 
  89 void wxSizerItem::Init(const wxSizerFlags
& flags
) 
  93     m_proportion 
= flags
.GetProportion(); 
  94     m_flag 
= flags
.GetFlags(); 
  95     m_border 
= flags
.GetBorderInPixels(); 
  98 wxSizerItem::wxSizerItem() 
 110 void wxSizerItem::SetWindow(wxWindow 
*window
) 
 112     wxCHECK_RET( window
, _T("NULL window in wxSizerItem::SetWindow()") ); 
 114     m_kind 
= Item_Window
; 
 117     // window doesn't become smaller than its initial size, whatever happens 
 118     m_minSize 
= window
->GetSize(); 
 120     if ( m_flag 
& wxFIXED_MINSIZE 
) 
 121         window
->SetMinSize(m_minSize
); 
 123     // aspect ratio calculated from initial size 
 127 wxSizerItem::wxSizerItem(wxWindow 
*window
, 
 132            : m_proportion(proportion
), 
 141 void wxSizerItem::SetSizer(wxSizer 
*sizer
) 
 147 wxSizerItem::wxSizerItem(wxSizer 
*sizer
, 
 152            : m_proportion(proportion
), 
 160     // m_minSize is set later 
 164 void wxSizerItem::SetSpacer(const wxSize
& size
) 
 166     m_kind 
= Item_Spacer
; 
 167     m_spacer 
= new wxSizerSpacer(size
); 
 172 wxSizerItem::wxSizerItem(int width
, 
 178            : m_minSize(width
, height
), // minimal size is the initial size 
 179              m_proportion(proportion
), 
 184     SetSpacer(width
, height
); 
 187 wxSizerItem::~wxSizerItem() 
 197             m_window
->SetContainingSizer(NULL
); 
 210             wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); 
 214 wxSize 
wxSizerItem::GetSpacer() const 
 217     if ( m_kind 
== Item_Spacer 
) 
 218         size 
= m_spacer
->GetSize(); 
 224 wxSize 
wxSizerItem::GetSize() const 
 233             ret 
= m_window
->GetSize(); 
 237             ret 
= m_sizer
->GetSize(); 
 241             ret 
= m_spacer
->GetSize(); 
 246             wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); 
 253     if (m_flag 
& wxNORTH
) 
 255     if (m_flag 
& wxSOUTH
) 
 261 wxSize 
wxSizerItem::CalcMin() 
 265         m_minSize 
= m_sizer
->GetMinSize(); 
 267         // if we have to preserve aspect ratio _AND_ this is 
 268         // the first-time calculation, consider ret to be initial size 
 269         if ( (m_flag 
& wxSHAPED
) && wxIsNullDouble(m_ratio
) ) 
 272     else if ( IsWindow() ) 
 274         // Since the size of the window may change during runtime, we 
 275         // should use the current minimal/best size. 
 276         m_minSize 
= m_window
->GetBestFittingSize(); 
 279     return GetMinSizeWithBorder(); 
 282 wxSize 
wxSizerItem::GetMinSizeWithBorder() const 
 284     wxSize ret 
= m_minSize
; 
 290     if (m_flag 
& wxNORTH
) 
 292     if (m_flag 
& wxSOUTH
) 
 299 void wxSizerItem::SetDimension( const wxPoint
& pos_
, const wxSize
& size_ 
) 
 303     if (m_flag 
& wxSHAPED
) 
 305         // adjust aspect ratio 
 306         int rwidth 
= (int) (size
.y 
* m_ratio
); 
 310             int rheight 
= (int) (size
.x 
/ m_ratio
); 
 311             // add vertical space 
 312             if (m_flag 
& wxALIGN_CENTER_VERTICAL
) 
 313                 pos
.y 
+= (size
.y 
- rheight
) / 2; 
 314             else if (m_flag 
& wxALIGN_BOTTOM
) 
 315                 pos
.y 
+= (size
.y 
- rheight
); 
 316             // use reduced dimensions 
 319         else if (rwidth 
< size
.x
) 
 321             // add horizontal space 
 322             if (m_flag 
& wxALIGN_CENTER_HORIZONTAL
) 
 323                 pos
.x 
+= (size
.x 
- rwidth
) / 2; 
 324             else if (m_flag 
& wxALIGN_RIGHT
) 
 325                 pos
.x 
+= (size
.x 
- rwidth
); 
 330     // This is what GetPosition() returns. Since we calculate 
 331     // borders afterwards, GetPosition() will be the left/top 
 332     // corner of the surrounding border. 
 344     if (m_flag 
& wxNORTH
) 
 349     if (m_flag 
& wxSOUTH
) 
 354     m_rect 
= wxRect(pos
, size
); 
 359             wxFAIL_MSG( _T("can't set size of uninitialized sizer item") ); 
 363             m_window
->SetSize(pos
.x
, pos
.y
, size
.x
, size
.y
, 
 364                               wxSIZE_ALLOW_MINUS_ONE
); 
 368             m_sizer
->SetDimension(pos
.x
, pos
.y
, size
.x
, size
.y
); 
 372             m_spacer
->SetSize(size
); 
 377             wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); 
 381 void wxSizerItem::DeleteWindows() 
 390             //We are deleting the window from this sizer - normally 
 391             //the window destroys the sizer associated with it, 
 392             //which might destroy this, which we don't want 
 393             m_window
->SetContainingSizer(NULL
); 
 395             //Putting this after the switch will result in a spacer 
 396             //not being deleted properly on destruction 
 401             m_sizer
->DeleteWindows(); 
 406             wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); 
 411 void wxSizerItem::Show( bool show 
) 
 416             wxFAIL_MSG( _T("can't show uninitialized sizer item") ); 
 420             m_window
->Show(show
); 
 428             m_spacer
->Show(show
); 
 433             wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); 
 437 bool wxSizerItem::IsShown() const 
 442             // we may be called from CalcMin(), just return false so that we're 
 447             return m_window
->IsShown(); 
 450             // arbitrarily decide that if at least one of our elements is 
 451             // shown, so are we (this arbitrariness is the reason for 
 452             // deprecating this function) 
 454                 for ( wxSizerItemList::compatibility_iterator
 
 455                         node 
= m_sizer
->GetChildren().GetFirst(); 
 457                       node 
= node
->GetNext() ) 
 459                     if ( node
->GetData()->IsShown() ) 
 466             return m_spacer
->IsShown(); 
 470             wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); 
 476 void wxSizerItem::SetOption( int option 
) 
 478     SetProportion( option 
); 
 481 int wxSizerItem::GetOption() const 
 483     return GetProportion(); 
 487 //--------------------------------------------------------------------------- 
 489 //--------------------------------------------------------------------------- 
 493     WX_CLEAR_LIST(wxSizerItemList
, m_children
); 
 496 wxSizerItem
* wxSizer::Insert( size_t index
, wxSizerItem 
*item 
) 
 498     m_children
.Insert( index
, item 
); 
 500     if ( item
->GetWindow() ) 
 501         item
->GetWindow()->SetContainingSizer( this ); 
 506 bool wxSizer::Remove( wxWindow 
*window 
) 
 508     return Detach( window 
); 
 511 bool wxSizer::Remove( wxSizer 
*sizer 
) 
 513     wxASSERT_MSG( sizer
, _T("Removing NULL sizer") ); 
 515     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 518         wxSizerItem     
*item 
= node
->GetData(); 
 520         if (item
->GetSizer() == sizer
) 
 523             m_children
.Erase( node 
); 
 527         node 
= node
->GetNext(); 
 533 bool wxSizer::Remove( int index 
) 
 535     wxCHECK_MSG( index 
>= 0 && (size_t)index 
< m_children
.GetCount(), 
 537                  _T("Remove index is out of range") ); 
 539     wxSizerItemList::compatibility_iterator node 
= m_children
.Item( index 
); 
 541     wxCHECK_MSG( node
, false, _T("Failed to find child node") ); 
 543     wxSizerItem 
*item 
= node
->GetData(); 
 545     if ( item
->IsWindow() ) 
 546         item
->GetWindow()->SetContainingSizer( NULL 
); 
 549     m_children
.Erase( node 
); 
 553 bool wxSizer::Detach( wxSizer 
*sizer 
) 
 555     wxASSERT_MSG( sizer
, _T("Detaching NULL sizer") ); 
 557     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 560         wxSizerItem     
*item 
= node
->GetData(); 
 562         if (item
->GetSizer() == sizer
) 
 566             m_children
.Erase( node 
); 
 569         node 
= node
->GetNext(); 
 575 bool wxSizer::Detach( wxWindow 
*window 
) 
 577     wxASSERT_MSG( window
, _T("Detaching NULL window") ); 
 579     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 582         wxSizerItem     
*item 
= node
->GetData(); 
 584         if (item
->GetWindow() == window
) 
 586             item
->GetWindow()->SetContainingSizer( NULL 
); 
 588             m_children
.Erase( node 
); 
 591         node 
= node
->GetNext(); 
 597 bool wxSizer::Detach( int index 
) 
 599     wxCHECK_MSG( index 
>= 0 && (size_t)index 
< m_children
.GetCount(), 
 601                  _T("Detach index is out of range") ); 
 603     wxSizerItemList::compatibility_iterator node 
= m_children
.Item( index 
); 
 605     wxCHECK_MSG( node
, false, _T("Failed to find child node") ); 
 607     wxSizerItem 
*item 
= node
->GetData(); 
 609     if ( item
->IsSizer() ) 
 611     else if ( item
->IsWindow() ) 
 612         item
->GetWindow()->SetContainingSizer( NULL 
); 
 615     m_children
.Erase( node 
); 
 619 void wxSizer::Clear( bool delete_windows 
) 
 621     // First clear the ContainingSizer pointers 
 622     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 625         wxSizerItem     
*item 
= node
->GetData(); 
 627         if (item
->IsWindow()) 
 628             item
->GetWindow()->SetContainingSizer( NULL 
); 
 629         node 
= node
->GetNext(); 
 632     // Destroy the windows if needed 
 636     // Now empty the list 
 637     WX_CLEAR_LIST(wxSizerItemList
, m_children
); 
 640 void wxSizer::DeleteWindows() 
 642     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 645         wxSizerItem     
*item 
= node
->GetData(); 
 647         item
->DeleteWindows(); 
 648         node 
= node
->GetNext(); 
 652 wxSize 
wxSizer::Fit( wxWindow 
*window 
) 
 654     wxSize 
size(window
->IsTopLevel() ? FitSize(window
) 
 655                                      : GetMinWindowSize(window
)); 
 657     window
->SetSize( size 
); 
 662 void wxSizer::FitInside( wxWindow 
*window 
) 
 665     if (window
->IsTopLevel()) 
 666         size 
= VirtualFitSize( window 
); 
 668         size 
= GetMinClientSize( window 
); 
 670     window
->SetVirtualSize( size 
); 
 673 void wxSizer::Layout() 
 675     // (re)calculates minimums needed for each item and other preparations 
 679     // Applies the layout and repositions/resizes the items 
 683 void wxSizer::SetSizeHints( wxWindow 
*window 
) 
 685     // Preserve the window's max size hints, but set the 
 686     // lower bound according to the sizer calculations. 
 688     wxSize size 
= Fit( window 
); 
 690     window
->SetSizeHints( size
.x
, 
 692                           window
->GetMaxWidth(), 
 693                           window
->GetMaxHeight() ); 
 696 void wxSizer::SetVirtualSizeHints( wxWindow 
*window 
) 
 698     // Preserve the window's max size hints, but set the 
 699     // lower bound according to the sizer calculations. 
 702     wxSize 
size( window
->GetVirtualSize() ); 
 703     window
->SetVirtualSizeHints( size
.x
, 
 705                                  window
->GetMaxWidth(), 
 706                                  window
->GetMaxHeight() ); 
 709 wxSize 
wxSizer::GetMaxWindowSize( wxWindow 
*window 
) const 
 711     return window
->GetMaxSize(); 
 714 wxSize 
wxSizer::GetMinWindowSize( wxWindow 
*window 
) 
 716     wxSize      
minSize( GetMinSize() ); 
 717     wxSize      
size( window
->GetSize() ); 
 718     wxSize      
client_size( window
->GetClientSize() ); 
 720     return wxSize( minSize
.x
+size
.x
-client_size
.x
, 
 721                    minSize
.y
+size
.y
-client_size
.y 
); 
 724 // TODO on mac we need a function that determines how much free space this 
 725 // min size contains, in order to make sure that we have 20 pixels of free 
 726 // space around the controls 
 728 // Return a window size that will fit within the screens dimensions 
 729 wxSize 
wxSizer::FitSize( wxWindow 
*window 
) 
 731     wxSize size     
= GetMinWindowSize( window 
); 
 732     wxSize sizeMax  
= GetMaxWindowSize( window 
); 
 734     // Limit the size if sizeMax != wxDefaultSize 
 736     if ( size
.x 
> sizeMax
.x 
&& sizeMax
.x 
!= wxDefaultCoord 
) 
 738     if ( size
.y 
> sizeMax
.y 
&& sizeMax
.y 
!= wxDefaultCoord 
) 
 744 wxSize 
wxSizer::GetMaxClientSize( wxWindow 
*window 
) const 
 746     wxSize 
maxSize( window
->GetMaxSize() ); 
 748     if ( maxSize 
!= wxDefaultSize 
) 
 750         wxSize 
size( window
->GetSize() ); 
 751         wxSize 
client_size( window
->GetClientSize() ); 
 753         return wxSize( maxSize
.x 
+ client_size
.x 
- size
.x
, 
 754                        maxSize
.y 
+ client_size
.y 
- size
.y 
); 
 757         return wxDefaultSize
; 
 760 wxSize 
wxSizer::GetMinClientSize( wxWindow 
*WXUNUSED(window
) ) 
 762     return GetMinSize();  // Already returns client size. 
 765 wxSize 
wxSizer::VirtualFitSize( wxWindow 
*window 
) 
 767     wxSize size     
= GetMinClientSize( window 
); 
 768     wxSize sizeMax  
= GetMaxClientSize( window 
); 
 770     // Limit the size if sizeMax != wxDefaultSize 
 772     if ( size
.x 
> sizeMax
.x 
&& sizeMax
.x 
!= wxDefaultCoord 
) 
 774     if ( size
.y 
> sizeMax
.y 
&& sizeMax
.y 
!= wxDefaultCoord 
) 
 780 void wxSizer::SetDimension( int x
, int y
, int width
, int height 
) 
 789 wxSize 
wxSizer::GetMinSize() 
 791     wxSize 
ret( CalcMin() ); 
 792     if (ret
.x 
< m_minSize
.x
) ret
.x 
= m_minSize
.x
; 
 793     if (ret
.y 
< m_minSize
.y
) ret
.y 
= m_minSize
.y
; 
 797 void wxSizer::DoSetMinSize( int width
, int height 
) 
 800     m_minSize
.y 
= height
; 
 803 bool wxSizer::DoSetItemMinSize( wxWindow 
*window
, int width
, int height 
) 
 805     wxASSERT_MSG( window
, _T("SetMinSize for NULL window") ); 
 807     // Is it our immediate child? 
 809     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 812         wxSizerItem     
*item 
= node
->GetData(); 
 814         if (item
->GetWindow() == window
) 
 816             item
->SetMinSize( width
, height 
); 
 819         node 
= node
->GetNext(); 
 822     // No?  Search any subsizers we own then 
 824     node 
= m_children
.GetFirst(); 
 827         wxSizerItem     
*item 
= node
->GetData(); 
 829         if ( item
->GetSizer() && 
 830              item
->GetSizer()->DoSetItemMinSize( window
, width
, height 
) ) 
 832             // A child sizer found the requested windw, exit. 
 835         node 
= node
->GetNext(); 
 841 bool wxSizer::DoSetItemMinSize( wxSizer 
*sizer
, int width
, int height 
) 
 843     wxASSERT_MSG( sizer
, _T("SetMinSize for NULL sizer") ); 
 845     // Is it our immediate child? 
 847     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 850         wxSizerItem     
*item 
= node
->GetData(); 
 852         if (item
->GetSizer() == sizer
) 
 854             item
->GetSizer()->DoSetMinSize( width
, height 
); 
 857         node 
= node
->GetNext(); 
 860     // No?  Search any subsizers we own then 
 862     node 
= m_children
.GetFirst(); 
 865         wxSizerItem     
*item 
= node
->GetData(); 
 867         if ( item
->GetSizer() && 
 868              item
->GetSizer()->DoSetItemMinSize( sizer
, width
, height 
) ) 
 870             // A child found the requested sizer, exit. 
 873         node 
= node
->GetNext(); 
 879 bool wxSizer::DoSetItemMinSize( size_t index
, int width
, int height 
) 
 881     wxSizerItemList::compatibility_iterator node 
= m_children
.Item( index 
); 
 883     wxCHECK_MSG( node
, false, _T("Failed to find child node") ); 
 885     wxSizerItem     
*item 
= node
->GetData(); 
 887     if (item
->GetSizer()) 
 889         // Sizers contains the minimal size in them, if not calculated ... 
 890         item
->GetSizer()->DoSetMinSize( width
, height 
); 
 894         // ... but the minimal size of spacers and windows is stored via the item 
 895         item
->SetMinSize( width
, height 
); 
 901 wxSizerItem
* wxSizer::GetItem( wxWindow 
*window
, bool recursive 
) 
 903     wxASSERT_MSG( window
, _T("GetItem for NULL window") ); 
 905     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 908         wxSizerItem     
*item 
= node
->GetData(); 
 910         if (item
->GetWindow() == window
) 
 914         else if (recursive 
&& item
->IsSizer()) 
 916             wxSizerItem 
*subitem 
= item
->GetSizer()->GetItem( window
, true ); 
 921         node 
= node
->GetNext(); 
 927 wxSizerItem
* wxSizer::GetItem( wxSizer 
*sizer
, bool recursive 
) 
 929     wxASSERT_MSG( sizer
, _T("GetItem for NULL sizer") ); 
 931     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 934         wxSizerItem 
*item 
= node
->GetData(); 
 936         if (item
->GetSizer() == sizer
) 
 940         else if (recursive 
&& item
->IsSizer()) 
 942             wxSizerItem 
*subitem 
= item
->GetSizer()->GetItem( sizer
, true ); 
 947         node 
= node
->GetNext(); 
 953 wxSizerItem
* wxSizer::GetItem( size_t index 
) 
 955     wxCHECK_MSG( index 
< m_children
.GetCount(), 
 957                  _T("GetItem index is out of range") ); 
 959     return m_children
.Item( index 
)->GetData(); 
 962 bool wxSizer::Show( wxWindow 
*window
, bool show
, bool recursive 
) 
 964     wxSizerItem 
*item 
= GetItem( window
, recursive 
); 
 975 bool wxSizer::Show( wxSizer 
*sizer
, bool show
, bool recursive 
) 
 977     wxSizerItem 
*item 
= GetItem( sizer
, recursive 
); 
 988 bool wxSizer::Show( size_t index
, bool show
) 
 990     wxSizerItem 
*item 
= GetItem( index 
); 
1001 void wxSizer::ShowItems( bool show 
) 
1003     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1006         node
->GetData()->Show( show 
); 
1007         node 
= node
->GetNext(); 
1011 bool wxSizer::IsShown( wxWindow 
*window 
) const 
1013     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1016         wxSizerItem     
*item 
= node
->GetData(); 
1018         if (item
->GetWindow() == window
) 
1020             return item
->IsShown(); 
1022         node 
= node
->GetNext(); 
1025     wxFAIL_MSG( _T("IsShown failed to find sizer item") ); 
1030 bool wxSizer::IsShown( wxSizer 
*sizer 
) const 
1032     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1035         wxSizerItem     
*item 
= node
->GetData(); 
1037         if (item
->GetSizer() == sizer
) 
1039             return item
->IsShown(); 
1041         node 
= node
->GetNext(); 
1044     wxFAIL_MSG( _T("IsShown failed to find sizer item") ); 
1049 bool wxSizer::IsShown( size_t index 
) const 
1051     wxCHECK_MSG( index 
< m_children
.GetCount(), 
1053                  _T("IsShown index is out of range") ); 
1055     return m_children
.Item( index 
)->GetData()->IsShown(); 
1059 //--------------------------------------------------------------------------- 
1061 //--------------------------------------------------------------------------- 
1063 wxGridSizer::wxGridSizer( int rows
, int cols
, int vgap
, int hgap 
) 
1064     : m_rows( ( cols 
== 0 && rows 
== 0 ) ? 1 : rows 
) 
1071 wxGridSizer::wxGridSizer( int cols
, int vgap
, int hgap 
) 
1072     : m_rows( cols 
== 0 ? 1 : 0 ) 
1079 int wxGridSizer::CalcRowsCols(int& nrows
, int& ncols
) const 
1081     int nitems 
= m_children
.GetCount(); 
1087             nrows 
= (nitems 
+ m_cols 
- 1) / m_cols
; 
1091             ncols 
= (nitems 
+ m_rows 
- 1) / m_rows
; 
1094         else // 0 columns, 0 rows? 
1096             wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") ); 
1105 void wxGridSizer::RecalcSizes() 
1107     int nitems
, nrows
, ncols
; 
1108     if ( (nitems 
= CalcRowsCols(nrows
, ncols
)) == 0 ) 
1111     wxSize 
sz( GetSize() ); 
1112     wxPoint 
pt( GetPosition() ); 
1114     int w 
= (sz
.x 
- (ncols 
- 1) * m_hgap
) / ncols
; 
1115     int h 
= (sz
.y 
- (nrows 
- 1) * m_vgap
) / nrows
; 
1118     for (int c 
= 0; c 
< ncols
; c
++) 
1121         for (int r 
= 0; r 
< nrows
; r
++) 
1123             int i 
= r 
* ncols 
+ c
; 
1126                 wxSizerItemList::compatibility_iterator node 
= m_children
.Item( i 
); 
1128                 wxASSERT_MSG( node
, _T("Failed to find SizerItemList node") ); 
1130                 SetItemBounds( node
->GetData(), x
, y
, w
, h
); 
1138 wxSize 
wxGridSizer::CalcMin() 
1141     if ( CalcRowsCols(nrows
, ncols
) == 0 ) 
1142         return wxSize(10, 10); 
1144     // Find the max width and height for any component 
1148     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1151         wxSizerItem     
*item 
= node
->GetData(); 
1152         wxSize           
sz( item
->CalcMin() ); 
1154         w 
= wxMax( w
, sz
.x 
); 
1155         h 
= wxMax( h
, sz
.y 
); 
1157         node 
= node
->GetNext(); 
1160     return wxSize( ncols 
* w 
+ (ncols
-1) * m_hgap
, 
1161                    nrows 
* h 
+ (nrows
-1) * m_vgap 
); 
1164 void wxGridSizer::SetItemBounds( wxSizerItem 
*item
, int x
, int y
, int w
, int h 
) 
1167     wxSize 
sz( item
->GetMinSizeWithBorder() ); 
1168     int flag 
= item
->GetFlag(); 
1170     if ((flag 
& wxEXPAND
) || (flag 
& wxSHAPED
)) 
1176         if (flag 
& wxALIGN_CENTER_HORIZONTAL
) 
1178             pt
.x 
= x 
+ (w 
- sz
.x
) / 2; 
1180         else if (flag 
& wxALIGN_RIGHT
) 
1182             pt
.x 
= x 
+ (w 
- sz
.x
); 
1185         if (flag 
& wxALIGN_CENTER_VERTICAL
) 
1187             pt
.y 
= y 
+ (h 
- sz
.y
) / 2; 
1189         else if (flag 
& wxALIGN_BOTTOM
) 
1191             pt
.y 
= y 
+ (h 
- sz
.y
); 
1195     item
->SetDimension(pt
, sz
); 
1198 //--------------------------------------------------------------------------- 
1200 //--------------------------------------------------------------------------- 
1202 wxFlexGridSizer::wxFlexGridSizer( int rows
, int cols
, int vgap
, int hgap 
) 
1203                : wxGridSizer( rows
, cols
, vgap
, hgap 
), 
1204                  m_flexDirection(wxBOTH
), 
1205                  m_growMode(wxFLEX_GROWMODE_SPECIFIED
) 
1209 wxFlexGridSizer::wxFlexGridSizer( int cols
, int vgap
, int hgap 
) 
1210                : wxGridSizer( cols
, vgap
, hgap 
), 
1211                  m_flexDirection(wxBOTH
), 
1212                  m_growMode(wxFLEX_GROWMODE_SPECIFIED
) 
1216 wxFlexGridSizer::~wxFlexGridSizer() 
1220 void wxFlexGridSizer::RecalcSizes() 
1222     int nitems
, nrows
, ncols
; 
1223     if ( (nitems 
= CalcRowsCols(nrows
, ncols
)) == 0 ) 
1226     wxPoint 
pt( GetPosition() ); 
1227     wxSize 
sz( GetSize() ); 
1229     AdjustForGrowables(sz
, m_calculatedMinSize
, nrows
, ncols
); 
1231     sz 
= wxSize( pt
.x 
+ sz
.x
, pt
.y 
+ sz
.y 
); 
1234     for (int c 
= 0; c 
< ncols
; c
++) 
1237         for (int r 
= 0; r 
< nrows
; r
++) 
1239             int i 
= r 
* ncols 
+ c
; 
1242                 wxSizerItemList::compatibility_iterator node 
= m_children
.Item( i 
); 
1244                 wxASSERT_MSG( node
, _T("Failed to find node") ); 
1246                 int w 
= wxMax( 0, wxMin( m_colWidths
[c
], sz
.x 
- x 
) ); 
1247                 int h 
= wxMax( 0, wxMin( m_rowHeights
[r
], sz
.y 
- y 
) ); 
1249                 SetItemBounds( node
->GetData(), x
, y
, w
, h
); 
1251             if (m_rowHeights
[r
] != -1) 
1252                 y 
= y 
+ m_rowHeights
[r
] + m_vgap
; 
1254         if (m_colWidths
[c
] != -1) 
1255             x 
= x 
+ m_colWidths
[c
] + m_hgap
; 
1259 wxSize 
wxFlexGridSizer::CalcMin() 
1265     // Number of rows/columns can change as items are added or removed. 
1266     if ( !CalcRowsCols(nrows
, ncols
) ) 
1267         return wxSize(10, 10); 
1269     m_rowHeights
.SetCount(nrows
); 
1270     m_colWidths
.SetCount(ncols
); 
1272     // We have to recalcuate the sizes in case the item minimum size has 
1273     // changed since the previous layout, or the item has been hidden using 
1274     // wxSizer::Show(). If all the items in a row/column are hidden, the final 
1275     // dimension of the row/column will be -1, indicating that the column 
1276     // itself is hidden. 
1277     for( s 
= m_rowHeights
.GetCount(), i 
= 0; i 
< s
; ++i 
) 
1278         m_rowHeights
[ i 
] = -1; 
1279     for( s 
= m_colWidths
.GetCount(), i 
= 0; i 
< s
; ++i 
) 
1280         m_colWidths
[ i 
] = -1; 
1282     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1287         wxSizerItem    
*item 
= node
->GetData(); 
1288         if ( item
->IsShown() ) 
1290             wxSize 
sz( item
->CalcMin() ); 
1291             int row 
= i 
/ ncols
; 
1292             int col 
= i 
% ncols
; 
1294             m_rowHeights
[ row 
] = wxMax( wxMax( 0, sz
.y 
), m_rowHeights
[ row 
] ); 
1295             m_colWidths
[ col 
] = wxMax( wxMax( 0, sz
.x 
), m_colWidths
[ col 
] ); 
1298         node 
= node
->GetNext(); 
1302     AdjustForFlexDirection(); 
1304     // Sum total minimum size, including gaps between rows/columns. 
1305     // -1 is used as a magic number meaning empty column. 
1307     for (int col 
= 0; col 
< ncols
; col
++) 
1308         if ( m_colWidths
[ col 
] != -1 ) 
1309             width 
+= m_colWidths
[ col 
] + m_hgap
; 
1314     for (int row 
= 0; row 
< nrows
; row
++) 
1315         if ( m_rowHeights
[ row 
] != -1 ) 
1316             height 
+= m_rowHeights
[ row 
] + m_vgap
; 
1320     m_calculatedMinSize 
= wxSize( width
, height 
); 
1321     return m_calculatedMinSize
; 
1324 void wxFlexGridSizer::AdjustForFlexDirection() 
1326     // the logic in CalcMin works when we resize flexibly in both directions 
1327     // but maybe this is not the case 
1328     if ( m_flexDirection 
!= wxBOTH 
) 
1330         // select the array corresponding to the direction in which we do *not* 
1332         wxArrayInt
& array 
= m_flexDirection 
== wxVERTICAL 
? m_colWidths
 
1335         const size_t count 
= array
.GetCount(); 
1337         // find the largest value in this array 
1341         for ( n 
= 0; n 
< count
; ++n 
) 
1343             if ( array
[n
] > largest 
) 
1347         // and now fill it with the largest value 
1348         for ( n 
= 0; n 
< count
; ++n 
) 
1356 void wxFlexGridSizer::AdjustForGrowables(const wxSize
& sz
, const wxSize
& minsz
, 
1357                                          int nrows
, int ncols
) 
1359     // what to do with the rows? by default, resize them proportionally 
1360     if ( sz
.y 
> minsz
.y 
&& ( (m_flexDirection 
& wxVERTICAL
) || (m_growMode 
== wxFLEX_GROWMODE_SPECIFIED
) ) ) 
1362         int sum_proportions 
= 0; 
1363         int growable_space 
= 0; 
1366         for (idx 
= 0; idx 
< m_growableRows
.GetCount(); idx
++) 
1368             // Since the number of rows/columns can change as items are 
1369             // inserted/deleted, we need to verify at runtime that the 
1370             // requested growable rows/columns are still valid. 
1371             if (m_growableRows
[idx
] >= nrows
) 
1374             // If all items in a row/column are hidden, that row/column will 
1375             // have a dimension of -1.  This causes the row/column to be 
1376             // hidden completely. 
1377             if (m_rowHeights
[ m_growableRows
[idx
] ] == -1) 
1379             sum_proportions 
+= m_growableRowsProportions
[idx
]; 
1380             growable_space 
+= m_rowHeights
[ m_growableRows
[idx
] ]; 
1386             for (idx 
= 0; idx 
< m_growableRows
.GetCount(); idx
++) 
1388                 if (m_growableRows
[idx
] >= nrows 
) 
1390                 if (m_rowHeights
[ m_growableRows
[idx
] ] == -1) 
1391                     m_rowHeights
[ m_growableRows
[idx
] ] = 0; 
1394                     int delta 
= (sz
.y 
- minsz
.y
); 
1395                     if (sum_proportions 
== 0) 
1396                         delta 
= (delta
/num
) + m_rowHeights
[ m_growableRows
[idx
] ]; 
1398                         delta 
= ((delta
+growable_space
)*m_growableRowsProportions
[idx
]) / sum_proportions
; 
1399                     m_rowHeights
[ m_growableRows
[idx
] ] = delta
; 
1404     else if ( (m_growMode 
== wxFLEX_GROWMODE_ALL
) && (sz
.y 
> minsz
.y
) ) 
1406         // rounding problem? 
1407         for ( int row 
= 0; row 
< nrows
; ++row 
) 
1408             m_rowHeights
[ row 
] = sz
.y 
/ nrows
; 
1411     // the same logic as above but for the columns 
1412     if ( sz
.x 
> minsz
.x 
&& ( (m_flexDirection 
& wxHORIZONTAL
) || (m_growMode 
== wxFLEX_GROWMODE_SPECIFIED
) ) ) 
1414         int sum_proportions 
= 0; 
1415         int growable_space 
= 0; 
1418         for (idx 
= 0; idx 
< m_growableCols
.GetCount(); idx
++) 
1420             // Since the number of rows/columns can change as items are 
1421             // inserted/deleted, we need to verify at runtime that the 
1422             // requested growable rows/columns are still valid. 
1423             if (m_growableCols
[idx
] >= ncols
) 
1426             // If all items in a row/column are hidden, that row/column will 
1427             // have a dimension of -1.  This causes the column to be hidden 
1429             if (m_colWidths
[ m_growableCols
[idx
] ] == -1) 
1431             sum_proportions 
+= m_growableColsProportions
[idx
]; 
1432             growable_space 
+= m_colWidths
[ m_growableCols
[idx
] ]; 
1438             for (idx 
= 0; idx 
< m_growableCols
.GetCount(); idx
++) 
1440                 if (m_growableCols
[idx
] >= ncols 
) 
1442                 if (m_colWidths
[ m_growableCols
[idx
] ] == -1) 
1443                     m_colWidths
[ m_growableCols
[idx
] ] = 0; 
1446                     int delta 
= (sz
.x 
- minsz
.x
); 
1447                     if (sum_proportions 
== 0) 
1448                         delta 
= (delta
/num
) + m_colWidths
[ m_growableCols
[idx
] ]; 
1450                         delta 
= ((delta
+growable_space
)*m_growableColsProportions
[idx
])/sum_proportions
; 
1451                     m_colWidths
[ m_growableCols
[idx
] ] = delta
; 
1456     else if ( (m_growMode 
== wxFLEX_GROWMODE_ALL
) && (sz
.x 
> minsz
.x
) ) 
1458         for ( int col
=0; col 
< ncols
; ++col 
) 
1459             m_colWidths
[ col 
] = sz
.x 
/ ncols
; 
1464 void wxFlexGridSizer::AddGrowableRow( size_t idx
, int proportion 
) 
1466     m_growableRows
.Add( idx 
); 
1467     m_growableRowsProportions
.Add( proportion 
); 
1470 void wxFlexGridSizer::RemoveGrowableRow( size_t idx 
) 
1472     m_growableRows
.Remove( idx 
); 
1475 void wxFlexGridSizer::AddGrowableCol( size_t idx
, int proportion 
) 
1477     m_growableCols
.Add( idx 
); 
1478     m_growableColsProportions
.Add( proportion 
); 
1481 void wxFlexGridSizer::RemoveGrowableCol( size_t idx 
) 
1483     m_growableCols
.Remove( idx 
); 
1486 //--------------------------------------------------------------------------- 
1488 //--------------------------------------------------------------------------- 
1490 wxBoxSizer::wxBoxSizer( int orient 
) 
1491     : m_orient( orient 
) 
1495 void wxBoxSizer::RecalcSizes() 
1497     if (m_children
.GetCount() == 0) 
1503         if (m_orient 
== wxHORIZONTAL
) 
1504             delta 
= m_size
.x 
- m_fixedWidth
; 
1506             delta 
= m_size
.y 
- m_fixedHeight
; 
1509     wxPoint 
pt( m_position 
); 
1511     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1514         wxSizerItem     
*item 
= node
->GetData(); 
1516         if (item
->IsShown()) 
1518             wxSize 
size( item
->GetMinSizeWithBorder() ); 
1520             if (m_orient 
== wxVERTICAL
) 
1522                 wxCoord height 
= size
.y
; 
1523                 if (item
->GetProportion()) 
1525                     // Because of at least one visible item has non-zero 
1526                     // proportion then m_stretchable is not zero 
1527                     height 
= (delta 
* item
->GetProportion()) / m_stretchable
; 
1530                 wxPoint 
child_pos( pt 
); 
1531                 wxSize  
child_size( size
.x
, height 
); 
1533                 if (item
->GetFlag() & (wxEXPAND 
| wxSHAPED
)) 
1534                     child_size
.x 
= m_size
.x
; 
1535                 else if (item
->GetFlag() & wxALIGN_RIGHT
) 
1536                     child_pos
.x 
+= m_size
.x 
- size
.x
; 
1537                 else if (item
->GetFlag() & (wxCENTER 
| wxALIGN_CENTER_HORIZONTAL
)) 
1538                 // XXX wxCENTER is added for backward compatibility; 
1539                 //     wxALIGN_CENTER should be used in new code 
1540                     child_pos
.x 
+= (m_size
.x 
- size
.x
) / 2; 
1542                 item
->SetDimension( child_pos
, child_size 
); 
1548                 wxCoord width 
= size
.x
; 
1549                 if (item
->GetProportion()) 
1551                     // Because of at least one visible item has non-zero 
1552                     // proportion then m_stretchable is not zero 
1553                     width 
= (delta 
* item
->GetProportion()) / m_stretchable
; 
1556                 wxPoint 
child_pos( pt 
); 
1557                 wxSize  
child_size( width
, size
.y 
); 
1559                 if (item
->GetFlag() & (wxEXPAND 
| wxSHAPED
)) 
1560                     child_size
.y 
= m_size
.y
; 
1561                 else if (item
->GetFlag() & wxALIGN_BOTTOM
) 
1562                     child_pos
.y 
+= m_size
.y 
- size
.y
; 
1563                 else if (item
->GetFlag() & (wxCENTER 
| wxALIGN_CENTER_VERTICAL
)) 
1564                 // XXX wxCENTER is added for backward compatibility; 
1565                 //     wxALIGN_CENTER should be used in new code 
1566                     child_pos
.y 
+= (m_size
.y 
- size
.y
) / 2; 
1568                 item
->SetDimension( child_pos
, child_size 
); 
1574         node 
= node
->GetNext(); 
1578 wxSize 
wxBoxSizer::CalcMin() 
1580     if (m_children
.GetCount() == 0) 
1581         return wxSize(10,10); 
1589     // precalc item minsizes and count proportions 
1590     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1593         wxSizerItem 
*item 
= node
->GetData(); 
1595         if ( item
->IsShown() ) 
1597             item
->CalcMin();  // result is stored in the item 
1599             m_stretchable 
+= item
->GetProportion(); 
1602         node 
= node
->GetNext(); 
1605     // Total minimum size (width or height) of sizer 
1608     node 
= m_children
.GetFirst(); 
1611         wxSizerItem 
*item 
= node
->GetData(); 
1613         if (item
->IsShown() && item
->GetProportion() != 0) 
1615             int stretch 
= item
->GetProportion(); 
1616             wxSize 
size( item
->GetMinSizeWithBorder() ); 
1619             // Integer division rounded up is (a + b - 1) / b 
1620             // Round up needed in order to guarantee that all 
1621             // all items will have size not less then their min size 
1622             if (m_orient 
== wxHORIZONTAL
) 
1623                 minSize 
= ( size
.x
*m_stretchable 
+ stretch 
- 1)/stretch
; 
1625                 minSize 
= ( size
.y
*m_stretchable 
+ stretch 
- 1)/stretch
; 
1627             if (minSize 
> maxMinSize
) 
1628                 maxMinSize 
= minSize
; 
1630         node 
= node
->GetNext(); 
1633     // Calculate overall minimum size 
1634     node 
= m_children
.GetFirst(); 
1637         wxSizerItem 
*item 
= node
->GetData(); 
1639         if (item
->IsShown()) 
1641             wxSize 
size( item
->GetMinSizeWithBorder() ); 
1642             if (item
->GetProportion() != 0) 
1644                 if (m_orient 
== wxHORIZONTAL
) 
1645                     size
.x 
= (maxMinSize
*item
->GetProportion())/m_stretchable
; 
1647                     size
.y 
= (maxMinSize
*item
->GetProportion())/m_stretchable
; 
1651                 if (m_orient 
== wxVERTICAL
) 
1653                     m_fixedHeight 
+= size
.y
; 
1654                     m_fixedWidth 
= wxMax( m_fixedWidth
, size
.x 
); 
1658                     m_fixedWidth 
+= size
.x
; 
1659                     m_fixedHeight 
= wxMax( m_fixedHeight
, size
.y 
); 
1663             if (m_orient 
== wxHORIZONTAL
) 
1665                 m_minWidth 
+= size
.x
; 
1666                 m_minHeight 
= wxMax( m_minHeight
, size
.y 
); 
1670                 m_minHeight 
+= size
.y
; 
1671                 m_minWidth 
= wxMax( m_minWidth
, size
.x 
); 
1674         node 
= node
->GetNext(); 
1677     return wxSize( m_minWidth
, m_minHeight 
); 
1680 //--------------------------------------------------------------------------- 
1682 //--------------------------------------------------------------------------- 
1686 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox 
*box
, int orient 
) 
1687     : wxBoxSizer( orient 
) 
1688     , m_staticBox( box 
) 
1690     wxASSERT_MSG( box
, wxT("wxStaticBoxSizer needs a static box") ); 
1693 wxStaticBoxSizer::wxStaticBoxSizer(int orient
, wxWindow 
*win
, const wxString
& s
) 
1694                 : wxBoxSizer(orient
), 
1695                   m_staticBox(new wxStaticBox(win
, wxID_ANY
, s
)) 
1699 static void GetStaticBoxBorders( wxStaticBox 
*box
, 
1703     // this has to be done platform by platform as there is no way to 
1704     // guess the thickness of a wxStaticBox border 
1705     box
->GetBordersForSizer(borderTop
, borderOther
); 
1708 void wxStaticBoxSizer::RecalcSizes() 
1710     int top_border
, other_border
; 
1711     GetStaticBoxBorders(m_staticBox
, &top_border
, &other_border
); 
1713     m_staticBox
->SetSize( m_position
.x
, m_position
.y
, m_size
.x
, m_size
.y 
); 
1715     wxPoint 
old_pos( m_position 
); 
1716     m_position
.x 
+= other_border
; 
1717     m_position
.y 
+= top_border
; 
1718     wxSize 
old_size( m_size 
); 
1719     m_size
.x 
-= 2*other_border
; 
1720     m_size
.y 
-= top_border 
+ other_border
; 
1722     wxBoxSizer::RecalcSizes(); 
1724     m_position 
= old_pos
; 
1728 wxSize 
wxStaticBoxSizer::CalcMin() 
1730     int top_border
, other_border
; 
1731     GetStaticBoxBorders(m_staticBox
, &top_border
, &other_border
); 
1733     wxSize 
ret( wxBoxSizer::CalcMin() ); 
1734     ret
.x 
+= 2*other_border
; 
1735     ret
.y 
+= other_border 
+ top_border
; 
1740 void wxStaticBoxSizer::ShowItems( bool show 
) 
1742     m_staticBox
->Show( show 
); 
1743     wxBoxSizer::ShowItems( show 
); 
1746 #endif // wxUSE_STATBOX 
1750 wxStdDialogButtonSizer::wxStdDialogButtonSizer() 
1751     : wxBoxSizer(wxHORIZONTAL
) 
1753     // Vertical buttons with lots of space on either side 
1754     // looks rubbish on WinCE, so let's not do this for now. 
1755     // If we are going to use vertical buttons, we should 
1756     // put the sizer to the right of other controls in the dialog, 
1757     // and that's beyond the scope of this sizer. 
1759     bool is_pda 
= (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA
); 
1760     // If we have a PDA screen, put yes/no button over 
1761     // all other buttons, otherwise on the left side. 
1763         m_orient 
= wxVERTICAL
; 
1766     m_buttonAffirmative 
= NULL
; 
1767     m_buttonApply 
= NULL
; 
1768     m_buttonNegative 
= NULL
; 
1769     m_buttonCancel 
= NULL
; 
1770     m_buttonHelp 
= NULL
; 
1773 void wxStdDialogButtonSizer::AddButton(wxButton 
*mybutton
) 
1775     switch (mybutton
->GetId()) 
1780             m_buttonAffirmative 
= mybutton
; 
1783             m_buttonApply 
= mybutton
; 
1786             m_buttonNegative 
= mybutton
; 
1789             m_buttonCancel 
= mybutton
; 
1792         case wxID_CONTEXT_HELP
: 
1793             m_buttonHelp 
= mybutton
; 
1800 void wxStdDialogButtonSizer::SetAffirmativeButton( wxButton 
*button 
) 
1802     m_buttonAffirmative 
= button
; 
1805 void wxStdDialogButtonSizer::SetNegativeButton( wxButton 
*button 
) 
1807     m_buttonNegative 
= button
; 
1810 void wxStdDialogButtonSizer::SetCancelButton( wxButton 
*button 
) 
1812     m_buttonCancel 
= button
; 
1815 void wxStdDialogButtonSizer::Realize() 
1818         Add(0, 0, 0, wxLEFT
, 6); 
1820             Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 6); 
1822         if (m_buttonNegative
){ 
1823             // HIG POLICE BULLETIN - destructive buttons need extra padding 
1824             // 24 pixels on either side 
1825             Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 12); 
1828         // extra whitespace between help/negative and cancel/ok buttons 
1829         Add(0, 0, 1, wxEXPAND
, 0); 
1831         if (m_buttonCancel
){ 
1832             Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 6); 
1833             // Cancel or help should be default 
1834             // m_buttonCancel->SetDefaultButton(); 
1837         // Ugh, Mac doesn't really have apply dialogs, so I'll just 
1838         // figure the best place is between Cancel and OK 
1840             Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 6); 
1842         if (m_buttonAffirmative
){ 
1843             Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE 
| wxLEFT
, 6); 
1845             if (m_buttonAffirmative
->GetId() == wxID_SAVE
){ 
1846                 // these buttons have set labels under Mac so we should use them 
1847                 m_buttonAffirmative
->SetLabel(_("Save")); 
1848                 m_buttonNegative
->SetLabel(_("Don't Save")); 
1852         // Extra space around and at the right 
1854 #elif defined(__WXGTK20__) 
1855         Add(0, 0, 0, wxLEFT
, 9); 
1857             Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 3); 
1859         // extra whitespace between help and cancel/ok buttons 
1860         Add(0, 0, 1, wxEXPAND
, 0); 
1862         if (m_buttonNegative
){ 
1863             Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 3); 
1866         if (m_buttonCancel
){ 
1867             Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 3); 
1868             // Cancel or help should be default 
1869             // m_buttonCancel->SetDefaultButton(); 
1873             Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 3); 
1875         if (m_buttonAffirmative
) 
1876             Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE 
| wxLEFT
, 6); 
1877 #elif defined(__WXMSW__) 
1880         // right-justify buttons 
1881         Add(0, 0, 1, wxEXPAND
, 0); 
1883         if (m_buttonAffirmative
){ 
1884             Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonAffirmative
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
1887         if (m_buttonNegative
){ 
1888             Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonNegative
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
1891         if (m_buttonCancel
){ 
1892             Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonCancel
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
1895             Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonApply
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
1898             Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonHelp
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
1900         // GTK+1 and any other platform 
1902         // Add(0, 0, 0, wxLEFT, 5); // Not sure what this was for but it unbalances the dialog 
1904             Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonHelp
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
1906         // extra whitespace between help and cancel/ok buttons 
1907         Add(0, 0, 1, wxEXPAND
, 0); 
1910             Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonApply
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
1912         if (m_buttonAffirmative
){ 
1913             Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonAffirmative
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
1916         if (m_buttonNegative
){ 
1917             Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonNegative
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
1920         if (m_buttonCancel
){ 
1921             Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonCancel
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
1922             // Cancel or help should be default 
1923             // m_buttonCancel->SetDefaultButton(); 
1929 #endif // wxUSE_BUTTON 
1931 #if WXWIN_COMPATIBILITY_2_4 
1933 // ---------------------------------------------------------------------------- 
1935 // ---------------------------------------------------------------------------- 
1938 IMPLEMENT_CLASS(wxBookCtrlSizer
, wxSizer
) 
1940 IMPLEMENT_CLASS(wxNotebookSizer
, wxBookCtrlSizer
) 
1941 #endif // wxUSE_NOTEBOOK 
1942 #endif // wxUSE_BOOKCTRL 
1946 wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrlBase 
*bookctrl
) 
1947                : m_bookctrl(bookctrl
) 
1949     wxASSERT_MSG( bookctrl
, wxT("wxBookCtrlSizer needs a control") ); 
1952 void wxBookCtrlSizer::RecalcSizes() 
1954     m_bookctrl
->SetSize( m_position
.x
, m_position
.y
, m_size
.x
, m_size
.y 
); 
1957 wxSize 
wxBookCtrlSizer::CalcMin() 
1959     wxSize sizeBorder 
= m_bookctrl
->CalcSizeFromPage(wxSize(0,0)); 
1964     if ( m_bookctrl
->GetPageCount() == 0 ) 
1966         return wxSize(sizeBorder
.x 
+ 10, sizeBorder
.y 
+ 10); 
1972     wxWindowList::compatibility_iterator
 
1973         node 
= m_bookctrl
->GetChildren().GetFirst(); 
1976         wxWindow 
*item 
= node
->GetData(); 
1977         wxSizer 
*itemsizer 
= item
->GetSizer(); 
1981             wxSize 
subsize( itemsizer
->CalcMin() ); 
1983             if (subsize
.x 
> maxX
) 
1985             if (subsize
.y 
> maxY
) 
1989         node 
= node
->GetNext(); 
1992     return wxSize( maxX
, maxY 
) + sizeBorder
; 
1997 wxNotebookSizer::wxNotebookSizer(wxNotebook 
*nb
) 
1999     wxASSERT_MSG( nb
, wxT("wxNotebookSizer needs a control") ); 
2003 #endif // wxUSE_NOTEBOOOK 
2004 #endif // wxUSE_BOOKCTRL 
2006 #endif // WXWIN_COMPATIBILITY_2_4