From 9f8845289521c7f53e95b6dfd8275daab8b05639 Mon Sep 17 00:00:00 2001
From: Robin Dunn <robin@alldunn.com>
Date: Thu, 24 Jun 2004 20:09:45 +0000
Subject: [PATCH] * Implemented BestSize cache

* Added calls to InvalidateBestSize where things affecting BestSize
  are modified.  There are probably several other places where this
  still needs to be done...

* Added wxWindowBase::GetBestFittingSize that will merge the BestSize
  into the MinSize, (if any) and return the result.

* SetBestFittingSize will now only set the MinSize to the value that
  was passed to it, without merging in the BestSize


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@28010 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/latex/wx/window.tex     | 26 +++++++++++++++++---
 include/wx/bmpbuttn.h        |  2 +-
 include/wx/control.h         |  3 +++
 include/wx/window.h          | 39 ++++++++++++++++++++++++------
 src/common/bookctrl.cpp      |  4 ++-
 src/common/ctrlcmn.cpp       | 24 +++++++++++++++---
 src/common/sizer.cpp         | 13 ++--------
 src/common/tbarbase.cpp      |  1 +
 src/common/wincmn.cpp        | 47 +++++++++++++++++++++---------------
 src/gtk/bmpbuttn.cpp         |  3 +++
 src/gtk/button.cpp           |  1 +
 src/gtk/choice.cpp           |  1 +
 src/gtk/combobox.cpp         |  2 ++
 src/gtk/control.cpp          |  5 +++-
 src/gtk/gauge.cpp            |  7 ++++--
 src/gtk/listbox.cpp          |  8 +++++-
 src/gtk/radiobox.cpp         |  1 +
 src/gtk/spinbutt.cpp         |  4 ++-
 src/gtk/spinctrl.cpp         |  4 ++-
 src/gtk/statbmp.cpp          |  3 ++-
 src/gtk/stattext.cpp         |  8 +++---
 src/gtk/tbargtk.cpp          |  2 ++
 src/gtk/textctrl.cpp         |  4 ++-
 src/gtk/tglbtn.cpp           | 10 +++++---
 src/gtk1/bmpbuttn.cpp        |  3 +++
 src/gtk1/button.cpp          |  1 +
 src/gtk1/choice.cpp          |  1 +
 src/gtk1/combobox.cpp        |  2 ++
 src/gtk1/control.cpp         |  5 +++-
 src/gtk1/gauge.cpp           |  7 ++++--
 src/gtk1/listbox.cpp         |  8 +++++-
 src/gtk1/radiobox.cpp        |  1 +
 src/gtk1/spinbutt.cpp        |  4 ++-
 src/gtk1/spinctrl.cpp        |  4 ++-
 src/gtk1/statbmp.cpp         |  3 ++-
 src/gtk1/stattext.cpp        |  8 +++---
 src/gtk1/tbargtk.cpp         |  2 ++
 src/gtk1/textctrl.cpp        |  4 ++-
 src/gtk1/tglbtn.cpp          | 10 +++++---
 src/mac/carbon/bmpbuttn.cpp  |  1 +
 src/mac/carbon/listbox.cpp   |  4 +++
 src/mac/carbon/statbmp.cpp   |  1 +
 src/mac/carbon/stattext.cpp  |  4 +--
 src/mac/carbon/toolbar.cpp   |  3 +++
 src/mac/classic/bmpbuttn.cpp |  1 +
 src/mac/classic/listbox.cpp  |  4 +++
 src/mac/classic/statbmp.cpp  |  1 +
 src/mac/classic/stattext.cpp |  4 ++-
 src/mac/classic/toolbar.cpp  |  3 +++
 src/msw/bmpbuttn.cpp         | 19 ++-------------
 src/msw/listbox.cpp          |  4 +++
 src/msw/statbmp.cpp          |  1 +
 src/msw/stattext.cpp         |  4 +--
 src/msw/tbar95.cpp           |  3 +++
 wxPython/src/_window.i       | 19 +++++++++++++--
 55 files changed, 258 insertions(+), 103 deletions(-)

diff --git a/docs/latex/wx/window.tex b/docs/latex/wx/window.tex
index 4386be9e9b..e69f493024 100644
--- a/docs/latex/wx/window.tex
+++ b/docs/latex/wx/window.tex
@@ -701,6 +701,19 @@ Returns the background colour of the window.
 \helpref{wxWindow::GetForegroundColour}{wxwindowgetforegroundcolour}
 
 
+\membersection{wxWindow::GetBestFittingSize}\label{wxwindowgetbestfittingsize}
+
+\constfunc{wxSize}{GetBestFittingSize}{\void}
+
+Merges the window's best size into the min size and returns the result.
+
+\wxheading{See also}
+
+\helpref{wxWindow::GetBestSize}{wxwindowgetbestsize},\rtfsp
+\helpref{wxWindow::SetBestFittingSize}{wxwindowsetbestfittingsize},\rtfsp
+\helpref{wxWindow::SetSizeHints}{wxwindowsetsizehints}
+
+
 \membersection{wxWindow::GetBestSize}\label{wxwindowgetbestsize}
 
 \constfunc{wxSize}{GetBestSize}{\void}
@@ -2390,18 +2403,23 @@ applications on the system.
 \helpref{wxWindow::Refresh}{wxwindowrefresh},\rtfsp
 \helpref{wxEraseEvent}{wxeraseevent}
 
+
 \membersection{wxWindow::SetBestFittingSize}\label{wxwindowsetbestfittingsize}
 
 \func{void}{SetBestFittingSize}{\param{const wxSize& }{size = wxDefaultSize}}
 
 A {\it smart} SetSize that will fill in default size components with the
-window's {\it best} size values.  Also set's the minsize for use with
-sizers.
+window's {\it best} size values.  Also sets the window's minsize to
+the value passed in for use with sizers.  This means that if a full or
+partial size is passed to this function then the sizers will use that
+size instead of the results of GetBestSize to determine the minimum
+needs of the window for layout.
 
 \wxheading{See also}
 
-\helpref{wxWindow::SetSize}{wxwindowsetsize}
-\helpref{wxWindow::GetBestSize}{wxwindowgetbestsize}
+\helpref{wxWindow::SetSize}{wxwindowsetsize},\rtfsp
+\helpref{wxWindow::GetBestSize}{wxwindowgetbestsize},\rtfsp
+\helpref{wxWindow::GetBestFittingSize}{wxwindowgetbestfittingsize},\rtfsp
 \helpref{wxWindow::SetSizeHints}{wxwindowsetsizehints}
 
 
diff --git a/include/wx/bmpbuttn.h b/include/wx/bmpbuttn.h
index c874c9d9da..54a38c4322 100644
--- a/include/wx/bmpbuttn.h
+++ b/include/wx/bmpbuttn.h
@@ -67,7 +67,7 @@ public:
 
 protected:
     // function called when any of the bitmaps changes
