From f27d62bf2f27f3b0b6e5cd608c8308c8bd81a93c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 22 May 2010 14:57:34 +0000 Subject: [PATCH] Modify wxBoxSizer minimal size calculations to respect the proportions. Make wxBoxSizer minimal size big enough to not only give each item enough space to satisfy its minimal size but also to respect the proportions among the items by default. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64382 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/common/sizer.cpp | 31 +++++++++++++++++++++++---- tests/sizers/boxsizer.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/src/common/sizer.cpp b/src/common/sizer.cpp index 31f2503..badc672 100644 --- a/src/common/sizer.cpp +++ b/src/common/sizer.cpp @@ -2300,7 +2300,12 @@ wxSize wxBoxSizer::CalcMin() m_totalProportion = 0; m_minSize = wxSize(0, 0); - // calculate the minimal sizes for all items and count sum of proportions + // 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 + // part, to respect the children proportion. To satisfy the latter + // condition we must find the greatest min-size-to-proportion ratio for all + // elements with non-zero proportion. + float maxMinSizeToProp = 0.; for ( wxSizerItemList::const_iterator i = m_children.begin(); i != m_children.end(); ++i ) @@ -2311,13 +2316,31 @@ wxSize wxBoxSizer::CalcMin() continue; const wxSize sizeMinThis = item->CalcMin(); - SizeInMajorDir(m_minSize) += GetSizeInMajorDir(sizeMinThis); + if ( const int propThis = item->GetProportion() ) + { + float minSizeToProp = GetSizeInMajorDir(sizeMinThis); + minSizeToProp /= propThis; + + if ( minSizeToProp > maxMinSizeToProp ) + maxMinSizeToProp = minSizeToProp; + + m_totalProportion += item->GetProportion(); + } + else // fixed size item + { + // Just account for its size directly + SizeInMajorDir(m_minSize) += GetSizeInMajorDir(sizeMinThis); + } + + // In the transversal direction we just need to find the maximum. if ( GetSizeInMinorDir(sizeMinThis) > GetSizeInMinorDir(m_minSize) ) SizeInMinorDir(m_minSize) = GetSizeInMinorDir(sizeMinThis); - - m_totalProportion += item->GetProportion(); } + // 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_minSize) += maxMinSizeToProp*m_totalProportion; + return m_minSize; } diff --git a/tests/sizers/boxsizer.cpp b/tests/sizers/boxsizer.cpp index 558f158..ca203d2 100644 --- a/tests/sizers/boxsizer.cpp +++ b/tests/sizers/boxsizer.cpp @@ -43,10 +43,12 @@ private: CPPUNIT_TEST_SUITE( BoxSizerTestCase ); CPPUNIT_TEST( Size1 ); CPPUNIT_TEST( Size3 ); + CPPUNIT_TEST( CalcMin ); CPPUNIT_TEST_SUITE_END(); void Size1(); void Size3(); + void CalcMin(); wxWindow *m_win; wxSizer *m_sizer; @@ -248,3 +250,54 @@ void BoxSizerTestCase::Size3() } } } + +void BoxSizerTestCase::CalcMin() +{ + static const unsigned NUM_TEST_ITEM = 3; + + static const struct CalcMinTestData + { + // proportions of the elements, if one of them is -1 it means to not + // use this window at all in this test + int prop[NUM_TEST_ITEM]; + + // minimal sizes of the elements in the sizer direction + int minsize[NUM_TEST_ITEM]; + + // the expected minimal sizer size + int total; + } calcMinTestData[] = + { + { { 1, 1, -1 }, { 30, 50, 0 }, 100 }, + { { 1, 1, 0 }, { 30, 50, 20 }, 120 }, + { { 10, 10, -1 }, { 30, 50, 0 }, 100 }, + { { 1, 2, 2 }, { 50, 50, 80 }, 250 }, + { { 1, 2, 2 }, { 100, 50, 80 }, 500 }, + }; + + unsigned n; + wxWindow *child[NUM_TEST_ITEM]; + for ( n = 0; n < NUM_TEST_ITEM; n++ ) + child[n] = new wxWindow(m_win, wxID_ANY); + + for ( unsigned i = 0; i < WXSIZEOF(calcMinTestData); i++ ) + { + m_sizer->Clear(); + + const CalcMinTestData& cmtd = calcMinTestData[i]; + for ( n = 0; n < NUM_TEST_ITEM; n++ ) + { + if ( cmtd.prop[n] != -1 ) + { + child[n]->SetInitialSize(wxSize(cmtd.minsize[n], -1)); + m_sizer->Add(child[n], wxSizerFlags(cmtd.prop[n])); + } + } + + WX_ASSERT_EQUAL_MESSAGE + ( + ("In test #%u", i), + cmtd.total, m_sizer->CalcMin().x + ); + } +} -- 2.7.4