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" 
  25     #include "wx/string.h" 
  31 #include "wx/statbox.h" 
  32 #include "wx/settings.h" 
  33 #include "wx/listimpl.cpp" 
  35 #if WXWIN_COMPATIBILITY_2_4 
  36     #include "wx/notebook.h" 
  39 //--------------------------------------------------------------------------- 
  41 IMPLEMENT_CLASS(wxSizerItem
, wxObject
) 
  42 IMPLEMENT_CLASS(wxSizer
, wxObject
) 
  43 IMPLEMENT_CLASS(wxGridSizer
, wxSizer
) 
  44 IMPLEMENT_CLASS(wxFlexGridSizer
, wxGridSizer
) 
  45 IMPLEMENT_CLASS(wxBoxSizer
, wxSizer
) 
  47 IMPLEMENT_CLASS(wxStaticBoxSizer
, wxBoxSizer
) 
  50 IMPLEMENT_CLASS(wxStdDialogButtonSizer
, wxBoxSizer
) 
  53 WX_DEFINE_EXPORTED_LIST( wxSizerItemList 
); 
  88 // ---------------------------------------------------------------------------- 
  90 // ---------------------------------------------------------------------------- 
  92 void wxSizerItem::Init(const wxSizerFlags
& flags
) 
  96     m_proportion 
= flags
.GetProportion(); 
  97     m_flag 
= flags
.GetFlags(); 
  98     m_border 
= flags
.GetBorderInPixels(); 
 101 wxSizerItem::wxSizerItem() 
 113 void wxSizerItem::SetWindow(wxWindow 
*window
) 
 115     wxCHECK_RET( window
, _T("NULL window in wxSizerItem::SetWindow()") ); 
 117     m_kind 
= Item_Window
; 
 120     // window doesn't become smaller than its initial size, whatever happens 
 121     m_minSize 
= window
->GetSize(); 
 123     if ( m_flag 
& wxFIXED_MINSIZE 
) 
 124         window
->SetMinSize(m_minSize
); 
 126     // aspect ratio calculated from initial size 
 130 wxSizerItem::wxSizerItem(wxWindow 
*window
, 
 135            : m_proportion(proportion
), 
 144 void wxSizerItem::SetSizer(wxSizer 
*sizer
) 
 150 wxSizerItem::wxSizerItem(wxSizer 
*sizer
, 
 155            : m_proportion(proportion
), 
 163     // m_minSize is set later 
 167 void wxSizerItem::SetSpacer(const wxSize
& size
) 
 169     m_kind 
= Item_Spacer
; 
 170     m_spacer 
= new wxSizerSpacer(size
); 
 175 wxSizerItem::wxSizerItem(int width
, 
 181            : m_minSize(width
, height
), // minimal size is the initial size 
 182              m_proportion(proportion
), 
 187     SetSpacer(width
, height
); 
 190 wxSizerItem::~wxSizerItem() 
 200             m_window
->SetContainingSizer(NULL
); 
 213             wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); 
 217 wxSize 
wxSizerItem::GetSpacer() const 
 220     if ( m_kind 
== Item_Spacer 
) 
 221         size 
= m_spacer
->GetSize(); 
 227 wxSize 
wxSizerItem::GetSize() const 
 236             ret 
= m_window
->GetSize(); 
 240             ret 
= m_sizer
->GetSize(); 
 244             ret 
= m_spacer
->GetSize(); 
 249             wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); 
 256     if (m_flag 
& wxNORTH
) 
 258     if (m_flag 
& wxSOUTH
) 
 264 wxSize 
wxSizerItem::CalcMin() 
 268         m_minSize 
= m_sizer
->GetMinSize(); 
 270         // if we have to preserve aspect ratio _AND_ this is 
 271         // the first-time calculation, consider ret to be initial size 
 272         if ((m_flag 
& wxSHAPED
) && !m_ratio
) 
 275     else if ( IsWindow() ) 
 277         // Since the size of the window may change during runtime, we 
 278         // should use the current minimal/best size. 
 279         m_minSize 
= m_window
->GetBestFittingSize(); 
 282     return GetMinSizeWithBorder(); 
 285 wxSize 
wxSizerItem::GetMinSizeWithBorder() const 
 287     wxSize ret 
= m_minSize
; 
 293     if (m_flag 
& wxNORTH
) 
 295     if (m_flag 
& wxSOUTH
) 
 302 void wxSizerItem::SetDimension( wxPoint pos
, wxSize size 
) 
 304     if (m_flag 
& wxSHAPED
) 
 306         // adjust aspect ratio 
 307         int rwidth 
= (int) (size
.y 
* m_ratio
); 
 311             int rheight 
= (int) (size
.x 
/ m_ratio
); 
 312             // add vertical space 
 313             if (m_flag 
& wxALIGN_CENTER_VERTICAL
) 
 314                 pos
.y 
+= (size
.y 
- rheight
) / 2; 
 315             else if (m_flag 
& wxALIGN_BOTTOM
) 
 316                 pos
.y 
+= (size
.y 
- rheight
); 
 317             // use reduced dimensions 
 320         else if (rwidth 
< size
.x
) 
 322             // add horizontal space 
 323             if (m_flag 
& wxALIGN_CENTER_HORIZONTAL
) 
 324                 pos
.x 
+= (size
.x 
- rwidth
) / 2; 
 325             else if (m_flag 
& wxALIGN_RIGHT
) 
 326                 pos
.x 
+= (size
.x 
- rwidth
); 
 331     // This is what GetPosition() returns. Since we calculate 
 332     // borders afterwards, GetPosition() will be the left/top 
 333     // corner of the surrounding border. 
 345     if (m_flag 
& wxNORTH
) 
 350     if (m_flag 
& wxSOUTH
) 
 355     m_rect 
= wxRect(pos
, size
); 
 360             wxFAIL_MSG( _T("can't set size of uninitialized sizer item") ); 
 364             m_window
->SetSize(pos
.x
, pos
.y
, size
.x
, size
.y
, 
 365                               wxSIZE_ALLOW_MINUS_ONE
); 
 369             m_sizer
->SetDimension(pos
.x
, pos
.y
, size
.x
, size
.y
); 
 373             m_spacer
->SetSize(size
); 
 378             wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); 
 382 void wxSizerItem::DeleteWindows() 
 391             //We are deleting the window from this sizer - normally 
 392             //the window destroys the sizer associated with it, 
 393             //which might destroy this, which we don't want 
 394             m_window