-    virtual void OnSetBitmap() { }
+    virtual void OnSetBitmap() { InvalidateBestSize(); }
 
     // the bitmaps for various states
     wxBitmap m_bmpNormal,
diff --git a/include/wx/control.h b/include/wx/control.h
index 6552443ecd..b6136bd449 100644
--- a/include/wx/control.h
+++ b/include/wx/control.h
@@ -63,6 +63,9 @@ public:
     // if the button was clicked)
     virtual void Command(wxCommandEvent &event);
 
+    virtual void SetLabel( const wxString &label );
+    virtual bool SetFont(const wxFont& font);
+
 protected:
     // creates the control (calls wxWindowBase::CreateBase inside) and adds it
     // to the list of parents children
diff --git a/include/wx/window.h b/include/wx/window.h
index 97b35334c0..566ba6c19d 100644
--- a/include/wx/window.h
+++ b/include/wx/window.h
@@ -230,9 +230,6 @@ public:
     void Move(const wxPoint& pt, int flags = wxSIZE_USE_EXISTING)
         { Move(pt.x, pt.y, flags); }
 
-    // A 'Smart' SetSize that will fill in default size values with 'best' size
-    void SetBestFittingSize(const wxSize& size=wxDefaultSize);
-
         // Z-order
     virtual void Raise() = 0;
     virtual void Lower() = 0;
@@ -297,17 +294,29 @@ public:
     }
 
         // get the size best suited for the window (in fact, minimal
-        // acceptable size using which it will still look "nice")
-    wxSize GetBestSize() const { return DoGetBestSize(); }
+        // acceptable size using which it will still look "nice" in
+        // most situations)
+    wxSize GetBestSize() const
+    {
+        if (m_bestSizeCache.IsFullySpecified())
+            return m_bestSizeCache;
+        return DoGetBestSize();
+    }
     void GetBestSize(int *w, int *h) const
     {
-        wxSize s = DoGetBestSize();
+        wxSize s = GetBestSize();
         if ( w )
             *w = s.x;
         if ( h )
             *h = s.y;
     }
 
+        // reset the cached best size value so it will be recalculated the
+        // next time it is needed.
+    void InvalidateBestSize() { m_bestSizeCache = wxDefaultSize; }
+    void CacheBestSize(const wxSize& size) const
+        { wxConstCast(this, wxWindowBase)->m_bestSizeCache = size; }
+    
         // There are times (and windows) where 'Best' size and 'Min' size
         // are vastly out of sync.  This should be remedied somehow, but in
         // the meantime, this method will return the larger of BestSize
@@ -315,10 +324,19 @@ public:
         // MinSize hint.
     wxSize GetAdjustedBestSize() const
     {
-        wxSize  s( DoGetBestSize() );
+        wxSize  s( GetBestSize() );
         return wxSize( wxMax( s.x, GetMinWidth() ), wxMax( s.y, GetMinHeight() ) );
     }
 
+        // This function will merge the window's best size into the window's
+        // minimum size, giving priority to the min size components, and
+        // returns the results.
+    wxSize GetBestFittingSize() const;
+    
+        // A 'Smart' SetSize that will fill in default size values with 'best'
+        // size.  Sets the minsize to what was passed in.
+    void SetBestFittingSize(const wxSize& size=wxDefaultSize);
+
         // the generic centre function - centers the window on parent by`
         // default or on screen if it doesn't have parent or
         // wxCENTER_ON_SCREEN flag is given
@@ -1137,11 +1155,15 @@ protected:
     static int WidthDefault(int w) { return w == -1 ? 20 : w; }
     static int HeightDefault(int h) { return h == -1 ? 20 : h; }
 
+
+    // Used to save the results of DoGetBestSize so it doesn't need to be
+    // recalculated each time the value is needed.
+    wxSize m_bestSizeCache;
+
     // keep the old name for compatibility, at least until all the internal
     // usages of it are changed to SetBestFittingSize
     void SetBestSize(const wxSize& size) { SetBestFittingSize(size); }
         
-
     // set the initial window size if none is given (i.e. at least one of the
     // components of the size passed to ctor/Create() is -1)
     //
@@ -1151,6 +1173,7 @@ protected:
     // can be accurately calculated
     virtual void SetInitialBestSize(const wxSize& WXUNUSED(size)) {}
 
+    
 
     // more pure virtual functions
     // ---------------------------
diff --git a/src/common/bookctrl.cpp b/src/common/bookctrl.cpp
index b04136183e..bf8a833434 100644
--- a/src/common/bookctrl.cpp
+++ b/src/common/bookctrl.cpp
@@ -130,7 +130,9 @@ wxSize wxBookCtrl::DoGetBestSize() const
 
     // convert display area to window area, adding the size neccessary for the
     // tabs
-    return CalcSizeFromPage(bestSize);
+    wxSize best = CalcSizeFromPage(bestSize);
+    CacheBestSize(best);
+    return best;
 }
 
 // ----------------------------------------------------------------------------
diff --git a/src/common/ctrlcmn.cpp b/src/common/ctrlcmn.cpp
index 242efdca1f..437aea4a0a 100644
--- a/src/common/ctrlcmn.cpp
+++ b/src/common/ctrlcmn.cpp
@@ -116,6 +116,19 @@ void wxControlBase::InitCommandEvent(wxCommandEvent& event) const
     }
 }
 
+
+void wxControlBase::SetLabel( const wxString &label )
+{
+    InvalidateBestSize();
+    wxWindow::SetLabel(label);   
+}
+
+bool wxControlBase::SetFont(const wxFont& font)
+{
+    InvalidateBestSize();
+    return wxWindow::SetFont(font);
+}
+
 // ----------------------------------------------------------------------------
 // wxStaticBitmap
 // ----------------------------------------------------------------------------
@@ -129,12 +142,15 @@ wxStaticBitmapBase::~wxStaticBitmapBase()
 
 wxSize wxStaticBitmapBase::DoGetBestSize() const
 {
+    wxSize best;
     wxBitmap bmp = GetBitmap();
     if ( bmp.Ok() )
-        return wxSize(bmp.GetWidth(), bmp.GetHeight());
-
-    // this is completely arbitrary
-    return wxSize(16, 16);
+        best = wxSize(bmp.GetWidth(), bmp.GetHeight());
+    else
+        // this is completely arbitrary
+        best = wxSize(16, 16);
+    CacheBestSize(best);
+    return best;
 }
 
 #endif // wxUSE_STATBMP
