1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/common/sizer.cpp 
   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" 
  20 #include "wx/display.h" 
  24     #include "wx/string.h" 
  28     #include "wx/settings.h" 
  29     #include "wx/button.h" 
  30     #include "wx/statbox.h" 
  31     #include "wx/toplevel.h" 
  34 #include "wx/listimpl.cpp" 
  37 //--------------------------------------------------------------------------- 
  39 IMPLEMENT_CLASS(wxSizerItem
, wxObject
) 
  40 IMPLEMENT_CLASS(wxSizer
, wxObject
) 
  41 IMPLEMENT_CLASS(wxGridSizer
, wxSizer
) 
  42 IMPLEMENT_CLASS(wxFlexGridSizer
, wxGridSizer
) 
  43 IMPLEMENT_CLASS(wxBoxSizer
, wxSizer
) 
  45 IMPLEMENT_CLASS(wxStaticBoxSizer
, wxBoxSizer
) 
  48 IMPLEMENT_CLASS(wxStdDialogButtonSizer
, wxBoxSizer
) 
  51 WX_DEFINE_EXPORTED_LIST( wxSizerItemList 
) 
  86 // ---------------------------------------------------------------------------- 
  88 // ---------------------------------------------------------------------------- 
  90 void wxSizerItem::Init(const wxSizerFlags
& flags
) 
  94     m_proportion 
= flags
.GetProportion(); 
  95     m_flag 
= flags
.GetFlags(); 
  96     m_border 
= flags
.GetBorderInPixels(); 
  99 wxSizerItem::wxSizerItem() 
 109 void wxSizerItem::DoSetWindow(wxWindow 
*window
) 
 111     wxCHECK_RET( window
, _T("NULL window in wxSizerItem::SetWindow()") ); 
 113     m_kind 
= Item_Window
; 
 116     // window doesn't become smaller than its initial size, whatever happens 
 117     m_minSize 
= window
->GetSize(); 
 119     if ( m_flag 
& wxFIXED_MINSIZE 
) 
 120         window
->SetMinSize(m_minSize
); 
 122     // aspect ratio calculated from initial size 
 126 wxSizerItem::wxSizerItem(wxWindow 
*window
, 
 132              m_proportion(proportion
), 
 141 void wxSizerItem::DoSetSizer(wxSizer 
*sizer
) 
 147 wxSizerItem::wxSizerItem(wxSizer 
*sizer
, 
 154              m_proportion(proportion
), 
 162     // m_minSize is set later 
 166 void wxSizerItem::DoSetSpacer(const wxSize
& size
) 
 168     m_kind 
= Item_Spacer
; 
 169     m_spacer 
= new wxSizerSpacer(size
); 
 174 wxSizerItem::wxSizerItem(int width
, 
 182              m_minSize(width
, height
), // minimal size is the initial size 
 183              m_proportion(proportion
), 
 188     DoSetSpacer(wxSize(width
, height
)); 
 191 wxSizerItem::~wxSizerItem() 
 197 void wxSizerItem::Free() 
 205             m_window
->SetContainingSizer(NULL
); 
 218             wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); 
 224 wxSize 
wxSizerItem::GetSpacer() const 
 227     if ( m_kind 
== Item_Spacer 
) 
 228         size 
= m_spacer
->GetSize(); 
 234 wxSize 
wxSizerItem::GetSize() const 
 243             ret 
= m_window
->GetSize(); 
 247             ret 
= m_sizer
->GetSize(); 
 251             ret 
= m_spacer
->GetSize(); 
 256             wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); 
 263     if (m_flag 
& wxNORTH
) 
 265     if (m_flag 
& wxSOUTH
) 
 271 wxSize 
wxSizerItem::CalcMin() 
 275         m_minSize 
= m_sizer
->GetMinSize(); 
 277         // if we have to preserve aspect ratio _AND_ this is 
 278         // the first-time calculation, consider ret to be initial size 
 279         if ( (m_flag 
& wxSHAPED
) && wxIsNullDouble(m_ratio
) ) 
 282     else if ( IsWindow() ) 
 284         // Since the size of the window may change during runtime, we 
 285         // should use the current minimal/best size. 
 286         m_minSize 
= m_window
->GetEffectiveMinSize(); 
 289     return GetMinSizeWithBorder(); 
 292 wxSize 
wxSizerItem::GetMinSizeWithBorder() const 
 294     wxSize ret 
= m_minSize
; 
 300     if (m_flag 
& wxNORTH
) 
 302     if (m_flag 
& wxSOUTH
) 
 309 void wxSizerItem::SetDimension( const wxPoint
& pos_
, const wxSize
& size_ 
) 
 313     if (m_flag 
& wxSHAPED
) 
 315         // adjust aspect ratio 
 316         int rwidth 
= (int) (size
.y 
* m_ratio
); 
 320             int rheight 
= (int) (size
.x 
/ m_ratio
); 
 321             // add vertical space 
 322             if (m_flag 
& wxALIGN_CENTER_VERTICAL
) 
 323                 pos
.y 
+= (size
.y 
- rheight
) / 2; 
 324             else if (m_flag 
& wxALIGN_BOTTOM
) 
 325                 pos
.y 
+= (size
.y 
- rheight
); 
 326             // use reduced dimensions 
 329         else if (rwidth 
< size
.x
) 
 331             // add horizontal space 
 332             if (m_flag 
& wxALIGN_CENTER_HORIZONTAL
) 
 333                 pos
.x 
+= (size
.x 
- rwidth
) / 2; 
 334             else if (m_flag 
& wxALIGN_RIGHT
) 
 335                 pos
.x 
+= (size
.x 
- rwidth
); 
 340     // This is what GetPosition() returns. Since we calculate 
 341     // borders afterwards, GetPosition() will be the left/top 
 342     // corner of the surrounding border. 
 354     if (m_flag 
& wxNORTH
) 
 359     if (m_flag 
& wxSOUTH
) 
 369     m_rect 
= wxRect(pos
, size
); 
 374             wxFAIL_MSG( _T("can't set size of uninitialized sizer item") ); 
 378             m_window
->SetSize(pos
.x
, pos
.y
, size
.x
, size
.y
, 
 379                               wxSIZE_ALLOW_MINUS_ONE
); 
 383             m_sizer
->SetDimension(pos
.x
, pos
.y
, size
.x
, size
.y
); 
 387             m_spacer
->SetSize(size
); 
 392             wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); 
 396 void wxSizerItem::DeleteWindows() 
 405             //We are deleting the window from this sizer - normally 
 406             //the window destroys the sizer associated with it, 
 407             //which might destroy this, which we don't want 
 408             m_window
->SetContainingSizer(NULL
); 
 410             //Putting this after the switch will result in a spacer 
 411             //not being deleted properly on destruction 
 416             m_sizer