->SetContainingSizer(NULL
); 
 396             //Putting this after the switch will result in a spacer 
 397             //not being deleted properly on destruction 
 402             m_sizer
->DeleteWindows(); 
 407             wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); 
 412 void wxSizerItem::Show( bool show 
) 
 417             wxFAIL_MSG( _T("can't show uninitialized sizer item") ); 
 421             m_window
->Show(show
); 
 429             m_spacer
->Show(show
); 
 434             wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); 
 438 bool wxSizerItem::IsShown() const 
 443             // we may be called from CalcMin(), just return false so that we're 
 448             return m_window
->IsShown(); 
 451             return m_sizer
->IsShown(); 
 454             return m_spacer
->IsShown(); 
 458             wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); 
 464 void wxSizerItem::SetOption( int option 
) 
 466     SetProportion( option 
); 
 469 int wxSizerItem::GetOption() const 
 471     return GetProportion(); 
 475 //--------------------------------------------------------------------------- 
 477 //--------------------------------------------------------------------------- 
 486     WX_CLEAR_LIST(wxSizerItemList
, m_children
); 
 489 wxSizerItem
* wxSizer::Insert( size_t index
, wxSizerItem 
*item 
) 
 491     m_children
.Insert( index
, item 
); 
 493     if ( item
->GetWindow() ) 
 494         item
->GetWindow()->SetContainingSizer( this ); 
 499 bool wxSizer::Remove( wxWindow 
*window 
) 
 501     return Detach( window 
); 
 504 bool wxSizer::Remove( wxSizer 
*sizer 
) 
 506     wxASSERT_MSG( sizer
, _T("Removing NULL sizer") ); 
 508     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 511         wxSizerItem     
*item 
= node
->GetData(); 
 513         if (item
->GetSizer() == sizer
) 
 516             m_children
.Erase( node 
); 
 520         node 
= node
->GetNext(); 
 526 bool wxSizer::Remove( int index 
) 
 528     wxCHECK_MSG( index 
>= 0 && (size_t)index 
< m_children
.GetCount(), 
 530                  _T("Remove index is out of range") ); 
 532     wxSizerItemList::compatibility_iterator node 
= m_children
.Item( index 
); 
 534     wxCHECK_MSG( node
, false, _T("Failed to find child node") ); 
 536     wxSizerItem 
*item 
= node
->GetData(); 
 538     if ( item
->IsWindow() ) 
 539         item
->GetWindow()->SetContainingSizer( NULL 
); 
 542     m_children
.Erase( node 
); 
 546 bool wxSizer::Detach( wxSizer 
*sizer 
) 
 548     wxASSERT_MSG( sizer
, _T("Detaching NULL sizer") ); 
 550     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 553         wxSizerItem     
*item 
= node
->GetData(); 
 555         if (item
->GetSizer() == sizer
) 
 559             m_children
.Erase( node 
); 
 562         node 
= node
->GetNext(); 
 568 bool wxSizer::Detach( wxWindow 
*window 
) 
 570     wxASSERT_MSG( window
, _T("Detaching NULL window") ); 
 572     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 575         wxSizerItem     
*item 
= node
->GetData(); 
 577         if (item
->GetWindow() == window
) 
 579             item
->GetWindow()->SetContainingSizer( NULL 
); 
 581             m_children
.Erase( node 
); 
 584         node 
= node
->GetNext(); 
 590 bool wxSizer::Detach( int index 
) 
 592     wxCHECK_MSG( index 
>= 0 && (size_t)index 
< m_children
.GetCount(), 
 594                  _T("Detach index is out of range") ); 
 596     wxSizerItemList::compatibility_iterator node 
= m_children
.Item( index 
); 
 598     wxCHECK_MSG( node
, false, _T("Failed to find child node") ); 
 600     wxSizerItem 
*item 
= node
->GetData(); 
 602     if ( item
->IsSizer() ) 
 604     else if ( item
->IsWindow() ) 
 605         item
->GetWindow()->SetContainingSizer( NULL 
); 
 608     m_children
.Erase( node 
); 
 612 void wxSizer::Clear( bool delete_windows 
) 
 614     // First clear the ContainingSizer pointers 
 615     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 618         wxSizerItem     
*item 
= node
->GetData(); 
 620         if (item
->IsWindow()) 
 621             item
->GetWindow()->SetContainingSizer( NULL 
); 
 622         node 
= node
->GetNext(); 
 625     // Destroy the windows if needed 
 629     // Now empty the list 
 630     WX_CLEAR_LIST(wxSizerItemList
, m_children
); 
 633 void wxSizer::DeleteWindows() 
 635     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 638         wxSizerItem     
*item 
= node
->GetData(); 
 640         item
->DeleteWindows(); 
 641         node 
= node
->GetNext(); 
 645 wxSize 
wxSizer::Fit( wxWindow 
*window 
) 
 647     wxSize 
size(window
->IsTopLevel() ? FitSize(window
) 
 648                                      : GetMinWindowSize(window
)); 
 650     window
->SetSize( size 
); 
 655 void wxSizer::FitInside( wxWindow 
*window 
) 
 658     if (window
->IsTopLevel()) 
 659         size 
= VirtualFitSize( window 
); 
 661         size 
= GetMinClientSize( window 
); 
 663     window
->SetVirtualSize( size 
); 
 666 void wxSizer::Layout() 
 668     // (re)calculates minimums needed for each item and other preparations 
 672     // Applies the layout and repositions/resizes the items 
 676 void wxSizer::SetSizeHints( wxWindow 
*window 
) 
 678     // Preserve the window's max size hints, but set the 
 679     // lower bound according to the sizer calculations. 
 681     wxSize size 
= Fit( window 
); 
 683     window
->SetSizeHints( size
.x
, 
 685                           window
->GetMaxWidth(), 
 686                           window
->GetMaxHeight() ); 
 689 void wxSizer::SetVirtualSizeHints( wxWindow 
*window 
) 
 691     // Preserve the window's max size hints, but set the 
 692     // lower bound according to the sizer calculations. 
 695     wxSize 
size( window
->GetVirtualSize() ); 
 696     window
->SetVirtualSizeHints( size
.x
, 
 698                                  window
->GetMaxWidth(), 
 699                                  window
->GetMaxHeight() ); 
 702 wxSize 
wxSizer::GetMaxWindowSize( wxWindow 
*window 
) const 
 704     return window