diff --git a/src/common/sizer.cpp b/src/common/sizer.cpp
index de1f1c2164..fb81a60daf 100644
--- a/src/common/sizer.cpp
+++ b/src/common/sizer.cpp
@@ -192,18 +192,9 @@ wxSize wxSizerItem::CalcMin()
         if ( IsWindow() && !(m_flag & wxFIXED_MINSIZE) )
         {
             // Since the size of the window may change during runtime, we
-            // should use the current minimal size.  If there is a MinSize,
-            // use it, otherwise use the BestSize.
-            wxSize min  = m_window->GetMinSize();
-            if (min.x == -1 || min.y == -1)
-            {
-                wxSize best = m_window->GetBestSize();
-                if (min.x == -1) min.x =  best.x;
-                if (min.y == -1) min.y =  best.y;
-            }
-            m_minSize = min;
+            // should use the current minimal/best size.
+            m_minSize = m_window->GetBestFittingSize();
         }
-
         ret = m_minSize;
     }
 
diff --git a/src/common/tbarbase.cpp b/src/common/tbarbase.cpp
index a2045d0f0c..2496b8a974 100644
--- a/src/common/tbarbase.cpp
+++ b/src/common/tbarbase.cpp
@@ -141,6 +141,7 @@ wxToolBarToolBase *wxToolBarBase::DoAddTool(int id,
                                             wxCoord WXUNUSED(xPos),
                                             wxCoord WXUNUSED(yPos))
 {
+    InvalidateBestSize();
     return InsertTool(GetToolsCount(), id, label, bitmap, bmpDisabled,
                       kind, shortHelp, longHelp, clientData);
 }
diff --git a/src/common/wincmn.cpp b/src/common/wincmn.cpp
index b62896002c..7c4c0ce62c 100644
--- a/src/common/wincmn.cpp
+++ b/src/common/wincmn.cpp
@@ -125,6 +125,9 @@ wxWindowBase::wxWindowBase()
     m_minHeight =
     m_maxHeight = wxDefaultSize.y;
 
+    // invalidiated cache value
+    m_bestSizeCache = wxDefaultSize;
+
     // window are created enabled and visible by default
     m_isShown =
     m_isEnabled = true;
@@ -482,7 +485,7 @@ void wxWindowBase::Fit()
 {
     if ( GetChildren().GetCount() > 0 )
     {
-        SetClientSize(DoGetBestSize());
+        SetClientSize(GetBestSize());
     }
     //else: do nothing if we have no children
 }
@@ -620,32 +623,36 @@ wxSize wxWindowBase::DoGetBestSize() const
     }
 }
 
-void wxWindowBase::SetBestFittingSize(const wxSize& size)
+
+wxSize wxWindowBase::GetBestFittingSize() const
 {
-    // If the given size is incomplete then merge with the best size.
-    wxSize sizeBest;
-    if ( size.x == wxDefaultSize.x || size.y == wxDefaultSize.y )
+    // merge the best size with the min size, giving priority to the min size
+    wxSize min = GetMinSize();
+    if (min.x == wxDefaultCoord || min.y == wxDefaultCoord)
     {
-        sizeBest = DoGetBestSize();
-        if ( size.x != wxDefaultSize.x )
-            sizeBest.x = size.x;
-        if ( size.y != wxDefaultSize.y )
-            sizeBest.y = size.y;
-    }
-    else // have complete explicit size
-    {
-        sizeBest = size;
+        wxSize best = GetBestSize();
+        if (min.x == wxDefaultCoord) min.x =  best.x;
+        if (min.y == wxDefaultCoord) min.y =  best.y;
     }
+    return min;
+}
 
-    // Change the size if needed
-    if (GetSize() != sizeBest)
-        SetSize(sizeBest);
 
-    // don't shrink the control below its best size
-    m_minWidth = sizeBest.x;
-    m_minHeight = sizeBest.y;
+void wxWindowBase::SetBestFittingSize(const wxSize& size)
+{
+    // Set the min size to the size passed in.  This will usually either be
+    // wxDefaultSize or the size passed to this window's ctor/Create function.
+    SetMinSize(size);
+
+    // Merge the size with the best size if needed
+    wxSize best = GetBestFittingSize();
+    
+    // If the current size doesn't match then change it
+    if (GetSize() != best)
+        SetSize(best);
 }
 
+
 // by default the origin is not shifted
 wxPoint wxWindowBase::GetClientAreaOrigin() const
 {
diff --git a/src/gtk/bmpbuttn.cpp b/src/gtk/bmpbuttn.cpp
index db11765013..34f5bab890 100644
--- a/src/gtk/bmpbuttn.cpp
+++ b/src/gtk/bmpbuttn.cpp
@@ -205,6 +205,8 @@ void wxBitmapButton::OnSetBitmap()
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid bitmap button") );
 
+    InvalidateBestSize();
+    
     wxBitmap the_one;
     if (!m_isEnabled)
         the_one = m_bmpDisabled;
@@ -258,6 +260,7 @@ wxSize wxBitmapButton::DoGetBestSize() const
         best.x = m_bmpNormal.GetWidth()+border;
         best.y = m_bmpNormal.GetHeight()+border;
     }
+    CacheBestSize(best);
     return best;
 }
 
diff --git a/src/gtk/button.cpp b/src/gtk/button.cpp
index d64273b780..d42f359e19 100644
--- a/src/gtk/button.cpp
+++ b/src/gtk/button.cpp
@@ -232,6 +232,7 @@ wxSize wxButton::DoGetBestSize() const
         if (ret.x < 80) ret.x = 80;
     }
 
+    CacheBestSize(ret);
     return ret;
 }
 
diff --git a/src/gtk/choice.cpp b/src/gtk/choice.cpp
index 28d895dd2e..4bef419b40 100644
--- a/src/gtk/choice.cpp
+++ b/src/gtk/choice.cpp
@@ -564,6 +564,7 @@ wxSize wxChoice::DoGetBestSize() const
     if (ret.y <= 18)
         ret.y = 8 + GetCharHeight();
 
+    CacheBestSize(ret);
     return ret;
 }
 
diff --git a/src/gtk/combobox.cpp b/src/gtk/combobox.cpp
index 2ddf6fcf95..acf403570b 100644
--- a/src/gtk/combobox.cpp
+++ b/src/gtk/combobox.cpp
@@ -773,6 +773,8 @@ wxSize wxComboBox::DoGetBestSize() const
     // empty combobox should have some reasonable default size too
     if ( ret.x < 100 )
         ret.x = 100;
+
+    CacheBestSize(ret);
     return ret;
 }
 
diff --git a/src/gtk/control.cpp b/src/gtk/control.cpp
index 41f5cc4ea1..f8ea0c9dc3 100644
--- a/src/gtk/control.cpp
+++ b/src/gtk/control.cpp
@@ -66,6 +66,7 @@ void wxControl::SetLabel( const wxString &label )
         }
         m_label << *pc;
     }
+    InvalidateBestSize();    
 }
 
 wxString wxControl::GetLabel() const
@@ -85,7 +86,9 @@ wxSize wxControl::DoGetBestSize() const
     (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_widget) )->size_request )
         (m_widget, &req );
 
-    return wxSize(req.width, req.height);
+    wxSize best(req.width, req.height);
+    CacheBestSize(best);
+    return best;
 }
 
 