->DeleteWindows(); 
 421             wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); 
 426 void wxSizerItem::Show( bool show 
) 
 431             wxFAIL_MSG( _T("can't show uninitialized sizer item") ); 
 435             m_window
->Show(show
); 
 443             m_spacer
->Show(show
); 
 448             wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); 
 452 bool wxSizerItem::IsShown() const 
 457             // we may be called from CalcMin(), just return false so that we're 
 462             return m_window
->IsShown(); 
 465             // arbitrarily decide that if at least one of our elements is 
 466             // shown, so are we (this arbitrariness is the reason for 
 467             // deprecating this function) 
 469                 // Some apps (such as dialog editors) depend on an empty sizer still 
 470                 // being laid out correctly and reporting the correct size and position. 
 471                 if (m_sizer
->GetChildren().GetCount() == 0) 
 474                 for ( wxSizerItemList::compatibility_iterator
 
 475                         node 
= m_sizer
->GetChildren().GetFirst(); 
 477                       node 
= node
->GetNext() ) 
 479                     if ( node
->GetData()->IsShown() ) 
 486             return m_spacer
->IsShown(); 
 490             wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); 
 496 #if WXWIN_COMPATIBILITY_2_6 
 497 void wxSizerItem::SetOption( int option 
) 
 499     SetProportion( option 
); 
 502 int wxSizerItem::GetOption() const 
 504     return GetProportion(); 
 506 #endif // WXWIN_COMPATIBILITY_2_6 
 509 //--------------------------------------------------------------------------- 
 511 //--------------------------------------------------------------------------- 
 515     WX_CLEAR_LIST(wxSizerItemList
, m_children
); 
 518 wxSizerItem
* wxSizer::Insert( size_t index
, wxSizerItem 
*item 
) 
 520     m_children
.Insert( index
, item 
); 
 522     if ( item
->GetWindow() ) 
 523         item
->GetWindow()->SetContainingSizer( this ); 
 528 void wxSizer::SetContainingWindow(wxWindow 
*win
) 
 530     if ( win 
== m_containingWindow 
) 
 533     m_containingWindow 
= win
; 
 535     // set the same window for all nested sizers as well, they also are in the 
 537     for ( wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 539           node 
= node
->GetNext() ) 
 541         wxSizerItem 
*const item 
= node
->GetData(); 
 542         wxSizer 
*const sizer 
= item
->GetSizer(); 
 546             sizer
->SetContainingWindow(win
); 
 551 #if WXWIN_COMPATIBILITY_2_6 
 552 bool wxSizer::Remove( wxWindow 
*window 
) 
 554     return Detach( window 
); 
 556 #endif // WXWIN_COMPATIBILITY_2_6 
 558 bool wxSizer::Remove( wxSizer 
*sizer 
) 
 560     wxASSERT_MSG( sizer
, _T("Removing NULL sizer") ); 
 562     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 565         wxSizerItem     
*item 
= node
->GetData(); 
 567         if (item
->GetSizer() == sizer
) 
 570             m_children
.Erase( node 
); 
 574         node 
= node
->GetNext(); 
 580 bool wxSizer::Remove( int index 
) 
 582     wxCHECK_MSG( index 
>= 0 && (size_t)index 
< m_children
.GetCount(), 
 584                  _T("Remove index is out of range") ); 
 586     wxSizerItemList::compatibility_iterator node 
= m_children
.Item( index 
); 
 588     wxCHECK_MSG( node
, false, _T("Failed to find child node") ); 
 590     wxSizerItem 
*item 
= node
->GetData(); 
 592     if ( item
->IsWindow() ) 
 593         item
->GetWindow()->SetContainingSizer( NULL 
); 
 596     m_children
.Erase( node 
); 
 600 bool wxSizer::Detach( wxSizer 
*sizer 
) 
 602     wxASSERT_MSG( sizer
, _T("Detaching NULL sizer") ); 
 604     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 607         wxSizerItem     
*item 
= node
->GetData(); 
 609         if (item
->GetSizer() == sizer
) 
 613             m_children
.Erase( node 
); 
 616         node 
= node
->GetNext(); 
 622 bool wxSizer::Detach( wxWindow 
*window 
) 
 624     wxASSERT_MSG( window
, _T("Detaching NULL window") ); 
 626     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 629         wxSizerItem     
*item 
= node
->GetData(); 
 631         if (item
->GetWindow() == window
) 
 633             item
->GetWindow()->SetContainingSizer( NULL 
); 
 635             m_children
.Erase( node 
); 
 638         node 
= node
->GetNext(); 
 644 bool wxSizer::Detach( int index 
) 
 646     wxCHECK_MSG( index 
>= 0 && (size_t)index 
< m_children
.GetCount(), 
 648                  _T("Detach index is out of range") ); 
 650     wxSizerItemList::compatibility_iterator node 
= m_children
.Item( index 
); 
 652     wxCHECK_MSG( node
, false, _T("Failed to find child node") ); 
 654     wxSizerItem 
*item 
= node
->GetData(); 
 656     if ( item
->IsSizer() ) 
 658     else if ( item
->IsWindow() ) 
 659         item
->GetWindow()->SetContainingSizer( NULL 
); 
 662     m_children
.Erase( node 
); 
 666 bool wxSizer::Replace( wxWindow 
*oldwin
, wxWindow 
*newwin
, bool recursive 
) 
 668     wxASSERT_MSG( oldwin
, _T("Replacing NULL window") ); 
 669     wxASSERT_MSG( newwin
, _T("Replacing with NULL window") ); 
 671     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 674         wxSizerItem     
*item 
= node
->GetData(); 
 676         if (item
->GetWindow() == oldwin
) 
 678             item
->GetWindow()->SetContainingSizer( NULL 
); 
 679             item
->SetWindow(newwin
); 
 680             newwin
->SetContainingSizer( this ); 
 683         else if (recursive 
&& item
->IsSizer()) 
 685             if (item
->GetSizer()->Replace( oldwin
, newwin
, true )) 
 689         node 
= node
->GetNext(); 
 695 bool wxSizer::Replace( wxSizer 
*oldsz
, wxSizer 
*newsz
, bool recursive 
) 
 697     wxASSERT_MSG( oldsz
, _T("Replacing NULL sizer") ); 
 698     wxASSERT_MSG( newsz
, _T("Replacing with NULL sizer") ); 
 700     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 703         wxSizerItem     
*item 
= node
->GetData(); 
 705         if (item
->GetSizer() == oldsz
) 
 707             wxSizer 
*old 
= item
->GetSizer(); 
 708             item
->SetSizer(newsz
); 
 712         else if (recursive 
&& item
->IsSizer()) 
 714             if (item
->GetSizer()->Replace( oldsz
, newsz
, true )) 
 718         node 
