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.
This commit is contained in:
Vadim Zeitlin 2015-10-11 01:13:33 +02:00
parent 7d9675472d
commit 622deec262
7 changed files with 84 additions and 72 deletions

View File

@ -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

View File

@ -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; }

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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();