diff --git a/src/gtk/gauge.cpp b/src/gtk/gauge.cpp
index 90aad2ca5b..985c42bcc3 100644
--- a/src/gtk/gauge.cpp
+++ b/src/gtk/gauge.cpp
@@ -72,10 +72,13 @@ void wxGauge::DoSetGauge()
 
 wxSize wxGauge::DoGetBestSize() const
 {
+    wxSize best;
     if (HasFlag(wxGA_VERTICAL))
-        return wxSize(28, 100);
+        best = wxSize(28, 100);
     else
-        return wxSize(100, 28);
+        best = wxSize(100, 28);
+    CacheBestSize(best);
+    return best;
 }
 
 void wxGauge::SetRange( int range )
diff --git a/src/gtk/listbox.cpp b/src/gtk/listbox.cpp
index 15c355869d..b2d8307151 100644
--- a/src/gtk/listbox.cpp
+++ b/src/gtk/listbox.cpp
@@ -439,6 +439,8 @@ void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
     wxASSERT_MSG( m_clientList.GetCount() == (size_t)GetCount(),
                   wxT("bug in client data management") );
 
+    InvalidateBestSize();
+
     GList *children = m_list->children;
     int length = g_list_length(children);
 
@@ -495,6 +497,8 @@ void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
 
 int wxListBox::DoAppend( const wxString& item )
 {
+    InvalidateBestSize();
+
     if (m_strings)
     {
         // need to determine the index
@@ -1076,7 +1080,9 @@ wxSize wxListBox::DoGetBestSize() const
     // make it too small neither
     lbHeight = (cy+4) * wxMin(wxMax(GetCount(), 3), 10);
 
-    return wxSize(lbWidth, lbHeight);
+    wxSize best(lbWidth, lbHeight);
+    CacheBestSize(best);        
+    return best;
 }
 
 void wxListBox::FixUpMouseEvent(GtkWidget *widget, wxCoord& x, wxCoord& y)
diff --git a/src/gtk/radiobox.cpp b/src/gtk/radiobox.cpp
index ea1eee5230..a2f712302d 100644
--- a/src/gtk/radiobox.cpp
+++ b/src/gtk/radiobox.cpp
@@ -286,6 +286,7 @@ wxSize wxRadioBox::DoGetBestSize() const
     if (req.width > size.x)
         size.x = req.width;
 
+    CacheBestSize(size);
     return size;
 }
 
diff --git a/src/gtk/spinbutt.cpp b/src/gtk/spinbutt.cpp
index a62d2c121e..4ac29c9c25 100644
--- a/src/gtk/spinbutt.cpp
+++ b/src/gtk/spinbutt.cpp
@@ -227,7 +227,9 @@ bool wxSpinButton::IsOwnGtkWindow( GdkWindow *window )
 
 wxSize wxSpinButton::DoGetBestSize() const
 {
-    return wxSize(15, 26); // FIXME
+    wxSize best(15, 26); // FIXME
+    CacheBestSize(best);
+    return best;
 }
 
 // static
diff --git a/src/gtk/spinctrl.cpp b/src/gtk/spinctrl.cpp
index 9390128cf0..18e8e0dff2 100644
--- a/src/gtk/spinctrl.cpp
+++ b/src/gtk/spinctrl.cpp
@@ -301,7 +301,9 @@ bool wxSpinCtrl::IsOwnGtkWindow( GdkWindow *window )
 wxSize wxSpinCtrl::DoGetBestSize() const
 {
     wxSize ret( wxControl::DoGetBestSize() );
-    return wxSize(95, ret.y);
+    wxSize best(95, ret.y);
+    CacheBestSize(best);
+    return best;
 }
 
 // static
diff --git a/src/gtk/statbmp.cpp b/src/gtk/statbmp.cpp
index 48a8dafe73..6ec5169750 100644
--- a/src/gtk/statbmp.cpp
+++ b/src/gtk/statbmp.cpp
@@ -113,7 +113,8 @@ void wxStaticBitmap::SetBitmap( const wxBitmap &bitmap )
             gtk_pixmap_set( GTK_PIXMAP(m_widget), m_bitmap.GetPixmap(), mask );
         }
 
-        SetBestSize(wxSize(bitmap.GetWidth(), bitmap.GetHeight()));
+        InvalidateBestSize();
+        SetSize(GetBestSize());
     }
 }
 
diff --git a/src/gtk/stattext.cpp b/src/gtk/stattext.cpp
index d659e8cc16..c245fd315c 100644
--- a/src/gtk/stattext.cpp
+++ b/src/gtk/stattext.cpp
@@ -150,8 +150,8 @@ void wxStaticText::SetLabel( const wxString &label )
     // adjust the label size to the new label unless disabled
     if (!HasFlag(wxST_NO_AUTORESIZE))
     {
+        InvalidateBestSize();
         SetSize( GetBestSize() );
-        SetSizeHints(GetSize());
     }
 }
 
@@ -162,8 +162,8 @@ bool wxStaticText::SetFont( const wxFont &font )
     // adjust the label size to the new label unless disabled
     if (!HasFlag(wxST_NO_AUTORESIZE))
     {
+        InvalidateBestSize();
         SetSize( GetBestSize() );
-        SetSizeHints(GetSize());
     }
     return ret;
 }
@@ -183,7 +183,9 @@ wxSize wxStaticText::DoGetBestSize() const
     (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_widget) )->size_request )
         (m_widget, &req );
 
-    return wxSize(req.width, req.height);
+    wxSize best(req.width, req.height);
+    CacheBestSize(best);
+    return best;
 }
 
 bool wxStaticText::SetForegroundColour(const wxColour& colour)
diff --git a/src/gtk/tbargtk.cpp b/src/gtk/tbargtk.cpp
index f94361eaa4..16ead462ac 100644
--- a/src/gtk/tbargtk.cpp
+++ b/src/gtk/tbargtk.cpp
@@ -501,6 +501,7 @@ bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase)
         (m_widget, &req );
     m_width = req.width + m_xMargin;
     m_height = req.height + 2*m_yMargin;
+    InvalidateBestSize();
 
     return TRUE;
 }
@@ -522,6 +523,7 @@ bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase)
         //case wxTOOL_STYLE_SEPARATOR: -- nothing to do
     }
 
+    InvalidateBestSize();
     return TRUE;
 }
 
diff --git a/src/gtk/textctrl.cpp b/src/gtk/textctrl.cpp
index 2d5b6460a5..5f80c5d19b 100644
--- a/src/gtk/textctrl.cpp
+++ b/src/gtk/textctrl.cpp
@@ -1633,7 +1633,9 @@ wxSize wxTextCtrl::DoGetBestSize() const
 {
     // FIXME should be different for multi-line controls...
     wxSize ret( wxControl::DoGetBestSize() );
-    return wxSize(80, ret.y);
+    wxSize best(80, ret.y);
+    CacheBestSize(best);
+    return best;
 }
 
 // ----------------------------------------------------------------------------
