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" 
  21 #include "wx/private/flagscheck.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/display.h" 
  35 #include "wx/vector.h" 
  36 #include "wx/listimpl.cpp" 
  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 // check for flags conflicts 
  93 static const int SIZER_FLAGS_MASK 
= 
  95     wxADD_FLAG(wxHORIZONTAL
, 
  96     wxADD_FLAG(wxVERTICAL
, 
 101     wxADD_FLAG(wxALIGN_NOT
, 
 102     wxADD_FLAG(wxALIGN_CENTER_HORIZONTAL
, 
 103     wxADD_FLAG(wxALIGN_RIGHT
, 
 104     wxADD_FLAG(wxALIGN_BOTTOM
, 
 105     wxADD_FLAG(wxALIGN_CENTER_VERTICAL
, 
 106     wxADD_FLAG(wxFIXED_MINSIZE
, 
 107     wxADD_FLAG(wxRESERVE_SPACE_EVEN_IF_HIDDEN
, 
 108     wxADD_FLAG(wxSTRETCH_NOT
, 
 114 #define ASSERT_VALID_SIZER_FLAGS(f)  wxASSERT_VALID_FLAGS(f, SIZER_FLAGS_MASK) 
 117 void wxSizerItem::Init(const wxSizerFlags
& flags
) 
 121     m_proportion 
= flags
.GetProportion(); 
 122     m_flag 
= flags
.GetFlags(); 
 123     m_border 
= flags
.GetBorderInPixels(); 
 125     ASSERT_VALID_SIZER_FLAGS( m_flag 
); 
 128 wxSizerItem::wxSizerItem() 
 139 void wxSizerItem::DoSetWindow(wxWindow 
*window
) 
 141     wxCHECK_RET( window
, wxT("NULL window in wxSizerItem::SetWindow()") ); 
 143     m_kind 
= Item_Window
; 
 146     // window doesn't become smaller than its initial size, whatever happens 
 147     m_minSize 
= window
->GetSize(); 
 149     if ( m_flag 
& wxFIXED_MINSIZE 
) 
 150         window
->SetMinSize(m_minSize
); 
 152     // aspect ratio calculated from initial size 
 156 wxSizerItem::wxSizerItem(wxWindow 
*window
, 
 162              m_proportion(proportion
), 
 168     ASSERT_VALID_SIZER_FLAGS( m_flag 
); 
 174 void wxSizerItem::DoSetSizer(wxSizer 
*sizer
) 
 180 wxSizerItem::wxSizerItem(wxSizer 
*sizer
, 
 187              m_proportion(proportion
), 
 194     ASSERT_VALID_SIZER_FLAGS( m_flag 
); 
 198     // m_minSize is set later 
 202 void wxSizerItem::DoSetSpacer(const wxSize
& size
) 
 204     m_kind 
= Item_Spacer
; 
 205     m_spacer 
= new wxSizerSpacer(size
); 
 210 wxSizerItem::wxSizerItem(int width
, 
 218              m_minSize(width
, height
), // minimal size is the initial size 
 219              m_proportion(proportion
), 
 225     ASSERT_VALID_SIZER_FLAGS( m_flag 
); 
 227     DoSetSpacer(wxSize(width
, height
)); 
 230 wxSizerItem::~wxSizerItem() 
 236 void wxSizerItem::Free() 
 244             m_window
->SetContainingSizer(NULL
); 
 257             wxFAIL_MSG( wxT("unexpected wxSizerItem::m_kind") ); 
 263 wxSize 
wxSizerItem::GetSpacer() const 
 266     if ( m_kind 
== Item_Spacer 
) 
 267         size 
= m_spacer
->GetSize(); 
 273 wxSize 
wxSizerItem::GetSize() const 
 282             ret 
= m_window
->GetSize(); 
 286             ret 
= m_sizer
->GetSize(); 
 290             ret 
= m_spacer
->GetSize(); 
 295             wxFAIL_MSG( wxT("unexpected wxSizerItem::m_kind") ); 
 302     if (m_flag 
& wxNORTH
) 
 304     if (m_flag 
& wxSOUTH
) 
 310 bool wxSizerItem::InformFirstDirection(int direction
, int size
, int availableOtherDir
) 
 312     // The size that come here will be including borders. Child items should get it 
 316         if( direction
==wxHORIZONTAL 
) 
 323         else if( direction
==wxVERTICAL 
) 
 325             if (m_flag 
& wxNORTH
) 
 327             if (m_flag 
& wxSOUTH
) 
 333     // Pass the information along to the held object 
 336         didUse 
= GetSizer()->InformFirstDirection(direction
,size
,availableOtherDir
); 
 338             m_minSize 
= GetSizer()->CalcMin(); 
 342         didUse 
=  GetWindow()->InformFirstDirection(direction
,size
,availableOtherDir
); 
 344             m_minSize 
= m_window
->GetEffectiveMinSize(); 
 346         // This information is useful for items with wxSHAPED flag, since 
 347         // we can request an optimal min size for such an item. Even if 
 348         // we overwrite the m_minSize member here, we can read it back from 
 349         // the owned window (happens automatically). 
 350         if( (m_flag 
& wxSHAPED
) && (m_flag 
& wxEXPAND
) && direction 
) 
 352             if( !wxIsNullDouble(m_ratio
) ) 
 354                 wxCHECK_MSG( (m_proportion
==0), false, wxT("Shaped item, non-zero proportion in wxSizerItem::InformFirstDirection()") ); 
 355                 if( direction
==wxHORIZONTAL 
&& !wxIsNullDouble(m_ratio
) ) 
 357                     // Clip size so that we don't take too much 
 358                     if( availableOtherDir
>=0 && int(size
/m_ratio
)-m_minSize
.y
>availableOtherDir 
) 
 359                         size 
= int((availableOtherDir
+m_minSize
.y
)*m_ratio
); 
 360                     m_minSize 
= wxSize(size
,int(size
/m_ratio
)); 
 362                 else if( direction
==wxVERTICAL 
) 
 364                     // Clip size so that we don't take too much 
 365                     if( availableOtherDir
>=0 && int(size
*m_ratio
)-m_minSize
.x
>availableOtherDir 
) 
 366                         size 
= int((availableOtherDir
+m_minSize
.x
)/m_ratio
); 
 367                     m_minSize 
= wxSize(int(size
*m_ratio
),size
); 
 377 wxSize 
wxSizerItem::CalcMin() 
 381         m_minSize 
= m_sizer
->GetMinSize(); 
 383         // if we have to preserve aspect ratio _AND_ this is 
 384         // the first-time calculation, consider ret to be initial size 
 385         if ( (m_flag 
& wxSHAPED
) && wxIsNullDouble(m_ratio
) ) 
 388     else if ( IsWindow() ) 
 390         // Since the size of the window may change during runtime, we 
 391         // should use the current minimal/best size. 
 392         m_minSize 
= m_window
->GetEffectiveMinSize(); 
 395     return GetMinSizeWithBorder(); 
 398 wxSize 
wxSizerItem::GetMinSizeWithBorder() const 
 400     wxSize ret 
= m_minSize
; 
 406     if (m_flag 
& wxNORTH
) 
 408     if (m_flag 
& wxSOUTH
) 
 415 void wxSizerItem::SetDimension( const wxPoint
& pos_
, const wxSize
& size_ 
) 
 419     if (m_flag 
& wxSHAPED
) 
 421         // adjust aspect ratio 
 422         int rwidth 
= (int) (size
.y 
* m_ratio
); 
 426             int rheight 
= (int) (size
.x 
/ m_ratio
); 
 427             // add vertical space 
 428             if (m_flag 
& wxALIGN_CENTER_VERTICAL
) 
 429                 pos
.y 
+= (size
.y 
- rheight
) / 2; 
 430             else if (m_flag 
& wxALIGN_BOTTOM
) 
 431                 pos
.y 
+= (size
.y 
- rheight
); 
 432             // use reduced dimensions 
 435         else if (rwidth 
< size
.x
) 
 437             // add horizontal space 
 438             if (m_flag 
& wxALIGN_CENTER_HORIZONTAL
) 
 439                 pos
.x 
+= (size
.x 
- rwidth
) / 2; 
 440             else if (m_flag 
& wxALIGN_RIGHT
) 
 441                 pos
.x 
+= (size
.x 
- rwidth
); 
 446     // This is what GetPosition() returns. Since we calculate 
 447     // borders afterwards, GetPosition() will be the left/top 
 448     // corner of the surrounding border. 
 460     if (m_flag 
& wxNORTH
) 
 465     if (m_flag 
& wxSOUTH
) 
 475     m_rect 
= wxRect(pos
, size
); 
 480             wxFAIL_MSG( wxT("can't set size of uninitialized sizer item") ); 
 485             // Use wxSIZE_FORCE_EVENT here since a sizer item might 
 486             // have changed alignment or some other property which would 
 487             // not change the size of the window. In such a case, no 
 488             // wxSizeEvent would normally be generated and thus the 
 489             // control wouldn't get layed out correctly here. 
 491             m_window
->SetSize(pos
.x
, pos
.y
, size
.x
, size
.y
, 
 492                               wxSIZE_ALLOW_MINUS_ONE
|wxSIZE_FORCE_EVENT 
); 
 494             m_window
->SetSize(pos
.x
, pos
.y
, size
.x
, size
.y
, 
 495                               wxSIZE_ALLOW_MINUS_ONE 
); 
 500             m_sizer
->SetDimension(pos
, size
); 
 504             m_spacer
->SetSize(size
); 
 509             wxFAIL_MSG( wxT("unexpected wxSizerItem::m_kind") ); 
 513 void wxSizerItem::DeleteWindows() 
 522             //We are deleting the window from this sizer - normally 
 523             //the window destroys the sizer associated with it, 
 524             //which might destroy this, which we don't want 
 525             m_window
->SetContainingSizer(NULL
); 
 527             //Putting this after the switch will result in a spacer 
 528             //not being deleted properly on destruction 
 533             m_sizer
->DeleteWindows(); 
 538             wxFAIL_MSG( wxT("unexpected wxSizerItem::m_kind") ); 
 543 void wxSizerItem::Show( bool show 
) 
 548             wxFAIL_MSG( wxT("can't show uninitialized sizer item") ); 
 552             m_window
->Show(show
); 
 560             m_spacer
->Show(show
); 
 565             wxFAIL_MSG( wxT("unexpected wxSizerItem::m_kind") ); 
 569 bool wxSizerItem::IsShown() const 
 571     if ( m_flag 
& wxRESERVE_SPACE_EVEN_IF_HIDDEN 
) 
 577             // we may be called from CalcMin(), just return false so that we're 
 582             return m_window
->IsShown(); 
 586             // arbitrarily decide that if at least one of our elements is 
 587             // shown, so are we (this arbitrariness is the reason for 
 588             // deprecating this function) 
 589             for ( wxSizerItemList::compatibility_iterator
 
 590                     node 
= m_sizer
->GetChildren().GetFirst(); 
 592                   node 
= node
->GetNext() ) 
 594                 if ( node
->GetData()->IsShown() ) 
 601             return m_spacer
->IsShown(); 
 605             wxFAIL_MSG( wxT("unexpected wxSizerItem::m_kind") ); 
 611 #if WXWIN_COMPATIBILITY_2_6 
 612 void wxSizerItem::SetOption( int option 
) 
 614     SetProportion( option 
); 
 617 int wxSizerItem::GetOption() const 
 619     return GetProportion(); 
 621 #endif // WXWIN_COMPATIBILITY_2_6 
 624 //--------------------------------------------------------------------------- 
 626 //--------------------------------------------------------------------------- 
 630     WX_CLEAR_LIST(wxSizerItemList
, m_children
); 
 633 wxSizerItem
* wxSizer::DoInsert( size_t index
, wxSizerItem 
*item 
) 
 635     m_children
.Insert( index
, item 
); 
 637     if ( item
->GetWindow() ) 
 638         item
->GetWindow()->SetContainingSizer( this ); 
 640     if ( item
->GetSizer() ) 
 641         item
->GetSizer()->SetContainingWindow( m_containingWindow 
); 
 646 void wxSizer::SetContainingWindow(wxWindow 
*win
) 
 648     if ( win 
== m_containingWindow 
) 
 651     m_containingWindow 
= win
; 
 653     // set the same window for all nested sizers as well, they also are in the 
 655     for ( wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 657           node 
= node
->GetNext() ) 
 659         wxSizerItem 
*const item 
= node
->GetData(); 
 660         wxSizer 
*const sizer 
= item
->GetSizer(); 
 664             sizer
->SetContainingWindow(win
); 
 669 #if WXWIN_COMPATIBILITY_2_6 
 670 bool wxSizer::Remove( wxWindow 
*window 
) 
 672     return Detach( window 
); 
 674 #endif // WXWIN_COMPATIBILITY_2_6 
 676 bool wxSizer::Remove( wxSizer 
*sizer 
) 
 678     wxASSERT_MSG( sizer
, wxT("Removing NULL sizer") ); 
 680     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 683         wxSizerItem     
*item 
= node
->GetData(); 
 685         if (item
->GetSizer() == sizer
) 
 688             m_children
.Erase( node 
); 
 692         node 
= node
->GetNext(); 
 698 bool wxSizer::Remove( int index 
) 
 700     wxCHECK_MSG( index 
>= 0 && (size_t)index 
< m_children
.GetCount(), 
 702                  wxT("Remove index is out of range") ); 
 704     wxSizerItemList::compatibility_iterator node 
= m_children
.Item( index 
); 
 706     wxCHECK_MSG( node
, false, wxT("Failed to find child node") ); 
 708     delete node
->GetData(); 
 709     m_children
.Erase( node 
); 
 714 bool wxSizer::Detach( wxSizer 
*sizer 
) 
 716     wxASSERT_MSG( sizer
, wxT("Detaching NULL sizer") ); 
 718     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 721         wxSizerItem     
*item 
= node
->GetData(); 
 723         if (item
->GetSizer() == sizer
) 
 727             m_children
.Erase( node 
); 
 730         node 
= node
->GetNext(); 
 736 bool wxSizer::Detach( wxWindow 
*window 
) 
 738     wxASSERT_MSG( window
, wxT("Detaching NULL window") ); 
 740     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 743         wxSizerItem     
*item 
= node
->GetData(); 
 745         if (item
->GetWindow() == window
) 
 748             m_children
.Erase( node 
); 
 751         node 
= node
->GetNext(); 
 757 bool wxSizer::Detach( int index 
) 
 759     wxCHECK_MSG( index 
>= 0 && (size_t)index 
< m_children
.GetCount(), 
 761                  wxT("Detach index is out of range") ); 
 763     wxSizerItemList::compatibility_iterator node 
= m_children
.Item( index 
); 
 765     wxCHECK_MSG( node
, false, wxT("Failed to find child node") ); 
 767     wxSizerItem 
*item 
= node
->GetData(); 
 769     if ( item
->IsSizer() ) 
 773     m_children
.Erase( node 
); 
 777 bool wxSizer::Replace( wxWindow 
*oldwin
, wxWindow 
*newwin
, bool recursive 
) 
 779     wxASSERT_MSG( oldwin
, wxT("Replacing NULL window") ); 
 780     wxASSERT_MSG( newwin
, wxT("Replacing with NULL window") ); 
 782     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 785         wxSizerItem     
*item 
= node
->GetData(); 
 787         if (item
->GetWindow() == oldwin
) 
 789             item
->AssignWindow(newwin
); 
 790             newwin
->SetContainingSizer( this ); 
 793         else if (recursive 
&& item
->IsSizer()) 
 795             if (item
->GetSizer()->Replace( oldwin
, newwin
, true )) 
 799         node 
= node
->GetNext(); 
 805 bool wxSizer::Replace( wxSizer 
*oldsz
, wxSizer 
*newsz
, bool recursive 
) 
 807     wxASSERT_MSG( oldsz
, wxT("Replacing NULL sizer") ); 
 808     wxASSERT_MSG( newsz
, wxT("Replacing with NULL sizer") ); 
 810     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 813         wxSizerItem     
*item 
= node
->GetData(); 
 815         if (item
->GetSizer() == oldsz
) 
 817             item
->AssignSizer(newsz
); 
 820         else if (recursive 
&& item
->IsSizer()) 
 822             if (item
->GetSizer()->Replace( oldsz
, newsz
, true )) 
 826         node 
= node
->GetNext(); 
 832 bool wxSizer::Replace( size_t old
, wxSizerItem 
*newitem 
) 
 834     wxCHECK_MSG( old 
< m_children
.GetCount(), false, wxT("Replace index is out of range") ); 
 835     wxASSERT_MSG( newitem
, wxT("Replacing with NULL item") ); 
 837     wxSizerItemList::compatibility_iterator node 
= m_children
.Item( old 
); 
 839     wxCHECK_MSG( node
, false, wxT("Failed to find child node") ); 
 841     wxSizerItem 
*item 
= node
->GetData(); 
 842     node
->SetData(newitem
); 
 848 void wxSizer::Clear( bool delete_windows 
) 
 850     // First clear the ContainingSizer pointers 
 851     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 854         wxSizerItem     
*item 
= node
->GetData(); 
 856         if (item
->IsWindow()) 
 857             item
->GetWindow()->SetContainingSizer( NULL 
); 
 858         node 
= node
->GetNext(); 
 861     // Destroy the windows if needed 
 865     // Now empty the list 
 866     WX_CLEAR_LIST(wxSizerItemList
, m_children
); 
 869 void wxSizer::DeleteWindows() 
 871     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
 874         wxSizerItem     
*item 
= node
->GetData(); 
 876         item
->DeleteWindows(); 
 877         node 
= node
->GetNext(); 
 881 wxSize 
wxSizer::ComputeFittingClientSize(wxWindow 
*window
) 
 883     wxCHECK_MSG( window
, wxDefaultSize
, "window can't be NULL" ); 
 885     // take the min size by default and limit it by max size 
 886     wxSize size 
= GetMinClientSize(window
); 
 889     wxTopLevelWindow 
*tlw 
= wxDynamicCast(window
, wxTopLevelWindow
); 
 892         // hack for small screen devices where TLWs are always full screen 
 893         if ( tlw
->IsAlwaysMaximized() ) 
 895             return tlw
->GetClientSize(); 
 898         // limit the window to the size of the display it is on 
 899         int disp 
= wxDisplay::GetFromWindow(window
); 
 900         if ( disp 
== wxNOT_FOUND 
) 
 902             // or, if we don't know which one it is, of the main one 
 906         sizeMax 
= wxDisplay(disp
).GetClientArea().GetSize(); 
 908         // space for decorations and toolbars etc. 
 909         sizeMax 
= tlw
->WindowToClientSize(sizeMax
); 
 913         sizeMax 
= GetMaxClientSize(window
); 
 916     if ( sizeMax
.x 
!= wxDefaultCoord 
&& size
.x 
> sizeMax
.x 
) 
 918     if ( sizeMax
.y 
!= wxDefaultCoord 
&& size
.y 
> sizeMax
.y 
) 
 924 wxSize 
wxSizer::ComputeFittingWindowSize(wxWindow 
*window
) 
 926     wxCHECK_MSG( window
, wxDefaultSize
, "window can't be NULL" ); 
 928     return window
->ClientToWindowSize(ComputeFittingClientSize(window
)); 
 931 wxSize 
wxSizer::Fit( wxWindow 
*window 
) 
 933     wxCHECK_MSG( window
, wxDefaultSize
, "window can't be NULL" ); 
 936     window
->SetClientSize(ComputeFittingClientSize(window
)); 
 938     // return entire size 
 939     return window
->GetSize(); 
 942 void wxSizer::FitInside( wxWindow 
*window 
) 
 945     if (window
->IsTopLevel()) 
 946         size 
= VirtualFitSize( window 
); 
 948         size 
= GetMinClientSize( window 
); 
 950     window
->SetVirtualSize( size 
); 
 953 void wxSizer::Layout() 
 955     // (re)calculates minimums needed for each item and other preparations 
 959     // Applies the layout and repositions/resizes the items 
 963 void wxSizer::SetSizeHints( wxWindow 
*window 
) 
 965     // Preserve the window's max size hints, but set the 
 966     // lower bound according to the sizer calculations. 
 968     // This is equivalent to calling Fit(), except that we need to set 
 969     // the size hints _in between_ the two steps performed by Fit 
 970     // (1. ComputeFittingClientSize, 2. SetClientSize). That's because 
 971     // otherwise SetClientSize() could have no effect if there already are 
 972     // size hints in effect that forbid requested client size. 
 974     const wxSize clientSize 
= ComputeFittingClientSize(window
); 
 976     window
->SetMinClientSize(clientSize
); 
 977     window
->SetClientSize(clientSize
); 
 980 #if WXWIN_COMPATIBILITY_2_8 
 981 void wxSizer::SetVirtualSizeHints( wxWindow 
*window 
) 
 985 #endif // WXWIN_COMPATIBILITY_2_8 
 987 // TODO on mac we need a function that determines how much free space this 
 988 // min size contains, in order to make sure that we have 20 pixels of free 
 989 // space around the controls 
 990 wxSize 
wxSizer::GetMaxClientSize( wxWindow 
*window 
) const 
 992     return window
->WindowToClientSize(window
->GetMaxSize()); 
 995 wxSize 
wxSizer::GetMinClientSize( wxWindow 
*WXUNUSED(window
) ) 
 997     return GetMinSize();  // Already returns client size. 
1000 wxSize 
wxSizer::VirtualFitSize( wxWindow 
*window 
) 
1002     wxSize size     
= GetMinClientSize( window 
); 
1003     wxSize sizeMax  
= GetMaxClientSize( window 
); 
1005     // Limit the size if sizeMax != wxDefaultSize 
1007     if ( size
.x 
> sizeMax
.x 
&& sizeMax
.x 
!= wxDefaultCoord 
) 
1009     if ( size
.y 
> sizeMax
.y 
&& sizeMax
.y 
!= wxDefaultCoord 
) 
1015 wxSize 
wxSizer::GetMinSize() 
1017     wxSize 
ret( CalcMin() ); 
1018     if (ret
.x 
< m_minSize
.x
) ret
.x 
= m_minSize
.x
; 
1019     if (ret
.y 
< m_minSize
.y
) ret
.y 
= m_minSize
.y
; 
1023 void wxSizer::DoSetMinSize( int width
, int height 
) 
1025     m_minSize
.x 
= width
; 
1026     m_minSize
.y 
= height
; 
1029 bool wxSizer::DoSetItemMinSize( wxWindow 
*window
, int width
, int height 
) 
1031     wxASSERT_MSG( window
, wxT("SetMinSize for NULL window") ); 
1033     // Is it our immediate child? 
1035     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1038         wxSizerItem     
*item 
= node
->GetData(); 
1040         if (item
->GetWindow() == window
) 
1042             item
->SetMinSize( width
, height 
); 
1045         node 
= node
->GetNext(); 
1048     // No?  Search any subsizers we own then 
1050     node 
= m_children
.GetFirst(); 
1053         wxSizerItem     
*item 
= node
->GetData(); 
1055         if ( item
->GetSizer() && 
1056              item
->GetSizer()->DoSetItemMinSize( window
, width
, height 
) ) 
1058             // A child sizer found the requested windw, exit. 
1061         node 
= node
->GetNext(); 
1067 bool wxSizer::DoSetItemMinSize( wxSizer 
*sizer
, int width
, int height 
) 
1069     wxASSERT_MSG( sizer
, wxT("SetMinSize for NULL sizer") ); 
1071     // Is it our immediate child? 
1073     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1076         wxSizerItem     
*item 
= node
->GetData(); 
1078         if (item
->GetSizer() == sizer
) 
1080             item
->GetSizer()->DoSetMinSize( width
, height 
); 
1083         node 
= node
->GetNext(); 
1086     // No?  Search any subsizers we own then 
1088     node 
= m_children
.GetFirst(); 
1091         wxSizerItem     
*item 
= node
->GetData(); 
1093         if ( item
->GetSizer() && 
1094              item
->GetSizer()->DoSetItemMinSize( sizer
, width
, height 
) ) 
1096             // A child found the requested sizer, exit. 
1099         node 
= node
->GetNext(); 
1105 bool wxSizer::DoSetItemMinSize( size_t index
, int width
, int height 
) 
1107     wxSizerItemList::compatibility_iterator node 
= m_children
.Item( index 
); 
1109     wxCHECK_MSG( node
, false, wxT("Failed to find child node") ); 
1111     wxSizerItem     
*item 
= node
->GetData(); 
1113     if (item
->GetSizer()) 
1115         // Sizers contains the minimal size in them, if not calculated ... 
1116         item
->GetSizer()->DoSetMinSize( width
, height 
); 
1120         // ... but the minimal size of spacers and windows is stored via the item 
1121         item
->SetMinSize( width
, height 
); 
1127 wxSizerItem
* wxSizer::GetItem( wxWindow 
*window
, bool recursive 
) 
1129     wxASSERT_MSG( window
, wxT("GetItem for NULL window") ); 
1131     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1134         wxSizerItem     
*item 
= node
->GetData(); 
1136         if (item
->GetWindow() == window
) 
1140         else if (recursive 
&& item
->IsSizer()) 
1142             wxSizerItem 
*subitem 
= item
->GetSizer()->GetItem( window
, true ); 
1147         node 
= node
->GetNext(); 
1153 wxSizerItem
* wxSizer::GetItem( wxSizer 
*sizer
, bool recursive 
) 
1155     wxASSERT_MSG( sizer
, wxT("GetItem for NULL sizer") ); 
1157     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1160         wxSizerItem 
*item 
= node
->GetData(); 
1162         if (item
->GetSizer() == sizer
) 
1166         else if (recursive 
&& item
->IsSizer()) 
1168             wxSizerItem 
*subitem 
= item
->GetSizer()->GetItem( sizer
, true ); 
1173         node 
= node
->GetNext(); 
1179 wxSizerItem
* wxSizer::GetItem( size_t index 
) 
1181     wxCHECK_MSG( index 
< m_children
.GetCount(), 
1183                  wxT("GetItem index is out of range") ); 
1185     return m_children
.Item( index 
)->GetData(); 
1188 wxSizerItem
* wxSizer::GetItemById( int id
, bool recursive 
) 
1190     // This gets a sizer item by the id of the sizer item 
1191     // and NOT the id of a window if the item is a window. 
1193     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1196         wxSizerItem     
*item 
= node
->GetData(); 
1198         if (item
->GetId() == id
) 
1202         else if (recursive 
&& item
->IsSizer()) 
1204             wxSizerItem 
*subitem 
= item
->GetSizer()->GetItemById( id
, true ); 
1209         node 
= node
->GetNext(); 
1215 bool wxSizer::Show( wxWindow 
*window
, bool show
, bool recursive 
) 
1217     wxSizerItem 
*item 
= GetItem( window
, recursive 
); 
1228 bool wxSizer::Show( wxSizer 
*sizer
, bool show
, bool recursive 
) 
1230     wxSizerItem 
*item 
= GetItem( sizer
, recursive 
); 
1241 bool wxSizer::Show( size_t index
, bool show
) 
1243     wxSizerItem 
*item 
= GetItem( index 
); 
1254 void wxSizer::ShowItems( bool show 
) 
1256     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1259         node
->GetData()->Show( show 
); 
1260         node 
= node
->GetNext(); 
1264 bool wxSizer::IsShown( wxWindow 
*window 
) const 
1266     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1269         wxSizerItem     
*item 
= node
->GetData(); 
1271         if (item
->GetWindow() == window
) 
1273             return item
->IsShown(); 
1275         node 
= node
->GetNext(); 
1278     wxFAIL_MSG( wxT("IsShown failed to find sizer item") ); 
1283 bool wxSizer::IsShown( wxSizer 
*sizer 
) const 
1285     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1288         wxSizerItem     
*item 
= node
->GetData(); 
1290         if (item
->GetSizer() == sizer
) 
1292             return item
->IsShown(); 
1294         node 
= node
->GetNext(); 
1297     wxFAIL_MSG( wxT("IsShown failed to find sizer item") ); 
1302 bool wxSizer::IsShown( size_t index 
) const 
1304     wxCHECK_MSG( index 
< m_children
.GetCount(), 
1306                  wxT("IsShown index is out of range") ); 
1308     return m_children
.Item( index 
)->GetData()->IsShown(); 
1312 //--------------------------------------------------------------------------- 
1314 //--------------------------------------------------------------------------- 
1316 wxGridSizer::wxGridSizer( int cols
, int vgap
, int hgap 
) 
1317     : m_rows( cols 
== 0 ? 1 : 0 ), 
1324 wxGridSizer::wxGridSizer( int cols
, const wxSize
& gap 
) 
1325     : m_rows( cols 
== 0 ? 1 : 0 ), 
1327       m_vgap( gap
.GetHeight() ), 
1328       m_hgap( gap
.GetWidth() ) 
1332 wxGridSizer::wxGridSizer( int rows
, int cols
, int vgap
, int hgap 
) 
1333     : m_rows( rows 
|| cols 
? rows 
: 1 ), 
1340 wxGridSizer::wxGridSizer( int rows
, int cols
, const wxSize
& gap 
) 
1341     : m_rows( rows 
|| cols 
? rows 
: 1 ), 
1343       m_vgap( gap
.GetHeight() ), 
1344       m_hgap( gap
.GetWidth() ) 
1348 wxSizerItem 
*wxGridSizer::DoInsert(size_t index
, wxSizerItem 
*item
) 
1350     // if only the number of columns or the number of rows is specified for a 
1351     // sizer, arbitrarily many items can be added to it but if both of them are 
1352     // fixed, then the sizer can't have more than that many items -- check for 
1353     // this here to ensure that we detect errors as soon as possible 
1354     if ( m_cols 
&& m_rows 
) 
1356         const int nitems 
= m_children
.GetCount(); 
1357         if ( nitems 
== m_cols
*m_rows 
) 
1361                     "too many items (%d > %d*%d) in grid sizer (maybe you " 
1362                     "should omit the number of either rows or columns?)", 
1363                 nitems 
+ 1, m_cols
, m_rows
) 
1366             // additionally, continuing to use the specified number of columns 
1367             // and rows is not a good idea as callers of CalcRowsCols() expect 
1368             // that all sizer items can fit into m_cols-/m_rows-sized arrays 
1369             // which is not the case if there are too many items and results in 
1370             // crashes, so let it compute the number of rows automatically by 
1371             // forgetting the (wrong) number of rows specified (this also has a 
1372             // nice side effect of giving only one assert even if there are 
1373             // many more items than allowed in this sizer) 
1378     return wxSizer::DoInsert(index
, item
); 
1381 int wxGridSizer::CalcRowsCols(int& nrows
, int& ncols
) const 
1383     const int nitems 
= m_children
.GetCount(); 
1385     ncols 
= GetEffectiveColsCount(); 
1386     nrows 
= GetEffectiveRowsCount(); 
1388     // Since Insert() checks for overpopulation, the following 
1389     // should only assert if the grid was shrunk via SetRows() / SetCols() 
1390     wxASSERT_MSG( nitems 
<= ncols
*nrows
, "logic error in wxGridSizer" ); 
1395 void wxGridSizer::RecalcSizes() 
1397     int nitems
, nrows
, ncols
; 
1398     if ( (nitems 
= CalcRowsCols(nrows
, ncols
)) == 0 ) 
1401     wxSize 
sz( GetSize() ); 
1402     wxPoint 
pt( GetPosition() ); 
1404     int w 
= (sz
.x 
- (ncols 
- 1) * m_hgap
) / ncols
; 
1405     int h 
= (sz
.y 
- (nrows 
- 1) * m_vgap
) / nrows
; 
1408     for (int c 
= 0; c 
< ncols
; c
++) 
1411         for (int r 
= 0; r 
< nrows
; r
++) 
1413             int i 
= r 
* ncols 
+ c
; 
1416                 wxSizerItemList::compatibility_iterator node 
= m_children
.Item( i 
); 
1418                 wxASSERT_MSG( node
, wxT("Failed to find SizerItemList node") ); 
1420                 SetItemBounds( node
->GetData(), x
, y
, w
, h
); 
1428 wxSize 
wxGridSizer::CalcMin() 
1431     if ( CalcRowsCols(nrows
, ncols
) == 0 ) 
1434     // Find the max width and height for any component 
1438     wxSizerItemList::compatibility_iterator node 
= m_children
.GetFirst(); 
1441         wxSizerItem     
*item 
= node
->GetData(); 
1442         wxSize           
sz( item
->CalcMin() ); 
1444         w 
= wxMax( w
, sz
.x 
); 
1445         h 
= wxMax( h
, sz
.y 
); 
1447         node 
= node
->GetNext(); 
1450     // In case we have a nested sizer with a two step algo , give it 
1451     // a chance to adjust to that (we give it width component) 
1452     node 
= m_children
.GetFirst(); 
1453     bool didChangeMinSize 
= false; 
1456         wxSizerItem     
*item 
= node
->GetData(); 
1457         didChangeMinSize 
|= item
->InformFirstDirection( wxHORIZONTAL
, w
, -1 ); 
1459         node 
= node
->GetNext(); 
1462     // And redo iteration in case min size changed 
1463     if( didChangeMinSize 
) 
1465         node 
= m_children
.GetFirst(); 
1469             wxSizerItem     
*item 
= node
->GetData(); 
1470             wxSize           
sz( item
->GetMinSizeWithBorder() ); 
1472             w 
= wxMax( w
, sz
.x 
); 
1473             h 
= wxMax( h
, sz
.y 
); 
1475             node 
= node
->GetNext(); 
1479     return wxSize( ncols 
* w 
+ (ncols
-1) * m_hgap
, 
1480                    nrows 
* h 
+ (nrows
-1) * m_vgap 
); 
1483 void wxGridSizer::SetItemBounds( wxSizerItem 
*item
, int x
, int y
, int w
, int h 
) 
1486     wxSize 
sz( item
->GetMinSizeWithBorder() ); 
1487     int flag 
= item
->GetFlag(); 
1489     if ((flag 
& wxEXPAND
) || (flag 
& wxSHAPED
)) 
1495         if (flag 
& wxALIGN_CENTER_HORIZONTAL
) 
1497             pt
.x 
= x 
+ (w 
- sz
.x
) / 2; 
1499         else if (flag 
& wxALIGN_RIGHT
) 
1501             pt
.x 
= x 
+ (w 
- sz
.x
); 
1504         if (flag 
& wxALIGN_CENTER_VERTICAL
) 
1506             pt
.y 
= y 
+ (h 
- sz
.y
) / 2; 
1508         else if (flag 
& wxALIGN_BOTTOM
) 
1510             pt
.y 
= y 
+ (h 
- sz
.y
); 
1514     item
->SetDimension(pt
, sz
); 
1517 //--------------------------------------------------------------------------- 
1519 //--------------------------------------------------------------------------- 
1521 wxFlexGridSizer::wxFlexGridSizer( int cols
, int vgap
, int hgap 
) 
1522                : wxGridSizer( cols
, vgap
, hgap 
), 
1523                  m_flexDirection(wxBOTH
), 
1524                  m_growMode(wxFLEX_GROWMODE_SPECIFIED
) 
1528 wxFlexGridSizer::wxFlexGridSizer( int cols
, const wxSize
& gap 
) 
1529                : wxGridSizer( cols
, gap 
), 
1530                  m_flexDirection(wxBOTH
), 
1531                  m_growMode(wxFLEX_GROWMODE_SPECIFIED
) 
1535 wxFlexGridSizer::wxFlexGridSizer( int rows
, int cols
, int vgap
, int hgap 
) 
1536                : wxGridSizer( rows
, cols
, vgap
, hgap 
), 
1537                  m_flexDirection(wxBOTH
), 
1538                  m_growMode(wxFLEX_GROWMODE_SPECIFIED
) 
1542 wxFlexGridSizer::wxFlexGridSizer( int rows
, int cols
, const wxSize
& gap 
) 
1543                : wxGridSizer( rows
, cols
, gap 
), 
1544                  m_flexDirection(wxBOTH
), 
1545                  m_growMode(wxFLEX_GROWMODE_SPECIFIED
) 
1549 wxFlexGridSizer::~wxFlexGridSizer() 
1553 void wxFlexGridSizer::RecalcSizes() 
1556     if ( !CalcRowsCols(nrows
, ncols
) ) 
1559     const wxPoint 
pt(GetPosition()); 
1560     const wxSize 
sz(GetSize()); 
1562     AdjustForGrowables(sz
); 
1564     wxSizerItemList::const_iterator i 
= m_children
.begin(); 
1565     const wxSizerItemList::const_iterator end 
= m_children
.end(); 
1568     for ( int r 
= 0; r 
< nrows
; r
++ ) 
1570         if ( m_rowHeights
[r
] == -1 ) 
1572             // this row is entirely hidden, skip it 
1573             for ( int c 
= 0; c 
< ncols
; c
++ ) 
1584         const int hrow 
= m_rowHeights
[r
]; 
1585         int h 
= sz
.y 
- y
; // max remaining height, don't overflow it 
1590         for ( int c 
= 0; c 
< ncols 
&& i 
!= end
; c
++, ++i 
) 
1592             const int wcol 
= m_colWidths
[c
]; 
1597             int w 
= sz
.x 
- x
; // max possible value, ensure we don't overflow 
1601             SetItemBounds(*i
, pt
.x 
+ x
, pt
.y 
+ y
, w
, h
); 
1613 // helper function used in CalcMin() to sum up the sizes of non-hidden items 
1614 static int SumArraySizes(const wxArrayInt
& sizes
, int gap
) 
1616     // Sum total minimum size, including gaps between rows/columns. 
1617     // -1 is used as a magic number meaning empty row/column. 
1620     const size_t count 
= sizes
.size(); 
1621     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1623         if ( sizes
[n
] != -1 ) 
1626                 total 
+= gap
; // separate from the previous column 
1635 void wxFlexGridSizer::FindWidthsAndHeights(int nrows
, int ncols
) 
1637     // We have to recalculate the sizes in case the item minimum size has 
1638     // changed since the previous layout, or the item has been hidden using 
1639     // wxSizer::Show(). If all the items in a row/column are hidden, the final 
1640     // dimension of the row/column will be -1, indicating that the column 
1641     // itself is hidden. 
1642     m_rowHeights
.assign(nrows
, -1); 
1643     m_colWidths
.assign(ncols
, -1); 
1645     // n is the index of the item in left-to-right top-to-bottom order 
1647     for ( wxSizerItemList::iterator i 
= m_children
.begin(); 
1648           i 
!= m_children
.end(); 
1651         wxSizerItem 
* const item 
= *i
; 
1652         if ( item
->IsShown() ) 
1654             // NOTE: Not doing the calculation here, this is just 
1655             // for finding max values. 
1656             const wxSize 
sz(item
->GetMinSizeWithBorder()); 
1658             const int row 
= n 
/ ncols
; 
1659             const int col 
= n 
% ncols
; 
1661             if ( sz
.y 
> m_rowHeights
[row
] ) 
1662                 m_rowHeights
[row
] = sz
.y
; 
1663             if ( sz
.x 
> m_colWidths
[col
] ) 
1664                 m_colWidths
[col
] = sz
.x
; 
1668     AdjustForFlexDirection(); 
1670     m_calculatedMinSize 
= wxSize(SumArraySizes(m_colWidths
, m_hgap
), 
1671                                  SumArraySizes(m_rowHeights
, m_vgap
)); 
1674 wxSize 
wxFlexGridSizer::CalcMin() 
1679     // Number of rows/columns can change as items are added or removed. 
1680     if ( !CalcRowsCols(nrows
, ncols
) ) 
1684     // We have to recalculate the sizes in case the item minimum size has 
1685     // changed since the previous layout, or the item has been hidden using 
1686     // wxSizer::Show(). If all the items in a row/column are hidden, the final 
1687     // dimension of the row/column will be -1, indicating that the column 
1688     // itself is hidden. 
1689     m_rowHeights
.assign(nrows
, -1); 
1690     m_colWidths
.assign(ncols
, -1); 
1692     for ( wxSizerItemList::iterator i 
= m_children
.begin(); 
1693           i 
!= m_children
.end(); 
1696         wxSizerItem 
* const item 
= *i
; 
1697         if ( item
->IsShown() ) 
1703     // The stage of looking for max values in each row/column has been 
1704     // made a separate function, since it's reused in AdjustForGrowables. 
1705     FindWidthsAndHeights(nrows
,ncols
); 
1707     return m_calculatedMinSize
; 
1710 void wxFlexGridSizer::AdjustForFlexDirection() 
1712     // the logic in CalcMin works when we resize flexibly in both directions 
1713     // but maybe this is not the case 
1714     if ( m_flexDirection 
!= wxBOTH 
) 
1716         // select the array corresponding to the direction in which we do *not* 
1718         wxArrayInt
& array 
= m_flexDirection 
== wxVERTICAL 
? m_colWidths
 
1721         const size_t count 
= array
.GetCount(); 
1723         // find the largest value in this array 
1727         for ( n 
= 0; n 
< count
; ++n 
) 
1729             if ( array
[n
] > largest 
) 
1733         // and now fill it with the largest value 
1734         for ( n 
= 0; n 
< count
; ++n 
) 
1736             // don't touch hidden rows 
1737             if ( array
[n
] != -1 ) 
1743 // helper of AdjustForGrowables() which is called for rows/columns separately 
1746 //      delta: the extra space, we do nothing unless it's positive 
1747 //      growable: indices or growable rows/cols in sizes array 
1748 //      sizes: the height/widths of rows/cols to adjust 
1749 //      proportions: proportions of the growable rows/cols or NULL if they all 
1750 //                   should be assumed to have proportion of 1 
1752 DoAdjustForGrowables(int delta
, 
1753                      const wxArrayInt
& growable
, 
1755                      const wxArrayInt 
*proportions
) 
1760     // total sum of proportions of all non-hidden rows 
1761     int sum_proportions 
= 0; 
1763     // number of currently shown growable rows 
1766     const int max_idx 
= sizes
.size(); 
1768     const size_t count 
= growable
.size(); 
1770     for ( idx 
= 0; idx 
< count
; idx
++ ) 
1772         // Since the number of rows/columns can change as items are 
1773         // inserted/deleted, we need to verify at runtime that the 
1774         // requested growable rows/columns are still valid. 
1775         if ( growable
[idx
] >= max_idx 
) 
1778         // If all items in a row/column are hidden, that row/column will 
1779         // have a dimension of -1.  This causes the row/column to be 
1780         // hidden completely. 
1781         if ( sizes
[growable
[idx
]] == -1 ) 
1785             sum_proportions 
+= (*proportions
)[idx
]; 
1793     // the remaining extra free space, adjusted during each iteration 
1794     for ( idx 
= 0; idx 
< count
; idx
++ ) 
1796         if ( growable
[idx
] >= max_idx 
) 
1799         if ( sizes
[ growable
[idx
] ] == -1 ) 
1803         if ( sum_proportions 
== 0 ) 
1805             // no growable rows -- divide extra space evenly among all 
1806             cur_delta 
= delta
/num
; 
1809         else // allocate extra space proportionally 
1811             const int cur_prop 
= (*proportions
)[idx
]; 
1812             cur_delta 
= (delta
*cur_prop
)/sum_proportions
; 
1813             sum_proportions 
-= cur_prop
; 
1816         sizes
[growable
[idx
]] += cur_delta
; 
1821 void wxFlexGridSizer::AdjustForGrowables(const wxSize
& sz
) 
1824     // by the time this function is called, the sizer should be already fully 
1825     // initialized and hence the number of its columns and rows is known and we 
1826     // can check that all indices in m_growableCols/Rows are valid (see also 
1827     // comments in AddGrowableCol/Row()) 
1828     if ( !m_rows 
|| !m_cols 
) 
1832             int nrows 
= CalcRows(); 
1834             for ( size_t n 
= 0; n 
< m_growableRows
.size(); n
++ ) 
1836                 wxASSERT_MSG( m_growableRows
[n
] < nrows
, 
1837                               "invalid growable row index" ); 
1843             int ncols 
= CalcCols(); 
1845             for ( size_t n 
= 0; n 
< m_growableCols
.size(); n
++ ) 
1847                 wxASSERT_MSG( m_growableCols
[n
] < ncols
, 
1848                               "invalid growable column index" ); 
1852 #endif // wxDEBUG_LEVEL 
1855     if ( (m_flexDirection 
& wxHORIZONTAL
) || (m_growMode 
!= wxFLEX_GROWMODE_NONE
) ) 
1857         DoAdjustForGrowables
 
1859             sz
.x 
- m_calculatedMinSize
.x
, 
1862             m_growMode 
== wxFLEX_GROWMODE_SPECIFIED 
? &m_growableColsProportions
 
1866         // This gives nested objects that benefit from knowing one size 
1867         // component in advance the chance to use that. 
1868         bool didAdjustMinSize 
= false; 
1870         // Iterate over all items and inform about column width 
1871         const int ncols 
= GetEffectiveColsCount(); 
1873         for ( wxSizerItemList::iterator i 
= m_children
.begin(); 
1874               i 
!= m_children
.end(); 
1877             didAdjustMinSize 
|= (*i
)->InformFirstDirection(wxHORIZONTAL
, m_colWidths
[col
], sz
.y 
- m_calculatedMinSize
.y
); 
1878             if ( ++col 
== ncols 
) 
1882         // Only redo if info was actually used 
1883         if( didAdjustMinSize 
) 
1885             DoAdjustForGrowables
 
1887                 sz
.x 
- m_calculatedMinSize
.x
, 
1890                 m_growMode 
== wxFLEX_GROWMODE_SPECIFIED 
? &m_growableColsProportions
 
1896     if ( (m_flexDirection 
& wxVERTICAL
) || (m_growMode 
!= wxFLEX_GROWMODE_NONE
) ) 
1898         // pass NULL instead of proportions if the grow mode is ALL as we 
1899         // should treat all rows as having proportion of 1 then 
1900         DoAdjustForGrowables
 
1902             sz
.y 
- m_calculatedMinSize
.y
, 
1905             m_growMode 
== wxFLEX_GROWMODE_SPECIFIED 
? &m_growableRowsProportions
 
1911 bool wxFlexGridSizer::IsRowGrowable( size_t idx 
) 
1913     return m_growableRows
.Index( idx 
) != wxNOT_FOUND
; 
1916 bool wxFlexGridSizer::IsColGrowable( size_t idx 
) 
1918     return m_growableCols
.Index( idx 
) != wxNOT_FOUND
; 
1921 void wxFlexGridSizer::AddGrowableRow( size_t idx
, int proportion 
) 
1923     wxASSERT_MSG( !IsRowGrowable( idx 
), 
1924                   "AddGrowableRow() called for growable row" ); 
1926     // notice that we intentionally don't check the index validity here in (the 
1927     // common) case when the number of rows was not specified in the ctor -- in 
1928     // this case it will be computed only later, when all items are added to 
1929     // the sizer, and the check will be done in AdjustForGrowables() 
1930     wxCHECK_RET( !m_rows 
|| idx 
< (size_t)m_rows
, "invalid row index" ); 
1932     m_growableRows
.Add( idx 
); 
1933     m_growableRowsProportions
.Add( proportion 
); 
1936 void wxFlexGridSizer::AddGrowableCol( size_t idx
, int proportion 
) 
1938     wxASSERT_MSG( !IsColGrowable( idx 
), 
1939                   "AddGrowableCol() called for growable column" ); 
1941     // see comment in AddGrowableRow(): although it's less common to omit the 
1942     // specification of the number of columns, it still can also happen 
1943     wxCHECK_RET( !m_cols 
|| idx 
< (size_t)m_cols
, "invalid column index" ); 
1945     m_growableCols
.Add( idx 
); 
1946     m_growableColsProportions
.Add( proportion 
); 
1949 // helper function for RemoveGrowableCol/Row() 
1951 DoRemoveFromArrays(size_t idx
, wxArrayInt
& items
, wxArrayInt
& proportions
) 
1953     const size_t count 
= items
.size(); 
1954     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1956         if ( (size_t)items
[n
] == idx 
) 
1959             proportions
.RemoveAt(n
); 
1964     wxFAIL_MSG( wxT("column/row is already not growable") ); 
1967 void wxFlexGridSizer::RemoveGrowableCol( size_t idx 
) 
1969     DoRemoveFromArrays(idx
, m_growableCols
, m_growableColsProportions
); 
1972 void wxFlexGridSizer::RemoveGrowableRow( size_t idx 
) 
1974     DoRemoveFromArrays(idx
, m_growableRows
, m_growableRowsProportions
); 
1977 //--------------------------------------------------------------------------- 
1979 //--------------------------------------------------------------------------- 
1981 wxSizerItem 
*wxBoxSizer::AddSpacer(int size
) 
1983     return IsVertical() ? Add(0, size
) : Add(size
, 0); 
1990     Helper of RecalcSizes(): checks if there is enough remaining space for the 
1991     min size of the given item and returns its min size or the entire remaining 
1992     space depending on which one is greater. 
1994     This function updates the remaining space parameter to account for the size 
1995     effectively allocated to the item. 
1998 GetMinOrRemainingSize(int orient
, const wxSizerItem 
*item
, int *remainingSpace_
) 
2000     int& remainingSpace 
= *remainingSpace_
; 
2003     if ( remainingSpace 
> 0 ) 
2005         const wxSize sizeMin 
= item
->GetMinSizeWithBorder(); 
2006         size 
= orient 
== wxHORIZONTAL 
? sizeMin
.x 
: sizeMin
.y
; 
2008         if ( size 
>= remainingSpace 
) 
2010             // truncate the item to fit in the remaining space, this is better 
2011             // than showing it only partially in general, even if both choices 
2012             // are bad -- but there is nothing else we can do 
2013             size 
= remainingSpace
; 
2016         remainingSpace 
-= size
; 
2018     else // no remaining space 
2020         // no space at all left, no need to even query the item for its min 
2021         // size as we can't give it to it anyhow 
2028 } // anonymous namespace 
2030 void wxBoxSizer::RecalcSizes() 
2032     if ( m_children
.empty() ) 
2035     const wxCoord totalMinorSize 
= GetSizeInMinorDir(m_size
); 
2036     const wxCoord totalMajorSize 
= GetSizeInMajorDir(m_size
); 
2038     // the amount of free space which we should redistribute among the 
2039     // stretchable items (i.e. those with non zero proportion) 
2040     int delta 
= totalMajorSize 
- GetSizeInMajorDir(m_minSize
); 
2042     // declare loop variables used below: 
2043     wxSizerItemList::const_iterator i
;  // iterator in m_children list 
2044     unsigned n 
= 0;                     // item index in majorSizes array 
2047     // First, inform item about the available size in minor direction as this 
2048     // can change their size in the major direction. Also compute the number of 
2049     // visible items and sum of their min sizes in major direction. 
2051     int minMajorSize 
= 0; 
2052     for ( i 
= m_children
.begin(); i 
!= m_children
.end(); ++i 
) 
2054         wxSizerItem 
* const item 
= *i
; 
2056         if ( !item
->IsShown() ) 
2059         wxSize szMinPrev 
= item
->GetMinSizeWithBorder(); 
2060         item
->InformFirstDirection(m_orient
^wxBOTH
,totalMinorSize
,delta
); 
2061         wxSize szMin 
= item
->GetMinSizeWithBorder(); 
2062         int deltaChange 
= GetSizeInMajorDir(szMin
-szMinPrev
); 
2065             // Since we passed available space along to the item, it should not 
2066             // take too much, so delta should not become negative. 
2067             delta 
-= deltaChange
; 
2069         minMajorSize 
+= GetSizeInMajorDir(item
->GetMinSizeWithBorder()); 
2072     // update our min size and delta which may have changed 
2073     SizeInMajorDir(m_minSize
) = minMajorSize
; 
2074     delta 
= totalMajorSize 
- minMajorSize
; 
2077     // space and sum of proportions for the remaining items, both may change 
2079     wxCoord remaining 
= totalMajorSize
; 
2080     int totalProportion 
= m_totalProportion
; 
2082     // size of the (visible) items in major direction, -1 means "not fixed yet" 
2083     wxVector
<int> majorSizes(GetItemCount(), wxDefaultCoord
); 
2086     // Check for the degenerated case when we don't have enough space for even 
2087     // the min sizes of all the items: in this case we really can't do much 
2088     // more than to to allocate the min size to as many of fixed size items as 
2089     // possible (on the assumption that variable size items such as text zones 
2090     // or list boxes may use scrollbars to show their content even if their 
2091     // size is less than min size but that fixed size items such as buttons 
2092     // will suffer even more if we don't give them their min size) 
2093     if ( totalMajorSize 
< minMajorSize 
) 
2095         // Second degenerated case pass: allocate min size to all fixed size 
2097         for ( i 
= m_children
.begin(), n 
= 0; i 
!= m_children
.end(); ++i
, ++n 
) 
2099             wxSizerItem 
* const item 
= *i
; 
2101             if ( !item
->IsShown() ) 
2104             // deal with fixed size items only during this pass 
2105             if ( item
->GetProportion() ) 
2108             majorSizes
[n
] = GetMinOrRemainingSize(m_orient
, item
, &remaining
); 
2112         // Third degenerated case pass: allocate min size to all the remaining, 
2113         // i.e. non-fixed size, items. 
2114         for ( i 
= m_children
.begin(), n 
= 0; i 
!= m_children
.end(); ++i
, ++n 
) 
2116             wxSizerItem 
* const item 
= *i
; 
2118             if ( !item
->IsShown() ) 
2121             // we've already dealt with fixed size items above 
2122             if ( !item
->GetProportion() ) 
2125             majorSizes
[n
] = GetMinOrRemainingSize(m_orient
, item
, &remaining
); 
2128     else // we do have enough space to give at least min sizes to all items 
2130         // Second and maybe more passes in the non-degenerated case: deal with 
2131         // fixed size items and items whose min size is greater than what we 
2132         // would allocate to them taking their proportion into account. For 
2133         // both of them, we will just use their min size, but for the latter we 
2134         // also need to reexamine all the items as the items which fitted 
2135         // before we adjusted their size upwards might not fit any more. This 
2136         // does make for a quadratic algorithm but it's not obvious how to 
2137         // avoid it and hopefully it's not a huge problem in practice as the 
2138         // sizers don't have many items usually (and, of course, the algorithm 
2139         // still reduces into a linear one if there is enough space for all the 
2141         bool nonFixedSpaceChanged 
= false; 
2142         for ( i 
= m_children
.begin(), n 
= 0; ; ++i
, ++n 
) 
2144             if ( nonFixedSpaceChanged 
) 
2146                 i 
= m_children
.begin(); 
2148                 nonFixedSpaceChanged 
= false; 
2151             // check for the end of the loop only after the check above as 
2152             // otherwise we wouldn't do another pass if the last child resulted 
2153             // in non fixed space reduction 
2154             if ( i 
== m_children
.end() ) 
2157             wxSizerItem 
* const item 
= *i
; 
2159             if ( !item
->IsShown() ) 
2162             // don't check the item which we had already dealt with during a 
2163             // previous pass (this is more than an optimization, the code 
2164             // wouldn't work correctly if we kept adjusting for the same item 
2165             // over and over again) 
2166             if ( majorSizes
[n
] != wxDefaultCoord 
) 
2169             wxCoord minMajor 
= GetSizeInMajorDir(item
->GetMinSizeWithBorder()); 
2171             // it doesn't make sense for min size to be negative but right now 
2172             // it's possible to create e.g. a spacer with (-1, 10) as size and 
2173             // people do it in their code apparently (see #11842) so ensure 
2174             // that we don't use this -1 as real min size as it conflicts with 
2175             // the meaning we use for it here and negative min sizes just don't 
2176             // make sense anyhow (which is why it might be a better idea to 
2177             // deal with them at wxSizerItem level in the future but for now 
2178             // this is the minimal fix for the bug) 
2182             const int propItem 
= item
->GetProportion(); 
2185                 // is the desired size of this item big enough? 
2186                 if ( (remaining
*propItem
)/totalProportion 
>= minMajor 
) 
2188                     // yes, it is, we'll determine the real size of this 
2189                     // item later, for now just leave it as wxDefaultCoord 
2193                 // the proportion of this item won't count, it has 
2194                 // effectively become fixed 
2195                 totalProportion 
-= propItem
; 
2198             // we can already allocate space for this item 
2199             majorSizes
[n
] = minMajor
; 
2201             // change the amount of the space remaining to the other items, 
2202             // as this can result in not being able to satisfy their 
2203             // proportions any more we will need to redo another loop 
2205             remaining 
-= minMajor
; 
2207             nonFixedSpaceChanged 
= true; 
2211         // Last by one pass: distribute the remaining space among the non-fixed 
2212         // items whose size weren't fixed yet according to their proportions. 
2213         for ( i 
= m_children
.begin(), n 
= 0; i 
!= m_children
.end(); ++i
, ++n 
) 
2215             wxSizerItem 
* const item 
= *i
; 
2217             if ( !item
->IsShown() ) 
2220             if ( majorSizes
[n
] == wxDefaultCoord 
) 
2222                 const int propItem 
= item
->GetProportion(); 
2223                 majorSizes
[n
] = (remaining
*propItem
)/totalProportion
; 
2225                 remaining 
-= majorSizes
[n
]; 
2226                 totalProportion 
-= propItem
; 
2232     // the position at which we put the next child 
2233     wxPoint 
pt(m_position
); 
2236     // Final pass: finally do position the items correctly using their sizes as 
2237     // determined above. 
2238     for ( i 
= m_children
.begin(), n 
= 0; i 
!= m_children
.end(); ++i
, ++n 
) 
2240         wxSizerItem 
* const item 
= *i
; 
2242         if ( !item
->IsShown() ) 
2245         const int majorSize 
= majorSizes
[n
]; 
2247         const wxSize 
sizeThis(item
->GetMinSizeWithBorder()); 
2249         // apply the alignment in the minor direction 
2250         wxPoint 
posChild(pt
); 
2252         wxCoord minorSize 
= GetSizeInMinorDir(sizeThis
); 
2253         const int flag 
= item
->GetFlag(); 
2254         if ( (flag 
& (wxEXPAND 
| wxSHAPED
)) || (minorSize 
> totalMinorSize
) ) 
2256             // occupy all the available space if wxEXPAND was given and also if 
2257             // the item is too big to fit -- in this case we truncate it below 
2258             // its minimal size which is bad but better than not showing parts 
2259             // of the window at all 
2260             minorSize 
= totalMinorSize
; 
2262         else if ( flag 
& (IsVertical() ? wxALIGN_RIGHT 
: wxALIGN_BOTTOM
) ) 
2264             PosInMinorDir(posChild
) += totalMinorSize 
- minorSize
; 
2266         // NB: wxCENTRE is used here only for backwards compatibility, 
2267         //     wxALIGN_CENTRE should be used in new code 
2268         else if ( flag 
& (wxCENTER 
| (IsVertical() ? wxALIGN_CENTRE_HORIZONTAL
 
2269                                                    : wxALIGN_CENTRE_VERTICAL
)) ) 
2271             PosInMinorDir(posChild
) += (totalMinorSize 
- minorSize
) / 2; 
2275         // apply RTL adjustment for horizontal sizers: 
2276         if ( !IsVertical() && m_containingWindow 
) 
2278             posChild
.x 
= m_containingWindow
->AdjustForLayoutDirection
 
2286         // finally set size of this child and advance to the next one 
2287         item
->SetDimension(posChild
, SizeFromMajorMinor(majorSize
, minorSize
)); 
2289         PosInMajorDir(pt
) += majorSize
; 
2293 wxSize 
wxBoxSizer::CalcMin() 
2295     m_totalProportion 
= 0; 
2296     m_minSize 
= wxSize(0, 0); 
2298     // The minimal size for the sizer should be big enough to allocate its 
2299     // element at least its minimal size but also, and this is the non trivial 
2300     // part, to respect the children proportion. To satisfy the latter 
2301     // condition we must find the greatest min-size-to-proportion ratio for all 
2302     // elements with non-zero proportion. 
2303     float maxMinSizeToProp 
= 0.; 
2304     for ( wxSizerItemList::const_iterator i 
= m_children
.begin(); 
2305           i 
!= m_children
.end(); 
2308         wxSizerItem 
* const item 
= *i
; 
2310         if ( !item
->IsShown() ) 
2313         const wxSize sizeMinThis 
= item
->CalcMin(); 
2314         if ( const int propThis 
= item
->GetProportion() ) 
2316             float minSizeToProp 
= GetSizeInMajorDir(sizeMinThis
); 
2317             minSizeToProp 
/= propThis
; 
2319             if ( minSizeToProp 
> maxMinSizeToProp 
) 
2320                 maxMinSizeToProp 
= minSizeToProp
; 
2322             m_totalProportion 
+= item
->GetProportion(); 
2324         else // fixed size item 
2326             // Just account for its size directly 
2327             SizeInMajorDir(m_minSize
) += GetSizeInMajorDir(sizeMinThis
); 
2330         // In the transversal direction we just need to find the maximum. 
2331         if ( GetSizeInMinorDir(sizeMinThis
) > GetSizeInMinorDir(m_minSize
) ) 
2332             SizeInMinorDir(m_minSize
) = GetSizeInMinorDir(sizeMinThis
); 
2335     // Using the max ratio ensures that the min size is big enough for all 
2336     // items to have their min size and satisfy the proportions among them. 
2337     SizeInMajorDir(m_minSize
) += maxMinSizeToProp
*m_totalProportion
; 
2342 //--------------------------------------------------------------------------- 
2344 //--------------------------------------------------------------------------- 
2348 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox 
*box
, int orient 
) 
2349     : wxBoxSizer( orient 
), 
2352     wxASSERT_MSG( box
, wxT("wxStaticBoxSizer needs a static box") ); 
2354     // do this so that our Detach() is called if the static box is destroyed 
2356     m_staticBox
->SetContainingSizer(this); 
2359 wxStaticBoxSizer::wxStaticBoxSizer(int orient
, wxWindow 
*win
, const wxString
& s
) 
2360                 : wxBoxSizer(orient
), 
2361                   m_staticBox(new wxStaticBox(win
, wxID_ANY
, s
)) 
2364     m_staticBox
->SetContainingSizer(this); 
2367 wxStaticBoxSizer::~wxStaticBoxSizer() 
2372 void wxStaticBoxSizer::RecalcSizes() 
2374     int top_border
, other_border
; 
2375     m_staticBox
->GetBordersForSizer(&top_border
, &other_border
); 
2377     m_staticBox
->SetSize( m_position
.x
, m_position
.y
, m_size
.x
, m_size
.y 
); 
2379     wxSize 
old_size( m_size 
); 
2380     m_size
.x 
-= 2*other_border
; 
2381     m_size
.y 
-= top_border 
+ other_border
; 
2383     wxPoint 
old_pos( m_position 
); 
2384     if (m_staticBox
->GetChildren().GetCount() > 0) 
2386 #if defined( __WXGTK20__ ) 
2387         // if the wxStaticBox has created a wxPizza to contain its children 
2388         // (see wxStaticBox::AddChild) then we need to place the items it contains 
2389         // in the wxBoxSizer::RecalcSizes() call below using coordinates relative 
2390         // to the top-left corner of the staticbox: 
2391         m_position
.x 
= m_position
.y 
= 0; 
2393         // if the wxStaticBox has childrens, then these windows must be placed 
2394         // by the wxBoxSizer::RecalcSizes() call below using coordinates relative 
2395         // to the top-left corner of the staticbox (but unlike wxGTK, we need 
2396         // to keep in count the static borders here!): 
2397         m_position
.x 
= other_border
; 
2398         m_position
.y 
= top_border
; 
2403         // the windows contained in the staticbox have been created as siblings of the 
2404         // staticbox (this is the "old" way of staticbox contents creation); in this 
2405         // case we need to position them with coordinates relative to our common parent 
2406         m_position
.x 
+= other_border
; 
2407         m_position
.y 
+= top_border
; 
2410     wxBoxSizer::RecalcSizes(); 
2412     m_position 
= old_pos
; 
2416 wxSize 
wxStaticBoxSizer::CalcMin() 
2418     int top_border
, other_border
; 
2419     m_staticBox
->GetBordersForSizer(&top_border
, &other_border
); 
2421     wxSize 
ret( wxBoxSizer::CalcMin() ); 
2422     ret
.x 
+= 2*other_border
; 
2424     // ensure that we're wide enough to show the static box label (there is no 
2425     // need to check for the static box best size in vertical direction though) 
2426     const int boxWidth 
= m_staticBox
->GetBestSize().x
; 
2427     if ( ret
.x 
< boxWidth 
) 
2430     ret
.y 
+= other_border 
+ top_border
; 
2435 void wxStaticBoxSizer::ShowItems( bool show 
) 
2437     m_staticBox
->Show( show 
); 
2438     wxBoxSizer::ShowItems( show 
); 
2441 bool wxStaticBoxSizer::Detach( wxWindow 
*window 
) 
2443     // avoid deleting m_staticBox in our dtor if it's being detached from the 
2444     // sizer (which can happen because it's being already destroyed for 
2446     if ( window 
== m_staticBox 
) 
2452     return wxSizer::Detach( window 
); 
2455 #endif // wxUSE_STATBOX 
2457 //--------------------------------------------------------------------------- 
2458 // wxStdDialogButtonSizer 
2459 //--------------------------------------------------------------------------- 
2463 wxStdDialogButtonSizer::wxStdDialogButtonSizer() 
2464     : wxBoxSizer(wxHORIZONTAL
) 
2466     // Vertical buttons with lots of space on either side 
2467     // looks rubbish on WinCE, so let's not do this for now. 
2468     // If we are going to use vertical buttons, we should 
2469     // put the sizer to the right of other controls in the dialog, 
2470     // and that's beyond the scope of this sizer. 
2472     bool is_pda 
= (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA
); 
2473     // If we have a PDA screen, put yes/no button over 
2474     // all other buttons, otherwise on the left side. 
2476         m_orient 
= wxVERTICAL
; 
2479     m_buttonAffirmative 
= NULL
; 
2480     m_buttonApply 
= NULL
; 
2481     m_buttonNegative 
= NULL
; 
2482     m_buttonCancel 
= NULL
; 
2483     m_buttonHelp 
= NULL
; 
2486 void wxStdDialogButtonSizer::AddButton(wxButton 
*mybutton
) 
2488     switch (mybutton
->GetId()) 
2493             m_buttonAffirmative 
= mybutton
; 
2496             m_buttonApply 
= mybutton
; 
2499             m_buttonNegative 
= mybutton
; 
2503             m_buttonCancel 
= mybutton
; 
2506         case wxID_CONTEXT_HELP
: 
2507             m_buttonHelp 
= mybutton
; 
2514 void wxStdDialogButtonSizer::SetAffirmativeButton( wxButton 
*button 
) 
2516     m_buttonAffirmative 
= button
; 
2519 void wxStdDialogButtonSizer::SetNegativeButton( wxButton 
*button 
) 
2521     m_buttonNegative 
= button
; 
2524 void wxStdDialogButtonSizer::SetCancelButton( wxButton 
*button 
) 
2526     m_buttonCancel 
= button
; 
2529 void wxStdDialogButtonSizer::Realize() 
2532         Add(0, 0, 0, wxLEFT
, 6); 
2534             Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 6); 
2536         if (m_buttonNegative
){ 
2537             // HIG POLICE BULLETIN - destructive buttons need extra padding 
2538             // 24 pixels on either side 
2539             Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 12); 
2542         // extra whitespace between help/negative and cancel/ok buttons 
2543         Add(0, 0, 1, wxEXPAND
, 0); 
2545         if (m_buttonCancel
){ 
2546             Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 6); 
2547             // Cancel or help should be default 
2548             // m_buttonCancel->SetDefaultButton(); 
2551         // Ugh, Mac doesn't really have apply dialogs, so I'll just 
2552         // figure the best place is between Cancel and OK 
2554             Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 6); 
2556         if (m_buttonAffirmative
){ 
2557             Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE 
| wxLEFT
, 6); 
2559             if (m_buttonAffirmative
->GetId() == wxID_SAVE
){ 
2560                 // these buttons have set labels under Mac so we should use them 
2561                 m_buttonAffirmative
->SetLabel(_("Save")); 
2562                 if (m_buttonNegative
) 
2563                     m_buttonNegative
->SetLabel(_("Don't Save")); 
2567         // Extra space around and at the right 
2569 #elif defined(__WXGTK20__) 
2570         Add(0, 0, 0, wxLEFT
, 9); 
2572             Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 3); 
2574         // extra whitespace between help and cancel/ok buttons 
2575         Add(0, 0, 1, wxEXPAND
, 0); 
2577         if (m_buttonNegative
){ 
2578             Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 3); 
2581         // according to HIG, in explicit apply windows the order is: 
2582         // [ Help                     Apply   Cancel   OK ] 
2584             Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 3); 
2586         if (m_buttonCancel
){ 
2587             Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, 3); 
2588             // Cancel or help should be default 
2589             // m_buttonCancel->SetDefaultButton(); 
2592         if (m_buttonAffirmative
) 
2593             Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE 
| wxLEFT
, 6); 
2594 #elif defined(__WXMSW__) 
2597         // right-justify buttons 
2598         Add(0, 0, 1, wxEXPAND
, 0); 
2600         if (m_buttonAffirmative
){ 
2601             Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonAffirmative
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
2604         if (m_buttonNegative
){ 
2605             Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonNegative
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
2608         if (m_buttonCancel
){ 
2609             Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonCancel
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
2612             Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonApply
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
2615             Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonHelp
->ConvertDialogToPixels(wxSize(2, 0)).x
); 
2617         // GTK+1 and any other platform 
2619         // Add(0, 0, 0, wxLEFT, 5); // Not sure what this was for but it unbalances the dialog 
2621             Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonHelp
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
2623         // extra whitespace between help and cancel/ok buttons 
2624         Add(0, 0, 1, wxEXPAND
, 0); 
2627             Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonApply
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
2629         if (m_buttonAffirmative
){ 
2630             Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonAffirmative
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
2633         if (m_buttonNegative
){ 
2634             Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonNegative
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
2637         if (m_buttonCancel
){ 
2638             Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE 
| wxLEFT 
| wxRIGHT
, m_buttonCancel
->ConvertDialogToPixels(wxSize(4, 0)).x
); 
2639             // Cancel or help should be default 
2640             // m_buttonCancel->SetDefaultButton(); 
2646 #endif // wxUSE_BUTTON