->GetMaxSize(); 
 707 wxSize 
wxSizer::GetMinWindowSize( wxWindow 
*window 
) 
 709     wxSize      
minSize( GetMinSize() ); 
 710     wxSize      
size( window
->GetSize() ); 
 711     wxSize      
client_size( window
->GetClientSize() ); 
 713     return wxSize( minSize
.x
+size
.x
-client_size
.x
, 
 714                    minSize
.y
+size
.y
-client_size
.y 
); 
 717 // TODO on mac we need a function that determines how much free space this 
 718 // min size contains, in order to make sure that we have 20 pixels of free 
 719 // space around the controls 
 721 // Return a window size that will fit within the screens dimensions 
 722 wxSize 
wxSizer::FitSize( wxWindow 
*window 
) 
 724     wxSize size     
= GetMinWindowSize( window 
); 
 725     wxSize sizeMax  
= GetMaxWindowSize( window 
); 
 727     // Limit the size if sizeMax != wxDefaultSize 
 729     if ( size
.x 
> sizeMax
.x 
&& sizeMax
.x 
!= wxDefaultCoord 
) 
 731     if ( size
.y 
> sizeMax
.y 
&& sizeMax
.y 
!= wxDefaultCoord 
) 
 737 wxSize 
wxSizer::GetMaxClientSize( wxWindow 
*window 
) const 
 739     wxSize 
maxSize( window
->GetMaxSize() ); 
 741     if ( maxSize 
!= wxDefaultSize 
) 
 743         wxSize 
size( window
->GetSize() ); 
 744         wxSize 
client_size( window
->GetClientSize() ); 
 746         return wxSize( maxSize
.x 
+ client_size
.x 
- size
.x
, 
 747                        maxSize
.y 
+ client_size
.y 
- size
.y 
); 
 750         return wxDefaultSize
; 
 753 wxSize 
wxSizer::GetMinClientSize( wxWindow 
*WXUNUSED(window
) ) 
 755     return GetMinSize();  // Already returns client size. 
 758 wxSize 
wxSizer::VirtualFitSize( wxWindow 
*window 
) 
 760     wxSize size     
= GetMinClientSize( window 
); 
 761     wxSize sizeMax  
= GetMaxClientSize( window 
); 
 763     // Limit the size if sizeMax != wxDefaultSize 
 765     if ( size
.x 
> sizeMax
.x 
&& sizeMax
.x 
!= wxDefaultCoord 
) 
 767     if ( size
.y 
> sizeMax
.y 
&& sizeMax
.y 
!= wxDefaultCoord 
) 
 773 void wxSizer::SetDimension( int x
, int y
, int width
, int height 
) 
 782 wxSize 
wxSizer::GetMinSize() 
 784     wxSize 
ret( CalcMin() ); 
 785     if (ret
.x 
< m_minSize
.x
) ret
.x 
= m_minSize
.x
; 
 786     if (ret
.y 
< m_minSize
.y
) ret
.y 
= m_minSize
.y
; 
 790 void wxSizer::DoSetMinSize( int width
, int height 
) 
 793     m_minSize
.y 
= height
; 
 796 bool wxSizer::DoSetItemMinSize( wxWindow 
*window
, int width
, int height 
) 
 798     wxASSERT_MSG( window
, _T("SetMinSize for NULL window") ); 
 800     // Is it our immediate child? 
 802     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 805         wxSizerItem     
*item 
= node
->GetData(); 
 807         if (item
->GetWindow() == window
) 
 809             item
->SetMinSize( width
, height 
); 
 812         node 
= node
->GetNext(); 
 815     // No?  Search any subsizers we own then 
 817     node 
= m_children
.GetFirst(); 
 820         wxSizerItem     
*item 
= node
->GetData(); 
 822         if ( item
->GetSizer() && 
 823              item
->GetSizer()->DoSetItemMinSize( window
, width
, height 
) ) 
 825             // A child sizer found the requested windw, exit. 
 828         node 
= node
->GetNext(); 
 834 bool wxSizer::DoSetItemMinSize( wxSizer 
*sizer
, int width
, int height 
) 
 836     wxASSERT_MSG( sizer
, _T("SetMinSize for NULL sizer") ); 
 838     // Is it our immediate child? 
 840     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 843         wxSizerItem     
*item 
= node
->GetData(); 
 845         if (item
->GetSizer() == sizer
) 
 847             item
->GetSizer()->DoSetMinSize( width
, height 
); 
 850         node 
= node
->GetNext(); 
 853     // No?  Search any subsizers we own then 
 855     node 
= m_children
.GetFirst(); 
 858         wxSizerItem     
*item 
= node
->GetData(); 
 860         if ( item
->GetSizer() && 
 861              item
->GetSizer()->DoSetItemMinSize( sizer
, width
, height 
) ) 
 863             // A child found the requested sizer, exit. 
 866         node 
= node
->GetNext(); 
 872 bool wxSizer::DoSetItemMinSize( size_t index
, int width
, int height 
) 
 874     wxSizerItemList::compatibility_iterator node 
= m_children
.Item( index 
); 
 876     wxCHECK_MSG( node
, false, _T("Failed to find child node") ); 
 878     wxSizerItem     
*item 
= node
->GetData(); 
 880     if (item
->GetSizer()) 
 882         // Sizers contains the minimal size in them, if not calculated ... 
 883         item
->GetSizer()->DoSetMinSize( width
, height 
); 
 887         // ... but the minimal size of spacers and windows is stored via the item 
 888         item
->SetMinSize( width
, height 
); 
 894 wxSizerItem
* wxSizer::GetItem( wxWindow 
*window
, bool recursive 
) 
 896     wxASSERT_MSG( window
, _T("GetItem for NULL window") ); 
 898     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 901         wxSizerItem     
*item 
= node
->GetData(); 
 903         if (item
->GetWindow() == window
) 
 907         else if (recursive 
&& item
->IsSizer()) 
 909             wxSizerItem 
*subitem 
= item
->GetSizer()->GetItem( window
, true ); 
 914         node 
= node
->GetNext(); 
 920 wxSizerItem
* wxSizer::GetItem( wxSizer 
*sizer
, bool recursive 
) 
 922     wxASSERT_MSG( sizer
, _T("GetItem for NULL sizer") ); 
 924     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 927         wxSizerItem 