diff --git a/src/gtk/tglbtn.cpp b/src/gtk/tglbtn.cpp
index 8ac7ec5a3c..cb4db530d7 100644
--- a/src/gtk/tglbtn.cpp
+++ b/src/gtk/tglbtn.cpp
@@ -123,6 +123,7 @@ void wxToggleBitmapButton::SetLabel(const wxBitmap& label)
     wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
 
     m_bitmap = label;
+    InvalidateBestSize();
     
     OnSetBitmap();
 }
@@ -192,7 +193,7 @@ void wxToggleBitmapButton::OnInternalIdle()
         UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
-// wxSize DoGetBestSize() const
+
 // Get the "best" size for this control.
 wxSize wxToggleBitmapButton::DoGetBestSize() const
 {
@@ -204,6 +205,7 @@ wxSize wxToggleBitmapButton::DoGetBestSize() const
         best.x = m_bitmap.GetWidth()+border;
         best.y = m_bitmap.GetHeight()+border;
     }
+    CacheBestSize(best);
     return best;
 }
 
@@ -332,7 +334,7 @@ void wxToggleButton::OnInternalIdle()
         UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
-// wxSize DoGetBestSize() const
+
 // Get the "best" size for this control.
 wxSize wxToggleButton::DoGetBestSize() const
 {
@@ -343,8 +345,8 @@ wxSize wxToggleButton::DoGetBestSize() const
         if (ret.x < 80) ret.x = 80;
     }
     
-
-   return ret;
+    CacheBestSize(ret);
+    return ret;
 }
 
 // static
diff --git a/src/gtk1/bmpbuttn.cpp b/src/gtk1/bmpbuttn.cpp
index db11765013..34f5bab890 100644
--- a/src/gtk1/bmpbuttn.cpp
+++ b/src/gtk1/bmpbuttn.cpp
@@ -205,6 +205,8 @@ void wxBitmapButton::OnSetBitmap()
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid bitmap button") );
 
+    InvalidateBestSize();
+    
     wxBitmap the_one;
     if (!m_isEnabled)
         the_one = m_bmpDisabled;
@@ -258,6 +260,7 @@ wxSize wxBitmapButton::DoGetBestSize() const
         best.x = m_bmpNormal.GetWidth()+border;
         best.y = m_bmpNormal.GetHeight()+border;
     }
+    CacheBestSize(best);
     return best;
 }
 
diff --git a/src/gtk1/button.cpp b/src/gtk1/button.cpp
index d64273b780..d42f359e19 100644
--- a/src/gtk1/button.cpp
+++ b/src/gtk1/button.cpp
@@ -232,6 +232,7 @@ wxSize wxButton::DoGetBestSize() const
         if (ret.x < 80) ret.x = 80;
     }
 
+    CacheBestSize(ret);
     return ret;
 }
 
diff --git a/src/gtk1/choice.cpp b/src/gtk1/choice.cpp
index 28d895dd2e..4bef419b40 100644
--- a/src/gtk1/choice.cpp
+++ b/src/gtk1/choice.cpp
@@ -564,6 +564,7 @@ wxSize wxChoice::DoGetBestSize() const
     if (ret.y <= 18)
         ret.y = 8 + GetCharHeight();
 
+    CacheBestSize(ret);
     return ret;
 }
 
diff --git a/src/gtk1/combobox.cpp b/src/gtk1/combobox.cpp
index 2ddf6fcf95..acf403570b 100644
--- a/src/gtk1/combobox.cpp
+++ b/src/gtk1/combobox.cpp
@@ -773,6 +773,8 @@ wxSize wxComboBox::DoGetBestSize() const
     // empty combobox should have some reasonable default size too
     if ( ret.x < 100 )
         ret.x = 100;
+
+    CacheBestSize(ret);
     return ret;
 }
 
diff --git a/src/gtk1/control.cpp b/src/gtk1/control.cpp
index 41f5cc4ea1..f8ea0c9dc3 100644
--- a/src/gtk1/control.cpp
+++ b/src/gtk1/control.cpp
@@ -66,6 +66,7 @@ void wxControl::SetLabel( const wxString &label )
         }
         m_label << *pc;
     }
+    InvalidateBestSize();    
 }
 
 wxString wxControl::GetLabel() const
@@ -85,7 +86,9 @@ wxSize wxControl::DoGetBestSize() const
     (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_widget) )->size_request )
         (m_widget, &req );
 
-    return wxSize(req.width, req.height);
+    wxSize best(req.width, req.height);
+    CacheBestSize(best);
+    return best;
 }
 
 
diff --git a/src/gtk1/gauge.cpp b/src/gtk1/gauge.cpp
index 90aad2ca5b..985c42bcc3 100644
--- a/src/gtk1/gauge.cpp
+++ b/src/gtk1/gauge.cpp
@@ -72,10 +72,13 @@ void wxGauge::DoSetGauge()
 
 wxSize wxGauge::DoGetBestSize() const
 {
+    wxSize best;
     if (HasFlag(wxGA_VERTICAL))
-        return wxSize(28, 100);
+        best = wxSize(28, 100);
     else
-        return wxSize(100, 28);
+        best = wxSize(100, 28);
+    CacheBestSize(best);
+    return best;
 }
 
 void wxGauge::SetRange( int range )
diff --git a/src/gtk1/listbox.cpp b/src/gtk1/listbox.cpp
index 15c355869d..b2d8307151 100644
--- a/src/gtk1/listbox.cpp
+++ b/src/gtk1/listbox.cpp
@@ -439,6 +439,8 @@ void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
     wxASSERT_MSG( m_clientList.GetCount() == (size_t)GetCount(),
                   wxT("bug in client data management") );
 
+    InvalidateBestSize();
+
     GList *children = m_list->children;
     int length = g_list_length(children);
 
@@ -495,6 +497,8 @@ void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
 
 int wxListBox::DoAppend( const wxString& item )
 {
+    InvalidateBestSize();
+
     if (m_strings)
     {
         // need to determine the index
@@ -1076,7 +1080,9 @@ wxSize wxListBox::DoGetBestSize() const
     // make it too small neither
     lbHeight = (cy+4) * wxMin(wxMax(GetCount(), 3), 10);
 
-    return wxSize(lbWidth, lbHeight);
+    wxSize best(lbWidth, lbHeight);
+    CacheBestSize(best);        
+    return best;
 }
 
 void wxListBox::FixUpMouseEvent(GtkWidget *widget, wxCoord& x, wxCoord& y)
diff --git a/src/gtk1/radiobox.cpp b/src/gtk1/radiobox.cpp
index ea1eee5230..a2f712302d 100644
--- a/src/gtk1/radiobox.cpp
+++ b/src/gtk1/radiobox.cpp
@@ -286,6 +286,7 @@ wxSize wxRadioBox::DoGetBestSize() const
     if (req.width > size.x)
         size.x = req.width;
 
+    CacheBestSize(size);
     return size;
 }
 