= node
->GetNext(); 
 724 bool wxSizer::Replace( size_t old
, wxSizerItem 
*newitem 
) 
 726     wxCHECK_MSG( old 
< m_children
.GetCount(), false, _T("Replace index is out of range") ); 
 727     wxASSERT_MSG( newitem
, _T("Replacing with NULL item") ); 
 729     wxSizerItemList::compatibility_iterator node 
= m_children
.Item( old 
); 
 731     wxCHECK_MSG( node
, false, _T("Failed to find child node") ); 
 733     wxSizerItem 
*item 
= node
->GetData(); 
 734     node
->SetData(newitem
); 
 740 void wxSizer::Clear( bool delete_windows 
) 
 742     // First clear the ContainingSizer pointers 
 743     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 746         wxSizerItem     
*item 
= node
->GetData(); 
 748         if (item
->IsWindow()) 
 749             item
->GetWindow()->SetContainingSizer( NULL 
); 
 750         node 
= node
->GetNext(); 
 753     // Destroy the windows if needed 
 757     // Now empty the list 
 758     WX_CLEAR_LIST(wxSizerItemList
, m_children
); 
 761 void wxSizer::DeleteWindows() 
 763     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 766         wxSizerItem     
*item 
= node
->GetData(); 
 768         item
->DeleteWindows(); 
 769         node 
= node
->GetNext(); 
 773 wxSize 
wxSizer::Fit( wxWindow 
*window 
) 
 775     // take the min size by default and limit it by max size 
 776     wxSize size 
= GetMinWindowSize(window
); 
 777     wxSize sizeMax 
= GetMaxWindowSize(window
); 
 779     wxTopLevelWindow 
*tlw 
= wxDynamicCast(window
, wxTopLevelWindow
); 
 782         // hack for small screen devices where TLWs are always full screen 
 783         if ( tlw
->IsAlwaysMaximized() ) 
 785             size 
= tlw
->GetSize(); 
 787         else // normal situation 
 789             // limit the window to the size of the display it is on 
 790             int disp 
= wxDisplay::GetFromWindow(window
); 
 791             if ( disp 
== wxNOT_FOUND 
) 
 793                 // or, if we don't know which one it is, of the main one 
 797             sizeMax 
= wxDisplay(disp
).GetClientArea().GetSize(); 
 801     if ( sizeMax
.x 
!= wxDefaultCoord 
&& size
.x 
> sizeMax
.x 
) 
 803     if ( sizeMax
.y 
!= wxDefaultCoord 
&& size
.y 
> sizeMax
.y 
) 
 807     window
->SetSize( size 
); 
 812 void wxSizer::FitInside( wxWindow 
*window 
) 
 815     if (window
->IsTopLevel()) 
 816         size 
= VirtualFitSize( window 
); 
 818         size 
= GetMinClientSize( window 
); 
 820     window
->SetVirtualSize( size 
); 
 823 void wxSizer::Layout() 
 825     // (re)calculates minimums needed for each item and other preparations 
 829     // Applies the layout and repositions/resizes the items 
 833 void wxSizer::SetSizeHints( wxWindow 
*window 
) 
 835     // Preserve the window's max size hints, but set the 
 836     // lower bound according to the sizer calculations. 
 838     wxSize size 
= Fit( window 
); 
 840     window
->SetSizeHints( size
.x
, 
 842                           window
->GetMaxWidth(), 
 843                           window
->GetMaxHeight() ); 
 846 void wxSizer::SetVirtualSizeHints( wxWindow 
*window 
) 
 848     // Preserve the window's max size hints, but set the 
 849     // lower bound according to the sizer calculations. 
 852     wxSize 
size( window
->GetVirtualSize() ); 
 853     window
->SetVirtualSizeHints( size
.x
, 
 855                                  window
->GetMaxWidth(), 
 856                                  window
->GetMaxHeight() ); 
 859 wxSize 
wxSizer::GetMaxWindowSize( wxWindow 
*window 
) const 
 861     return window
->GetMaxSize(); 
 864 wxSize 
wxSizer::GetMinWindowSize( wxWindow 
*window 
) 
 866     wxSize      
minSize( GetMinSize() ); 
 867     wxSize      
size( window
->GetSize() ); 
 868     wxSize      
client_size( window
->GetClientSize() ); 
 870     return wxSize( minSize
.x
+size
.x
-client_size
.x
, 
 871                    minSize
.y
+size
.y
-client_size
.y 
); 
 874 // TODO on mac we need a function that determines how much free space this 
 875 // min size contains, in order to make sure that we have 20 pixels of free 
 876 // space around the controls 
 877 wxSize 
wxSizer::GetMaxClientSize( wxWindow 
*window 
) const 
 879     wxSize 
maxSize( window
->GetMaxSize() ); 
 881     if ( maxSize 
!= wxDefaultSize 
) 
 883         wxSize 
size( window
->GetSize() ); 
 884         wxSize 
client_size( window
->GetClientSize() ); 
 886         return wxSize( maxSize
.x 
+ client_size
.x 
- size
.x
, 
 887                        maxSize
.y 
+ client_size
.y 
- size
.y 
); 
 890         return wxDefaultSize
; 
 893 wxSize 
wxSizer::GetMinClientSize( wxWindow 
*WXUNUSED(window
) ) 
 895     return GetMinSize();  // Already returns client size. 
 898 wxSize 
wxSizer::VirtualFitSize( wxWindow 
*window 
) 
 900     wxSize size     
= GetMinClientSize( window 
); 
 901     wxSize sizeMax  
= GetMaxClientSize( window 
); 
 903     // Limit the size if sizeMax != wxDefaultSize 
 905     if ( size
.x 
> sizeMax
.x 
&& sizeMax
.x 
!= wxDefaultCoord 
) 
 907     if ( size
.y 
> sizeMax
.y 
&& sizeMax
.y 
!= wxDefaultCoord 
) 
 913 void wxSizer::SetDimension( int x
, int y
, int width
, int height 
) 
 922 wxSize 
wxSizer::GetMinSize() 
 924     wxSize 
ret( CalcMin() ); 
 925     if (ret
.x 
< m_minSize
.x
) ret
.x 
= m_minSize
.x
; 
 926     if (ret
.y 
< m_minSize
.y
) ret
.y 
= m_minSize
.y
; 
 930 void wxSizer::DoSetMinSize( int width
, int height 
) 
 933     m_minSize
.y 
= height
; 
 936 bool wxSizer::DoSetItemMinSize( wxWindow 
*window
, int width
, int height 
) 
 938     wxASSERT_MSG( window
, _T("SetMinSize for NULL window") ); 
 940     // Is it our immediate child? 
 942     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 945         wxSizerItem     
*item 
= node
->GetData(); 
 947         if (item
->GetWindow() == window
) 
 949             item