*item 
= node
->GetData(); 
 929         if (item
->GetSizer() == sizer
) 
 933         else if (recursive 
&& item
->IsSizer()) 
 935             wxSizerItem 
*subitem 
= item
->GetSizer()->GetItem( sizer
, true ); 
 940         node 
= node
->GetNext(); 
 946 wxSizerItem
* wxSizer::GetItem( size_t index 
) 
 948     wxCHECK_MSG( index 
< m_children
.GetCount(), 
 950                  _T("GetItem index is out of range") ); 
 952     return m_children
.Item( index 
)->GetData(); 
 955 bool wxSizer::Show( wxWindow 
*window
, bool show
, bool recursive 
) 
 957     wxSizerItem 
*item 
= GetItem( window
, recursive 
); 
 968 bool wxSizer::Show( wxSizer 
*sizer
, bool show
, bool recursive 
) 
 970     wxSizerItem 
*item 
= GetItem( sizer
, recursive 
); 
 981 bool wxSizer::Show( size_t index
, bool show
) 
 983     wxSizerItem 
*item 
= GetItem( index 
); 
 994 void wxSizer::ShowItems( bool show 
) 
 996     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 999         node
->GetData()->Show( show 
); 
1000         node 
= node
->GetNext(); 
1004 bool wxSizer::IsShown( wxWindow 
*window 
) const 
1006     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1009         wxSizerItem     
*item 
= node
->GetData(); 
1011         if (item
->GetWindow() == window
) 
1013             return item
->IsShown(); 
1015         node 
= node
->GetNext(); 
1018     wxFAIL_MSG( _T("IsShown failed to find sizer item") ); 
1023 bool wxSizer::IsShown( wxSizer 
*sizer 
) const 
1025     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1028         wxSizerItem     
*item 
= node
->GetData(); 
1030         if (item
->GetSizer() == sizer
) 
1032             return item
->IsShown(); 
1034         node 
= node
->GetNext(); 
1037     wxFAIL_MSG( _T("IsShown failed to find sizer item") ); 
1042 bool wxSizer::IsShown( size_t index 
) const 
1044     wxCHECK_MSG( index 
< m_children
.GetCount(), 
1046                  _T("IsShown index is out of range") ); 
1048     return m_children
.Item( index 
)->GetData()->IsShown(); 
1052 //--------------------------------------------------------------------------- 
1054 //--------------------------------------------------------------------------- 
1056 wxGridSizer::wxGridSizer( int rows
, int cols
, int vgap
, int hgap 
) 
1057     : m_rows( ( cols 
== 0 && rows 
== 0 ) ? 1 : rows 
) 
1064 wxGridSizer::wxGridSizer( int cols
, int vgap
, int hgap 
) 
1065     : m_rows( cols 
== 0 ? 1 : 0 ) 
1072 int wxGridSizer::CalcRowsCols(int& nrows
, int& ncols
) const 
1074     int nitems 
= m_children
.GetCount(); 
1080             nrows 
= (nitems 
+ m_cols 
- 1) / m_cols
; 
1084             ncols 
= (nitems 
+ m_rows 
- 1) / m_rows
; 
1087         else // 0 columns, 0 rows? 
1089             wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") ); 
1098 void wxGridSizer::RecalcSizes() 
1100     int nitems
, nrows
, ncols
; 
1101     if ( (nitems 
= CalcRowsCols(nrows
, ncols
)) == 0 ) 
1104     wxSize 
sz( GetSize() ); 
1105     wxPoint 
pt( GetPosition() ); 
1107     int w 
= (sz
.x 
- (ncols 
- 1) * m_hgap
) / ncols
; 
1108     int h 
= (sz
.y 
- (nrows 
- 1) * m_vgap
) / nrows
; 
1111     for (int c 
= 0; c 
< ncols
; c
++) 
1114         for (int r 
= 0; r 
< nrows
; r
++) 
1116             int i 
= r 
* ncols 
+ c
; 
1119                 wxSizerItemList::compatibility_iterator node 
= m_children
.Item( i 
); 
1121                 wxASSERT_MSG( node
, _T("Failed to find SizerItemList node") ); 
1123                 SetItemBounds( node
->GetData(), x
, y
, w
, h
); 
1131 wxSize 
wxGridSizer::CalcMin() 
1134     if ( CalcRowsCols(nrows
, ncols
) == 0 ) 
1135         return wxSize(10, 10); 
1137     // Find the max width and height for any component 
1141     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1144         wxSizerItem     
*item 
= node
->GetData(); 
1145         wxSize           
sz( item
->CalcMin() ); 
1147         w 
= wxMax( w
, sz
.x 
); 
1148         h 
= wxMax( h
, sz
.y 
); 
1150         node 
= node
->GetNext(); 
1153     return wxSize( ncols 
* w 
+ (ncols
-1) * m_hgap
, 
1154                    nrows 
* h 
+ (nrows
-1) * m_vgap 
); 
1157 void wxGridSizer::SetItemBounds( wxSizerItem 
*item
, int x
, int y
, int w
, int h 
) 
1160     wxSize 
sz( item
->GetMinSizeWithBorder() ); 
1161     int flag 
= item
->GetFlag(); 
1163     if ((flag 
& wxEXPAND
) || (flag 
& wxSHAPED
)) 
1169         if (flag 
& wxALIGN_CENTER_HORIZONTAL
) 
1171             pt
.x 
= x 
+ (w 
- sz
.x
) / 2; 
1173         else if (flag 
& wxALIGN_RIGHT
) 
1175             pt
.x 
= x 
+ (w 
- sz
.x
); 
1178         if (flag 
& wxALIGN_CENTER_VERTICAL
) 
1180             pt
.y 
= y 
+ (h 
- sz
.y
) / 2; 
1182         else if (flag 
& wxALIGN_BOTTOM
) 
1184             pt
.y 
= y 
+ (h 
- sz
.y
); 
1188     item
->SetDimension(pt
, sz
); 
1191 //--------------------------------------------------------------------------- 
1193 //--------------------------------------------------------------------------- 
1195 wxFlexGridSizer::wxFlexGridSizer( int rows
, int cols
, int vgap
, int hgap 
) 
1196                : wxGridSizer( rows
, cols
, vgap
, hgap 
), 
1197                  m_flexDirection(wxBOTH
), 
1198                  m_growMode(wxFLEX_GROWMODE_SPECIFIED
) 
1202 wxFlexGridSizer::wxFlexGridSizer( int cols
, int vgap
, int hgap 
) 
1203                : wxGridSizer( cols
, vgap
, hgap 
), 
1204                  m_flexDirection(wxBOTH
), 
1205                  m_growMode(wxFLEX_GROWMODE_SPECIFIED
) 
1209 wxFlexGridSizer::~wxFlexGridSizer() 
1213 void wxFlexGridSizer::RecalcSizes() 
1215     int nitems
, nrows
, ncols
; 
1216     if ( (nitems 
= CalcRowsCols(nrows
, ncols
)) == 0 ) 
1219     wxPoint 
pt( GetPosition() ); 
1220     wxSize 
sz( GetSize() ); 
1222     AdjustForGrowables(sz
, m_calculatedMinSize
, nrows
, ncols
); 
1224     sz 
= wxSize( pt
.x 
+ sz
.x
, pt
.y 
+ sz
.y 
); 
1227     for (int c 
= 0; c 
< ncols
; c
++) 
1230         for (int r 
= 0; r 
< nrows
; r
++) 
1232             int i 
= r 
* ncols 
+ c
; 
1235                 wxSizerItemList::compatibility_iterator node 
= m_children
.Item( i 
); 
1237                 wxASSERT_MSG( node
, _T("Failed to find node") ); 
1239                 int w 
= wxMax( 0, wxMin( m_colWidths
[c
], sz
.x 
- x 
) ); 
1240                 int h 
= wxMax( 0, wxMin( m_rowHeights
[r
], sz
.y 
- y 
) ); 
1242                 SetItemBounds( node
->GetData(), x
, y
, w
, h
); 
1244             if (m_rowHeights
[r
] != -1) 
1245                 y 
= y 
+ m_rowHeights
[r
] + m_vgap
; 
1247         if (m_colWidths
[c
] != -1) 
1248             x 
= x 
+ m_colWidths
[c
] + m_hgap
; 
1252 wxSize 
wxFlexGridSizer::CalcMin() 
1258     // Number of rows/columns can change as items are added or removed. 
1259     if ( !CalcRowsCols(nrows
, ncols
) ) 
1260         return wxSize(10, 10); 
1262     m_rowHeights
.SetCount(nrows
); 
1263     m_colWidths
.SetCount(ncols
); 
1265     // We have to recalcuate the sizes in case the item minimum size has 
1266     // changed since the previous layout, or the item has been hidden using 
1267     // wxSizer::Show(). If all the items in a row/column are hidden, the final 
1268     // dimension of the row/column will be -1, indicating that the column 
1269     // itself is hidden. 
1270     for( s 
= m_rowHeights
.GetCount(), i 
= 0; i 
< s
; ++i 
) 
1271         m_rowHeights
[ i 
] = -1; 
1272     for( s 
= m_colWidths
.GetCount(), i 
= 0; i 
< s
; ++i 
) 
1273         m_colWidths
[ i 
] = -1; 
1275     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1280         wxSizerItem    
*item 
= node
->GetData(); 
1281         if ( item
->IsShown() ) 
1283             wxSize 
sz( item
->CalcMin() ); 
1284             int row 
= i 
/ ncols
; 
1285             int col 
= i 
% ncols
; 
1287             m_rowHeights
[ row 
] = wxMax( wxMax( 0, sz
.y 
), m_rowHeights
[ row 
] ); 
1288             m_colWidths
[ col 
] = wxMax( wxMax( 0, sz
.x 
), m_colWidths
[ col 
] ); 
1291         node 
= node
->GetNext(); 
1295     AdjustForFlexDirection(); 
1297     // Sum total minimum size, including gaps between rows/columns. 
1298     // -1 is used as a magic number meaning empty column. 
1300     for (int col 
= 0; col 
< ncols
; col
++) 
1301         if ( m_colWidths
[ col 
] != -1 ) 
1302             width 
+= m_colWidths
[ col 
] + m_hgap
; 
1307     for (int row 
= 0; row 
< nrows
; row
++) 
1308         if ( m_rowHeights
[ row 
] != -1 ) 
1309             height 
+= m_rowHeights
[ row 
] + m_vgap
; 
1313     m_calculatedMinSize 
= wxSize( width
, height 
); 
1314     return m_calculatedMinSize
; 
1317 void wxFlexGridSizer::AdjustForFlexDirection() 
1319     // the logic in CalcMin works when we resize flexibly in both directions 
1320     // but maybe this is not the case 
1321     if ( m_flexDirection 
!= wxBOTH 
) 
1323         // select the array corresponding to the direction in which we do *not* 
1325         wxArrayInt
& array 
= m_flexDirection 
== wxVERTICAL 
? m_colWidths
 