diff --git a/src/gtk1/spinbutt.cpp b/src/gtk1/spinbutt.cpp
index a62d2c121e..4ac29c9c25 100644
--- a/src/gtk1/spinbutt.cpp
+++ b/src/gtk1/spinbutt.cpp
@@ -227,7 +227,9 @@ bool wxSpinButton::IsOwnGtkWindow( GdkWindow *window )
 
 wxSize wxSpinButton::DoGetBestSize() const
 {
-    return wxSize(15, 26); // FIXME
+    wxSize best(15, 26); // FIXME
+    CacheBestSize(best);
+    return best;
 }
 
 // static
diff --git a/src/gtk1/spinctrl.cpp b/src/gtk1/spinctrl.cpp
index 9390128cf0..18e8e0dff2 100644
--- a/src/gtk1/spinctrl.cpp
+++ b/src/gtk1/spinctrl.cpp
@@ -301,7 +301,9 @@ bool wxSpinCtrl::IsOwnGtkWindow( GdkWindow *window )
 wxSize wxSpinCtrl::DoGetBestSize() const
 {
     wxSize ret( wxControl::DoGetBestSize() );
-    return wxSize(95, ret.y);
+    wxSize best(95, ret.y);
+    CacheBestSize(best);
+    return best;
 }
 
 // static
diff --git a/src/gtk1/statbmp.cpp b/src/gtk1/statbmp.cpp
index 48a8dafe73..6ec5169750 100644
--- a/src/gtk1/statbmp.cpp
+++ b/src/gtk1/statbmp.cpp
@@ -113,7 +113,8 @@ void wxStaticBitmap::SetBitmap( const wxBitmap &bitmap )
             gtk_pixmap_set( GTK_PIXMAP(m_widget), m_bitmap.GetPixmap(), mask );
         }
 
-        SetBestSize(wxSize(bitmap.GetWidth(), bitmap.GetHeight()));
+        InvalidateBestSize();
+        SetSize(GetBestSize());
     }
 }
 
diff --git a/src/gtk1/stattext.cpp b/src/gtk1/stattext.cpp
index d659e8cc16..c245fd315c 100644
--- a/src/gtk1/stattext.cpp
+++ b/src/gtk1/stattext.cpp
@@ -150,8 +150,8 @@ void wxStaticText::SetLabel( const wxString &label )
     // adjust the label size to the new label unless disabled
     if (!HasFlag(wxST_NO_AUTORESIZE))
     {
+        InvalidateBestSize();
         SetSize( GetBestSize() );
-        SetSizeHints(GetSize());
     }
 }
 
@@ -162,8 +162,8 @@ bool wxStaticText::SetFont( const wxFont &font )
     // adjust the label size to the new label unless disabled
     if (!HasFlag(wxST_NO_AUTORESIZE))
     {
+        InvalidateBestSize();
         SetSize( GetBestSize() );
-        SetSizeHints(GetSize());
     }
     return ret;
 }
@@ -183,7 +183,9 @@ wxSize wxStaticText::DoGetBestSize() const
     (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_widget) )->size_request )
         (m_widget, &req );
 
-    return wxSize(req.width, req.height);
+    wxSize best(req.width, req.height);
+    CacheBestSize(best);
+    return best;
 }
 
 bool wxStaticText::SetForegroundColour(const wxColour& colour)
diff --git a/src/gtk1/tbargtk.cpp b/src/gtk1/tbargtk.cpp
index f94361eaa4..16ead462ac 100644
--- a/src/gtk1/tbargtk.cpp
+++ b/src/gtk1/tbargtk.cpp
@@ -501,6 +501,7 @@ bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase)
         (m_widget, &req );
     m_width = req.width + m_xMargin;
     m_height = req.height + 2*m_yMargin;
+    InvalidateBestSize();
 
     return TRUE;
 }
@@ -522,6 +523,7 @@ bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase)
         //case wxTOOL_STYLE_SEPARATOR: -- nothing to do
     }
 
+    InvalidateBestSize();
     return TRUE;
 }
 
diff --git a/src/gtk1/textctrl.cpp b/src/gtk1/textctrl.cpp
index 2d5b6460a5..5f80c5d19b 100644
--- a/src/gtk1/textctrl.cpp
+++ b/src/gtk1/textctrl.cpp
@@ -1633,7 +1633,9 @@ wxSize wxTextCtrl::DoGetBestSize() const
 {
     // FIXME should be different for multi-line controls...
     wxSize ret( wxControl::DoGetBestSize() );
-    return wxSize(80, ret.y);
+    wxSize best(80, ret.y);
+    CacheBestSize(best);
+    return best;
 }
 
 // ----------------------------------------------------------------------------
diff --git a/src/gtk1/tglbtn.cpp b/src/gtk1/tglbtn.cpp
index 8ac7ec5a3c..cb4db530d7 100644
--- a/src/gtk1/tglbtn.cpp
+++ b/src/gtk1/tglbtn.cpp
@@ -123,6 +123,7 @@ void wxToggleBitmapButton::SetLabel(const wxBitmap& label)
     wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
 
     m_bitmap = label;
+    InvalidateBestSize();
     
     OnSetBitmap();
 }
@@ -192,7 +193,7 @@ void wxToggleBitmapButton::OnInternalIdle()
         UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
-// wxSize DoGetBestSize() const
+
 // Get the "best" size for this control.
 wxSize wxToggleBitmapButton::DoGetBestSize() const
 {
@@ -204,6 +205,7 @@ wxSize wxToggleBitmapButton::DoGetBestSize() const
         best.x = m_bitmap.GetWidth()+border;
         best.y = m_bitmap.GetHeight()+border;
     }
+    CacheBestSize(best);
     return best;
 }
 
@@ -332,7 +334,7 @@ void wxToggleButton::OnInternalIdle()
         UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
-// wxSize DoGetBestSize() const
+
 // Get the "best" size for this control.
 wxSize wxToggleButton::DoGetBestSize() const
 {
@@ -343,8 +345,8 @@ wxSize wxToggleButton::DoGetBestSize() const
         if (ret.x < 80) ret.x = 80;
     }
     
-
-   return ret;
+    CacheBestSize(ret);
+    return ret;
 }
 
 // static