->SetMinSize( width
, height 
); 
 952         node 
= node
->GetNext(); 
 955     // No?  Search any subsizers we own then 
 957     node 
= m_children
.GetFirst(); 
 960         wxSizerItem     
*item 
= node
->GetData(); 
 962         if ( item
->GetSizer() && 
 963              item
->GetSizer()->DoSetItemMinSize( window
, width
, height 
) ) 
 965             // A child sizer found the requested windw, exit. 
 968         node 
= node
->GetNext(); 
 974 bool wxSizer::DoSetItemMinSize( wxSizer 
*sizer
, int width
, int height 
) 
 976     wxASSERT_MSG( sizer
, _T("SetMinSize for NULL sizer") ); 
 978     // Is it our immediate child? 
 980     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 983         wxSizerItem     
*item 
= node
->GetData(); 
 985         if (item
->GetSizer() == sizer
) 
 987             item
->GetSizer()->DoSetMinSize( width
, height 
); 
 990         node 
= node
->GetNext(); 
 993     // No?  Search any subsizers we own then 
 995     node 
= m_children
.GetFirst(); 
 998         wxSizerItem     
*item 
= node
->GetData(); 
1000         if ( item
->GetSizer() && 
1001              item
->GetSizer()->DoSetItemMinSize( sizer
, width
, height 
) ) 
1003             // A child found the requested sizer, exit. 
1006         node 
= node
->GetNext(); 
1012 bool wxSizer::DoSetItemMinSize( size_t index
, int width
, int height 
) 
1014     wxSizerItemList::compatibility_iterator node 
= m_children
.Item( index 
); 
1016     wxCHECK_MSG( node
, false, _T("Failed to find child node") ); 
1018     wxSizerItem     
*item 
= node
->GetData(); 
1020     if (item
->GetSizer()) 
1022         // Sizers contains the minimal size in them, if not calculated ... 
1023         item
->GetSizer()->DoSetMinSize( width
, height 
); 
1027         // ... but the minimal size of spacers and windows is stored via the item 
1028         item
->SetMinSize( width
, height 
); 
1034 wxSizerItem
* wxSizer::GetItem( wxWindow 
*window
, bool recursive 
) 
1036     wxASSERT_MSG( window
, _T("GetItem for NULL window") ); 
1038     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1041         wxSizerItem     
*item 
= node
->GetData(); 
1043         if (item
->GetWindow() == window
) 
1047         else if (recursive 
&& item
->IsSizer()) 
1049             wxSizerItem 
*subitem 
= item
->GetSizer()->GetItem( window
, true ); 
1054         node 
= node
->GetNext(); 
1060 wxSizerItem
* wxSizer::GetItem( wxSizer 
*sizer
, bool recursive 
) 
1062     wxASSERT_MSG( sizer
, _T("GetItem for NULL sizer") ); 
1064     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1067         wxSizerItem 
*item 
= node
->GetData(); 
1069         if (item
->GetSizer() == sizer
) 
1073         else if (recursive 
&& item
->IsSizer()) 
1075             wxSizerItem 
*subitem 
= item
->GetSizer()->GetItem( sizer
, true ); 
1080         node 
= node
->GetNext(); 
1086 wxSizerItem
* wxSizer::GetItem( size_t index 
) 
1088     wxCHECK_MSG( index 
< m_children
.GetCount(), 
1090                  _T("GetItem index is out of range") ); 
1092     return m_children
.Item( index 
)->GetData(); 
1095 bool wxSizer::Show( wxWindow 
*window
, bool show
, bool recursive 
) 
1097     wxSizerItem 
*item 
= GetItem( window
, recursive 
); 
1108 bool wxSizer::Show( wxSizer 
*sizer
, bool show
, bool recursive 
) 
1110     wxSizerItem 
*item 
= GetItem( sizer
, recursive 
); 
1121 bool wxSizer::Show( size_t index
, bool show
) 
1123     wxSizerItem 
*item 
= GetItem( index 
); 
1134 void wxSizer::ShowItems( bool show 
) 
1136     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1139         node
->GetData()->Show( show 
); 
1140         node 
= node
->GetNext(); 
1144 bool wxSizer::IsShown( wxWindow 
*window 
) const 
1146     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1149         wxSizerItem     
*item 
= node
->GetData(); 
1151         if (item
->GetWindow() == window
) 
1153             return item
->IsShown(); 
1155         node 
= node
->GetNext(); 
1158     wxFAIL_MSG( _T("IsShown failed to find sizer item") ); 
1163 bool wxSizer::IsShown( wxSizer 
*sizer 
) const 
1165     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1168         wxSizerItem     
*item 
= node
->GetData(); 
1170         if (item
->GetSizer() == sizer
) 
1172             return item
->IsShown(); 
1174         node 
= node
->GetNext(); 
1177     wxFAIL_MSG( _T("IsShown failed to find sizer item") ); 
1182 bool wxSizer::IsShown( size_t index 
) const 
1184     wxCHECK_MSG( index 
< m_children
.GetCount(), 
1186                  _T("IsShown index is out of range") ); 
1188     return m_children
.Item( index 
)->GetData()->IsShown(); 
1192 //--------------------------------------------------------------------------- 
1194 //--------------------------------------------------------------------------- 
1196 wxGridSizer::wxGridSizer( int rows
, int cols
, int vgap
, int hgap 
) 
1197     : m_rows( ( cols 
== 0 && rows 
== 0 ) ? 1 : rows 
) 
1204 wxGridSizer::wxGridSizer( int cols
, int vgap
, int hgap 
) 
1205     : m_rows( cols 
== 0 ? 1 : 0 ) 
1212 int wxGridSizer::CalcRowsCols(int& nrows
, int& ncols
) const 
1214     int nitems 
= m_children
.GetCount(); 
1220             nrows 
= (nitems 
+ m_cols 
- 1) / m_cols
; 
1224             ncols 
= (nitems 
+ m_rows 
- 1) / m_rows
; 
1227         else // 0 columns, 0 rows? 
1229             wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") ); 
1238 void wxGridSizer::RecalcSizes() 
1240     int nitems
, nrows
, ncols
; 
1241     if ( (nitems 
= CalcRowsCols(nrows
, ncols
)) == 0 ) 
1244     wxSize 
sz( GetSize() ); 
1245     wxPoint 
pt( GetPosition() ); 
1247     int w 
= (sz
.x 
- (ncols 
- 1) * m_hgap
) / ncols
; 
1248     int h 
= (sz
.y 
- (nrows 
- 1) * m_vgap
) / nrows
; 
1251     for (int c 
= 0; c 
< ncols
; c
++) 
1254         for (int r 
= 0; r 
< nrows
; r
++) 
1256             int i 
= r 
* ncols 
+ c
; 
1259                 wxSizerItemList::compatibility_iterator node 
= m_children
.Item( i 
); 
1261                 wxASSERT_MSG( node
, _T("Failed to find SizerItemList node") ); 
1263                 SetItemBounds( node
->GetData(), x
, y
, w
, h
); 
1271 wxSize 
wxGridSizer::CalcMin() 
1274     if ( CalcRowsCols(nrows
, ncols
) == 0 ) 
1277     // Find the max width and height for any component 
1281     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1284         wxSizerItem     
*item 
= node
->GetData(); 
1285         wxSize           
sz( item
->CalcMin() ); 
1287         w 
= wxMax( w
, sz
.x 
); 
1288         h 
= wxMax( h
, sz
.y 
); 
1290         node 
= node
->GetNext(); 
1293     return wxSize( ncols 
* w 
+ (ncols
-1) * m_hgap
, 
1294                    nrows 
* h 
+ (nrows
-1) * m_vgap 
); 
1297 void wxGridSizer::SetItemBounds( wxSizerItem 
*item
, int x
, int y
, int w
, int h 
) 
1300     wxSize 
sz( item
->GetMinSizeWithBorder() ); 
1301     int flag 
= item
->GetFlag(); 
1303     if ((flag 
& wxEXPAND
) || (flag 
& wxSHAPED
)) 
1309         if (flag 
& wxALIGN_CENTER_HORIZONTAL
) 
1311             pt
.x 
= x 
+ (w 
- sz
.x
) / 2; 
1313         else if (flag 
& wxALIGN_RIGHT
) 
1315             pt
.x 
= x 
+ (w 
- sz
.x
); 
1318         if (flag 
& wxALIGN_CENTER_VERTICAL
) 
1320             pt
.y 
= y 
+ (h 
- sz
.y
) / 2; 
1322         else if (flag 
& wxALIGN_BOTTOM
) 
1324             pt
.y 
= y 
+ (h 
- sz
.y
); 
1328     item
->SetDimension(pt
, sz
); 
1331 //--------------------------------------------------------------------------- 
1333 //--------------------------------------------------------------------------- 
1335 wxFlexGridSizer::wxFlexGridSizer( int rows
, int cols
, int vgap
, int hgap 
) 
1336                : wxGridSizer( rows
, cols
, vgap
, hgap 
), 
1337                  m_flexDirection(wxBOTH
), 
1338                  m_growMode(wxFLEX_GROWMODE_SPECIFIED
) 
1342 wxFlexGridSizer::wxFlexGridSizer( int cols
, int vgap
, int hgap 
) 
1343                : wxGridSizer( cols
, vgap
, hgap 
), 
1344                  m_flexDirection(wxBOTH
), 
1345                  m_growMode(wxFLEX_GROWMODE_SPECIFIED
) 
1349 wxFlexGridSizer::~wxFlexGridSizer() 
1353 void wxFlexGridSizer::RecalcSizes() 
1355     int nitems
, nrows
, ncols
; 
1356     if ( (nitems 
= CalcRowsCols(nrows
, ncols
)) == 0 ) 
1359     wxPoint 
pt( GetPosition() ); 
1360     wxSize 
sz( GetSize() ); 
1362     AdjustForGrowables(sz
, m_calculatedMinSize
, nrows
, ncols
); 
1364     sz 
= wxSize( pt
.x 
+ sz
.x
, pt
.y 
+ sz
.y 
); 
1367     for (int c 
= 0; c 
< ncols
; c
++) 
1370         for (int r 
= 0; r 
< nrows
; r
++) 
1372             int i 
= r 
* ncols 
+ c
; 
1375                 wxSizerItemList::compatibility_iterator node 
= m_children
.Item( i 
); 
1377                 wxASSERT_MSG( node
, _T("Failed to find node") ); 
1379                 int w 
= wxMax( 0, wxMin( m_colWidths
[c
], sz
.x 
- x 
) ); 
1380                 int h 
= wxMax( 0, wxMin( m_rowHeights
[r
], sz
.y 
- y 
) ); 
1382                 SetItemBounds( node
->GetData(), x
, y
, w
, h
); 
1384             if (m_rowHeights
[r
] != -1) 
1385                 y 
= y 
+ m_rowHeights
[r
] + m_vgap
; 
1387         if (m_colWidths
[c
] != -1) 
1388             x 
= x 
+ m_colWidths
[c
] + m_hgap
; 
1392 wxSize 
wxFlexGridSizer::CalcMin() 
1398     // Number of rows/columns can change as items are added or removed. 
1399     if ( !CalcRowsCols(nrows
, ncols
) ) 
1402     m_rowHeights
.SetCount(nrows
); 
1403     m_colWidths
.SetCount(ncols
); 
1405     // We have to recalcuate the sizes in case the item minimum size has 
1406     // changed since the previous layout, or the item has been hidden using 
1407     // wxSizer::Show(). If all the items in a row/column are hidden, the final 
1408     // dimension of the row/column will be -1, indicating that the column 
1409     // itself is hidden. 
1410     for( s 
= m_rowHeights
.GetCount(), i 
= 0; i 
< s
; ++i 
) 
1411         m_rowHeights
[ i 
] = -1; 
1412     for( s 
= m_colWidths
.GetCount(), i 
= 0; i 
< s
; ++i 
) 
1413         m_colWidths
[ i 
] = -1; 
1415     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1420         wxSizerItem    
*item 
= node
->GetData(); 
1421         if ( item
->IsShown() ) 
1423             wxSize 
sz( item
->CalcMin() ); 
1424             int row 
= i 
/ ncols
; 
1425             int col 
= i 
% ncols
; 
1427             m_rowHeights
[ row 
] = wxMax( wxMax( 0, sz
.y 
), m_rowHeights
[ row 
] ); 
1428             m_colWidths
[ col 
] = wxMax( wxMax( 0, sz
.x 
), m_colWidths
[ col 
] ); 
1431         node 
= node
->GetNext(); 
1435     AdjustForFlexDirection(); 
1437     // Sum total minimum size, including gaps between rows/columns. 
1438     // -1 is used as a magic number meaning empty column. 
1440     for (int col 
= 0; col 
< ncols
; col
++) 
1441         if ( m_colWidths
[ col 
] != -1 ) 
1442             width 
+= m_colWidths
[ col 
] + m_hgap
; 
1447     for (int row 
= 0; row 
< nrows
; row
++) 
1448         if ( m_rowHeights
[ row 
] != -1 ) 
1449             height 
+= m_rowHeights
[ row 
] + m_vgap
; 
1453     m_calculatedMinSize 
= wxSize( width
, height 
); 
1454     return m_calculatedMinSize
; 
1457 void wxFlexGridSizer::AdjustForFlexDirection() 
1459     // the logic in CalcMin works when we resize flexibly in both directions 
1460     // but maybe this is not the case 
1461     if ( m_flexDirection 
!= wxBOTH 
) 
1463         // select the array corresponding to the direction in which we do *not* 
1465         wxArrayInt
& array 
= m_flexDirection 
== wxVERTICAL 
? m_colWidths
 
