From 622deec2624d4c8bf5549bf749711db985fd128f Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 11 Oct 2015 01:13:33 +0200 Subject: [PATCH] Replace wxSizer::RecalcSizes() with RepositionChildren() The new method takes minimal size just computed by RecalcSizes() as its argument making it unnecessary to store it as a member variable in the derived classes such as wx{Box,FlexGrid}Sizer. The old method can still be overridden for compatibility and by the derived class that don't need minimal size when updating children. --- include/wx/gbsizer.h | 2 +- include/wx/sizer.h | 43 +++++++++++++--------- include/wx/wrapsizer.h | 8 +++-- interface/wx/sizer.h | 13 ++++--- src/common/gbsizer.cpp | 7 ++-- src/common/sizer.cpp | 77 +++++++++++++++++++--------------------- src/common/wrapsizer.cpp | 6 ++-- 7 files changed, 84 insertions(+), 72 deletions(-) diff --git a/include/wx/gbsizer.h b/include/wx/gbsizer.h index 501b5d8188..3ddb9be5c4 100644 --- a/include/wx/gbsizer.h +++ b/include/wx/gbsizer.h @@ -291,8 +291,8 @@ public: // These are what make the sizer do size calculations and layout - virtual void RecalcSizes() wxOVERRIDE; virtual wxSize CalcMin() wxOVERRIDE; + virtual void RepositionChildren(const wxSize& minSize) wxOVERRIDE; // Look at all items and see if any intersect (or would overlap) the given diff --git a/include/wx/sizer.h b/include/wx/sizer.h index 16c86222a1..4f34ccd3ed 100644 --- a/include/wx/sizer.h +++ b/include/wx/sizer.h @@ -658,10 +658,26 @@ public: // These virtual functions are used by the layout algorithm: first // CalcMin() is called to calculate the minimal size of the sizer and - // prepare for laying it out and then RecalcSizes() is called to really - // update all the sizer items + // prepare for laying it out and then RepositionChildren() is called with + // this size to really update all the sizer items. virtual wxSize CalcMin() = 0; - virtual void RecalcSizes() = 0; + + // This method should be overridden but isn't pure virtual for backwards + // compatibility. + virtual void RepositionChildren(const wxSize& WXUNUSED(minSize)) + { + RecalcSizes(); + } + + // This is a deprecated version of RepositionChildren() which doesn't take + // the minimal size parameter which is not needed for very simple sizers + // but typically is for anything more complicated, so prefer to override + // RepositionChildren() in new code. + // + // If RepositionChildren() is not overridden, this method must be + // overridden, calling the base class version results in an assertion + // failure. + virtual void RecalcSizes(); virtual void Layout(); @@ -770,7 +786,7 @@ public: wxGridSizer( int rows, int cols, int vgap, int hgap ); wxGridSizer( int rows, int cols, const wxSize& gap ); - virtual void RecalcSizes() wxOVERRIDE; + virtual void RepositionChildren(const wxSize& minSize) wxOVERRIDE; virtual wxSize CalcMin() wxOVERRIDE; void SetCols( int cols ) @@ -901,13 +917,13 @@ public: const wxArrayInt& GetColWidths() const { return m_colWidths; } // implementation - virtual void RecalcSizes() wxOVERRIDE; + virtual void RepositionChildren(const wxSize& minSize) wxOVERRIDE; virtual wxSize CalcMin() wxOVERRIDE; protected: void AdjustForFlexDirection(); - void AdjustForGrowables(const wxSize& sz); - void FindWidthsAndHeights(int nrows, int ncols); + void AdjustForGrowables(const wxSize& sz, const wxSize& minSize); + wxSize FindWidthsAndHeights(int nrows, int ncols); // the heights/widths of all rows/columns wxArrayInt m_rowHeights, @@ -926,9 +942,6 @@ protected: int m_flexDirection; wxFlexSizerGrowMode m_growMode; - // saves CalcMin result to optimize RecalcSizes - wxSize m_calculatedMinSize; - private: wxDECLARE_CLASS(wxFlexGridSizer); wxDECLARE_NO_COPY_CLASS(wxFlexGridSizer); @@ -960,7 +973,7 @@ public: // implementation of our resizing logic virtual wxSize CalcMin() wxOVERRIDE; - virtual void RecalcSizes() wxOVERRIDE; + virtual void RepositionChildren(const wxSize& minSize) wxOVERRIDE; virtual bool InformFirstDirection(int direction, int size, @@ -1022,10 +1035,6 @@ protected: // the sum of proportion of all of our elements int m_totalProportion; - // the minimal size needed for this sizer as calculated by the last call to - // our CalcMin() - wxSize m_calculatedMinSize; - private: wxDECLARE_CLASS(wxBoxSizer); }; @@ -1045,8 +1054,8 @@ public: wxStaticBoxSizer(int orient, wxWindow *win, const wxString& label = wxEmptyString); virtual ~wxStaticBoxSizer(); - void RecalcSizes() wxOVERRIDE; - wxSize CalcMin() wxOVERRIDE; + virtual wxSize CalcMin() wxOVERRIDE; + virtual void RepositionChildren(const wxSize& minSize) wxOVERRIDE; wxStaticBox *GetStaticBox() const { return m_staticBox; } diff --git a/include/wx/wrapsizer.h b/include/wx/wrapsizer.h index f401c260df..d0494a14a4 100644 --- a/include/wx/wrapsizer.h +++ b/include/wx/wrapsizer.h @@ -36,7 +36,7 @@ public: // override base class virtual methods virtual wxSize CalcMin() wxOVERRIDE; - virtual void RecalcSizes() wxOVERRIDE; + virtual void RepositionChildren(const wxSize& minSize) wxOVERRIDE; virtual bool InformFirstDirection(int direction, int size, @@ -84,13 +84,17 @@ protected: bool m_lastUsed; // Indicates whether value from InformFirst... has // been used yet - // The sizes below are computed by RecalcSizes(), i.e. they don't have + // The sizes below are computed by RepositionChildren(), i.e. they don't have // valid values during the initial call to CalcMin() and they are only // valid for the current layout (i.e. the current number of rows) int m_minSizeMinor; // Min size in minor direction int m_maxSizeMajor; // Size of longest row int m_minItemMajor; // Size of smallest item in major direction + // the minimal size needed for this sizer as calculated by the last call to + // our CalcMin() + wxSize m_calculatedMinSize; + wxBoxSizer m_rows; // Sizer containing multiple rows of our items wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxWrapSizer); diff --git a/interface/wx/sizer.h b/interface/wx/sizer.h index f1e3295f52..1cc562ac76 100644 --- a/interface/wx/sizer.h +++ b/interface/wx/sizer.h @@ -725,11 +725,16 @@ public: wxSizerItem* PrependStretchSpacer(int prop = 1); /** - This method is abstract and has to be overwritten by any derived class. - Here, the sizer will do the actual calculation of its children's - positions and sizes. + Method which must be overridden in the derived sizer classes. + + The implementation should reposition the children using the current + total size available to the sizer (@c m_size) and the size computed by + the last call to CalcMin(). + + @since 3.1.3, before this version RecalcSizes() method not taking any + arguments had to be overridden in the derived classes instead. */ - virtual void RecalcSizes() = 0; + virtual void RepositionChildren(const wxSize& minSize) = 0; /** Removes a child window from the sizer, but does @b not destroy it diff --git a/src/common/gbsizer.cpp b/src/common/gbsizer.cpp index 3b291872a4..7ee9b8273a 100644 --- a/src/common/gbsizer.cpp +++ b/src/common/gbsizer.cpp @@ -497,13 +497,12 @@ wxSize wxGridBagSizer::CalcMin() for (idx=0; idx < m_rows; idx++) height += m_rowHeights[idx] + ( idx == m_rows-1 ? 0 : m_vgap ); - m_calculatedMinSize = wxSize(width, height); - return m_calculatedMinSize; + return wxSize(width, height); } -void wxGridBagSizer::RecalcSizes() +void wxGridBagSizer::RepositionChildren(const wxSize& minSize) { // We can't lay out our elements if we don't have at least a single row and // a single column. Notice that this may happen even if we have some @@ -519,7 +518,7 @@ void wxGridBagSizer::RecalcSizes() m_cols = m_colWidths.GetCount(); int idx, width, height; - AdjustForGrowables(sz); + AdjustForGrowables(sz, minSize); // Find the start positions on the window of the rows and columns wxArrayInt rowpos; diff --git a/src/common/sizer.cpp b/src/common/sizer.cpp index 9bc0d295fb..651af1c48f 100644 --- a/src/common/sizer.cpp +++ b/src/common/sizer.cpp @@ -984,16 +984,23 @@ void wxSizer::FitInside( wxWindow *window ) window->SetVirtualSize( size ); } +void wxSizer::RecalcSizes() +{ + // It is recommended to override RepositionChildren() in the derived + // classes, but if they don't do it, this method must be overridden. + wxFAIL_MSG( wxS("Must be overridden if RepositionChildren() is not") ); +} + void wxSizer::Layout() { // (re)calculates minimums needed for each item and other preparations // for layout - CalcMin(); + const wxSize minSize = CalcMin(); // Applies the layout and repositions/resizes the items wxWindow::ChildrenRepositioningGuard repositionGuard(m_containingWindow); - RecalcSizes(); + RepositionChildren(minSize); } void wxSizer::SetSizeHints( wxWindow *window ) @@ -1457,7 +1464,7 @@ int wxGridSizer::CalcRowsCols(int& nrows, int& ncols) const return nitems; } -void wxGridSizer::RecalcSizes() +void wxGridSizer::RepositionChildren(const wxSize& WXUNUSED(minSize)) { int nitems, nrows, ncols; if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 ) @@ -1625,7 +1632,7 @@ wxFlexGridSizer::~wxFlexGridSizer() { } -void wxFlexGridSizer::RecalcSizes() +void wxFlexGridSizer::RepositionChildren(const wxSize& minSize) { int nrows, ncols; if ( !CalcRowsCols(nrows, ncols) ) @@ -1634,7 +1641,7 @@ void wxFlexGridSizer::RecalcSizes() const wxPoint pt(GetPosition()); const wxSize sz(GetSize()); - AdjustForGrowables(sz); + AdjustForGrowables(sz, minSize); wxSizerItemList::const_iterator i = m_children.begin(); const wxSizerItemList::const_iterator end = m_children.end(); @@ -1707,16 +1714,8 @@ static int SumArraySizes(const wxArrayInt& sizes, int gap) return total; } -void wxFlexGridSizer::FindWidthsAndHeights(int nrows, int ncols) +wxSize wxFlexGridSizer::FindWidthsAndHeights(int WXUNUSED(nrows), int ncols) { - // We have to recalculate the sizes in case the item minimum size has - // changed since the previous layout, or the item has been hidden using - // wxSizer::Show(). If all the items in a row/column are hidden, the final - // dimension of the row/column will be -1, indicating that the column - // itself is hidden. - 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(); @@ -1742,8 +1741,8 @@ void wxFlexGridSizer::FindWidthsAndHeights(int nrows, int ncols) AdjustForFlexDirection(); - m_calculatedMinSize = wxSize(SumArraySizes(m_colWidths, m_hgap), - SumArraySizes(m_rowHeights, m_vgap)); + return wxSize(SumArraySizes(m_colWidths, m_hgap), + SumArraySizes(m_rowHeights, m_vgap)); } wxSize wxFlexGridSizer::CalcMin() @@ -1775,11 +1774,7 @@ wxSize wxFlexGridSizer::CalcMin() } } - // 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); - - return m_calculatedMinSize; + return FindWidthsAndHeights(nrows,ncols); } void wxFlexGridSizer::AdjustForFlexDirection() @@ -1893,7 +1888,7 @@ DoAdjustForGrowables(int delta, } } -void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz) +void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz, const wxSize& minSize) { #if wxDEBUG_LEVEL // by the time this function is called, the sizer should be already fully @@ -1931,7 +1926,7 @@ void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz) { DoAdjustForGrowables ( - sz.x - m_calculatedMinSize.x, + sz.x - minSize.x, m_growableCols, m_colWidths, m_growMode == wxFLEX_GROWMODE_SPECIFIED ? &m_growableColsProportions @@ -1949,7 +1944,7 @@ void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz) i != m_children.end(); ++i ) { - didAdjustMinSize |= (*i)->InformFirstDirection(wxHORIZONTAL, m_colWidths[col], sz.y - m_calculatedMinSize.y); + didAdjustMinSize |= (*i)->InformFirstDirection(wxHORIZONTAL, m_colWidths[col], sz.y - minSize.y); if ( ++col == ncols ) col = 0; } @@ -1959,7 +1954,7 @@ void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz) { DoAdjustForGrowables ( - sz.x - m_calculatedMinSize.x, + sz.x - minSize.x, m_growableCols, m_colWidths, m_growMode == wxFLEX_GROWMODE_SPECIFIED ? &m_growableColsProportions @@ -1974,7 +1969,7 @@ void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz) // should treat all rows as having proportion of 1 then DoAdjustForGrowables ( - sz.y - m_calculatedMinSize.y, + sz.y - minSize.y, m_growableRows, m_rowHeights, m_growMode == wxFLEX_GROWMODE_SPECIFIED ? &m_growableRowsProportions @@ -2123,9 +2118,9 @@ namespace { /* - Helper of RecalcSizes(): checks if there is enough remaining space for the - min size of the given item and returns its min size or the entire remaining - space depending on which one is greater. + Helper of RepositionChildren(): checks if there is enough remaining space + for the min size of the given item and returns its min size or the entire + remaining space depending on which one is greater. This function updates the remaining space parameter to account for the size effectively allocated to the item. @@ -2163,7 +2158,7 @@ GetMinOrRemainingSize(int orient, const wxSizerItem *item, int *remainingSpace_) } // anonymous namespace -void wxBoxSizer::RecalcSizes() +void wxBoxSizer::RepositionChildren(const wxSize& minSize) { if ( m_children.empty() ) return; @@ -2173,7 +2168,7 @@ void wxBoxSizer::RecalcSizes() // the amount of free space which we should redistribute among the // stretchable items (i.e. those with non zero proportion) - int delta = totalMajorSize - GetSizeInMajorDir(m_calculatedMinSize); + int delta = totalMajorSize - GetSizeInMajorDir(minSize); // declare loop variables used below: wxSizerItemList::const_iterator i; // iterator in m_children list @@ -2492,7 +2487,7 @@ void wxBoxSizer::RecalcSizes() wxSize wxBoxSizer::CalcMin() { m_totalProportion = 0; - m_calculatedMinSize = wxSize(0, 0); + wxSize minSize; // The minimal size for the sizer should be big enough to allocate its // element at least its minimal size but also, and this is the non trivial @@ -2523,19 +2518,19 @@ wxSize wxBoxSizer::CalcMin() else // fixed size item { // Just account for its size directly - SizeInMajorDir(m_calculatedMinSize) += GetSizeInMajorDir(sizeMinThis); + SizeInMajorDir(minSize) += GetSizeInMajorDir(sizeMinThis); } // In the transversal direction we just need to find the maximum. - if ( GetSizeInMinorDir(sizeMinThis) > GetSizeInMinorDir(m_calculatedMinSize) ) - SizeInMinorDir(m_calculatedMinSize) = GetSizeInMinorDir(sizeMinThis); + if ( GetSizeInMinorDir(sizeMinThis) > GetSizeInMinorDir(minSize) ) + SizeInMinorDir(minSize) = GetSizeInMinorDir(sizeMinThis); } // Using the max ratio ensures that the min size is big enough for all // items to have their min size and satisfy the proportions among them. - SizeInMajorDir(m_calculatedMinSize) += (int)(maxMinSizeToProp*m_totalProportion); + SizeInMajorDir(minSize) += (int)(maxMinSizeToProp*m_totalProportion); - return m_calculatedMinSize; + return minSize; } bool @@ -2604,7 +2599,7 @@ wxStaticBoxSizer::~wxStaticBoxSizer() m_staticBox->WXDestroyWithoutChildren(); } -void wxStaticBoxSizer::RecalcSizes() +void wxStaticBoxSizer::RepositionChildren(const wxSize& minSize) { int top_border, other_border; m_staticBox->GetBordersForSizer(&top_border, &other_border); @@ -2621,7 +2616,7 @@ void wxStaticBoxSizer::RecalcSizes() #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 + // in the base class version called below using coordinates relative // to the top-left corner of the staticbox: m_position.x = m_position.y = 0; #elif defined(__WXOSX__) && wxOSX_USE_COCOA @@ -2630,7 +2625,7 @@ void wxStaticBoxSizer::RecalcSizes() m_position.x = m_position.y = 10; #else // if the wxStaticBox has children, then these windows must be placed - // by the wxBoxSizer::RecalcSizes() call below using coordinates relative + // by the base class version called 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; @@ -2646,7 +2641,7 @@ void wxStaticBoxSizer::RecalcSizes() m_position.y += top_border; } - wxBoxSizer::RecalcSizes(); + wxBoxSizer::RepositionChildren(minSize); m_position = old_pos; m_size = old_size; diff --git a/src/common/wrapsizer.cpp b/src/common/wrapsizer.cpp index 90118e3c74..155eb95341 100644 --- a/src/common/wrapsizer.cpp +++ b/src/common/wrapsizer.cpp @@ -92,8 +92,8 @@ void wxWrapSizer::ClearRows() { // all elements of the row sizers are also elements of this one (we // directly add pointers to elements of our own m_children list to the row - // sizers in RecalcSizes()), so we need to detach them from the row sizer - // to avoid double deletion + // sizers in RepositionChildren()), so we need to detach them from the row + // sizer to avoid double deletion wxSizerItemList& rows = m_rows.GetChildren(); for ( wxSizerItemList::iterator i = rows.begin(), end = rows.end(); @@ -485,7 +485,7 @@ void wxWrapSizer::FinishRow(size_t n, AdjustLastRowItemProp(n, itemLast); } -void wxWrapSizer::RecalcSizes() +void wxWrapSizer::RepositionChildren(const wxSize& WXUNUSED(minSize)) { // First restore any proportions we may have changed and remove the old rows ClearRows();