diff --git a/src/mac/carbon/bmpbuttn.cpp b/src/mac/carbon/bmpbuttn.cpp
index 704b1728ba..a8dc4295c4 100644
--- a/src/mac/carbon/bmpbuttn.cpp
+++ b/src/mac/carbon/bmpbuttn.cpp
@@ -89,6 +89,7 @@ bool wxBitmapButton::Create(wxWindow *parent, wxWindowID id, const wxBitmap& bit
 void wxBitmapButton::SetBitmapLabel(const wxBitmap& bitmap)
 {
     m_bmpNormal = bitmap;
+    InvalidateBestSize();
 
     ControlButtonContentInfo info ;
     wxMacCreateBitmapButton( &info , m_bmpNormal ) ;
diff --git a/src/mac/carbon/listbox.cpp b/src/mac/carbon/listbox.cpp
index 361bc4def7..4fe7f3e815 100644
--- a/src/mac/carbon/listbox.cpp
+++ b/src/mac/carbon/listbox.cpp
@@ -324,6 +324,8 @@ void wxListBox::Delete(int N)
 
 int wxListBox::DoAppend(const wxString& item)
 {
+    InvalidateBestSize();
+
     int index = m_noItems ;
     m_stringArray.Add( item ) ;
     m_dataArray.Add( NULL );
@@ -511,6 +513,8 @@ void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
     wxCHECK_RET( pos >= 0 && pos <= m_noItems,
         wxT("invalid index in wxListBox::InsertItems") );
     
+    InvalidateBestSize();
+
     int nItems = items.GetCount();
     
     for ( int i = 0 ; i < nItems ; i++ )
diff --git a/src/mac/carbon/statbmp.cpp b/src/mac/carbon/statbmp.cpp
index f8fb079fd4..69b6f8b448 100644
--- a/src/mac/carbon/statbmp.cpp
+++ b/src/mac/carbon/statbmp.cpp
@@ -59,6 +59,7 @@ bool wxStaticBitmap::Create(wxWindow *parent, wxWindowID id,
 void wxStaticBitmap::SetBitmap(const wxBitmap& bitmap)
 {
     m_bitmap = bitmap;
+    InvalidateBestSize();
     SetSize(GetBestSize());
     Refresh() ;
 }
diff --git a/src/mac/carbon/stattext.cpp b/src/mac/carbon/stattext.cpp
index f4757d19d7..024cc6eed7 100644
--- a/src/mac/carbon/stattext.cpp
+++ b/src/mac/carbon/stattext.cpp
@@ -94,8 +94,8 @@ void wxStaticText::SetLabel(const wxString& st )
 
     if ( !(GetWindowStyle() & wxST_NO_AUTORESIZE) )
     {
+        InvalidateBestSize();
         SetSize( GetBestSize() ) ;
-        SetSizeHints(GetSize());
     }
 
     Update() ;
@@ -109,8 +109,8 @@ bool wxStaticText::SetFont(const wxFont& font)
 	{
 	    if ( !(GetWindowStyle() & wxST_NO_AUTORESIZE) )
             {
+                InvalidateBestSize();
 	        SetSize( GetBestSize() );
-                SetSizeHints(GetSize());
             }
 	}
 
diff --git a/src/mac/carbon/toolbar.cpp b/src/mac/carbon/toolbar.cpp
index 8014c63119..b240fa221b 100644
--- a/src/mac/carbon/toolbar.cpp
+++ b/src/mac/carbon/toolbar.cpp
@@ -377,6 +377,7 @@ bool wxToolBar::Realize()
     }
     
     SetSize( maxWidth, maxHeight );
+    InvalidateBestSize();
     
     return TRUE;
 }
@@ -473,6 +474,7 @@ bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos),
 {
     // nothing special to do here - we relayout in Realize() later
     tool->Attach(this);
+    InvalidateBestSize();
 
     return TRUE;
 }
@@ -519,6 +521,7 @@ bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool)
         tool2->SetPosition( pt ) ;
     }
     
+    InvalidateBestSize();
     return TRUE ;
 }
 
diff --git a/src/mac/classic/bmpbuttn.cpp b/src/mac/classic/bmpbuttn.cpp
index f6ce4dd00c..d08470d719 100644
--- a/src/mac/classic/bmpbuttn.cpp
+++ b/src/mac/classic/bmpbuttn.cpp
@@ -91,6 +91,7 @@ bool wxBitmapButton::Create(wxWindow *parent, wxWindowID id, const wxBitmap& bit
 void wxBitmapButton::SetBitmapLabel(const wxBitmap& bitmap)
 {
     m_bmpNormal = bitmap;
+    InvalidateBestSize();
 
     ControlButtonContentInfo info ;
     wxMacCreateBitmapButton( &info , m_bmpNormal ) ;
diff --git a/src/mac/classic/listbox.cpp b/src/mac/classic/listbox.cpp
index 8322a7a2f2..a0d3e05482 100644
--- a/src/mac/classic/listbox.cpp
+++ b/src/mac/classic/listbox.cpp
@@ -401,6 +401,8 @@ void wxListBox::Delete(int N)
 
 int wxListBox::DoAppend(const wxString& item)
 {
+    InvalidateBestSize();
+
     int index = m_noItems ;
     m_stringArray.Add( item ) ;
     m_dataArray.Add( NULL );
@@ -595,6 +597,8 @@ void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
     wxCHECK_RET( pos >= 0 && pos <= m_noItems,
         wxT("invalid index in wxListBox::InsertItems") );
     
+    InvalidateBestSize();
+
     int nItems = items.GetCount();
     
     for ( int i = 0 ; i < nItems ; i++ )
diff --git a/src/mac/classic/statbmp.cpp b/src/mac/classic/statbmp.cpp
index 68bc4efa6a..9bd84f6aa8 100644
--- a/src/mac/classic/statbmp.cpp
+++ b/src/mac/classic/statbmp.cpp
@@ -67,6 +67,7 @@ bool wxStaticBitmap::Create(wxWindow *parent, wxWindowID id,
 void wxStaticBitmap::SetBitmap(const wxBitmap& bitmap)
 {
     m_bitmap = bitmap;
+    InvalidateBestSize();
     SetSize(wxSize(bitmap.GetWidth(), bitmap.GetHeight()));
     Refresh() ;
 }
diff --git a/src/mac/classic/stattext.cpp b/src/mac/classic/stattext.cpp
index 1c0facdbf7..38c4b1041b 100644
--- a/src/mac/classic/stattext.cpp
+++ b/src/mac/classic/stattext.cpp
@@ -236,6 +236,7 @@ void wxStaticText::SetLabel(const wxString& st )
     {
         // temporary fix until layout measurement and drawing are in synch again
         Refresh() ;
+        InvalidateBestSize();
         SetSize( GetBestSize() ) ;
     }
     Refresh() ;
@@ -253,7 +254,8 @@ bool wxStaticText::SetFont(const wxFont& font)
 	    if ( !(GetWindowStyle() & wxST_NO_AUTORESIZE) )
 	    {
 	        // temporary fix until layout measurement and drawing are in synch again
-            Refresh() ;
+                Refresh() ;
+                InvalidateBestSize();
 	        SetSize( GetBestSize() );
 	    }
 	}
diff --git a/src/mac/classic/toolbar.cpp b/src/mac/classic/toolbar.cpp
index d8bdac1326..1b4b9733d0 100644
--- a/src/mac/classic/toolbar.cpp
+++ b/src/mac/classic/toolbar.cpp
@@ -377,6 +377,7 @@ bool wxToolBar::Realize()
     }
     
     SetSize(maxWidth, maxHeight);
+    InvalidateBestSize();
     
     return TRUE;
 }
@@ -494,6 +495,7 @@ bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos),
 {
     // nothing special to do here - we relayout in Realize() later
     tool->Attach(this);
+    InvalidateBestSize();
 
     return TRUE;
 }
