distribute only the extra, free, space according to the items proportions in wxBoxSizer and not the entire available space
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45577 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -19,6 +19,13 @@ Changes in behaviour not resulting in compilation errors, please read this!
|
|||||||
other platforms in the future), use wxWindow::Navigate() or NavigateIn()
|
other platforms in the future), use wxWindow::Navigate() or NavigateIn()
|
||||||
instead.
|
instead.
|
||||||
|
|
||||||
|
- Sizers distribute only the extra space between the stretchable items
|
||||||
|
according to their proportions and not all available space. We believe the
|
||||||
|
new behaviour corresponds better to user expectations but if you did rely
|
||||||
|
on the old behaviour you will have to update your code to set the minimal
|
||||||
|
sizes of the sizer items to be in the same proportion as the items
|
||||||
|
proportions to return to the old behaviour.
|
||||||
|
|
||||||
Changes in behaviour which may result in compilation errors
|
Changes in behaviour which may result in compilation errors
|
||||||
-----------------------------------------------------------
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
@@ -73,7 +73,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// some shortcuts for Align()
|
// some shortcuts for Align()
|
||||||
wxSizerFlags& Centre() { return Align(wxCENTRE); }
|
wxSizerFlags& Centre() { return Align(wxALIGN_CENTRE); }
|
||||||
wxSizerFlags& Center() { return Centre(); }
|
wxSizerFlags& Center() { return Centre(); }
|
||||||
wxSizerFlags& Top() { return Align(wxALIGN_TOP); }
|
wxSizerFlags& Top() { return Align(wxALIGN_TOP); }
|
||||||
wxSizerFlags& Left() { return Align(wxALIGN_LEFT); }
|
wxSizerFlags& Left() { return Align(wxALIGN_LEFT); }
|
||||||
@@ -569,8 +569,12 @@ public:
|
|||||||
// Calculate the minimal size or return m_minSize if bigger.
|
// Calculate the minimal size or return m_minSize if bigger.
|
||||||
wxSize GetMinSize();
|
wxSize GetMinSize();
|
||||||
|
|
||||||
virtual void RecalcSizes() = 0;
|
// 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
|
||||||
virtual wxSize CalcMin() = 0;
|
virtual wxSize CalcMin() = 0;
|
||||||
|
virtual void RecalcSizes() = 0;
|
||||||
|
|
||||||
virtual void Layout();
|
virtual void Layout();
|
||||||
|
|
||||||
@@ -765,24 +769,80 @@ private:
|
|||||||
class WXDLLEXPORT wxBoxSizer: public wxSizer
|
class WXDLLEXPORT wxBoxSizer: public wxSizer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
wxBoxSizer( int orient );
|
wxBoxSizer(int orient)
|
||||||
|
{
|
||||||
|
m_orient = orient;
|
||||||
|
|
||||||
void RecalcSizes();
|
wxASSERT_MSG( m_orient == wxHORIZONTAL || m_orient == wxVERTICAL,
|
||||||
wxSize CalcMin();
|
_T("invalid value for wxBoxSizer orientation") );
|
||||||
|
}
|
||||||
|
|
||||||
int GetOrientation() const
|
int GetOrientation() const { return m_orient; }
|
||||||
{ return m_orient; }
|
|
||||||
|
|
||||||
void SetOrientation(int orient)
|
bool IsVertical() const { return m_orient == wxVERTICAL; }
|
||||||
{ m_orient = orient; }
|
|
||||||
|
void SetOrientation(int orient) { m_orient = orient; }
|
||||||
|
|
||||||
|
// implementation of our resizing logic
|
||||||
|
virtual wxSize CalcMin();
|
||||||
|
virtual void RecalcSizes();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// helpers for our code: this returns the component of the given wxSize in
|
||||||
|
// the direction of the sizer and in the other direction, respectively
|
||||||
|
int SizeInMajorDir(const wxSize& sz) const
|
||||||
|
{
|
||||||
|
return m_orient == wxHORIZONTAL ? sz.x : sz.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
int& SizeInMajorDir(wxSize& sz)
|
||||||
|
{
|
||||||
|
return m_orient == wxHORIZONTAL ? sz.x : sz.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
int& PosInMajorDir(wxPoint& pt)
|
||||||
|
{
|
||||||
|
return m_orient == wxHORIZONTAL ? pt.x : pt.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SizeInMinorDir(const wxSize& sz) const
|
||||||
|
{
|
||||||
|
return m_orient == wxHORIZONTAL ? sz.y : sz.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
int& SizeInMinorDir(wxSize& sz)
|
||||||
|
{
|
||||||
|
return m_orient == wxHORIZONTAL ? sz.y : sz.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
int& PosInMinorDir(wxPoint& pt)
|
||||||
|
{
|
||||||
|
return m_orient == wxHORIZONTAL ? pt.y : pt.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// another helper: creates wxSize from major and minor components
|
||||||
|
wxSize SizeFromMajorMinor(int major, int minor) const
|
||||||
|
{
|
||||||
|
if ( m_orient == wxHORIZONTAL )
|
||||||
|
{
|
||||||
|
return wxSize(major, minor);
|
||||||
|
}
|
||||||
|
else // wxVERTICAL
|
||||||
|
{
|
||||||
|
return wxSize(minor, major);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// either wxHORIZONTAL or wxVERTICAL
|
||||||
int m_orient;
|
int m_orient;
|
||||||
int m_stretchable;
|
|
||||||
int m_minWidth;
|
// the sum of proportion of all of our elements
|
||||||
int m_minHeight;
|
int m_totalProportion;
|
||||||
int m_fixedWidth;
|
|
||||||
int m_fixedHeight;
|
// the minimal size needed for this sizer as calculated by the last call to
|
||||||
|
// our CalcMin()
|
||||||
|
wxSize m_minSize;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DECLARE_CLASS(wxBoxSizer)
|
DECLARE_CLASS(wxBoxSizer)
|
||||||
|
@@ -1628,204 +1628,106 @@ void wxFlexGridSizer::RemoveGrowableRow( size_t idx )
|
|||||||
// wxBoxSizer
|
// wxBoxSizer
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
wxBoxSizer::wxBoxSizer( int orient )
|
|
||||||
: m_orient( orient )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void wxBoxSizer::RecalcSizes()
|
void wxBoxSizer::RecalcSizes()
|
||||||
{
|
{
|
||||||
if (m_children.GetCount() == 0)
|
if ( m_children.empty() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int delta = 0;
|
// the amount of free space which we should redistribute among the
|
||||||
if (m_stretchable)
|
// stretchable items (i.e. those with non zero proportion)
|
||||||
{
|
const int delta = SizeInMajorDir(m_size) - SizeInMajorDir(m_minSize);
|
||||||
if (m_orient == wxHORIZONTAL)
|
|
||||||
delta = m_size.x - m_fixedWidth;
|
|
||||||
else
|
|
||||||
delta = m_size.y - m_fixedHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// the position at which we put the next child
|
||||||
wxPoint pt(m_position);
|
wxPoint pt(m_position);
|
||||||
|
|
||||||
wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
|
const wxCoord totalMinorSize = SizeInMinorDir(m_size);
|
||||||
while (node)
|
|
||||||
{
|
|
||||||
wxSizerItem *item = node->GetData();
|
|
||||||
|
|
||||||
if (item->IsShown())
|
for ( wxSizerItemList::const_iterator i = m_children.begin();
|
||||||
|
i != m_children.end();
|
||||||
|
++i )
|
||||||
{
|
{
|
||||||
wxSize size( item->GetMinSizeWithBorder() );
|
wxSizerItem * const item = *i;
|
||||||
|
|
||||||
if (m_orient == wxVERTICAL)
|
if ( !item->IsShown() )
|
||||||
{
|
continue;
|
||||||
wxCoord height = size.y;
|
|
||||||
|
const wxSize sizeThis(item->GetMinSizeWithBorder());
|
||||||
|
|
||||||
|
|
||||||
|
// adjust the size in the major direction using the proportion
|
||||||
|
wxCoord majorSize = SizeInMajorDir(sizeThis);
|
||||||
if ( item->GetProportion() )
|
if ( item->GetProportion() )
|
||||||
{
|
{
|
||||||
// Because of at least one visible item has non-zero
|
// as at least one visible item has non-zero proportion the total
|
||||||
// proportion then m_stretchable is not zero
|
// proportion must be non zero
|
||||||
height = (delta * item->GetProportion()) / m_stretchable;
|
majorSize += (delta * item->GetProportion()) / m_totalProportion;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxPoint child_pos( pt );
|
|
||||||
wxSize child_size( size.x, height );
|
|
||||||
|
|
||||||
if (item->GetFlag() & (wxEXPAND | wxSHAPED))
|
// apply the alignment in the minor direction
|
||||||
child_size.x = m_size.x;
|
wxPoint posChild(pt);
|
||||||
else if (item->GetFlag() & wxALIGN_RIGHT)
|
|
||||||
child_pos.x += m_size.x - size.x;
|
|
||||||
else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
|
|
||||||
// XXX wxCENTER is added for backward compatibility;
|
|
||||||
// wxALIGN_CENTER should be used in new code
|
|
||||||
child_pos.x += (m_size.x - size.x) / 2;
|
|
||||||
|
|
||||||
item->SetDimension( child_pos, child_size );
|
wxCoord minorSize = SizeInMinorDir(sizeThis);
|
||||||
|
const int flag = item->GetFlag();
|
||||||
pt.y += height;
|
if ( flag & (wxEXPAND | wxSHAPED) )
|
||||||
|
{
|
||||||
|
minorSize = totalMinorSize;
|
||||||
}
|
}
|
||||||
else
|
else if ( flag & (IsVertical() ? wxALIGN_RIGHT : wxALIGN_BOTTOM) )
|
||||||
{
|
{
|
||||||
wxCoord width = size.x;
|
PosInMinorDir(posChild) += totalMinorSize - minorSize;
|
||||||
if (item->GetProportion())
|
}
|
||||||
|
// NB: wxCENTRE is used here only for backwards compatibility,
|
||||||
|
// wxALIGN_CENTRE should be used in new code
|
||||||
|
else if ( flag & (wxCENTER | wxALIGN_CENTRE) )
|
||||||
{
|
{
|
||||||
// Because of at least one visible item has non-zero
|
PosInMinorDir(posChild) += (totalMinorSize - minorSize) / 2;
|
||||||
// proportion then m_stretchable is not zero
|
|
||||||
width = (delta * item->GetProportion()) / m_stretchable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxPoint child_pos( pt );
|
|
||||||
wxSize child_size( width, size.y );
|
|
||||||
|
|
||||||
if (item->GetFlag() & (wxEXPAND | wxSHAPED))
|
// apply RTL adjustment for horizontal sizers:
|
||||||
child_size.y = m_size.y;
|
if ( !IsVertical() && m_containingWindow )
|
||||||
else if (item->GetFlag() & wxALIGN_BOTTOM)
|
|
||||||
child_pos.y += m_size.y - size.y;
|
|
||||||
else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
|
|
||||||
// XXX wxCENTER is added for backward compatibility;
|
|
||||||
// wxALIGN_CENTER should be used in new code
|
|
||||||
child_pos.y += (m_size.y - size.y) / 2;
|
|
||||||
|
|
||||||
if ( m_containingWindow )
|
|
||||||
{
|
{
|
||||||
child_pos.x = m_containingWindow->AdjustForLayoutDirection
|
posChild.x = m_containingWindow->AdjustForLayoutDirection
|
||||||
(
|
(
|
||||||
child_pos.x,
|
posChild.x,
|
||||||
width,
|
majorSize,
|
||||||
m_size.x
|
m_size.x
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
item->SetDimension( child_pos, child_size );
|
// finally set size of this child and advance to the next one
|
||||||
|
item->SetDimension(posChild, SizeFromMajorMinor(majorSize, minorSize));
|
||||||
|
|
||||||
pt.x += width;
|
PosInMajorDir(pt) += majorSize;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
node = node->GetNext();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wxSize wxBoxSizer::CalcMin()
|
wxSize wxBoxSizer::CalcMin()
|
||||||
{
|
{
|
||||||
if (m_children.GetCount() == 0)
|
m_totalProportion = 0;
|
||||||
return wxSize();
|
m_minSize = wxSize(0, 0);
|
||||||
|
|
||||||
m_stretchable = 0;
|
// calculate the minimal sizes for all items and count sum of proportions
|
||||||
m_minWidth = 0;
|
for ( wxSizerItemList::const_iterator i = m_children.begin();
|
||||||
m_minHeight = 0;
|
i != m_children.end();
|
||||||
m_fixedWidth = 0;
|
++i )
|
||||||
m_fixedHeight = 0;
|
|
||||||
|
|
||||||
// precalc item minsizes and count proportions
|
|
||||||
wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
|
|
||||||
while (node)
|
|
||||||
{
|
{
|
||||||
wxSizerItem *item = node->GetData();
|
wxSizerItem * const item = *i;
|
||||||
|
|
||||||
if ( item->IsShown() )
|
if ( !item->IsShown() )
|
||||||
{
|
continue;
|
||||||
item->CalcMin(); // result is stored in the item
|
|
||||||
|
|
||||||
m_stretchable += item->GetProportion();
|
const wxSize sizeMinThis = item->CalcMin();
|
||||||
|
|
||||||
|
SizeInMajorDir(m_minSize) += SizeInMajorDir(sizeMinThis);
|
||||||
|
if ( SizeInMinorDir(sizeMinThis) > SizeInMinorDir(m_minSize) )
|
||||||
|
SizeInMinorDir(m_minSize) = SizeInMinorDir(sizeMinThis);
|
||||||
|
|
||||||
|
m_totalProportion += item->GetProportion();
|
||||||
}
|
}
|
||||||
|
|
||||||
node = node->GetNext();
|
return m_minSize;
|
||||||
}
|
|
||||||
|
|
||||||
// Total minimum size (width or height) of sizer
|
|
||||||
int maxMinSize = 0;
|
|
||||||
|
|
||||||
node = m_children.GetFirst();
|
|
||||||
while (node)
|
|
||||||
{
|
|
||||||
wxSizerItem *item = node->GetData();
|
|
||||||
|
|
||||||
if (item->IsShown() && item->GetProportion() != 0)
|
|
||||||
{
|
|
||||||
int stretch = item->GetProportion();
|
|
||||||
wxSize size( item->GetMinSizeWithBorder() );
|
|
||||||
int minSize;
|
|
||||||
|
|
||||||
// Integer division rounded up is (a + b - 1) / b
|
|
||||||
// Round up needed in order to guarantee that all
|
|
||||||
// all items will have size not less then their min size
|
|
||||||
if (m_orient == wxHORIZONTAL)
|
|
||||||
minSize = ( size.x*m_stretchable + stretch - 1)/stretch;
|
|
||||||
else
|
|
||||||
minSize = ( size.y*m_stretchable + stretch - 1)/stretch;
|
|
||||||
|
|
||||||
if (minSize > maxMinSize)
|
|
||||||
maxMinSize = minSize;
|
|
||||||
}
|
|
||||||
node = node->GetNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate overall minimum size
|
|
||||||
node = m_children.GetFirst();
|
|
||||||
while (node)
|
|
||||||
{
|
|
||||||
wxSizerItem *item = node->GetData();
|
|
||||||
|
|
||||||
if (item->IsShown())
|
|
||||||
{
|
|
||||||
wxSize size( item->GetMinSizeWithBorder() );
|
|
||||||
if (item->GetProportion() != 0)
|
|
||||||
{
|
|
||||||
if (m_orient == wxHORIZONTAL)
|
|
||||||
size.x = (maxMinSize*item->GetProportion())/m_stretchable;
|
|
||||||
else
|
|
||||||
size.y = (maxMinSize*item->GetProportion())/m_stretchable;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (m_orient == wxVERTICAL)
|
|
||||||
{
|
|
||||||
m_fixedHeight += size.y;
|
|
||||||
m_fixedWidth = wxMax( m_fixedWidth, size.x );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_fixedWidth += size.x;
|
|
||||||
m_fixedHeight = wxMax( m_fixedHeight, size.y );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_orient == wxHORIZONTAL)
|
|
||||||
{
|
|
||||||
m_minWidth += size.x;
|
|
||||||
m_minHeight = wxMax( m_minHeight, size.y );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_minHeight += size.y;
|
|
||||||
m_minWidth = wxMax( m_minWidth, size.x );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
node = node->GetNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
return wxSize( m_minWidth, m_minHeight );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
Reference in New Issue
Block a user