]> git.saurik.com Git - wxWidgets.git/commitdiff
Respect item max sizes in wxBoxSizer.
authorVadim Zeitlin <vadim@wxwidgets.org>
Wed, 15 Aug 2012 23:34:27 +0000 (23:34 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Wed, 15 Aug 2012 23:34:27 +0000 (23:34 +0000)
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

docs/changes.txt
include/wx/sizer.h
src/common/sizer.cpp
tests/sizers/boxsizer.cpp

index 9c7e7df2fe23a4a54c43e0b1d1b2cca1f4270c86..f3e736c6beb1a4f1660b45152af31296937eb86b 100644 (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).
index 73229cc8a177ab8f73b25abab067cc6c56c97124..ff462469b230d46a5342a1a362c9de07328bfd13 100644 (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() )
index e0bdaa7c5b4488f7ef16de70dae846aa57db60ef..88c971ab58c0d6a6cc3ca3adff3b1882e57d434d 100644 (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;
         }
index 0266af8b3e4bee220156d65a7eb6f9c516f174f3..118cacf49443bd16cf4e11377451a876ebc18e8f 100644 (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());
+}