@@ -540,6 +542,7 @@ bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool)
         tool2->SetPosition( pt ) ;
     }
     
+    InvalidateBestSize();
     return TRUE ;
 }
 
diff --git a/src/msw/bmpbuttn.cpp b/src/msw/bmpbuttn.cpp
index bb2e787838..7788ce8b2b 100644
--- a/src/msw/bmpbuttn.cpp
+++ b/src/msw/bmpbuttn.cpp
@@ -126,25 +126,11 @@ bool wxBitmapButton::Create(wxWindow *parent, wxWindowID id,
         m_marginY = wxDEFAULT_BUTTON_MARGIN;
     }
 
-    int x = pos.x;
-    int y = pos.y;
-    int width = size.x;
-    int height = size.y;
-
     if (id == -1)
         m_windowId = NewControlId();
     else
         m_windowId = id;
 
-    if ( bitmap.Ok() )
-    {
-        wxSize newSize = DoGetBestSize();
-        if ( width == -1 )
-            width = newSize.x;
-        if ( height == -1 )
-            height = newSize.y;
-    }
-
     long msStyle = WS_VISIBLE | WS_TABSTOP | WS_CHILD | BS_OWNERDRAW ;
 
     if ( m_windowStyle & wxCLIP_SIBLINGS )
@@ -176,9 +162,8 @@ bool wxBitmapButton::Create(wxWindow *parent, wxWindowID id,
     // Subclass again for purposes of dialog editing mode
     SubclassWin(m_hWnd);
 
-    SetFont(parent->GetFont());
-
-    SetSize(x, y, width, height);
+    SetPosition(pos);
+    SetBestSize(size);
 
     return true;
 }
diff --git a/src/msw/listbox.cpp b/src/msw/listbox.cpp
index b3037577bc..eea13ecbe3 100644
--- a/src/msw/listbox.cpp
+++ b/src/msw/listbox.cpp
@@ -287,6 +287,8 @@ void wxListBox::Delete(int N)
 
 int wxListBox::DoAppend(const wxString& item)
 {
+    InvalidateBestSize();
+
     int index = ListBox_AddString(GetHwnd(), item);
     m_noItems++;
 
@@ -522,6 +524,8 @@ wxListBox::DoInsertItems(const wxArrayString& items, int pos)
     wxCHECK_RET( pos >= 0 && pos <= m_noItems,
                  wxT("invalid index in wxListBox::InsertItems") );
 
+    InvalidateBestSize();
+
     int nItems = items.GetCount();
     for ( int i = 0; i < nItems; i++ )
     {
diff --git a/src/msw/statbmp.cpp b/src/msw/statbmp.cpp
index b437dcf26a..86fda57454 100644
--- a/src/msw/statbmp.cpp
+++ b/src/msw/statbmp.cpp
@@ -217,6 +217,7 @@ void wxStaticBitmap::SetImage( const wxGDIImage* image )
 {
     wxGDIImage* convertedImage = ConvertImage( *image );
     SetImageNoCopy( convertedImage );
+    InvalidateBestSize();
 }
 
 void wxStaticBitmap::SetImageNoCopy( wxGDIImage* image)
diff --git a/src/msw/stattext.cpp b/src/msw/stattext.cpp
index 12b7403018..0f6faf5e03 100644
--- a/src/msw/stattext.cpp
+++ b/src/msw/stattext.cpp
@@ -215,8 +215,8 @@ void wxStaticText::SetLabel(const wxString& label)
     // disabled
     if ( !(GetWindowStyle() & wxST_NO_AUTORESIZE) )
     {
+        InvalidateBestSize();
         DoSetSize(-1, -1, -1, -1, wxSIZE_AUTO_WIDTH | wxSIZE_AUTO_HEIGHT);
-        SetSizeHints(GetSize());
     }
 }
 
@@ -229,8 +229,8 @@ bool wxStaticText::SetFont(const wxFont& font)
     // disabled
     if ( !(GetWindowStyle() & wxST_NO_AUTORESIZE) )
     {
+        InvalidateBestSize();
         DoSetSize(-1, -1, -1, -1, wxSIZE_AUTO_WIDTH | wxSIZE_AUTO_HEIGHT);
-        SetSizeHints(GetSize());
     }
 
     return ret;
diff --git a/src/msw/tbar95.cpp b/src/msw/tbar95.cpp
index 717e5ff7c9..de0cc3ffaa 100644
--- a/src/msw/tbar95.cpp
+++ b/src/msw/tbar95.cpp
@@ -388,6 +388,7 @@ bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool)
     // Realize() later
     tool->Attach(this);
 
+    InvalidateBestSize();
     return TRUE;
 }
 
@@ -465,6 +466,7 @@ bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool)
         }
     }
 
+    InvalidateBestSize();
     return TRUE;
 }
 
@@ -922,6 +924,7 @@ bool wxToolBar::Realize()
         }
     }
 
+    InvalidateBestSize();
     return TRUE;
 }
 
diff --git a/wxPython/src/_window.i b/wxPython/src/_window.i
index cb217eea1a..7a10cf71c5 100644
--- a/wxPython/src/_window.i
+++ b/wxPython/src/_window.i
@@ -509,6 +509,21 @@ after calling Fit.", "");
         GetBestSizeTuple);
     
 
+    DocDeclStr(
+        void , InvalidateBestSize(),
+        "Reset the cached best size value so it will be recalculated the next
+time it is needed.", "");
+
+
+    
+    DocDeclStr(
+        wxSize , GetBestFittingSize() const,
+        "This function will merge the window's best size into the window's
+minimum size, giving priority to the min size components, and returns
+the results.
+", "");
+    
+
     DocDeclStr(
         wxSize , GetAdjustedBestSize() const,
         "This method is similar to GetBestSize, except in one
@@ -1325,7 +1340,7 @@ The cursor may be wx.NullCursor in which case the window cursor will
 be reset back to default.", "");
     
     DocDeclStr(
-        wxCursor& , GetCursor(),
+        wxCursor , GetCursor(),
         "Return the cursor associated with this window.", "");
     
 
@@ -1341,7 +1356,7 @@ be reset back to default.", "");
 
     
     DocDeclStr(
-        wxFont& , GetFont(),
+        wxFont , GetFont(),
         "Returns the default font used for this window.", "");
 
     
-- 
2.47.2