Respect item max sizes in wxBoxSizer.

Don't give more space than the max size, if set, to wxBoxSizer elements.

Closes #11497.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@72345 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2012-08-15 23:34:27 +00:00
parent 465de0be70
commit 93b87dd910
4 changed files with 156 additions and 1 deletions

View File

@@ -534,6 +534,7 @@ All:
All (GUI):
- Respect window max size in wxBoxSizer (Nathan Ridge).
- Add possibility to hide and show again wxRibbonBar pages (wxBen).
- Add expand/collapse button to wxRibbonBar (rakeshthp).
- Fix item data access in wxDataViewListCtrl (Kry).

View File

@@ -311,6 +311,10 @@ public:
{ return m_minSize; }
wxSize GetMinSizeWithBorder() const;
wxSize GetMaxSize() const
{ return IsWindow() ? m_window->GetMaxSize() : wxDefaultSize; }
wxSize GetMaxSizeWithBorder() const;
void SetMinSize(const wxSize& size)
{
if ( IsWindow() )

View File

@@ -417,6 +417,10 @@ wxSize wxSizerItem::GetMinSizeWithBorder() const
return AddBorderToSize(m_minSize);
}
wxSize wxSizerItem::GetMaxSizeWithBorder() const
{
return AddBorderToSize(GetMaxSize());
}
void wxSizerItem::SetDimension( const wxPoint& pos_, const wxSize& size_ )
{
@@ -2226,6 +2230,66 @@ void wxBoxSizer::RecalcSizes()
nonFixedSpaceChanged = true;
}
// Similar to the previous loop, but dealing with items whose max size
// is less than what we would allocate to them taking their proportion
// into account.
nonFixedSpaceChanged = false;
for ( i = m_children.begin(), n = 0; ; ++i, ++n )
{
if ( nonFixedSpaceChanged )
{
i = m_children.begin();
n = 0;
nonFixedSpaceChanged = false;
}
// check for the end of the loop only after the check above as
// otherwise we wouldn't do another pass if the last child resulted
// in non fixed space reduction
if ( i == m_children.end() )
break;
wxSizerItem * const item = *i;
if ( !item->IsShown() )
continue;
// don't check the item which we had already dealt with during a
// previous pass (this is more than an optimization, the code
// wouldn't work correctly if we kept adjusting for the same item
// over and over again)
if ( majorSizes[n] != wxDefaultCoord )
continue;
wxCoord maxMajor = GetSizeInMajorDir(item->GetMaxSizeWithBorder());
// must be nonzero, fixed-size items were dealt with in previous loop
const int propItem = item->GetProportion();
// is the desired size of this item small enough?
if ( maxMajor < 0 ||
(remaining*propItem)/totalProportion <= maxMajor )
{
// yes, it is, we'll determine the real size of this
// item later, for now just leave it as wxDefaultCoord
continue;
}
// the proportion of this item won't count, it has
// effectively become fixed
totalProportion -= propItem;
// we can already allocate space for this item
majorSizes[n] = maxMajor;
// change the amount of the space remaining to the other items,
// as this can result in not being able to satisfy their
// proportions any more we will need to redo another loop
// iteration
remaining -= maxMajor;
nonFixedSpaceChanged = true;
}
// Last by one pass: distribute the remaining space among the non-fixed
// items whose size weren't fixed yet according to their proportions.
@@ -2277,8 +2341,15 @@ void wxBoxSizer::RecalcSizes()
// its minimal size which is bad but better than not showing parts
// of the window at all
minorSize = totalMinorSize;
// do not allow the size in the minor direction to grow beyond the max
// size of the item in the minor direction
const wxCoord maxMinorSize = GetSizeInMinorDir(item->GetMaxSizeWithBorder());
if ( maxMinorSize >= 0 && minorSize > maxMinorSize )
minorSize = maxMinorSize;
}
else if ( flag & (IsVertical() ? wxALIGN_RIGHT : wxALIGN_BOTTOM) )
if ( flag & (IsVertical() ? wxALIGN_RIGHT : wxALIGN_BOTTOM) )
{
PosInMinorDir(posChild) += totalMinorSize - minorSize;
}