1328         const int count 
= array
.GetCount(); 
1330         // find the largest value in this array 
1332         for ( n 
= 0; n 
< count
; ++n 
) 
1334             if ( array
[n
] > largest 
) 
1338         // and now fill it with the largest value 
1339         for ( n 
= 0; n 
< count
; ++n 
) 
1347 void wxFlexGridSizer::AdjustForGrowables(const wxSize
& sz
, const wxSize
& minsz
, 
1348                                          int nrows
, int ncols
) 
1350     // what to do with the rows? by default, resize them proportionally 
1351     if ( sz
.y 
> minsz
.y 
&& ( (m_flexDirection 
& wxVERTICAL
) || (m_growMode 
== wxFLEX_GROWMODE_SPECIFIED
) ) ) 
1353         int sum_proportions 
= 0; 
1354         int growable_space 
= 0; 
1357         for (idx 
= 0; idx 
< m_growableRows
.GetCount(); idx
++) 
1359             // Since the number of rows/columns can change as items are 
1360             // inserted/deleted, we need to verify at runtime that the 
1361             // requested growable rows/columns are still valid. 
1362             if (m_growableRows
[idx
] >= nrows
) 
1365             // If all items in a row/column are hidden, that row/column will 
1366             // have a dimension of -1.  This causes the row/column to be 
1367             // hidden completely. 
1368             if (m_rowHeights
[ m_growableRows
[idx
] ] == -1) 
1370             sum_proportions 
+= m_growableRowsProportions
[idx
]; 
1371             growable_space 
+= m_rowHeights
[ m_growableRows
[idx
] ]; 
1377             for (idx 
= 0; idx 
< m_growableRows
.GetCount(); idx
++) 
1379                 if (m_growableRows
[idx
] >= nrows 
) 
1381                 if (m_rowHeights
[ m_growableRows
[idx
] ] == -1) 
1382                     m_rowHeights
[ m_growableRows
[idx
] ] = 0; 
1385                     int delta 
= (sz
.y 
- minsz
.y
); 
1386                     if (sum_proportions 
== 0) 
1387                         delta 
= (delta
/num
) + m_rowHeights
[ m_growableRows
[idx
] ]; 
1389                         delta 
= ((delta
+growable_space
)*m_growableRowsProportions
[idx
]) / sum_proportions
; 
1390                     m_rowHeights
[ m_growableRows
[idx
] ] = delta
; 
1395     else if ( (m_growMode 
== wxFLEX_GROWMODE_ALL
) && (sz
.y 
> minsz
.y
) ) 
1397         // rounding problem? 
1398         for ( int row 
= 0; row 
< nrows
; ++row 
) 
1399             m_rowHeights
[ row 
] = sz
.y 
/ nrows
; 
1402     // the same logic as above but for the columns 
1403     if ( sz
.x 
> minsz
.x 
&& ( (m_flexDirection 
& wxHORIZONTAL
) || (m_growMode 
== wxFLEX_GROWMODE_SPECIFIED
) ) ) 
1405         int sum_proportions 
= 0; 
1406         int growable_space 
= 0; 
1409         for (idx 
= 0; idx 
< m_growableCols
.GetCount(); idx
++) 
1411             // Since the number of rows/columns can change as items are 
1412             // inserted/deleted, we need to verify at runtime that the 
1413             // requested growable rows/columns are still valid. 
1414             if (m_growableCols
[idx
] >= ncols
) 
1417             // If all items in a row/column are hidden, that row/column will 
1418             // have a dimension of -1.  This causes the column to be hidden 
1420             if (m_colWidths
[ m_growableCols
[idx
] ] == -1) 
1422             sum_proportions 
+= m_growableColsProportions
[idx
]; 
1423             growable_space 
+= m_colWidths
[ m_growableCols
[idx
] ]; 
1429             for (idx 
= 0; idx 
< m_growableCols
.GetCount(); idx
++) 
1431                 if (m_growableCols
[idx
] >= ncols 
) 
1433                 if (m_colWidths
[ m_growableCols
[idx
] ] == -1) 
1434                     m_colWidths
[ m_growableCols
[idx
] ] = 0; 
1437                     int delta 
= (sz
.x 
- minsz
.x
); 
1438                     if (sum_proportions 
== 0) 
1439                         delta 
= (delta
/num
) + m_colWidths
[ m_growableCols
[idx
] ]; 
1441                         delta 
= ((delta
+growable_space
)*m_growableColsProportions
[idx
])/sum_proportions
; 
1442                     m_colWidths
[ m_growableCols
[idx
] ] = delta
; 
1447     else if ( (m_growMode 
== wxFLEX_GROWMODE_ALL
) && (sz
.x 
> minsz
.x
) ) 
1449         for ( int col
=0; col 
< ncols
; ++col 
) 
1450             m_colWidths
[ col 
] = sz
.x 
/ ncols
; 
1455 void wxFlexGridSizer::AddGrowableRow( size_t idx
, int proportion 
) 
1457     m_growableRows
.Add( idx 
); 
1458     m_growableRowsProportions
.Add( proportion 
); 
1461 void wxFlexGridSizer::RemoveGrowableRow( size_t idx 
) 
1463     m_growableRows
.Remove( idx 
); 
1466 void wxFlexGridSizer::AddGrowableCol( size_t idx
, int proportion 
) 
1468     m_growableCols
.Add( idx 
); 
1469     m_growableColsProportions
.Add( proportion 
); 
1472 void wxFlexGridSizer::RemoveGrowableCol( size_t idx 
) 
1474     m_growableCols
.Remove( idx 
); 
1477 //--------------------------------------------------------------------------- 
1479 //--------------------------------------------------------------------------- 
1481 wxBoxSizer::wxBoxSizer( int orient 
) 
1482     : m_orient( orient 
) 
1486 void wxBoxSizer::RecalcSizes() 
1488     if (m_children
.GetCount() == 0) 
1494         if (m_orient 
== wxHORIZONTAL
) 
1495             delta 
= m_size
.x 
- m_fixedWidth
; 
1497             delta 
= m_size
.y 
- m_fixedHeight
; 
1500     wxPoint 
pt( m_position 
); 
1502     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1505         wxSizerItem     
*item 
= node
->GetData(); 
1507         if (item
->IsShown()) 
1509             wxSize 
size( item
->GetMinSizeWithBorder() ); 
1511             if (m_orient 
== wxVERTICAL
) 
1513                 wxCoord height 
= size
.y
; 
1514                 if (item
->GetProportion()) 
1516                     // Because of at least one visible item has non-zero 
1517                     // proportion then m_stretchable is not zero 
1518                     height 
= (delta 
* item
->GetProportion()) / m_stretchable
; 
1521                 wxPoint 
child_pos( pt 
); 
1522                 wxSize  
child_size( size
.x
, height 
); 
1524                 if (item
->GetFlag() & (wxEXPAND 
| wxSHAPED
)) 
1525                     child_size
.x 
= m_size
.x
; 
1526                 else if (item
->GetFlag() & wxALIGN_RIGHT
) 
1527                     child_pos
.x 
+= m_size
.x 
- size
.x
; 
1528                 else if (item
->GetFlag() & (wxCENTER 
| wxALIGN_CENTER_HORIZONTAL
)) 
1529                 // XXX wxCENTER is added for backward compatibility; 
1530                 //     wxALIGN_CENTER should be used in new code 
1531                     child_pos
.x 
+= (m_size
.x 
- size
.x
) / 2; 
1533                 item
->SetDimension( child_pos
, child_size 
); 
1539                 wxCoord width 
= size
.x
; 
1540                 if (item
->GetProportion()) 
1542                     // Because of at least one visible item has non-zero 
1543                     // proportion then m_stretchable is not zero 
1544                     width 
= (delta 
* item
->GetProportion()) / m_stretchable
; 
1547                 wxPoint 
child_pos( pt 
); 
1548                 wxSize  
child_size( width
, size
.y 
); 
1550                 if (item
->GetFlag() & (wxEXPAND 
| wxSHAPED
)) 
1551                     child_size
.y 
= m_size
.y
; 
1552                 else if (item
->GetFlag() & wxALIGN_BOTTOM
) 
1553                     child_pos
.y 
+= m_size
.y 
- size
.y
; 
1554                 else if (item
->GetFlag() & (wxCENTER 
| wxALIGN_CENTER_VERTICAL
)) 
1555                 // XXX wxCENTER is added for backward compatibility; 
1556                 //     wxALIGN_CENTER should be used in new code 
1557                     child_pos
.y 
+= (m_size
.y 
- size
.y
) / 2; 
1559                 item
->SetDimension( child_pos
, child_size 
); 
1565         node 
= node
->GetNext(); 
1569 wxSize 
wxBoxSizer::CalcMin() 
1571     if (m_children
.GetCount() == 0) 
1572         return wxSize(10,10); 
1580     // precalc item minsizes and count proportions 
1581     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1584         wxSizerItem 
*item 
= node
->GetData(); 
1586         if ( item
->IsShown() ) 
1588             item
->CalcMin();  // result is stored in the item 
1590             m_stretchable 
+= item
->GetProportion(); 
1593         node 
= node
->GetNext(); 
1596     // Total minimum size (width or height) of sizer 
1599     node 
= m_children
.GetFirst(); 
1602         wxSizerItem 
*item 
= node
->GetData(); 
1604         if (item
->IsShown() && item
->GetProportion() != 0) 
1606             int stretch 
= item
->GetProportion(); 
1607             wxSize 
size( item
->GetMinSizeWithBorder() ); 
1610             // Integer division rounded up is (a + b - 1) / b 
1611             // Round up needed in order to guarantee that all 
1612             // all items will have size not less then their min size 
1613             if (m_orient 
== wxHORIZONTAL
) 
1614                 minSize 
= ( size
.x
*m_stretchable 
+ stretch 
- 1)/stretch
; 
1616                 minSize 
= ( size
.y
*m_stretchable 
+ stretch 
- 1)/stretch
; 
1618             if (minSize 
> maxMinSize
) 
1619                 maxMinSize 
= minSize
; 
1621         node 
= node
->GetNext(); 
1624     // Calculate overall minimum size 
1625     node 
= m_children
.GetFirst(); 
1628         wxSizerItem 
*item 
= node
->GetData(); 
1630         if (item
->IsShown()) 
1632             wxSize 
size( item
->GetMinSizeWithBorder() ); 
1633             if (item
->GetProportion() != 0) 
1635                 if (m_orient 
== wxHORIZONTAL
) 
1636                     size
.x 
= (maxMinSize
*item
->GetProportion())/m_stretchable
; 
1638                     size
.y 
= (maxMinSize
*item
->GetProportion())/m_stretchable
; 
1642                 if (m_orient 
== wxVERTICAL
) 
1644                     m_fixedHeight 
+= size
.y
; 
1645                     m_fixedWidth 
= wxMax( m_fixedWidth
, size
.x 
); 
1649                     m_fixedWidth 
+= size
.x
; 
1650                     m_fixedHeight 
= wxMax( m_fixedHeight
, size
.y 
); 
1654             if (m_orient 
== wxHORIZONTAL
) 
1656                 m_minWidth 
+= size
.x
; 
1657                 m_minHeight 
= wxMax( m_minHeight
, size
.y 
); 
1661                 m_minHeight 
+= size
.y
; 
1662                 m_minWidth 
= wxMax( m_minWidth
, size
.x 
); 
1665         node 
= node
->GetNext(); 
1668     return wxSize( m_minWidth
, m_minHeight 
); 
1671 //--------------------------------------------------------------------------- 
1673 //--------------------------------------------------------------------------- 
1677 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox 
*box
, int orient 
) 
1678     : wxBoxSizer( orient 
) 
1679     , m_staticBox( box 
) 
1681     wxASSERT_MSG( box
, wxT("wxStaticBoxSizer needs a static box") ); 
1684 wxStaticBoxSizer::wxStaticBoxSizer(int orient
, wxWindow 
*win
, const wxString
& s
) 
1685                 : wxBoxSizer(orient
), 
1686                   m_staticBox(new wxStaticBox(win
, wxID_ANY
, s
)) 
1690 static void GetStaticBoxBorders( wxStaticBox 
*box
, 
1694     // this has to be done platform by platform as there is no way to 
1695     // guess the thickness of a wxStaticBox border 
1696     box
->GetBordersForSizer(borderTop
, borderOther
); 
1699 void wxStaticBoxSizer::RecalcSizes() 
1701     int top_border
, other_border
; 
1702     GetStaticBoxBorders(m_staticBox
, &top_border
, &other_border
); 
1704     m_staticBox
->SetSize( m_position
.x
, m_position
.y
, m_size
.x
, m_size
.y 
); 
1706     wxPoint 
old_pos( m_position 
); 
1707     m_position
.x 
+= other_border
; 
1708     m_position
.y 
+= top_border
; 
1709     wxSize 
old_size( m_size 
); 
1710     m_size
.x 
-= 2*other_border
; 
1711     m_size
.y 
-= top_border 
+ other_border
; 
1713     wxBoxSizer::RecalcSizes(); 
1715     m_position 
= old_pos
; 
1719 wxSize 
wxStaticBoxSizer::CalcMin() 
1721     int top_border
, other_border
; 
1722     GetStaticBoxBorders(m_staticBox
, &top_border
, &other_border
); 
1724     wxSize 
ret( wxBoxSizer::CalcMin() ); 
1725     ret
.x 
+= 2*other_border
; 
1726     ret
.y 
+= other_border 
+ top_border
; 
1731 void wxStaticBoxSizer::ShowItems( bool show 
) 
1733     m_staticBox
->Show( show 
); 
1734     wxBoxSizer::ShowItems( show 
); 
1737 #endif // wxUSE_STATBOX 
1741 wxStdDialogButtonSizer::wxStdDialogButtonSizer() 
1742     : wxBoxSizer(wxHORIZONTAL
) 
1744     // Vertical buttons with lots of space on either side 
1745     // looks rubbish on WinCE, so let's not do this for now. 
1746     // If we are going to use vertical buttons, we should 
1747     // put the sizer to the right of other controls in the dialog, 
1748     // and that's beyond the scope of this sizer. 
1750     bool is_pda 
= (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA
); 
1751     // If we have a PDA screen, put yes/no button over 
1752     // all other buttons, otherwise on the left side. 
1754         m_orient 
= wxVERTICAL
; 
1757     m_buttonAffirmative 
= NULL
; 
1758     m_buttonApply 
= NULL
; 
1759     m_buttonNegative 
= NULL
; 
1760     m_buttonCancel 
= NULL
; 
1761     m_buttonHelp 
= NULL
; 
1764 void wxStdDialogButtonSizer::AddButton(wxButton 
*mybutton
) 
1766     switch (mybutton
->GetId()) 
1771             m_buttonAffirmative 
= mybutton
; 
1774             m_buttonApply 
= mybutton
; 
1777             m_buttonNegative 
= mybutton
; 
1780             m_buttonCancel 
= mybutton
; 
1783         case wxID_CONTEXT_HELP
: 
1784             m_buttonHelp 
= mybutton
; 
1791 void wxStdDialogButtonSizer::SetAffirmativeButton( wxButton 
*button 
) 
1793     m_buttonAffirmative 
= button
; 
1796 void wxStdDialogButtonSizer::SetNegativeButton( wxButton 
*button 
) 
1798     m_buttonNegative 
= button
; 
1801 void wxStdDialogButtonSizer::SetCancelButton( wxButton 
*button 
) 
1803     m_buttonCancel 
= button
; 
1806 void wxStdDialogButtonSizer::Realize() 
1809         Add(0, 0, 0, wxLEFT
, 6); 
1811             Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 6); 
1813         if (m_buttonNegative
){ 
1814             // HIG POLICE BULLETIN - destructive buttons need extra padding 
1815             // 24 pixels on either side 
1816             Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 12); 
1819         // extra whitespace between help/negative and cancel/ok buttons 
1820         Add(0, 0, 1, wxEXPAND
, 0); 
1822         if (m_buttonCancel
){ 
1823             Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 6); 
1824             // Cancel or help should be default 
1825             // m_buttonCancel->SetDefaultButton(); 
1828         // Ugh, Mac doesn't really have apply dialogs, so I'll just 
1829         // figure the best place is between Cancel and OK 
1831             Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 6); 
1833         if (m_buttonAffirmative
){ 
1834             Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE 
| wxLEFT
, 6); 
1836             if (m_buttonAffirmative
->GetId() == wxID_SAVE
){ 
1837                 // these buttons have set labels under Mac so we should use them 
1838                 m_buttonAffirmative
->SetLabel(_("Save")); 
1839                 m_buttonNegative
->SetLabel(_("Don't Save")); 
1843         // Extra space around and at the right 
1845 #elif defined(__WXGTK20__) 
1846         Add(0, 0, 0, wxLEFT
, 9); 
1848             Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 3); 
1850         // extra whitespace between help and cancel/ok buttons 
1851         Add(0, 0, 1, wxEXPAND
, 0); 
1853         if (m_buttonNegative
){ 
1854             Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 3); 
1857         if (m_buttonCancel
){ 
1858             Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 3); 
1859             // Cancel or help should be default 
1860             // m_buttonCancel->SetDefaultButton(); 
1864             Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 3); 
1866         if (m_buttonAffirmative
) 
1867             Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE 
| wxLEFT
, 6); 
1868 #elif defined(__WXMSW__) 
1871         // right-justify buttons 
1872         Add(0, 0, 1, wxEXPAND
, 0); 
1874         if (m_buttonAffirmative
){ 
1875             Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonAffirmative
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
1878         if (m_buttonNegative
){ 
1879             Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonNegative
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
1882         if (m_buttonCancel
){ 
1883             Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonCancel
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
1886             Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonApply
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
1889             Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonHelp
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
1891         // GTK+1 and any other platform 
1893         // Add(0, 0, 0, wxLEFT, 5); // Not sure what this was for but it unbalances the dialog 
1895             Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonHelp
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
1897         // extra whitespace between help and cancel/ok buttons 
1898         Add(0, 0, 1, wxEXPAND
, 0); 
1901             Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonApply
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
1903         if (m_buttonAffirmative
){ 
1904             Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonAffirmative
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
1907         if (m_buttonNegative
){ 
1908             Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonNegative
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
1911         if (m_buttonCancel
){ 
1912             Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonCancel
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
1913             // Cancel or help should be default 
1914             // m_buttonCancel->SetDefaultButton(); 
1920 #endif // wxUSE_BUTTON 
1922 #if WXWIN_COMPATIBILITY_2_4 
1924 // ---------------------------------------------------------------------------- 
1926 // ---------------------------------------------------------------------------- 
1929 IMPLEMENT_CLASS(wxBookCtrlSizer
, wxSizer
) 
1931 IMPLEMENT_CLASS(wxNotebookSizer
, wxBookCtrlSizer
) 
1932 #endif // wxUSE_NOTEBOOK 
1933 #endif // wxUSE_BOOKCTRL 
1937 wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrlBase 
*bookctrl
) 
1938                : m_bookctrl(bookctrl
) 
1940     wxASSERT_MSG( bookctrl
, wxT("wxBookCtrlSizer needs a control") ); 
1943 void wxBookCtrlSizer::RecalcSizes() 
1945     m_bookctrl
->SetSize( m_position
.x
, m_position
.y
, m_size
.x
, m_size
.y 
); 
1948 wxSize 
wxBookCtrlSizer::CalcMin() 
1950     wxSize sizeBorder 
= m_bookctrl
->CalcSizeFromPage(wxSize(0,0)); 
1955     if ( m_bookctrl
->GetPageCount() == 0 ) 
1957         return wxSize(sizeBorder
.x 
+ 10, sizeBorder
.y 
+ 10); 
1963     wxWindowList::compatibility_iterator
 
1964         node 
= m_bookctrl
->GetChildren().GetFirst(); 
1967         wxWindow 
*item 
= node
->GetData(); 
1968         wxSizer 
*itemsizer 
= item
->GetSizer(); 
1972             wxSize 
subsize( itemsizer
->CalcMin() ); 
1974             if (subsize
.x 
> maxX
) 
1976             if (subsize
.y 
> maxY
) 
1980         node 
= node
->GetNext(); 
1983     return wxSize( maxX
, maxY 
) + sizeBorder
; 
1988 wxNotebookSizer::wxNotebookSizer(wxNotebook 
*nb
) 
1990     wxASSERT_MSG( nb
, wxT("wxNotebookSizer needs a control") ); 
1994 #endif // wxUSE_NOTEBOOOK 
1995 #endif // wxUSE_BOOKCTRL 
1997 #endif // WXWIN_COMPATIBILITY_2_4