X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/15f7c30516facfb272fc116aec4d3f9c3a9de085..26022721e88892446ebcfc34bc34384492952fa9:/src/common/sizer.cpp diff --git a/src/common/sizer.cpp b/src/common/sizer.cpp index 3b18a56b59..ad0abd60ed 100644 --- a/src/common/sizer.cpp +++ b/src/common/sizer.cpp @@ -17,8 +17,8 @@ #pragma hdrstop #endif -#include "wx/display.h" #include "wx/sizer.h" +#include "wx/private/flagscheck.h" #ifndef WX_PRECOMP #include "wx/string.h" @@ -31,6 +31,7 @@ #include "wx/toplevel.h" #endif // WX_PRECOMP +#include "wx/display.h" #include "wx/listimpl.cpp" @@ -87,6 +88,31 @@ WX_DEFINE_EXPORTED_LIST( wxSizerItemList ) // wxSizerItem // ---------------------------------------------------------------------------- +// check for flags conflicts +static const int SIZER_FLAGS_MASK = + wxADD_FLAG(wxCENTRE, + wxADD_FLAG(wxHORIZONTAL, + wxADD_FLAG(wxVERTICAL, + wxADD_FLAG(wxLEFT, + wxADD_FLAG(wxRIGHT, + wxADD_FLAG(wxUP, + wxADD_FLAG(wxDOWN, + wxADD_FLAG(wxALIGN_NOT, + wxADD_FLAG(wxALIGN_CENTER_HORIZONTAL, + wxADD_FLAG(wxALIGN_RIGHT, + wxADD_FLAG(wxALIGN_BOTTOM, + wxADD_FLAG(wxALIGN_CENTER_VERTICAL, + wxADD_FLAG(wxFIXED_MINSIZE, + wxADD_FLAG(wxRESERVE_SPACE_EVEN_IF_HIDDEN, + wxADD_FLAG(wxSTRETCH_NOT, + wxADD_FLAG(wxSHRINK, + wxADD_FLAG(wxGROW, + wxADD_FLAG(wxSHAPED, + 0)))))))))))))))))); + +#define ASSERT_VALID_SIZER_FLAGS(f) wxASSERT_VALID_FLAGS(f, SIZER_FLAGS_MASK) + + void wxSizerItem::Init(const wxSizerFlags& flags) { Init(); @@ -94,6 +120,8 @@ void wxSizerItem::Init(const wxSizerFlags& flags) m_proportion = flags.GetProportion(); m_flag = flags.GetFlags(); m_border = flags.GetBorderInPixels(); + + ASSERT_VALID_SIZER_FLAGS( m_flag ); } wxSizerItem::wxSizerItem() @@ -109,7 +137,7 @@ wxSizerItem::wxSizerItem() // window item void wxSizerItem::DoSetWindow(wxWindow *window) { - wxCHECK_RET( window, _T("NULL window in wxSizerItem::SetWindow()") ); + wxCHECK_RET( window, wxT("NULL window in wxSizerItem::SetWindow()") ); m_kind = Item_Window; m_window = window; @@ -136,6 +164,8 @@ wxSizerItem::wxSizerItem(wxWindow *window, m_id(wxID_NONE), m_userData(userData) { + ASSERT_VALID_SIZER_FLAGS( m_flag ); + DoSetWindow(window); } @@ -160,6 +190,8 @@ wxSizerItem::wxSizerItem(wxSizer *sizer, m_ratio(0.0), m_userData(userData) { + ASSERT_VALID_SIZER_FLAGS( m_flag ); + DoSetSizer(sizer); // m_minSize is set later @@ -189,6 +221,8 @@ wxSizerItem::wxSizerItem(int width, m_id(wxID_NONE), m_userData(userData) { + ASSERT_VALID_SIZER_FLAGS( m_flag ); + DoSetSpacer(wxSize(width, height)); } @@ -219,7 +253,7 @@ void wxSizerItem::Free() case Item_Max: default: - wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); + wxFAIL_MSG( wxT("unexpected wxSizerItem::m_kind") ); } m_kind = Item_None; @@ -257,7 +291,7 @@ wxSize wxSizerItem::GetSize() const case Item_Max: default: - wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); + wxFAIL_MSG( wxT("unexpected wxSizerItem::m_kind") ); } if (m_flag & wxWEST) @@ -274,68 +308,68 @@ wxSize wxSizerItem::GetSize() const bool wxSizerItem::InformFirstDirection(int direction, int size, int availableOtherDir) { - // The size that come here will be including borders. Child items should get it - // without borders. - if( size>0 ) - { - if( direction==wxHORIZONTAL ) - { - if (m_flag & wxWEST) - size -= m_border; - if (m_flag & wxEAST) - size -= m_border; - } - else if( direction==wxVERTICAL ) - { - if (m_flag & wxNORTH) - size -= m_border; - if (m_flag & wxSOUTH) - size -= m_border; - } - } - + // The size that come here will be including borders. Child items should get it + // without borders. + if( size>0 ) + { + if( direction==wxHORIZONTAL ) + { + if (m_flag & wxWEST) + size -= m_border; + if (m_flag & wxEAST) + size -= m_border; + } + else if( direction==wxVERTICAL ) + { + if (m_flag & wxNORTH) + size -= m_border; + if (m_flag & wxSOUTH) + size -= m_border; + } + } + bool didUse = false; // Pass the information along to the held object if (IsSizer()) { didUse = GetSizer()->InformFirstDirection(direction,size,availableOtherDir); if (didUse) - m_minSize = GetSizer()->CalcMin(); + m_minSize = GetSizer()->CalcMin(); } else if (IsWindow()) { didUse = GetWindow()->InformFirstDirection(direction,size,availableOtherDir); if (didUse) m_minSize = m_window->GetEffectiveMinSize(); - - // This information is useful for items with wxSHAPED flag, since - // we can request an optimal min size for such an item. Even if - // we overwrite the m_minSize member here, we can read it back from - // the owned window (happens automatically). - if( (m_flag & wxSHAPED) && (m_flag & wxEXPAND) && direction ) - { - if( !wxIsNullDouble(m_ratio) ) - { - wxCHECK_MSG( (m_proportion==0), false, _T("Shaped item, non-zero proportion in wxSizerItem::InformFirstDirection()") ); - if( direction==wxHORIZONTAL && !wxIsNullDouble(m_ratio) ) - { - // Clip size so that we don't take too much - if( availableOtherDir>=0 && int(size/m_ratio)-m_minSize.y>availableOtherDir ) - size = int((availableOtherDir+m_minSize.y)*m_ratio); - m_minSize = wxSize(size,int(size/m_ratio)); - } - else if( direction==wxVERTICAL ) - { - // Clip size so that we don't take too much - if( availableOtherDir>=0 && int(size*m_ratio)-m_minSize.x>availableOtherDir ) - size = int((availableOtherDir+m_minSize.x)/m_ratio); - m_minSize = wxSize(int(size*m_ratio),size); - } - didUse = true; - } - } - } - + + // This information is useful for items with wxSHAPED flag, since + // we can request an optimal min size for such an item. Even if + // we overwrite the m_minSize member here, we can read it back from + // the owned window (happens automatically). + if( (m_flag & wxSHAPED) && (m_flag & wxEXPAND) && direction ) + { + if( !wxIsNullDouble(m_ratio) ) + { + wxCHECK_MSG( (m_proportion==0), false, wxT("Shaped item, non-zero proportion in wxSizerItem::InformFirstDirection()") ); + if( direction==wxHORIZONTAL && !wxIsNullDouble(m_ratio) ) + { + // Clip size so that we don't take too much + if( availableOtherDir>=0 && int(size/m_ratio)-m_minSize.y>availableOtherDir ) + size = int((availableOtherDir+m_minSize.y)*m_ratio); + m_minSize = wxSize(size,int(size/m_ratio)); + } + else if( direction==wxVERTICAL ) + { + // Clip size so that we don't take too much + if( availableOtherDir>=0 && int(size*m_ratio)-m_minSize.x>availableOtherDir ) + size = int((availableOtherDir+m_minSize.x)/m_ratio); + m_minSize = wxSize(int(size*m_ratio),size); + } + didUse = true; + } + } + } + return didUse; } @@ -442,16 +476,27 @@ void wxSizerItem::SetDimension( const wxPoint& pos_, const wxSize& size_ ) switch ( m_kind ) { case Item_None: - wxFAIL_MSG( _T("can't set size of uninitialized sizer item") ); + wxFAIL_MSG( wxT("can't set size of uninitialized sizer item") ); break; case Item_Window: + { + // Use wxSIZE_FORCE_EVENT here since a sizer item might + // have changed alignment or some other property which would + // not change the size of the window. In such a case, no + // wxSizeEvent would normally be generated and thus the + // control wouldn't get layed out correctly here. +#if 1 + m_window->SetSize(pos.x, pos.y, size.x, size.y, + wxSIZE_ALLOW_MINUS_ONE|wxSIZE_FORCE_EVENT ); +#else m_window->SetSize(pos.x, pos.y, size.x, size.y, - wxSIZE_ALLOW_MINUS_ONE); + wxSIZE_ALLOW_MINUS_ONE ); +#endif break; - + } case Item_Sizer: - m_sizer->SetDimension(pos.x, pos.y, size.x, size.y); + m_sizer->SetDimension(pos, size); break; case Item_Spacer: @@ -460,7 +505,7 @@ void wxSizerItem::SetDimension( const wxPoint& pos_, const wxSize& size_ ) case Item_Max: default: - wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); + wxFAIL_MSG( wxT("unexpected wxSizerItem::m_kind") ); } } @@ -489,7 +534,7 @@ void wxSizerItem::DeleteWindows() case Item_Max: default: - wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); + wxFAIL_MSG( wxT("unexpected wxSizerItem::m_kind") ); } } @@ -499,7 +544,7 @@ void wxSizerItem::Show( bool show ) switch ( m_kind ) { case Item_None: - wxFAIL_MSG( _T("can't show uninitialized sizer item") ); + wxFAIL_MSG( wxT("can't show uninitialized sizer item") ); break; case Item_Window: @@ -516,12 +561,15 @@ void wxSizerItem::Show( bool show ) case Item_Max: default: - wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); + wxFAIL_MSG( wxT("unexpected wxSizerItem::m_kind") ); } } bool wxSizerItem::IsShown() const { + if ( m_flag & wxRESERVE_SPACE_EVEN_IF_HIDDEN ) + return true; + switch ( m_kind ) { case Item_None: @@ -558,7 +606,7 @@ bool wxSizerItem::IsShown() const case Item_Max: default: - wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") ); + wxFAIL_MSG( wxT("unexpected wxSizerItem::m_kind") ); } return false; @@ -586,7 +634,7 @@ wxSizer::~wxSizer() WX_CLEAR_LIST(wxSizerItemList, m_children); } -wxSizerItem* wxSizer::Insert( size_t index, wxSizerItem *item ) +wxSizerItem* wxSizer::DoInsert( size_t index, wxSizerItem *item ) { m_children.Insert( index, item ); @@ -631,7 +679,7 @@ bool wxSizer::Remove( wxWindow *window ) bool wxSizer::Remove( wxSizer *sizer ) { - wxASSERT_MSG( sizer, _T("Removing NULL sizer") ); + wxASSERT_MSG( sizer, wxT("Removing NULL sizer") ); wxSizerItemList::compatibility_iterator node = m_children.GetFirst(); while (node) @@ -655,11 +703,11 @@ bool wxSizer::Remove( int index ) { wxCHECK_MSG( index >= 0 && (size_t)index < m_children.GetCount(), false, - _T("Remove index is out of range") ); + wxT("Remove index is out of range") ); wxSizerItemList::compatibility_iterator node = m_children.Item( index ); - wxCHECK_MSG( node, false, _T("Failed to find child node") ); + wxCHECK_MSG( node, false, wxT("Failed to find child node") ); delete node->GetData(); m_children.Erase( node ); @@ -669,7 +717,7 @@ bool wxSizer::Remove( int index ) bool wxSizer::Detach( wxSizer *sizer ) { - wxASSERT_MSG( sizer, _T("Detaching NULL sizer") ); + wxASSERT_MSG( sizer, wxT("Detaching NULL sizer") ); wxSizerItemList::compatibility_iterator node = m_children.GetFirst(); while (node) @@ -691,7 +739,7 @@ bool wxSizer::Detach( wxSizer *sizer ) bool wxSizer::Detach( wxWindow *window ) { - wxASSERT_MSG( window, _T("Detaching NULL window") ); + wxASSERT_MSG( window, wxT("Detaching NULL window") ); wxSizerItemList::compatibility_iterator node = m_children.GetFirst(); while (node) @@ -714,11 +762,11 @@ bool wxSizer::Detach( int index ) { wxCHECK_MSG( index >= 0 && (size_t)index < m_children.GetCount(), false, - _T("Detach index is out of range") ); + wxT("Detach index is out of range") ); wxSizerItemList::compatibility_iterator node = m_children.Item( index ); - wxCHECK_MSG( node, false, _T("Failed to find child node") ); + wxCHECK_MSG( node, false, wxT("Failed to find child node") ); wxSizerItem *item = node->GetData(); @@ -732,8 +780,8 @@ bool wxSizer::Detach( int index ) bool wxSizer::Replace( wxWindow *oldwin, wxWindow *newwin, bool recursive ) { - wxASSERT_MSG( oldwin, _T("Replacing NULL window") ); - wxASSERT_MSG( newwin, _T("Replacing with NULL window") ); + wxASSERT_MSG( oldwin, wxT("Replacing NULL window") ); + wxASSERT_MSG( newwin, wxT("Replacing with NULL window") ); wxSizerItemList::compatibility_iterator node = m_children.GetFirst(); while (node) @@ -760,8 +808,8 @@ bool wxSizer::Replace( wxWindow *oldwin, wxWindow *newwin, bool recursive ) bool wxSizer::Replace( wxSizer *oldsz, wxSizer *newsz, bool recursive ) { - wxASSERT_MSG( oldsz, _T("Replacing NULL sizer") ); - wxASSERT_MSG( newsz, _T("Replacing with NULL sizer") ); + wxASSERT_MSG( oldsz, wxT("Replacing NULL sizer") ); + wxASSERT_MSG( newsz, wxT("Replacing with NULL sizer") ); wxSizerItemList::compatibility_iterator node = m_children.GetFirst(); while (node) @@ -787,12 +835,12 @@ bool wxSizer::Replace( wxSizer *oldsz, wxSizer *newsz, bool recursive ) bool wxSizer::Replace( size_t old, wxSizerItem *newitem ) { - wxCHECK_MSG( old < m_children.GetCount(), false, _T("Replace index is out of range") ); - wxASSERT_MSG( newitem, _T("Replacing with NULL item") ); + wxCHECK_MSG( old < m_children.GetCount(), false, wxT("Replace index is out of range") ); + wxASSERT_MSG( newitem, wxT("Replacing with NULL item") ); wxSizerItemList::compatibility_iterator node = m_children.Item( old ); - wxCHECK_MSG( node, false, _T("Failed to find child node") ); + wxCHECK_MSG( node, false, wxT("Failed to find child node") ); wxSizerItem *item = node->GetData(); node->SetData(newitem); @@ -834,11 +882,13 @@ void wxSizer::DeleteWindows() } } -wxSize wxSizer::Fit( wxWindow *window ) +wxSize wxSizer::ComputeFittingClientSize(wxWindow *window) { + wxCHECK_MSG( window, wxDefaultSize, "window can't be NULL" ); + // take the min size by default and limit it by max size - wxSize size = GetMinWindowSize(window); - wxSize sizeMax = GetMaxWindowSize(window); + wxSize size = GetMinClientSize(window); + wxSize sizeMax; wxTopLevelWindow *tlw = wxDynamicCast(window, wxTopLevelWindow); if ( tlw ) @@ -846,31 +896,51 @@ wxSize wxSizer::Fit( wxWindow *window ) // hack for small screen devices where TLWs are always full screen if ( tlw->IsAlwaysMaximized() ) { - size = tlw->GetSize(); + return tlw->GetClientSize(); } - else // normal situation - { - // limit the window to the size of the display it is on - int disp = wxDisplay::GetFromWindow(window); - if ( disp == wxNOT_FOUND ) - { - // or, if we don't know which one it is, of the main one - disp = 0; - } - sizeMax = wxDisplay(disp).GetClientArea().GetSize(); + // limit the window to the size of the display it is on + int disp = wxDisplay::GetFromWindow(window); + if ( disp == wxNOT_FOUND ) + { + // or, if we don't know which one it is, of the main one + disp = 0; } + + sizeMax = wxDisplay(disp).GetClientArea().GetSize(); + + // space for decorations and toolbars etc. + sizeMax = tlw->WindowToClientSize(sizeMax); + } + else + { + sizeMax = GetMaxClientSize(window); } if ( sizeMax.x != wxDefaultCoord && size.x > sizeMax.x ) - size.x = sizeMax.x; + size.x = sizeMax.x; if ( sizeMax.y != wxDefaultCoord && size.y > sizeMax.y ) - size.y = sizeMax.y; + size.y = sizeMax.y; + + return size; +} + +wxSize wxSizer::ComputeFittingWindowSize(wxWindow *window) +{ + wxCHECK_MSG( window, wxDefaultSize, "window can't be NULL" ); + return window->ClientToWindowSize(ComputeFittingClientSize(window)); +} - window->SetSize( size ); +wxSize wxSizer::Fit( wxWindow *window ) +{ + wxCHECK_MSG( window, wxDefaultSize, "window can't be NULL" ); - return size; + // set client size + window->SetClientSize(ComputeFittingClientSize(window)); + + // return entire size + return window->GetSize(); } void wxSizer::FitInside( wxWindow *window ) @@ -899,59 +969,31 @@ void wxSizer::SetSizeHints( wxWindow *window ) // Preserve the window's max size hints, but set the // lower bound according to the sizer calculations. - wxSize size = Fit( window ); + // This is equivalent to calling Fit(), except that we need to set + // the size hints _in between_ the two steps performed by Fit + // (1. ComputeFittingClientSize, 2. SetClientSize). That's because + // otherwise SetClientSize() could have no effect if there already are + // size hints in effect that forbid requested client size. + + const wxSize clientSize = ComputeFittingClientSize(window); - window->SetSizeHints( size.x, - size.y, - window->GetMaxWidth(), - window->GetMaxHeight() ); + window->SetMinClientSize(clientSize); + window->SetClientSize(clientSize); } +#if WXWIN_COMPATIBILITY_2_8 void wxSizer::SetVirtualSizeHints( wxWindow *window ) { - // Preserve the window's max size hints, but set the - // lower bound according to the sizer calculations. - FitInside( window ); - wxSize size( window->GetVirtualSize() ); - window->SetVirtualSizeHints( size.x, - size.y, - window->GetMaxWidth(), - window->GetMaxHeight() ); -} - -wxSize wxSizer::GetMaxWindowSize( wxWindow *window ) const -{ - return window->GetMaxSize(); -} - -wxSize wxSizer::GetMinWindowSize( wxWindow *window ) -{ - wxSize minSize( GetMinSize() ); - wxSize size( window->GetSize() ); - wxSize client_size( window->GetClientSize() ); - - return wxSize( minSize.x+size.x-client_size.x, - minSize.y+size.y-client_size.y ); } +#endif // WXWIN_COMPATIBILITY_2_8 // TODO on mac we need a function that determines how much free space this // min size contains, in order to make sure that we have 20 pixels of free // space around the controls wxSize wxSizer::GetMaxClientSize( wxWindow *window ) const { - wxSize maxSize( window->GetMaxSize() ); - - if ( maxSize != wxDefaultSize ) - { - wxSize size( window->GetSize() ); - wxSize client_size( window->GetClientSize() ); - - return wxSize( maxSize.x + client_size.x - size.x, - maxSize.y + client_size.y - size.y ); - } - else - return wxDefaultSize; + return window->WindowToClientSize(window->GetMaxSize()); } wxSize wxSizer::GetMinClientSize( wxWindow *WXUNUSED(window) ) @@ -974,15 +1016,6 @@ wxSize wxSizer::VirtualFitSize( wxWindow *window ) return size; } -void wxSizer::SetDimension( int x, int y, int width, int height ) -{ - m_position.x = x; - m_position.y = y; - m_size.x = width; - m_size.y = height; - Layout(); -} - wxSize wxSizer::GetMinSize() { wxSize ret( CalcMin() ); @@ -999,7 +1032,7 @@ void wxSizer::DoSetMinSize( int width, int height ) bool wxSizer::DoSetItemMinSize( wxWindow *window, int width, int height ) { - wxASSERT_MSG( window, _T("SetMinSize for NULL window") ); + wxASSERT_MSG( window, wxT("SetMinSize for NULL window") ); // Is it our immediate child? @@ -1037,7 +1070,7 @@ bool wxSizer::DoSetItemMinSize( wxWindow *window, int width, int height ) bool wxSizer::DoSetItemMinSize( wxSizer *sizer, int width, int height ) { - wxASSERT_MSG( sizer, _T("SetMinSize for NULL sizer") ); + wxASSERT_MSG( sizer, wxT("SetMinSize for NULL sizer") ); // Is it our immediate child? @@ -1077,7 +1110,7 @@ bool wxSizer::DoSetItemMinSize( size_t index, int width, int height ) { wxSizerItemList::compatibility_iterator node = m_children.Item( index ); - wxCHECK_MSG( node, false, _T("Failed to find child node") ); + wxCHECK_MSG( node, false, wxT("Failed to find child node") ); wxSizerItem *item = node->GetData(); @@ -1097,7 +1130,7 @@ bool wxSizer::DoSetItemMinSize( size_t index, int width, int height ) wxSizerItem* wxSizer::GetItem( wxWindow *window, bool recursive ) { - wxASSERT_MSG( window, _T("GetItem for NULL window") ); + wxASSERT_MSG( window, wxT("GetItem for NULL window") ); wxSizerItemList::compatibility_iterator node = m_children.GetFirst(); while (node) @@ -1123,7 +1156,7 @@ wxSizerItem* wxSizer::GetItem( wxWindow *window, bool recursive ) wxSizerItem* wxSizer::GetItem( wxSizer *sizer, bool recursive ) { - wxASSERT_MSG( sizer, _T("GetItem for NULL sizer") ); + wxASSERT_MSG( sizer, wxT("GetItem for NULL sizer") ); wxSizerItemList::compatibility_iterator node = m_children.GetFirst(); while (node) @@ -1151,7 +1184,7 @@ wxSizerItem* wxSizer::GetItem( size_t index ) { wxCHECK_MSG( index < m_children.GetCount(), NULL, - _T("GetItem index is out of range") ); + wxT("GetItem index is out of range") ); return m_children.Item( index )->GetData(); } @@ -1246,7 +1279,7 @@ bool wxSizer::IsShown( wxWindow *window ) const node = node->GetNext(); } - wxFAIL_MSG( _T("IsShown failed to find sizer item") ); + wxFAIL_MSG( wxT("IsShown failed to find sizer item") ); return false; } @@ -1265,7 +1298,7 @@ bool wxSizer::IsShown( wxSizer *sizer ) const node = node->GetNext(); } - wxFAIL_MSG( _T("IsShown failed to find sizer item") ); + wxFAIL_MSG( wxT("IsShown failed to find sizer item") ); return false; } @@ -1274,7 +1307,7 @@ bool wxSizer::IsShown( size_t index ) const { wxCHECK_MSG( index < m_children.GetCount(), false, - _T("IsShown index is out of range") ); + wxT("IsShown index is out of range") ); return m_children.Item( index )->GetData()->IsShown(); } @@ -1284,45 +1317,82 @@ bool wxSizer::IsShown( size_t index ) const // wxGridSizer //--------------------------------------------------------------------------- +wxGridSizer::wxGridSizer( int cols, int vgap, int hgap ) + : m_rows( cols == 0 ? 1 : 0 ), + m_cols( cols ), + m_vgap( vgap ), + m_hgap( hgap ) +{ +} + +wxGridSizer::wxGridSizer( int cols, const wxSize& gap ) + : m_rows( cols == 0 ? 1 : 0 ), + m_cols( cols ), + m_vgap( gap.GetHeight() ), + m_hgap( gap.GetWidth() ) +{ +} + wxGridSizer::wxGridSizer( int rows, int cols, int vgap, int hgap ) - : m_rows( ( cols == 0 && rows == 0 ) ? 1 : rows ) - , m_cols( cols ) - , m_vgap( vgap ) - , m_hgap( hgap ) + : m_rows( rows || cols ? rows : 1 ), + m_cols( cols ), + m_vgap( vgap ), + m_hgap( hgap ) { } -wxGridSizer::wxGridSizer( int cols, int vgap, int hgap ) - : m_rows( cols == 0 ? 1 : 0 ) - , m_cols( cols ) - , m_vgap( vgap ) - , m_hgap( hgap ) +wxGridSizer::wxGridSizer( int rows, int cols, const wxSize& gap ) + : m_rows( rows || cols ? rows : 1 ), + m_cols( cols ), + m_vgap( gap.GetHeight() ), + m_hgap( gap.GetWidth() ) { } -int wxGridSizer::CalcRowsCols(int& nrows, int& ncols) const +wxSizerItem *wxGridSizer::DoInsert(size_t index, wxSizerItem *item) { - int nitems = m_children.GetCount(); - if ( nitems) + // if only the number of columns or the number of rows is specified for a + // sizer, arbitrarily many items can be added to it but if both of them are + // fixed, then the sizer can't have more than that many items -- check for + // this here to ensure that we detect errors as soon as possible + if ( m_cols && m_rows ) { - if ( m_cols ) - { - ncols = m_cols; - nrows = (nitems + m_cols - 1) / m_cols; - } - else if ( m_rows ) - { - ncols = (nitems + m_rows - 1) / m_rows; - nrows = m_rows; - } - else // 0 columns, 0 rows? + const int nitems = m_children.GetCount(); + if ( nitems == m_cols*m_rows ) { - wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") ); - - nrows = ncols = 0; + wxFAIL_MSG( + wxString::Format( + "too many items (%d > %d*%d) in grid sizer (maybe you " + "should omit the number of either rows or columns?)", + nitems + 1, m_cols, m_rows) + ); + + // additionally, continuing to use the specified number of columns + // and rows is not a good idea as callers of CalcRowsCols() expect + // that all sizer items can fit into m_cols-/m_rows-sized arrays + // which is not the case if there are too many items and results in + // crashes, so let it compute the number of rows automatically by + // forgetting the (wrong) number of rows specified (this also has a + // nice side effect of giving only one assert even if there are + // many more items than allowed in this sizer) + m_rows = 0; } } + return wxSizer::DoInsert(index, item); +} + +int wxGridSizer::CalcRowsCols(int& nrows, int& ncols) const +{ + const int nitems = m_children.GetCount(); + + ncols = GetEffectiveColsCount(); + nrows = GetEffectiveRowsCount(); + + // Since Insert() checks for overpopulation, the following + // should only assert if the grid was shrunk via SetRows() / SetCols() + wxASSERT_MSG( nitems <= ncols*nrows, "logic error in wxGridSizer" ); + return nitems; } @@ -1349,7 +1419,7 @@ void wxGridSizer::RecalcSizes() { wxSizerItemList::compatibility_iterator node = m_children.Item( i ); - wxASSERT_MSG( node, _T("Failed to find SizerItemList node") ); + wxASSERT_MSG( node, wxT("Failed to find SizerItemList node") ); SetItemBounds( node->GetData(), x, y, w, h); } @@ -1381,7 +1451,7 @@ wxSize wxGridSizer::CalcMin() node = node->GetNext(); } - // In case we have a nested sizer with a two step algo , give it + // In case we have a nested sizer with a two step algo , give it // a chance to adjust to that (we give it width component) node = m_children.GetFirst(); bool didChangeMinSize = false; @@ -1389,10 +1459,10 @@ wxSize wxGridSizer::CalcMin() { wxSizerItem *item = node->GetData(); didChangeMinSize |= item->InformFirstDirection( wxHORIZONTAL, w, -1 ); - + node = node->GetNext(); } - + // And redo iteration in case min size changed if( didChangeMinSize ) { @@ -1407,9 +1477,9 @@ wxSize wxGridSizer::CalcMin() h = wxMax( h, sz.y ); node = node->GetNext(); - } + } } - + return wxSize( ncols * w + (ncols-1) * m_hgap, nrows * h + (nrows-1) * m_vgap ); } @@ -1452,6 +1522,20 @@ void wxGridSizer::SetItemBounds( wxSizerItem *item, int x, int y, int w, int h ) // wxFlexGridSizer //--------------------------------------------------------------------------- +wxFlexGridSizer::wxFlexGridSizer( int cols, int vgap, int hgap ) + : wxGridSizer( cols, vgap, hgap ), + m_flexDirection(wxBOTH), + m_growMode(wxFLEX_GROWMODE_SPECIFIED) +{ +} + +wxFlexGridSizer::wxFlexGridSizer( int cols, const wxSize& gap ) + : wxGridSizer( cols, gap ), + m_flexDirection(wxBOTH), + m_growMode(wxFLEX_GROWMODE_SPECIFIED) +{ +} + wxFlexGridSizer::wxFlexGridSizer( int rows, int cols, int vgap, int hgap ) : wxGridSizer( rows, cols, vgap, hgap ), m_flexDirection(wxBOTH), @@ -1459,8 +1543,8 @@ wxFlexGridSizer::wxFlexGridSizer( int rows, int cols, int vgap, int hgap ) { } -wxFlexGridSizer::wxFlexGridSizer( int cols, int vgap, int hgap ) - : wxGridSizer( cols, vgap, hgap ), +wxFlexGridSizer::wxFlexGridSizer( int rows, int cols, const wxSize& gap ) + : wxGridSizer( rows, cols, gap ), m_flexDirection(wxBOTH), m_growMode(wxFLEX_GROWMODE_SPECIFIED) { @@ -1571,7 +1655,7 @@ void wxFlexGridSizer::FindWidthsAndHeights(int nrows, int ncols) wxSizerItem * const item = *i; if ( item->IsShown() ) { - // NOTE: Not doing the calculation here, this is just + // NOTE: Not doing the calculation here, this is just // for finding max values. const wxSize sz(item->GetMinSizeWithBorder()); @@ -1609,11 +1693,9 @@ wxSize wxFlexGridSizer::CalcMin() m_rowHeights.assign(nrows, -1); m_colWidths.assign(ncols, -1); - // n is the index of the item in left-to-right top-to-bottom order - size_t n = 0; for ( wxSizerItemList::iterator i = m_children.begin(); i != m_children.end(); - ++i, ++n ) + ++i) { wxSizerItem * const item = *i; if ( item->IsShown() ) @@ -1622,7 +1704,7 @@ wxSize wxFlexGridSizer::CalcMin() } } - // The stage of looking for max values in each row/column has been + // The stage of looking for max values in each row/column has been // made a separate function, since it's reused in AdjustForGrowables. FindWidthsAndHeights(nrows,ncols); @@ -1742,6 +1824,38 @@ DoAdjustForGrowables(int delta, void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz) { +#if wxDEBUG_LEVEL + // by the time this function is called, the sizer should be already fully + // initialized and hence the number of its columns and rows is known and we + // can check that all indices in m_growableCols/Rows are valid (see also + // comments in AddGrowableCol/Row()) + if ( !m_rows || !m_cols ) + { + if ( !m_rows ) + { + int nrows = CalcRows(); + + for ( size_t n = 0; n < m_growableRows.size(); n++ ) + { + wxASSERT_MSG( m_growableRows[n] < nrows, + "invalid growable row index" ); + } + } + + if ( !m_cols ) + { + int ncols = CalcCols(); + + for ( size_t n = 0; n < m_growableCols.size(); n++ ) + { + wxASSERT_MSG( m_growableCols[n] < ncols, + "invalid growable column index" ); + } + } + } +#endif // wxDEBUG_LEVEL + + if ( (m_flexDirection & wxHORIZONTAL) || (m_growMode != wxFLEX_GROWMODE_NONE) ) { DoAdjustForGrowables @@ -1752,36 +1866,36 @@ void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz) m_growMode == wxFLEX_GROWMODE_SPECIFIED ? &m_growableColsProportions : NULL ); - - // This gives nested objects that benefit from knowing one size - // component in advance the chance to use that. + + // This gives nested objects that benefit from knowing one size + // component in advance the chance to use that. bool didAdjustMinSize = false; - int nrows, ncols; - CalcRowsCols(nrows, ncols); - + // Iterate over all items and inform about column width - size_t n = 0; + const int ncols = GetEffectiveColsCount(); + int col = 0; for ( wxSizerItemList::iterator i = m_children.begin(); i != m_children.end(); - ++i, ++n ) + ++i ) { - const int col = n % ncols; didAdjustMinSize |= (*i)->InformFirstDirection(wxHORIZONTAL, m_colWidths[col], sz.y - m_calculatedMinSize.y); - } + if ( ++col == ncols ) + col = 0; + } - // Only redo if info was actually used + // Only redo if info was actually used if( didAdjustMinSize ) - { - DoAdjustForGrowables - ( - sz.x - m_calculatedMinSize.x, - m_growableCols, - m_colWidths, - m_growMode == wxFLEX_GROWMODE_SPECIFIED ? &m_growableColsProportions - : NULL - ); + { + DoAdjustForGrowables + ( + sz.x - m_calculatedMinSize.x, + m_growableCols, + m_colWidths, + m_growMode == wxFLEX_GROWMODE_SPECIFIED ? &m_growableColsProportions + : NULL + ); + } } -} if ( (m_flexDirection & wxVERTICAL) || (m_growMode != wxFLEX_GROWMODE_NONE) ) { @@ -1798,15 +1912,40 @@ void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz) } } +bool wxFlexGridSizer::IsRowGrowable( size_t idx ) +{ + return m_growableRows.Index( idx ) != wxNOT_FOUND; +} + +bool wxFlexGridSizer::IsColGrowable( size_t idx ) +{ + return m_growableCols.Index( idx ) != wxNOT_FOUND; +} void wxFlexGridSizer::AddGrowableRow( size_t idx, int proportion ) { + wxASSERT_MSG( !IsRowGrowable( idx ), + "AddGrowableRow() called for growable row" ); + + // notice that we intentionally don't check the index validity here in (the + // common) case when the number of rows was not specified in the ctor -- in + // this case it will be computed only later, when all items are added to + // the sizer, and the check will be done in AdjustForGrowables() + wxCHECK_RET( !m_rows || idx < (size_t)m_rows, "invalid row index" ); + m_growableRows.Add( idx ); m_growableRowsProportions.Add( proportion ); } void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion ) { + wxASSERT_MSG( !IsColGrowable( idx ), + "AddGrowableCol() called for growable column" ); + + // see comment in AddGrowableRow(): although it's less common to omit the + // specification of the number of columns, it still can also happen + wxCHECK_RET( !m_cols || idx < (size_t)m_cols, "invalid column index" ); + m_growableCols.Add( idx ); m_growableColsProportions.Add( proportion ); } @@ -1826,7 +1965,7 @@ DoRemoveFromArrays(size_t idx, wxArrayInt& items, wxArrayInt& proportions) } } - wxFAIL_MSG( _T("column/row is already not growable") ); + wxFAIL_MSG( wxT("column/row is already not growable") ); } void wxFlexGridSizer::RemoveGrowableCol( size_t idx ) @@ -1843,22 +1982,29 @@ void wxFlexGridSizer::RemoveGrowableRow( size_t idx ) // wxBoxSizer //--------------------------------------------------------------------------- +wxSizerItem *wxBoxSizer::AddSpacer(int size) +{ + return IsVertical() ? Add(0, size) : Add(size, 0); +} + void wxBoxSizer::RecalcSizes() { if ( m_children.empty() ) return; - const wxCoord totalMinorSize = SizeInMinorDir(m_size); + const wxCoord totalMinorSize = GetSizeInMinorDir(m_size); + const wxCoord totalMajorSize = GetSizeInMajorDir(m_size); // the amount of free space which we should redistribute among the // stretchable items (i.e. those with non zero proportion) - int delta = SizeInMajorDir(m_size) - SizeInMajorDir(m_minSize); + int delta = totalMajorSize - GetSizeInMajorDir(m_minSize); + - // Inform child items about the size in minor direction, that can // change how much free space we have in major dir and how to distribute it. int majorMinSum = 0; - for ( wxSizerItemList::const_iterator i = m_children.begin(); + wxSizerItemList::const_iterator i ; + for ( i = m_children.begin(); i != m_children.end(); ++i ) { @@ -1870,27 +2016,30 @@ void wxBoxSizer::RecalcSizes() wxSize szMinPrev = item->GetMinSizeWithBorder(); item->InformFirstDirection(m_orient^wxBOTH,totalMinorSize,delta); wxSize szMin = item->GetMinSizeWithBorder(); - int deltaChange = SizeInMajorDir(szMin-szMinPrev); + int deltaChange = GetSizeInMajorDir(szMin-szMinPrev); if( deltaChange ) { - // Since we passed available space along to the item, it should not - // take too much ,so delat should not become negative. - delta -= deltaChange; + // Since we passed available space along to the item, it should not + // take too much, so delta should not become negative. + delta -= deltaChange; } - majorMinSum += SizeInMajorDir(item->GetMinSizeWithBorder()); + majorMinSum += GetSizeInMajorDir(item->GetMinSizeWithBorder()); } // And update our min size SizeInMajorDir(m_minSize) = majorMinSum; // might have a new delta now - delta = SizeInMajorDir(m_size) - SizeInMajorDir(m_minSize); - + delta = totalMajorSize - GetSizeInMajorDir(m_minSize); + // the position at which we put the next child wxPoint pt(m_position); + // space remaining for the items + wxCoord majorRemaining = totalMajorSize; + int totalProportion = m_totalProportion; - for ( wxSizerItemList::const_iterator i = m_children.begin(); + for ( i = m_children.begin(); i != m_children.end(); ++i ) { @@ -1898,33 +2047,45 @@ void wxBoxSizer::RecalcSizes() if ( !item->IsShown() ) continue; - -#ifndef __DMC__ - // DMC doesn't distinguish between - // int SizeInMajorDir(const wxSize& sz) const - // and int& SizeInMajorDir(wxSize& sz) - const -#endif - wxSize sizeThis(item->GetMinSizeWithBorder()); + + const wxSize sizeThis(item->GetMinSizeWithBorder()); // adjust the size in the major direction using the proportion - wxCoord majorSize = SizeInMajorDir(sizeThis); - const int propItem = item->GetProportion(); - if ( propItem ) + wxCoord majorSize = GetSizeInMajorDir(sizeThis); + + if ( delta > 0 ) { - const int deltaItem = (delta * propItem) / totalProportion; + // distribute extra space among the items respecting their + // proportions + const int propItem = item->GetProportion(); + if ( propItem ) + { + const int deltaItem = (delta * propItem) / totalProportion; - majorSize += deltaItem; + majorSize += deltaItem; - delta -= deltaItem; - totalProportion -= propItem; + delta -= deltaItem; + totalProportion -= propItem; + } + } + else // delta < 0 + { + // we're not going to have enough space for making all items even + // of their minimal size, check if this item still fits at all and + // truncate it if it doesn't -- even if it means giving it 0 size + // and thus making it invisible because we just can't do anything + // else + if ( majorSize > majorRemaining ) + majorSize = majorRemaining; + + majorRemaining -= majorSize; } // apply the alignment in the minor direction wxPoint posChild(pt); - wxCoord minorSize = SizeInMinorDir(sizeThis); + wxCoord minorSize = GetSizeInMinorDir(sizeThis); const int flag = item->GetFlag(); if ( flag & (wxEXPAND | wxSHAPED) ) { @@ -1936,7 +2097,7 @@ void wxBoxSizer::RecalcSizes() } // NB: wxCENTRE is used here only for backwards compatibility, // wxALIGN_CENTRE should be used in new code - else if ( flag & (wxCENTER | wxALIGN_CENTRE) ) + else if ( flag & (wxCENTER | (IsVertical() ? wxALIGN_CENTRE_HORIZONTAL : wxALIGN_CENTRE_VERTICAL))) { PosInMinorDir(posChild) += (totalMinorSize - minorSize) / 2; } @@ -1974,14 +2135,11 @@ wxSize wxBoxSizer::CalcMin() if ( !item->IsShown() ) continue; -#ifndef __DMC__ - const // see __DMC__ above -#endif - wxSize sizeMinThis = item->CalcMin(); - SizeInMajorDir(m_minSize) += SizeInMajorDir(sizeMinThis); - if ( SizeInMinorDir(sizeMinThis) > SizeInMinorDir(m_minSize) ) - SizeInMinorDir(m_minSize) = SizeInMinorDir(sizeMinThis); + const wxSize sizeMinThis = item->CalcMin(); + SizeInMajorDir(m_minSize) += GetSizeInMajorDir(sizeMinThis); + if ( GetSizeInMinorDir(sizeMinThis) > GetSizeInMinorDir(m_minSize) ) + SizeInMinorDir(m_minSize) = GetSizeInMinorDir(sizeMinThis); m_totalProportion += item->GetProportion(); } @@ -1989,224 +2147,6 @@ wxSize wxBoxSizer::CalcMin() return m_minSize; } -//--------------------------------------------------------------------------- -// wxWrapSizer -//--------------------------------------------------------------------------- - -#define wxDEFAULT_PROPORTION_LAST 1000000 - -// User data to hold old proportion for last item on line -// (which might be extended) -struct wxPropHolder : public wxObject -{ - wxPropHolder( ) : m_item(0), m_propOld(0) { } - void Init( wxSizerItem *item, int propOld ) { m_item=item; m_propOld=propOld; } - - wxSizerItem *m_item; - int m_propOld; -}; - -IMPLEMENT_DYNAMIC_CLASS(wxWrapSizer, wxBoxSizer); - -wxWrapSizer::wxWrapSizer( int orient, int flags ) - : wxBoxSizer(orient), - m_prim_size_last( -1 ), - m_rows(orient^wxBOTH), - m_flags(flags) -{ -} - -wxWrapSizer::~wxWrapSizer() -{ - // Have to clear grand child items so that they're not deleted twice - for( int ix=m_rows.GetChildren().GetCount()-1; ix>=0; ix-- ) - { - wxSizer *psz = m_rows.GetItem((size_t)ix)->GetSizer(); - wxSizerItemList &sl = psz->GetChildren(); - while( sl.GetLast() ) - sl.Erase( sl.GetLast() ); - } -} - - -bool wxWrapSizer::InformFirstDirection( int direction, int size, int WXUNUSED(availableOtherDir) ) -{ - if( !direction ) - { - // Better to keep value, then CalcMin will work better - //m_prim_size_last = -1; - return false; - } - if( direction==m_orient ) - { - // The direction is same as our primary, so we can make use of it - m_prim_size_last = size; - return true; - } - else - return false; -} - - -void wxWrapSizer::AdjustPropLastItem(wxSizer *psz, wxSizerItem *itemLast) -{ - wxSizerItem *psi = m_rows.GetItem(psz); - wxASSERT(psi); - wxPropHolder *pph = (wxPropHolder*)psi->GetUserData(); - if ( !pph ) - psi->SetUserData( pph=new wxPropHolder ); - - pph->Init( itemLast, itemLast->GetProportion() ); - itemLast->SetProportion( wxDEFAULT_PROPORTION_LAST ); -} - -void wxWrapSizer::RecalcSizes() -{ - wxASSERT( m_orient&wxBOTH ); - if (m_children.GetCount() == 0) - return; - - // What we do here is to put our items into child box sizers, - // as many of them as we have lines. - - // Empty all items in all rows in owned sizer. - // We have to access the list directly, since we don't want to - // destroy the wxSizerItems. - for( int ix=m_rows.GetChildren().GetCount()-1; ix>=0; ix-- ){ - wxSizerItem *psi = m_rows.GetItem( (size_t)ix ); - - // Restore proportion for last item on line (if item has not been deleted) - wxPropHolder *pph = (wxPropHolder*)psi->GetUserData(); - if( pph && GetChildren().Find(pph->m_item) ) - pph->m_item->SetProportion(pph->m_propOld); - - wxSizer *psz = psi->GetSizer(); - wxASSERT( psz ); - wxSizerItemList &sl = psz->GetChildren(); - while( sl.GetLast() ) - sl.Erase( sl.GetLast() ); - } - - int lineSumMajor = 0; - int majorSize = SizeInMajorDir(m_size); - - // Make sure we have at least one child sizer - m_n_line = 1; - if( !m_rows.GetChildren().GetCount() ) - m_rows.Add( new wxBoxSizer(GetOrientation()), 1, wxEXPAND ); - - // The sizer where to insert items in - wxSizer *psz = m_rows.GetItem((size_t)0)->GetSizer(); - wxASSERT( psz ); - - // Now put our child items into child sizers instead - wxSizerItemList::compatibility_iterator node = m_children.GetFirst(); - wxSizerItem *item = NULL, *itemLast=NULL; - while (node) - { - item = node->GetData(); - if ( item->IsShown() ) - { - wxSize minSz = item->GetMinSize(); - int minSzMajor = SizeInMajorDir(minSz); - - // More space on this line? - if( !lineSumMajor || lineSumMajor+minSzMajor<=majorSize ) - { - lineSumMajor += minSzMajor; - } - else - { - lineSumMajor = minSzMajor; - // Get a new empty sizer to insert into - if( (int)m_rows.GetChildren().GetCount()<=m_n_line ) - m_rows.Add( new wxBoxSizer(GetOrientation()), 1, wxEXPAND ); - - // If we have extend-last-on-each-line mode, then do so now - // Note: We must store old proportion value then. - if( m_flags&wxEXTEND_LAST_ON_EACH_LINE ) - AdjustPropLastItem(psz,itemLast); - - // The sizer where to insert items in - psz = m_rows.GetItem(m_n_line++)->GetSizer(); - } - itemLast = item; - psz->Add( item ); - // If item is a window, it now has a pointer to the child sizer, - // which is wrong. Set it to point to us. - if( item->GetWindow() ) - item->GetWindow()->SetContainingSizer( this ); - } - node = node->GetNext(); - } - - // If we have extend-last-on-each-line mode, then do so now - if( m_flags&wxEXTEND_LAST_ON_EACH_LINE ) - AdjustPropLastItem(psz,itemLast); - - // If we have more sizers than lines, remove them - while( (int)m_rows.GetChildren().GetCount()>m_n_line ) - m_rows.Remove( m_n_line ); - - // Now do layout on row sizer - m_rows.SetDimension( m_position.x, m_position.y, m_size.x, m_size.y ); - - // Remember this to next time (will be overridden by InformFirstDirection if used) - m_prim_size_last = SizeInMajorDir(m_size); -} - - -wxSize wxWrapSizer::CalcMin() -{ - if (m_children.GetCount() == 0) - return wxSize(); - - // Algorithm for calculating min size: (assuming horizontal orientation) - // X: Max width of all members - // Y: Based on last X, calculate how many lines needed - // First time around, assume all items fits on one line - - int maxMajor = 0; - int minorSum = 0; - int lineMaxMinor = 0; - int lineSumMajor = 0; - m_n_line = 0; - - // precalc item minsizes and fit on lines (preliminary) - wxSizerItemList::compatibility_iterator node = m_children.GetFirst(); - while (node) - { - wxSizerItem *item = node->GetData(); - if ( item->IsShown() ) - { - wxSize minSz = item->CalcMin(); - int szMajor = SizeInMajorDir(minSz); - int szMinor = SizeInMinorDir(minSz); - if( szMajor>maxMajor ) maxMajor = szMajor; - // More space on this line? - if( m_prim_size_last<0 || !lineSumMajor || - lineSumMajor+szMajor<=m_prim_size_last ) - { - lineSumMajor += szMajor; - if( szMinor>lineMaxMinor ) - lineMaxMinor = szMinor; - } - else - { - minorSum += lineMaxMinor; // Add height of highest item on last line - m_n_line++; - lineMaxMinor = szMinor; - lineSumMajor = szMajor; - } - } - node = node->GetNext(); - } - minorSum += lineMaxMinor; // Add height of highest item on last line - - m_minSize = SizeFromMajorMinor(maxMajor, minorSum); - return m_minSize; -} - //--------------------------------------------------------------------------- // wxStaticBoxSizer //--------------------------------------------------------------------------- @@ -2237,29 +2177,44 @@ wxStaticBoxSizer::~wxStaticBoxSizer() delete m_staticBox; } -static void GetStaticBoxBorders( wxStaticBox *box, - int *borderTop, - int *borderOther) -{ - // this has to be done platform by platform as there is no way to - // guess the thickness of a wxStaticBox border - box->GetBordersForSizer(borderTop, borderOther); -} - void wxStaticBoxSizer::RecalcSizes() { int top_border, other_border; - GetStaticBoxBorders(m_staticBox, &top_border, &other_border); + m_staticBox->GetBordersForSizer(&top_border, &other_border); m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y ); - wxPoint old_pos( m_position ); - m_position.x += other_border; - m_position.y += top_border; wxSize old_size( m_size ); m_size.x -= 2*other_border; m_size.y -= top_border + other_border; + wxPoint old_pos( m_position ); + if (m_staticBox->GetChildren().GetCount() > 0) + { +#if defined( __WXGTK20__ ) + // if the wxStaticBox has created a wxPizza to contain its children + // (see wxStaticBox::AddChild) then we need to place the items it contains + // in the wxBoxSizer::RecalcSizes() call below using coordinates relative + // to the top-left corner of the staticbox: + m_position.x = m_position.y = 0; +#else + // if the wxStaticBox has childrens, then these windows must be placed + // by the wxBoxSizer::RecalcSizes() call below using coordinates relative + // to the top-left corner of the staticbox (but unlike wxGTK, we need + // to keep in count the static borders here!): + m_position.x = other_border; + m_position.y = top_border; +#endif + } + else + { + // the windows contained in the staticbox have been created as siblings of the + // staticbox (this is the "old" way of staticbox contents creation); in this + // case we need to position them with coordinates relative to our common parent + m_position.x += other_border; + m_position.y += top_border; + } + wxBoxSizer::RecalcSizes(); m_position = old_pos; @@ -2269,10 +2224,17 @@ void wxStaticBoxSizer::RecalcSizes() wxSize wxStaticBoxSizer::CalcMin() { int top_border, other_border; - GetStaticBoxBorders(m_staticBox, &top_border, &other_border); + m_staticBox->GetBordersForSizer(&top_border, &other_border); wxSize ret( wxBoxSizer::CalcMin() ); ret.x += 2*other_border; + + // ensure that we're wide enough to show the static box label (there is no + // need to check for the static box best size in vertical direction though) + const int boxWidth = m_staticBox->GetBestSize().x; + if ( ret.x < boxWidth ) + ret.x = boxWidth; + ret.y += other_border + top_border; return ret; @@ -2300,6 +2262,10 @@ bool wxStaticBoxSizer::Detach( wxWindow *window ) #endif // wxUSE_STATBOX +//--------------------------------------------------------------------------- +// wxStdDialogButtonSizer +//--------------------------------------------------------------------------- + #if wxUSE_BUTTON wxStdDialogButtonSizer::wxStdDialogButtonSizer() @@ -2407,7 +2373,7 @@ void wxStdDialogButtonSizer::Realize() } // Extra space around and at the right - Add(12, 24); + Add(12, 40); #elif defined(__WXGTK20__) Add(0, 0, 0, wxLEFT, 9); if (m_buttonHelp)