]> git.saurik.com Git - wxWidgets.git/commitdiff
Modify wxBoxSizer minimal size calculations to respect the proportions.
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 22 May 2010 14:57:34 +0000 (14:57 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 22 May 2010 14:57:34 +0000 (14:57 +0000)
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
tests/sizers/boxsizer.cpp

index 31f25038500cd3385d5d1f6ceabb0ff140163e8a..badc6724abbe1dc33b52c1b435c9935328767ec2 100644 (file)
@@ -2300,7 +2300,12 @@ wxSize wxBoxSizer::CalcMin()
     m_totalProportion = 0;
     m_minSize = wxSize(0, 0);
 
     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 )
     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();
             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);
         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;
 }
 
     return m_minSize;
 }
 
index 558f15883babacffbe5fd3ec97290d7381f8074c..ca203d23796cdf2a2a8eb819261213b4847dc64c 100644 (file)
@@ -43,10 +43,12 @@ private:
     CPPUNIT_TEST_SUITE( BoxSizerTestCase );
         CPPUNIT_TEST( Size1 );
         CPPUNIT_TEST( Size3 );
     CPPUNIT_TEST_SUITE( BoxSizerTestCase );
         CPPUNIT_TEST( Size1 );
         CPPUNIT_TEST( Size3 );
+        CPPUNIT_TEST( CalcMin );
     CPPUNIT_TEST_SUITE_END();
 
     void Size1();
     void Size3();
     CPPUNIT_TEST_SUITE_END();
 
     void Size1();
     void Size3();
+    void CalcMin();
 
     wxWindow *m_win;
     wxSizer *m_sizer;
 
     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
+        );
+    }
+}