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 )
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;
}
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;
}
}
}
+
+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
+ );
+ }
+}