1468         const size_t count 
= array
.GetCount(); 
1470         // find the largest value in this array 
1474         for ( n 
= 0; n 
< count
; ++n 
) 
1476             if ( array
[n
] > largest 
) 
1480         // and now fill it with the largest value 
1481         for ( n 
= 0; n 
< count
; ++n 
) 
1489 void wxFlexGridSizer::AdjustForGrowables(const wxSize
& sz
, const wxSize
& minsz
, 
1490                                          int nrows
, int ncols
) 
1492     // what to do with the rows? by default, resize them proportionally 
1493     if ( sz
.y 
> minsz
.y 
&& ( (m_flexDirection 
& wxVERTICAL
) || (m_growMode 
== wxFLEX_GROWMODE_SPECIFIED
) ) ) 
1495         int sum_proportions 
= 0; 
1496         int growable_space 
= 0; 
1499         for (idx 
= 0; idx 
< m_growableRows
.GetCount(); idx
++) 
1501             // Since the number of rows/columns can change as items are 
1502             // inserted/deleted, we need to verify at runtime that the 
1503             // requested growable rows/columns are still valid. 
1504             if (m_growableRows
[idx
] >= nrows
) 
1507             // If all items in a row/column are hidden, that row/column will 
1508             // have a dimension of -1.  This causes the row/column to be 
1509             // hidden completely. 
1510             if (m_rowHeights
[ m_growableRows
[idx
] ] == -1) 
1512             sum_proportions 
+= m_growableRowsProportions
[idx
]; 
1513             growable_space 
+= m_rowHeights
[ m_growableRows
[idx
] ]; 
1519             for (idx 
= 0; idx 
< m_growableRows
.GetCount(); idx
++) 
1521                 if (m_growableRows
[idx
] >= nrows 
) 
1523                 if (m_rowHeights
[ m_growableRows
[idx
] ] == -1) 
1524                     m_rowHeights
[ m_growableRows
[idx
] ] = 0; 
1527                     int delta 
= (sz
.y 
- minsz
.y
); 
1528                     if (sum_proportions 
== 0) 
1529                         delta 
= (delta
/num
) + m_rowHeights
[ m_growableRows
[idx
] ]; 
1531                         delta 
= ((delta
+growable_space
)*m_growableRowsProportions
[idx
]) / sum_proportions
; 
1532                     m_rowHeights
[ m_growableRows
[idx
] ] = delta
; 
1537     else if ( (m_growMode 
== wxFLEX_GROWMODE_ALL
) && (sz
.y 
> minsz
.y
) ) 
1539         // rounding problem? 
1540         for ( int row 
= 0; row 
< nrows
; ++row 
) 
1541             m_rowHeights
[ row 
] = sz
.y 
/ nrows
; 
1544     // the same logic as above but for the columns 
1545     if ( sz
.x 
> minsz
.x 
&& ( (m_flexDirection 
& wxHORIZONTAL
) || (m_growMode 
== wxFLEX_GROWMODE_SPECIFIED
) ) ) 
1547         int sum_proportions 
= 0; 
1548         int growable_space 
= 0; 
1551         for (idx 
= 0; idx 
< m_growableCols
.GetCount(); idx
++) 
1553             // Since the number of rows/columns can change as items are 
1554             // inserted/deleted, we need to verify at runtime that the 
1555             // requested growable rows/columns are still valid. 
1556             if (m_growableCols
[idx
] >= ncols
) 
1559             // If all items in a row/column are hidden, that row/column will 
1560             // have a dimension of -1.  This causes the column to be hidden 
1562             if (m_colWidths
[ m_growableCols
[idx
] ] == -1) 
1564             sum_proportions 
+= m_growableColsProportions
[idx
]; 
1565             growable_space 
+= m_colWidths
[ m_growableCols
[idx
] ]; 
1571             for (idx 
= 0; idx 
< m_growableCols
.GetCount(); idx
++) 
1573                 if (m_growableCols
[idx
] >= ncols 
) 
1575                 if (m_colWidths
[ m_growableCols
[idx
] ] == -1) 
1576                     m_colWidths
[ m_growableCols
[idx
] ] = 0; 
1579                     int delta 
= (sz
.x 
- minsz
.x
); 
1580                     if (sum_proportions 
== 0) 
1581                         delta 
= (delta
/num
) + m_colWidths
[ m_growableCols
[idx
] ]; 
1583                         delta 
= ((delta
+growable_space
)*m_growableColsProportions
[idx
])/sum_proportions
; 
1584                     m_colWidths
[ m_growableCols
[idx
] ] = delta
; 
1589     else if ( (m_growMode 
== wxFLEX_GROWMODE_ALL
) && (sz
.x 
> minsz
.x
) ) 
1591         for ( int col
=0; col 
< ncols
; ++col 
) 
1592             m_colWidths
[ col 
] = sz
.x 
/ ncols
; 
1597 void wxFlexGridSizer::AddGrowableRow( size_t idx
, int proportion 
) 
1599     m_growableRows
.Add( idx 
); 
1600     m_growableRowsProportions
.Add( proportion 
); 
1603 void wxFlexGridSizer::AddGrowableCol( size_t idx
, int proportion 
) 
1605     m_growableCols
.Add( idx 
); 
1606     m_growableColsProportions
.Add( proportion 
); 
1609 // helper function for RemoveGrowableCol/Row() 
1611 DoRemoveFromArrays(size_t idx
, wxArrayInt
& items
, wxArrayInt
& proportions
) 
1613     const size_t count 
= items
.size(); 
1614     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1616         if ( (size_t)items
[n
] == idx 
) 
1619             proportions
.RemoveAt(n
); 
1624     wxFAIL_MSG( _T("column/row is already not growable") ); 
1627 void wxFlexGridSizer::RemoveGrowableCol( size_t idx 
) 
1629     DoRemoveFromArrays(idx
, m_growableCols
, m_growableColsProportions
); 
1632 void wxFlexGridSizer::RemoveGrowableRow( size_t idx 
) 
1634     DoRemoveFromArrays(idx
, m_growableRows
, m_growableRowsProportions
); 
1637 //--------------------------------------------------------------------------- 
1639 //--------------------------------------------------------------------------- 
1641 wxBoxSizer::wxBoxSizer( int orient 
) 
1642     : m_orient( orient 
) 
1646 void wxBoxSizer::RecalcSizes() 
1648     if (m_children
.GetCount() == 0) 
1654         if (m_orient 
== wxHORIZONTAL
) 
1655             delta 
= m_size
.x 
- m_fixedWidth
; 
1657             delta 
= m_size
.y 
- m_fixedHeight
; 
1660     wxPoint 
pt( m_position 
); 
1662     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1665         wxSizerItem     
*item 
= node
->GetData(); 
1667         if (item
->IsShown()) 
1669             wxSize 
size( item
->GetMinSizeWithBorder() ); 
1671             if (m_orient 
== wxVERTICAL
) 
1673                 wxCoord height 
= size
.y
; 
1674                 if (item
->GetProportion()) 
1676                     // Because of at least one visible item has non-zero 
1677                     // proportion then m_stretchable is not zero 
1678                     height 
= (delta 
* item
->GetProportion()) / m_stretchable
; 
1681                 wxPoint 
child_pos( pt 
); 
1682                 wxSize  
child_size( size
.x
, height 
); 
1684                 if (item
->GetFlag() & (wxEXPAND 
| wxSHAPED
)) 
1685                     child_size
.x 
= m_size
.x
; 
1686                 else if (item
->GetFlag() & wxALIGN_RIGHT
) 
1687                     child_pos
.x 
+= m_size
.x 
- size
.x
; 
1688                 else if (item
->GetFlag() & (wxCENTER 
| wxALIGN_CENTER_HORIZONTAL
)) 
1689                 // XXX wxCENTER is added for backward compatibility; 
1690                 //     wxALIGN_CENTER should be used in new code 
1691                     child_pos
.x 
+= (m_size
.x 
- size
.x
) / 2; 
1693                 item
->SetDimension( child_pos
, child_size 
); 
1699                 wxCoord width 
= size
.x
; 
1700                 if (item
->GetProportion()) 
1702                     // Because of at least one visible item has non-zero 
1703                     // proportion then m_stretchable is not zero 
1704                     width 
= (delta 
* item
->GetProportion()) / m_stretchable
; 
1707                 wxPoint 
child_pos( pt 
); 
1708                 wxSize  
child_size( width
, size
.y 
); 
1710                 if (item
->GetFlag() & (wxEXPAND 
| wxSHAPED
)) 
1711                     child_size
.y 
= m_size
.y
; 
1712                 else if (item
->GetFlag() & wxALIGN_BOTTOM
) 
1713                     child_pos
.y 
+= m_size
.y 
- size
.y
; 
1714                 else if (item
->GetFlag() & (wxCENTER 
| wxALIGN_CENTER_VERTICAL
)) 
1715                 // XXX wxCENTER is added for backward compatibility; 
1716                 //     wxALIGN_CENTER should be used in new code 
1717                     child_pos
.y 
+= (m_size
.y 
- size
.y
) / 2; 
1719                 if ( m_containingWindow 
) 
1721                     child_pos
.x 
= m_containingWindow
->AdjustForLayoutDirection
 