View File

@@ -20,6 +20,7 @@
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/sizer.h"
#include "wx/listbox.h"
#endif // WX_PRECOMP
#include "asserthelper.h"
@@ -41,11 +42,17 @@ private:
CPPUNIT_TEST( Size1 );
CPPUNIT_TEST( Size3 );
CPPUNIT_TEST( CalcMin );
CPPUNIT_TEST( BestSizeRespectsMaxSize );
CPPUNIT_TEST( RecalcSizesRespectsMaxSize1 );
CPPUNIT_TEST( RecalcSizesRespectsMaxSize2 );
CPPUNIT_TEST_SUITE_END();
void Size1();
void Size3();
void CalcMin();
void BestSizeRespectsMaxSize();
void RecalcSizesRespectsMaxSize1();
void RecalcSizesRespectsMaxSize2();
wxWindow *m_win;
wxSizer *m_sizer;
@@ -298,3 +305,75 @@ void BoxSizerTestCase::CalcMin()
);
}
}
void BoxSizerTestCase::BestSizeRespectsMaxSize()
{
m_sizer->Clear();
const int maxWidth = 100;
wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
wxListBox* listbox = new wxListBox(m_win, wxID_ANY);
listbox->Append("some very very very very very very very very very very very long string");
listbox->SetMaxSize(wxSize(maxWidth, -1));
sizer->Add(listbox);
m_sizer->Add(sizer);
m_win->Layout();
CPPUNIT_ASSERT_EQUAL(maxWidth, listbox->GetSize().GetWidth());
}
void BoxSizerTestCase::RecalcSizesRespectsMaxSize1()
{
m_sizer->Clear();
const int maxWidth = 100;
m_win->SetClientSize(300, 300);
wxSizer* sizer1 = new wxBoxSizer(wxVERTICAL);
m_sizer->Add(sizer1);
wxListBox* listbox1 = new wxListBox(m_win, wxID_ANY);
listbox1->Append("some very very very very very very very very very very very long string");
sizer1->Add(listbox1);
wxSizer* sizer2 = new wxBoxSizer(wxHORIZONTAL);
sizer1->Add(sizer2, wxSizerFlags().Expand());
wxListBox* listbox2 = new wxListBox(m_win, wxID_ANY);
listbox2->Append("some string");
listbox2->SetMaxSize(wxSize(100, -1));
sizer2->Add(listbox2, wxSizerFlags().Proportion(1));
m_win->Layout();
CPPUNIT_ASSERT_EQUAL(maxWidth, listbox2->GetSize().GetWidth());
}
void BoxSizerTestCase::RecalcSizesRespectsMaxSize2()
{
m_sizer->Clear();
m_win->SetClientSize(300, 300);
wxSizer* sizer1 = new wxBoxSizer(wxVERTICAL);
m_sizer->Add(sizer1, wxSizerFlags().Expand());
wxWindow* child1 = new wxWindow(m_win, wxID_ANY);
sizer1->Add(child1, wxSizerFlags().Proportion(1));
wxWindow* child2 = new wxWindow(m_win, wxID_ANY);
child2->SetMaxSize(wxSize(-1, 50));
sizer1->Add(child2, wxSizerFlags().Proportion(1));
wxWindow* child3 = new wxWindow(m_win, wxID_ANY);
sizer1->Add(child3, wxSizerFlags().Proportion(1));
m_win->Layout();
CPPUNIT_ASSERT_EQUAL(125, child1->GetSize().GetHeight());
CPPUNIT_ASSERT_EQUAL(50, child2->GetSize().GetHeight());
CPPUNIT_ASSERT_EQUAL(125, child3->GetSize().GetHeight());
}