1729                 item
->SetDimension( child_pos
, child_size 
); 
1735         node 
= node
->GetNext(); 
1739 wxSize 
wxBoxSizer::CalcMin() 
1741     if (m_children
.GetCount() == 0) 
1750     // precalc item minsizes and count proportions 
1751     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1754         wxSizerItem 
*item 
= node
->GetData(); 
1756         if ( item
->IsShown() ) 
1758             item
->CalcMin();  // result is stored in the item 
1760             m_stretchable 
+= item
->GetProportion(); 
1763         node 
= node
->GetNext(); 
1766     // Total minimum size (width or height) of sizer 
1769     node 
= m_children
.GetFirst(); 
1772         wxSizerItem 
*item 
= node
->GetData(); 
1774         if (item
->IsShown() && item
->GetProportion() != 0) 
1776             int stretch 
= item
->GetProportion(); 
1777             wxSize 
size( item
->GetMinSizeWithBorder() ); 
1780             // Integer division rounded up is (a + b - 1) / b 
1781             // Round up needed in order to guarantee that all 
1782             // all items will have size not less then their min size 
1783             if (m_orient 
== wxHORIZONTAL
) 
1784                 minSize 
= ( size
.x
*m_stretchable 
+ stretch 
- 1)/stretch
; 
1786                 minSize 
= ( size
.y
*m_stretchable 
+ stretch 
- 1)/stretch
; 
1788             if (minSize 
> maxMinSize
) 
1789                 maxMinSize 
= minSize
; 
1791         node 
= node
->GetNext(); 
1794     // Calculate overall minimum size 
1795     node 
= m_children
.GetFirst(); 
1798         wxSizerItem 
*item 
= node
->GetData(); 
1800         if (item
->IsShown()) 
1802             wxSize 
size( item
->GetMinSizeWithBorder() ); 
1803             if (item
->GetProportion() != 0) 
1805                 if (m_orient 
== wxHORIZONTAL
) 
1806                     size
.x 
= (maxMinSize
*item
->GetProportion())/m_stretchable
; 
1808                     size
.y 
= (maxMinSize
*item
->GetProportion())/m_stretchable
; 
1812                 if (m_orient 
== wxVERTICAL
) 
1814                     m_fixedHeight 
+= size
.y
; 
1815                     m_fixedWidth 
= wxMax( m_fixedWidth
, size
.x 
); 
1819                     m_fixedWidth 
+= size
.x
; 
1820                     m_fixedHeight 
= wxMax( m_fixedHeight
, size
.y 
); 
1824             if (m_orient 
== wxHORIZONTAL
) 
1826                 m_minWidth 
+= size
.x
; 
1827                 m_minHeight 
= wxMax( m_minHeight
, size
.y 
); 
1831                 m_minHeight 
+= size
.y
; 
1832                 m_minWidth 
= wxMax( m_minWidth
, size
.x 
); 
1835         node 
= node
->GetNext(); 
1838     return wxSize( m_minWidth
, m_minHeight 
); 
1841 //--------------------------------------------------------------------------- 
1843 //--------------------------------------------------------------------------- 
1847 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox 
*box
, int orient 
) 
1848     : wxBoxSizer( orient 
), 
1851     wxASSERT_MSG( box
, wxT("wxStaticBoxSizer needs a static box") ); 
1853     // do this so that our Detach() is called if the static box is destroyed 
1855     m_staticBox
->SetContainingSizer(this); 
1858 wxStaticBoxSizer::wxStaticBoxSizer(int orient
, wxWindow 
*win
, const wxString
& s
) 
1859                 : wxBoxSizer(orient
), 
1860                   m_staticBox(new wxStaticBox(win
, wxID_ANY
, s
)) 
1863     m_staticBox
->SetContainingSizer(this); 
1866 wxStaticBoxSizer::~wxStaticBoxSizer() 
1871 static void GetStaticBoxBorders( wxStaticBox 
*box
, 
1875     // this has to be done platform by platform as there is no way to 
1876     // guess the thickness of a wxStaticBox border 
1877     box
->GetBordersForSizer(borderTop
, borderOther
); 
1880 void wxStaticBoxSizer::RecalcSizes() 
1882     int top_border
, other_border
; 
1883     GetStaticBoxBorders(m_staticBox
, &top_border
, &other_border
); 
1885     m_staticBox
->SetSize( m_position
.x
, m_position
.y
, m_size
.x
, m_size
.y 
); 
1887     wxPoint 
old_pos( m_position 
); 
1888     m_position
.x 
+= other_border
; 
1889     m_position
.y 
+= top_border
; 
1890     wxSize 
old_size( m_size 
); 
1891     m_size
.x 
-= 2*other_border
; 
1892     m_size
.y 
-= top_border 
+ other_border
; 
1894     wxBoxSizer::RecalcSizes(); 
1896     m_position 
= old_pos
; 
1900 wxSize 
wxStaticBoxSizer::CalcMin() 
1902     int top_border
, other_border
; 
1903     GetStaticBoxBorders(m_staticBox
, &top_border
, &other_border
); 
1905     wxSize 
ret( wxBoxSizer::CalcMin() ); 
1906     ret
.x 
+= 2*other_border
; 
1907     ret
.y 
+= other_border 
+ top_border
; 
1912 void wxStaticBoxSizer::ShowItems( bool show 
) 
1914     m_staticBox
->Show( show 
); 
1915     wxBoxSizer::ShowItems( show 
); 
1918 bool wxStaticBoxSizer::Detach( wxWindow 
*window 
) 
1920     // avoid deleting m_staticBox in our dtor if it's being detached from the 
1921     // sizer (which can happen because it's being already destroyed for 
1923     if ( window 
== m_staticBox 
) 
1929     return wxSizer::Detach( window 
); 
1932 #endif // wxUSE_STATBOX 
1936 wxStdDialogButtonSizer::wxStdDialogButtonSizer() 
1937     : wxBoxSizer(wxHORIZONTAL
) 
1939     // Vertical buttons with lots of space on either side 
1940     // looks rubbish on WinCE, so let's not do this for now. 
1941     // If we are going to use vertical buttons, we should 
1942     // put the sizer to the right of other controls in the dialog, 
1943     // and that's beyond the scope of this sizer. 
1945     bool is_pda 
= (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA
); 
1946     // If we have a PDA screen, put yes/no button over 
1947     // all other buttons, otherwise on the left side. 
1949         m_orient 
= wxVERTICAL
; 
1952     m_buttonAffirmative 
= NULL
; 
1953     m_buttonApply 
= NULL
; 
1954     m_buttonNegative 
= NULL
; 
1955     m_buttonCancel 
= NULL
; 
1956     m_buttonHelp 
= NULL
; 
1959 void wxStdDialogButtonSizer::AddButton(wxButton 
*mybutton
) 
1961     switch (mybutton
->GetId()) 
1966             m_buttonAffirmative 
= mybutton
; 
1969             m_buttonApply 
= mybutton
; 
1972             m_buttonNegative 
= mybutton
; 
1975             m_buttonCancel 
= mybutton
; 
1978         case wxID_CONTEXT_HELP
: 
1979             m_buttonHelp 
= mybutton
; 
1986 void wxStdDialogButtonSizer::SetAffirmativeButton( wxButton 
*button 
) 
1988     m_buttonAffirmative 
= button
; 
1991 void wxStdDialogButtonSizer::SetNegativeButton( wxButton 
*button 
) 
1993     m_buttonNegative 
= button
; 
1996 void wxStdDialogButtonSizer::SetCancelButton( wxButton 
*button 
) 
1998     m_buttonCancel 
= button
; 
2001 void wxStdDialogButtonSizer::Realize() 
2004         Add(0, 0, 0, wxLEFT
, 6); 
2006             Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 6); 
2008         if (m_buttonNegative
){ 
2009             // HIG POLICE BULLETIN - destructive buttons need extra padding 
2010             // 24 pixels on either side 
2011             Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 12); 
2014         // extra whitespace between help/negative and cancel/ok buttons 
2015         Add(0, 0, 1, wxEXPAND
, 0); 
2017         if (m_buttonCancel
){ 
2018             Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 6); 
2019             // Cancel or help should be default 
2020             // m_buttonCancel->SetDefaultButton(); 
2023         // Ugh, Mac doesn't really have apply dialogs, so I'll just 
2024         // figure the best place is between Cancel and OK 
2026             Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 6); 
2028         if (m_buttonAffirmative
){ 
2029             Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE 
| wxLEFT
, 6); 
2031             if (m_buttonAffirmative
->GetId() == wxID_SAVE
){ 
2032                 // these buttons have set labels under Mac so we should use them 
2033                 m_buttonAffirmative
->SetLabel(_("Save")); 
2034                 if (m_buttonNegative
) 
2035                     m_buttonNegative
->SetLabel(_("Don't Save")); 
2039         // Extra space around and at the right 
2041 #elif defined(__WXGTK20__) 
2042         Add(0, 0, 0, wxLEFT
, 9); 
2044             Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 3); 
2046         // extra whitespace between help and cancel/ok buttons 
2047         Add(0, 0, 1, wxEXPAND
, 0); 
2049         if (m_buttonNegative
){ 
2050             Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 3); 
2053         if (m_buttonCancel
){ 
2054             Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 3); 
2055             // Cancel or help should be default 
2056             // m_buttonCancel->SetDefaultButton(); 
2060             Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 3); 
2062         if (m_buttonAffirmative
) 
2063             Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE 
| wxLEFT
, 6); 
2064 #elif defined(__WXMSW__) 
2067         // right-justify buttons 
2068         Add(0, 0, 1, wxEXPAND
, 0); 
2070         if (m_buttonAffirmative
){ 
2071             Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonAffirmative
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
2074         if (m_buttonNegative
){ 
2075             Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonNegative
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
2078         if (m_buttonCancel
){ 
2079             Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonCancel
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
2082             Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonApply
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
2085             Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonHelp
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
2087         // GTK+1 and any other platform 
2089         // Add(0, 0, 0, wxLEFT, 5); // Not sure what this was for but it unbalances the dialog 
2091             Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonHelp
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
2093         // extra whitespace between help and cancel/ok buttons 
2094         Add(0, 0, 1, wxEXPAND
, 0); 
2097             Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonApply
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
2099         if (m_buttonAffirmative
){ 
2100             Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonAffirmative
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
2103         if (m_buttonNegative
){ 
2104             Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonNegative
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
2107         if (m_buttonCancel
){ 
2108             Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonCancel
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
2109             // Cancel or help should be default 
2110             // m_buttonCancel->SetDefaultButton(); 
2116 #endif // wxUSE_BUTTON