]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/sizer.cpp
Rework the wxCusor ctor taking wx stock number to provide as many cursors as
[wxWidgets.git] / src / common / sizer.cpp
index 21f311e59b65958a5fe4f494d48c0e133843c870..c8965d7295d0ff10480e912aa3f2450c6c940206 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////
-// Name:        sizer.cpp
+// Name:        src/common/sizer.cpp
 // Purpose:     provide new wxSizer class for layout
 // Author:      Robert Roebling and Robin Dunn, contributions by
 //              Dirk Holtwick, Ron Lee
 // Purpose:     provide new wxSizer class for layout
 // Author:      Robert Roebling and Robin Dunn, contributions by
 //              Dirk Holtwick, Ron Lee
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
-#ifdef __GNUG__
-#pragma implementation "sizer.h"
-#endif
-
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
     #pragma hdrstop
 #endif
 
     #pragma hdrstop
 #endif
 
+#include "wx/display.h"
 #include "wx/sizer.h"
 #include "wx/sizer.h"
-#include "wx/utils.h"
-#include "wx/statbox.h"
-#include "wx/notebook.h"
-#include <wx/listimpl.cpp>
+
+#ifndef WX_PRECOMP
+    #include "wx/string.h"
+    #include "wx/intl.h"
+    #include "wx/math.h"
+    #include "wx/utils.h"
+    #include "wx/settings.h"
+    #include "wx/button.h"
+    #include "wx/statbox.h"
+    #include "wx/toplevel.h"
+#endif // WX_PRECOMP
+
+#include "wx/listimpl.cpp"
+
 
 //---------------------------------------------------------------------------
 
 
 //---------------------------------------------------------------------------
 
@@ -37,79 +44,217 @@ IMPLEMENT_CLASS(wxBoxSizer, wxSizer)
 #if wxUSE_STATBOX
 IMPLEMENT_CLASS(wxStaticBoxSizer, wxBoxSizer)
 #endif
 #if wxUSE_STATBOX
 IMPLEMENT_CLASS(wxStaticBoxSizer, wxBoxSizer)
 #endif
-#if wxUSE_NOTEBOOK
-IMPLEMENT_CLASS(wxNotebookSizer, wxSizer)
+#if wxUSE_BUTTON
+IMPLEMENT_CLASS(wxStdDialogButtonSizer, wxBoxSizer)
 #endif
 
 #endif
 
-WX_DEFINE_EXPORTED_LIST( wxSizerItemList );
+WX_DEFINE_EXPORTED_LIST( wxSizerItemList )
+
+/*
+    TODO PROPERTIES
+      sizeritem
+        object
+        object_ref
+          minsize
+          option
+          flag
+          border
+     spacer
+        option
+        flag
+        borfder
+    boxsizer
+       orient
+    staticboxsizer
+       orient
+       label
+    gridsizer
+       rows
+       cols
+       vgap
+       hgap
+    flexgridsizer
+       rows
+       cols
+       vgap
+       hgap
+       growablerows
+       growablecols
+    minsize
+*/
+
+// ----------------------------------------------------------------------------
+// wxSizerItem
+// ----------------------------------------------------------------------------
 
 
+void wxSizerItem::Init(const wxSizerFlags& flags)
+{
+    Init();
 
 
-//---------------------------------------------------------------------------
-// wxSizerItem
-//---------------------------------------------------------------------------
+    m_proportion = flags.GetProportion();
+    m_flag = flags.GetFlags();
+    m_border = flags.GetBorderInPixels();
+}
+
+wxSizerItem::wxSizerItem()
+{
+    Init();
+
+    m_proportion = 0;
+    m_border = 0;
+    m_flag = 0;
+}
 
 
-wxSizerItem::wxSizerItem( int width, int height, int proportion, int flag, int border, wxObject* userData )
-    : m_window( NULL )
-    , m_sizer( NULL )
-    , m_size( wxSize( width, height ) ) // size is set directly
-    , m_minSize( m_size )               // minimal size is the initial size
-    , m_proportion( proportion )
-    , m_border( border )
-    , m_flag( flag )
-    , m_show( true )
-    , m_userData( userData )
-{
-    SetRatio( m_size );
-}
-
-wxSizerItem::wxSizerItem( wxWindow *window, int proportion, int flag, int border, wxObject* userData )
-    : m_window( window )
-    , m_sizer( NULL )
-    , m_minSize( window->GetSize() )    // minimal size is the initial size
-    , m_proportion( proportion )
-    , m_border( border )
-    , m_flag( flag )
-    , m_show( true )
-    , m_userData( userData )
+// window item
+void wxSizerItem::DoSetWindow(wxWindow *window)
 {
 {
+    wxCHECK_RET( window, _T("NULL window in wxSizerItem::SetWindow()") );
+
+    m_kind = Item_Window;
+    m_window = window;
+
+    // window doesn't become smaller than its initial size, whatever happens
+    m_minSize = window->GetSize();
+
+    if ( m_flag & wxFIXED_MINSIZE )
+        window->SetMinSize(m_minSize);
+
     // aspect ratio calculated from initial size
     // aspect ratio calculated from initial size
-    SetRatio( m_minSize );
+    SetRatio(m_minSize);
+}
+
+wxSizerItem::wxSizerItem(wxWindow *window,
+                         int proportion,
+                         int flag,
+                         int border,
+                         wxObject* userData)
+           : m_kind(Item_None),
+             m_proportion(proportion),
+             m_border(border),
+             m_flag(flag),
+             m_userData(userData)
+{
+    DoSetWindow(window);
+}
+
+// sizer item
+void wxSizerItem::DoSetSizer(wxSizer *sizer)
+{
+    m_kind = Item_Sizer;
+    m_sizer = sizer;
+}
+
+wxSizerItem::wxSizerItem(wxSizer *sizer,
+                         int proportion,
+                         int flag,
+                         int border,
+                         wxObject* userData)
+           : m_kind(Item_None),
+             m_sizer(NULL),
+             m_proportion(proportion),
+             m_border(border),
+             m_flag(flag),
+             m_ratio(0.0),
+             m_userData(userData)
+{
+    DoSetSizer(sizer);
 
 
-    // m_size is calculated later
+    // m_minSize is set later
 }
 
 }
 
-wxSizerItem::wxSizerItem( wxSizer *sizer, int proportion, int flag, int border, wxObject* userData )
-    : m_window( NULL )
-    , m_sizer( sizer )
-    , m_proportion( proportion )
-    , m_border( border )
-    , m_flag( flag )
-    , m_show( true )
-    , m_ratio( 0.0 )
-    , m_userData( userData )
+// spacer item
+void wxSizerItem::DoSetSpacer(const wxSize& size)
 {
 {
-    // m_minSize is calculated later
-    // m_size is calculated later
+    m_kind = Item_Spacer;
+    m_spacer = new wxSizerSpacer(size);
+    m_minSize = size;
+    SetRatio(size);
+}
+
+wxSizerItem::wxSizerItem(int width,
+                         int height,
+                         int proportion,
+                         int flag,
+                         int border,
+                         wxObject* userData)
+           : m_kind(Item_None),
+             m_sizer(NULL),
+             m_minSize(width, height), // minimal size is the initial size
+             m_proportion(proportion),
+             m_border(border),
+             m_flag(flag),
+             m_userData(userData)
+{
+    DoSetSpacer(wxSize(width, height));
 }
 
 wxSizerItem::~wxSizerItem()
 {
 }
 
 wxSizerItem::~wxSizerItem()
 {
-    if (m_userData)
-        delete m_userData;
-    if (m_sizer)
-        delete m_sizer;
+    delete m_userData;
+    Free();
+}
+
+void wxSizerItem::Free()
+{
+    switch ( m_kind )
+    {
+        case Item_None:
+            break;
+
+        case Item_Window:
+            m_window->SetContainingSizer(NULL);
+            break;
+
+        case Item_Sizer:
+            delete m_sizer;
+            break;
+
+        case Item_Spacer:
+            delete m_spacer;
+            break;
+
+        case Item_Max:
+        default:
+            wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
+    }
+
+    m_kind = Item_None;
+}
+
+wxSize wxSizerItem::GetSpacer() const
+{
+    wxSize size;
+    if ( m_kind == Item_Spacer )
+        size = m_spacer->GetSize();
+
+    return size;
 }
 
 
 wxSize wxSizerItem::GetSize() const
 {
     wxSize ret;
 }
 
 
 wxSize wxSizerItem::GetSize() const
 {
     wxSize ret;
-    if (IsSizer())
-        ret = m_sizer->GetSize();
-    else
-    if (IsWindow())
-        ret = m_window->GetSize();
-    else ret = m_size;
+    switch ( m_kind )
+    {
+        case Item_None:
+            break;
+
+        case Item_Window:
+            ret = m_window->GetSize();
+            break;
+
+        case Item_Sizer:
+            ret = m_sizer->GetSize();
+            break;
+
+        case Item_Spacer:
+            ret = m_spacer->GetSize();
+            break;
+
+        case Item_Max:
+        default:
+            wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
+    }
 
     if (m_flag & wxWEST)
         ret.x += m_border;
 
     if (m_flag & wxWEST)
         ret.x += m_border;
@@ -125,30 +270,29 @@ wxSize wxSizerItem::GetSize() const
 
 wxSize wxSizerItem::CalcMin()
 {
 
 wxSize wxSizerItem::CalcMin()
 {
-    wxSize ret;
     if (IsSizer())
     {
     if (IsSizer())
     {
-        ret = m_sizer->GetMinSize();
+        m_minSize = m_sizer->GetMinSize();
 
         // if we have to preserve aspect ratio _AND_ this is
         // the first-time calculation, consider ret to be initial size
 
         // if we have to preserve aspect ratio _AND_ this is
         // the first-time calculation, consider ret to be initial size
-        if ((m_flag & wxSHAPED) && !m_ratio)
-            SetRatio(ret);
+        if ( (m_flag & wxSHAPED) && wxIsNullDouble(m_ratio) )
+            SetRatio(m_minSize);
     }
     }
-    else
+    else if ( IsWindow() )
     {
     {
-        if ( IsWindow() && (m_flag & wxADJUST_MINSIZE) )
-        {
-            // By user request, keep the minimal size for this item
-            // in sync with the largest of BestSize and any user supplied
-            // minimum size hint.  Useful in cases where the item is
-            // changeable -- static text labels, etc.
-            m_minSize = m_window->GetAdjustedBestSize();
-        }
-
-        ret = m_minSize;
+        // Since the size of the window may change during runtime, we
+        // should use the current minimal/best size.
+        m_minSize = m_window->GetEffectiveMinSize();
     }
 
     }
 
+    return GetMinSizeWithBorder();
+}
+
+wxSize wxSizerItem::GetMinSizeWithBorder() const
+{
+    wxSize ret = m_minSize;
+
     if (m_flag & wxWEST)
         ret.x += m_border;
     if (m_flag & wxEAST)
     if (m_flag & wxWEST)
         ret.x += m_border;
     if (m_flag & wxEAST)
@@ -161,8 +305,11 @@ wxSize wxSizerItem::CalcMin()
     return ret;
 }
 
     return ret;
 }
 
-void wxSizerItem::SetDimension( wxPoint pos, wxSize size )
+
+void wxSizerItem::SetDimension( const wxPoint& pos_, const wxSize& size_ )
 {
 {
+    wxPoint pos = pos_;
+    wxSize size = size_;
     if (m_flag & wxSHAPED)
     {
         // adjust aspect ratio
     if (m_flag & wxSHAPED)
     {
         // adjust aspect ratio
@@ -214,184 +361,215 @@ void wxSizerItem::SetDimension( wxPoint pos, wxSize size )
         size.y -= m_border;
     }
 
         size.y -= m_border;
     }
 
-    if (IsSizer())
-        m_sizer->SetDimension( pos.x, pos.y, size.x, size.y );
+    if (size.x < 0)
+        size.x = 0;
+    if (size.y < 0)
+        size.y = 0;
 
 
-    if (IsWindow())
-        m_window->SetSize( pos.x, pos.y, size.x, size.y, wxSIZE_ALLOW_MINUS_ONE );
+    m_rect = wxRect(pos, size);
 
 
-    m_size = size;
-}
+    switch ( m_kind )
+    {
+        case Item_None:
+            wxFAIL_MSG( _T("can't set size of uninitialized sizer item") );
+            break;
 
 
-void wxSizerItem::DeleteWindows()
-{
-    if (m_window)
-         m_window->Destroy();
+        case Item_Window:
+            m_window->SetSize(pos.x, pos.y, size.x, size.y,
+                              wxSIZE_ALLOW_MINUS_ONE);
+            break;
 
 
-    if (m_sizer)
-        m_sizer->DeleteWindows();
-}
+        case Item_Sizer:
+            m_sizer->SetDimension(pos.x, pos.y, size.x, size.y);
+            break;
 
 
-bool wxSizerItem::IsWindow() const
-{
-    return (m_window != NULL);
-}
+        case Item_Spacer:
+            m_spacer->SetSize(size);
+            break;
 
 
-bool wxSizerItem::IsSizer() const
-{
-    return (m_sizer != NULL);
+        case Item_Max:
+        default:
+            wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
+    }
 }
 
 }
 
-bool wxSizerItem::IsSpacer() const
+void wxSizerItem::DeleteWindows()
 {
 {
-    return (m_window == NULL) && (m_sizer == NULL);
-}
+    switch ( m_kind )
+    {
+        case Item_None:
+        case Item_Spacer:
+            break;
 
 
-void wxSizerItem::Show( bool show )
-{
-    m_show = show;
+        case Item_Window:
+            //We are deleting the window from this sizer - normally
+            //the window destroys the sizer associated with it,
+            //which might destroy this, which we don't want
+            m_window->SetContainingSizer(NULL);
+            m_window->Destroy();
+            //Putting this after the switch will result in a spacer
+            //not being deleted properly on destruction
+            m_kind = Item_None;
+            break;
 
 
-    if( IsWindow() )
-        m_window->Show( show );
-    else if( IsSizer() )
-        m_sizer->ShowItems( show );
+        case Item_Sizer:
+            m_sizer->DeleteWindows();
+            break;
 
 
-    // ... nothing else to do to hide/show spacers
-}
+        case Item_Max:
+        default:
+            wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
+    }
 
 
-void wxSizerItem::SetOption( int option )
-{
-    SetProportion( option );
 }
 
 }
 
-int wxSizerItem::GetOption() const
+void wxSizerItem::Show( bool show )
 {
 {
-    return GetProportion();
-}
+    switch ( m_kind )
+    {
+        case Item_None:
+            wxFAIL_MSG( _T("can't show uninitialized sizer item") );
+            break;
 
 
+        case Item_Window:
+            m_window->Show(show);
+            break;
 
 
-//---------------------------------------------------------------------------
-// wxSizer
-//---------------------------------------------------------------------------
+        case Item_Sizer:
+            m_sizer->Show(show);
+            break;
 
 
-wxSizer::wxSizer()
-    : m_minSize( wxSize( 0, 0 ) )
-{
-    m_children.DeleteContents( true );
-}
+        case Item_Spacer:
+            m_spacer->Show(show);
+            break;
 
 
-wxSizer::~wxSizer()
-{
-    Clear();
+        case Item_Max:
+        default:
+            wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
+    }
 }
 
 }
 
-void wxSizer::Add( wxWindow *window, int proportion, int flag, int border, wxObject* userData )
+bool wxSizerItem::IsShown() const
 {
 {
-    m_children.Append( new wxSizerItem( window, proportion, flag, border, userData ) );
-    window->SetContainingSizer( this );
-}
+    switch ( m_kind )
+    {
+        case Item_None:
+            // we may be called from CalcMin(), just return false so that we're
+            // not used
+            break;
 
 
-void wxSizer::Add( wxSizer *sizer, int proportion, int flag, int border, wxObject* userData )
-{
-    m_children.Append( new wxSizerItem( sizer, proportion, flag, border, userData ) );
-}
+        case Item_Window:
+            return m_window->IsShown();
 
 
-void wxSizer::Add( int width, int height, int proportion, int flag, int border, wxObject* userData )
-{
-    m_children.Append( new wxSizerItem( width, height, proportion, flag, border, userData ) );
-}
+        case Item_Sizer:
+            // arbitrarily decide that if at least one of our elements is
+            // shown, so are we (this arbitrariness is the reason for
+            // deprecating this function)
+            {
+                // Some apps (such as dialog editors) depend on an empty sizer still
+                // being laid out correctly and reporting the correct size and position.
+                if (m_sizer->GetChildren().GetCount() == 0)
+                    return true;
+
+                for ( wxSizerItemList::compatibility_iterator
+                        node = m_sizer->GetChildren().GetFirst();
+                      node;
+                      node = node->GetNext() )
+                {
+                    if ( node->GetData()->IsShown() )
+                        return true;
+                }
+            }
+            return false;
 
 
-void wxSizer::Add( wxSizerItem *item )
-{
-    m_children.Append( item );
+        case Item_Spacer:
+            return m_spacer->IsShown();
 
 
-    if( item->GetWindow() )
-        item->GetWindow()->SetContainingSizer( this );
+        case Item_Max:
+        default:
+            wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
+    }
+
+    return false;
 }
 
 }
 
-void wxSizer::Prepend( wxWindow *window, int proportion, int flag, int border, wxObject* userData )
+#if WXWIN_COMPATIBILITY_2_6
+void wxSizerItem::SetOption( int option )
 {
 {
-    m_children.Insert( new wxSizerItem( window, proportion, flag, border, userData ) );
-    window->SetContainingSizer( this );
+    SetProportion( option );
 }
 
 }
 
-void wxSizer::Prepend( wxSizer *sizer, int proportion, int flag, int border, wxObject* userData )
+int wxSizerItem::GetOption() const
 {
 {
-    m_children.Insert( new wxSizerItem( sizer, proportion, flag, border, userData ) );
+    return GetProportion();
 }
 }
+#endif // WXWIN_COMPATIBILITY_2_6
+
+
+//---------------------------------------------------------------------------
+// wxSizer
+//---------------------------------------------------------------------------
 
 
-void wxSizer::Prepend( int width, int height, int proportion, int flag, int border, wxObject* userData )
+wxSizer::~wxSizer()
 {
 {
-    m_children.Insert( new wxSizerItem( width, height, proportion, flag, border, userData ) );
+    WX_CLEAR_LIST(wxSizerItemList, m_children);
 }
 
 }
 
-void wxSizer::Prepend( wxSizerItem *item )
+wxSizerItem* wxSizer::Insert( size_t index, wxSizerItem *item )
 {
 {
-    m_children.Insert( item );
+    m_children.Insert( index, item );
 
 
-    if( item->GetWindow() )
+    if ( item->GetWindow() )
         item->GetWindow()->SetContainingSizer( this );
         item->GetWindow()->SetContainingSizer( this );
-}
 
 
-void wxSizer::Insert( size_t index,
-                      wxWindow *window,
-                      int proportion,
-                      int flag,
-                      int border,
-                      wxObject* userData )
-{
-    m_children.Insert( index,
-                       new wxSizerItem( window, proportion, flag, border, userData ) );
-    window->SetContainingSizer( this );
+    return item;
 }
 
 }
 
-void wxSizer::Insert( size_t index,
-                      wxSizer *sizer,
-                      int proportion,
-                      int flag,
-                      int border,
-                      wxObject* userData )
+void wxSizer::SetContainingWindow(wxWindow *win)
 {
 {
-    m_children.Insert( index,
-                       new wxSizerItem( sizer, proportion, flag, border, userData ) );
-}
+    if ( win == m_containingWindow )
+        return;
 
 
-void wxSizer::Insert( size_t index,
-                      int width,
-                      int height,
-                      int proportion,
-                      int flag,
-                      int border,
-                      wxObject* userData )
-{
-    m_children.Insert( index,
-                       new wxSizerItem( width, height, proportion, flag, border, userData ) );
-}
+    m_containingWindow = win;
 
 
-void wxSizer::Insert( size_t index, wxSizerItem *item )
-{
-    m_children.Insert( index, item );
+    // set the same window for all nested sizers as well, they also are in the
+    // same window
+    for ( wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
+          node;
+          node = node->GetNext() )
+    {
+        wxSizerItem *const item = node->GetData();
+        wxSizer *const sizer = item->GetSizer();
 
 
-    if( item->GetWindow() )
-        item->GetWindow()->SetContainingSizer( this );
+        if ( sizer )
+        {
+            sizer->SetContainingWindow(win);
+        }
+    }
 }
 
 }
 
+#if WXWIN_COMPATIBILITY_2_6
 bool wxSizer::Remove( wxWindow *window )
 {
     return Detach( window );
 }
 bool wxSizer::Remove( wxWindow *window )
 {
     return Detach( window );
 }
+#endif // WXWIN_COMPATIBILITY_2_6
 
 bool wxSizer::Remove( wxSizer *sizer )
 {
     wxASSERT_MSG( sizer, _T("Removing NULL sizer") );
 
 
 bool wxSizer::Remove( wxSizer *sizer )
 {
     wxASSERT_MSG( sizer, _T("Removing NULL sizer") );
 
-    wxSizerItemList::Node   *node = m_children.GetFirst();
+    wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
     while (node)
     {
         wxSizerItem     *item = node->GetData();
 
         if (item->GetSizer() == sizer)
     while (node)
     {
         wxSizerItem     *item = node->GetData();
 
         if (item->GetSizer() == sizer)
-            return m_children.DeleteNode( node );
+        {
+            delete item;
+            m_children.Erase( node );
+            return true;
+        }
 
         node = node->GetNext();
     }
 
         node = node->GetNext();
     }
@@ -405,23 +583,21 @@ bool wxSizer::Remove( int index )
                  false,
                  _T("Remove index is out of range") );
 
                  false,
                  _T("Remove index is out of range") );
 
-    wxSizerItemList::Node *node = m_children.Item( index );
+    wxSizerItemList::compatibility_iterator node = m_children.Item( index );
 
     wxCHECK_MSG( node, false, _T("Failed to find child node") );
 
 
     wxCHECK_MSG( node, false, _T("Failed to find child node") );
 
-    wxSizerItem *item = node->GetData();
-
-    if( item->IsWindow() )
-        item->GetWindow()->SetContainingSizer( NULL );
+    delete node->GetData();
+    m_children.Erase( node );
 
 
-    return m_children.DeleteNode( node );
+    return true;
 }
 
 bool wxSizer::Detach( wxSizer *sizer )
 {
     wxASSERT_MSG( sizer, _T("Detaching NULL sizer") );
 
 }
 
 bool wxSizer::Detach( wxSizer *sizer )
 {
     wxASSERT_MSG( sizer, _T("Detaching NULL sizer") );
 
-    wxSizerItemList::Node   *node = m_children.GetFirst();
+    wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
     while (node)
     {
         wxSizerItem     *item = node->GetData();
     while (node)
     {
         wxSizerItem     *item = node->GetData();
@@ -429,7 +605,9 @@ bool wxSizer::Detach( wxSizer *sizer )
         if (item->GetSizer() == sizer)
         {
             item->DetachSizer();
         if (item->GetSizer() == sizer)
         {
             item->DetachSizer();
-            return m_children.DeleteNode( node );
+            delete item;
+            m_children.Erase( node );
+            return true;
         }
         node = node->GetNext();
     }
         }
         node = node->GetNext();
     }
@@ -441,15 +619,16 @@ bool wxSizer::Detach( wxWindow *window )
 {
     wxASSERT_MSG( window, _T("Detaching NULL window") );
 
 {
     wxASSERT_MSG( window, _T("Detaching NULL window") );
 
-    wxSizerItemList::Node   *node = m_children.GetFirst();
+    wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
     while (node)
     {
         wxSizerItem     *item = node->GetData();
 
         if (item->GetWindow() == window)
         {
     while (node)
     {
         wxSizerItem     *item = node->GetData();
 
         if (item->GetWindow() == window)
         {
-            item->GetWindow()->SetContainingSizer( NULL );
-            return m_children.DeleteNode( node );
+            delete item;
+            m_children.Erase( node );
+            return true;
         }
         node = node->GetNext();
     }
         }
         node = node->GetNext();
     }
@@ -463,24 +642,95 @@ bool wxSizer::Detach( int index )
                  false,
                  _T("Detach index is out of range") );
 
                  false,
                  _T("Detach index is out of range") );
 
-    wxSizerItemList::Node *node = m_children.Item( index );
+    wxSizerItemList::compatibility_iterator node = m_children.Item( index );
 
     wxCHECK_MSG( node, false, _T("Failed to find child node") );
 
     wxSizerItem *item = node->GetData();
 
 
     wxCHECK_MSG( node, false, _T("Failed to find child node") );
 
     wxSizerItem *item = node->GetData();
 
-    if( item->IsSizer() )
+    if ( item->IsSizer() )
         item->DetachSizer();
         item->DetachSizer();
-    else if( item->IsWindow() )
-        item->GetWindow()->SetContainingSizer( NULL );
 
 
-    return m_children.DeleteNode( node );
+    delete item;
+    m_children.Erase( node );
+    return true;
+}
+
+bool wxSizer::Replace( wxWindow *oldwin, wxWindow *newwin, bool recursive )
+{
+    wxASSERT_MSG( oldwin, _T("Replacing NULL window") );
+    wxASSERT_MSG( newwin, _T("Replacing with NULL window") );
+
+    wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
+    while (node)
+    {
+        wxSizerItem     *item = node->GetData();
+
+        if (item->GetWindow() == oldwin)
+        {
+            item->AssignWindow(newwin);
+            newwin->SetContainingSizer( this );
+            return true;
+        }
+        else if (recursive && item->IsSizer())
+        {
+            if (item->GetSizer()->Replace( oldwin, newwin, true ))
+                return true;
+        }
+
+        node = node->GetNext();
+    }
+
+    return false;
+}
+
+bool wxSizer::Replace( wxSizer *oldsz, wxSizer *newsz, bool recursive )
+{
+    wxASSERT_MSG( oldsz, _T("Replacing NULL sizer") );
+    wxASSERT_MSG( newsz, _T("Replacing with NULL sizer") );
+
+    wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
+    while (node)
+    {
+        wxSizerItem     *item = node->GetData();
+
+        if (item->GetSizer() == oldsz)
+        {
+            item->AssignSizer(newsz);
+            return true;
+        }
+        else if (recursive && item->IsSizer())
+        {
+            if (item->GetSizer()->Replace( oldsz, newsz, true ))
+                return true;
+        }
+
+        node = node->GetNext();
+    }
+
+    return false;
+}
+
+bool wxSizer::Replace( size_t old, wxSizerItem *newitem )
+{
+    wxCHECK_MSG( old < m_children.GetCount(), false, _T("Replace index is out of range") );
+    wxASSERT_MSG( newitem, _T("Replacing with NULL item") );
+
+    wxSizerItemList::compatibility_iterator node = m_children.Item( old );
+
+    wxCHECK_MSG( node, false, _T("Failed to find child node") );
+
+    wxSizerItem *item = node->GetData();
+    node->SetData(newitem);
+    delete item;
+
+    return true;
 }
 
 void wxSizer::Clear( bool delete_windows )
 {
     // First clear the ContainingSizer pointers
 }
 
 void wxSizer::Clear( bool delete_windows )
 {
     // First clear the ContainingSizer pointers
-    wxSizerItemList::Node   *node = m_children.GetFirst();
+    wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
     while (node)
     {
         wxSizerItem     *item = node->GetData();
     while (node)
     {
         wxSizerItem     *item = node->GetData();
@@ -495,12 +745,12 @@ void wxSizer::Clear( bool delete_windows )
         DeleteWindows();
 
     // Now empty the list
         DeleteWindows();
 
     // Now empty the list
-    m_children.Clear();
+    WX_CLEAR_LIST(wxSizerItemList, m_children);
 }
 
 void wxSizer::DeleteWindows()
 {
 }
 
 void wxSizer::DeleteWindows()
 {
-    wxSizerItemList::Node   *node = m_children.GetFirst();
+    wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
     while (node)
     {
         wxSizerItem     *item = node->GetData();
     while (node)
     {
         wxSizerItem     *item = node->GetData();
@@ -512,11 +762,37 @@ void wxSizer::DeleteWindows()
 
 wxSize wxSizer::Fit( wxWindow *window )
 {
 
 wxSize wxSizer::Fit( wxWindow *window )
 {
-    wxSize size;
-    if (window->IsTopLevel())
-        size = FitSize( window );
-    else
-        size = GetMinWindowSize( window );
+    // take the min size by default and limit it by max size
+    wxSize size = GetMinWindowSize(window);
+    wxSize sizeMax = GetMaxWindowSize(window);
+
+    wxTopLevelWindow *tlw = wxDynamicCast(window, wxTopLevelWindow);
+    if ( tlw )
+    {
+        // hack for small screen devices where TLWs are always full screen
+        if ( tlw->IsAlwaysMaximized() )
+        {
+            size = tlw->GetSize();
+        }
+        else // normal situation
+        {
+            // limit the window to the size of the display it is on
+            int disp = wxDisplay::GetFromWindow(window);
+            if ( disp == wxNOT_FOUND )
+            {
+                // or, if we don't know which one it is, of the main one
+                disp = 0;
+            }
+
+            sizeMax = wxDisplay(disp).GetClientArea().GetSize();
+        }
+    }
+
+    if ( sizeMax.x != wxDefaultCoord && size.x > sizeMax.x )
+        size.x = sizeMax.x;
+    if ( sizeMax.y != wxDefaultCoord && size.y > sizeMax.y )
+        size.y = sizeMax.y;
+
 
     window->SetSize( size );
 
 
     window->SetSize( size );
 
@@ -536,7 +812,11 @@ void wxSizer::FitInside( wxWindow *window )
 
 void wxSizer::Layout()
 {
 
 void wxSizer::Layout()
 {
+    // (re)calculates minimums needed for each item and other preparations
+    // for layout
     CalcMin();
     CalcMin();
+
+    // Applies the layout and repositions/resizes the items
     RecalcSizes();
 }
 
     RecalcSizes();
 }
 
@@ -581,27 +861,14 @@ wxSize wxSizer::GetMinWindowSize( wxWindow *window )
                    minSize.y+size.y-client_size.y );
 }
 
                    minSize.y+size.y-client_size.y );
 }
 
-// Return a window size that will fit within the screens dimensions
-wxSize wxSizer::FitSize( wxWindow *window )
-{
-    wxSize size     = GetMinWindowSize( window );
-    wxSize sizeMax  = GetMaxWindowSize( window );
-
-    // Limit the size if sizeMax != wxDefaultSize
-
-    if ( size.x > sizeMax.x && sizeMax.x != -1 )
-        size.x = sizeMax.x;
-    if ( size.y > sizeMax.y && sizeMax.y != -1 )
-        size.y = sizeMax.y;
-
-    return size;
-}
-
+// TODO on mac we need a function that determines how much free space this
+// min size contains, in order to make sure that we have 20 pixels of free
+// space around the controls
 wxSize wxSizer::GetMaxClientSize( wxWindow *window ) const
 {
     wxSize maxSize( window->GetMaxSize() );
 
 wxSize wxSizer::GetMaxClientSize( wxWindow *window ) const
 {
     wxSize maxSize( window->GetMaxSize() );
 
-    if( maxSize != wxDefaultSize )
+    if ( maxSize != wxDefaultSize )
     {
         wxSize size( window->GetSize() );
         wxSize client_size( window->GetClientSize() );
     {
         wxSize size( window->GetSize() );
         wxSize client_size( window->GetClientSize() );
@@ -625,9 +892,9 @@ wxSize wxSizer::VirtualFitSize( wxWindow *window )
 
     // Limit the size if sizeMax != wxDefaultSize
 
 
     // Limit the size if sizeMax != wxDefaultSize
 
-    if ( size.x > sizeMax.x && sizeMax.x != -1 )
+    if ( size.x > sizeMax.x && sizeMax.x != wxDefaultCoord )
         size.x = sizeMax.x;
         size.x = sizeMax.x;
-    if ( size.y > sizeMax.y && sizeMax.y != -1 )
+    if ( size.y > sizeMax.y && sizeMax.y != wxDefaultCoord )
         size.y = sizeMax.y;
 
     return size;
         size.y = sizeMax.y;
 
     return size;
@@ -662,14 +929,14 @@ bool wxSizer::DoSetItemMinSize( wxWindow *window, int width, int height )
 
     // Is it our immediate child?
 
 
     // Is it our immediate child?
 
-    wxSizerItemList::Node   *node = m_children.GetFirst();
+    wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
     while (node)
     {
         wxSizerItem     *item = node->GetData();
 
         if (item->GetWindow() == window)
         {
     while (node)
     {
         wxSizerItem     *item = node->GetData();
 
         if (item->GetWindow() == window)
         {
-            item->SetInitSize( width, height );
+            item->SetMinSize( width, height );
             return true;
         }
         node = node->GetNext();
             return true;
         }
         node = node->GetNext();
@@ -700,7 +967,7 @@ bool wxSizer::DoSetItemMinSize( wxSizer *sizer, int width, int height )
 
     // Is it our immediate child?
 
 
     // Is it our immediate child?
 
-    wxSizerItemList::Node   *node = m_children.GetFirst();
+    wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
     while (node)
     {
         wxSizerItem     *item = node->GetData();
     while (node)
     {
         wxSizerItem     *item = node->GetData();
@@ -734,7 +1001,7 @@ bool wxSizer::DoSetItemMinSize( wxSizer *sizer, int width, int height )
 
 bool wxSizer::DoSetItemMinSize( size_t index, int width, int height )
 {
 
 bool wxSizer::DoSetItemMinSize( size_t index, int width, int height )
 {
-    wxSizerItemList::Node   *node = m_children.Item( index );
+    wxSizerItemList::compatibility_iterator node = m_children.Item( index );
 
     wxCHECK_MSG( node, false, _T("Failed to find child node") );
 
 
     wxCHECK_MSG( node, false, _T("Failed to find child node") );
 
@@ -747,60 +1014,116 @@ bool wxSizer::DoSetItemMinSize( size_t index, int width, int height )
     }
     else
     {
     }
     else
     {
-        // ... but the minimal size of spacers and windows in stored in them
-        item->SetInitSize( width, height );
+        // ... but the minimal size of spacers and windows is stored via the item
+        item->SetMinSize( width, height );
     }
 
     return true;
 }
 
     }
 
     return true;
 }
 
-void wxSizer::Show( wxWindow *window, bool show )
+wxSizerItem* wxSizer::GetItem( wxWindow *window, bool recursive )
 {
 {
-    wxASSERT_MSG( window, _T("Show for NULL window") );
+    wxASSERT_MSG( window, _T("GetItem for NULL window") );
 
 
-    wxSizerItemList::Node   *node = m_children.GetFirst();
+    wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
     while (node)
     {
         wxSizerItem     *item = node->GetData();
 
         if (item->GetWindow() == window)
         {
     while (node)
     {
         wxSizerItem     *item = node->GetData();
 
         if (item->GetWindow() == window)
         {
-            item->Show( show );
-            break;
+            return item;
         }
         }
+        else if (recursive && item->IsSizer())
+        {
+            wxSizerItem *subitem = item->GetSizer()->GetItem( window, true );
+            if (subitem)
+                return subitem;
+        }
+
         node = node->GetNext();
     }
         node = node->GetNext();
     }
+
+    return NULL;
 }
 
 }
 
-void wxSizer::Show( wxSizer *sizer, bool show )
+wxSizerItem* wxSizer::GetItem( wxSizer *sizer, bool recursive )
 {
 {
-    wxASSERT_MSG( sizer, _T("Show for NULL sizer") );
+    wxASSERT_MSG( sizer, _T("GetItem for NULL sizer") );
 
 
-    wxSizerItemList::Node   *node = m_children.GetFirst();
+    wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
     while (node)
     {
     while (node)
     {
-        wxSizerItem     *item = node->GetData();
+        wxSizerItem *item = node->GetData();
 
         if (item->GetSizer() == sizer)
         {
 
         if (item->GetSizer() == sizer)
         {
-            item->Show( show );
-            break;
+            return item;
+        }
+        else if (recursive && item->IsSizer())
+        {
+            wxSizerItem *subitem = item->GetSizer()->GetItem( sizer, true );
+            if (subitem)
+                return subitem;
         }
         }
+
         node = node->GetNext();
     }
         node = node->GetNext();
     }
+
+    return NULL;
+}
+
+wxSizerItem* wxSizer::GetItem( size_t index )
+{
+    wxCHECK_MSG( index < m_children.GetCount(),
+                 NULL,
+                 _T("GetItem index is out of range") );
+
+    return m_children.Item( index )->GetData();
+}
+
+bool wxSizer::Show( wxWindow *window, bool show, bool recursive )
+{
+    wxSizerItem *item = GetItem( window, recursive );
+
+    if ( item )
+    {
+         item->Show( show );
+         return true;
+    }
+
+    return false;
+}
+
+bool wxSizer::Show( wxSizer *sizer, bool show, bool recursive )
+{
+    wxSizerItem *item = GetItem( sizer, recursive );
+
+    if ( item )
+    {
+         item->Show( show );
+         return true;
+    }
+
+    return false;
 }
 
 }
 
-void wxSizer::Show( size_t index, bool show )
+bool wxSizer::Show( size_t index, bool show)
 {
 {
-    wxCHECK_RET( index < m_children.GetCount(),
-                 _T("Show index is out of range") );
+    wxSizerItem *item = GetItem( index );
 
 
-    m_children.Item( index )->GetData()->Show( show );
+    if ( item )
+    {
+         item->Show( show );
+         return true;
+    }
+
+    return false;
 }
 
 void wxSizer::ShowItems( bool show )
 {
 }
 
 void wxSizer::ShowItems( bool show )
 {
-    wxSizerItemList::Node   *node = m_children.GetFirst();
+    wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
     while (node)
     {
         node->GetData()->Show( show );
     while (node)
     {
         node->GetData()->Show( show );
@@ -810,7 +1133,7 @@ void wxSizer::ShowItems( bool show )
 
 bool wxSizer::IsShown( wxWindow *window ) const
 {
 
 bool wxSizer::IsShown( wxWindow *window ) const
 {
-    wxSizerItemList::Node   *node = m_children.GetFirst();
+    wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
     while (node)
     {
         wxSizerItem     *item = node->GetData();
     while (node)
     {
         wxSizerItem     *item = node->GetData();
@@ -829,7 +1152,7 @@ bool wxSizer::IsShown( wxWindow *window ) const
 
 bool wxSizer::IsShown( wxSizer *sizer ) const
 {
 
 bool wxSizer::IsShown( wxSizer *sizer ) const
 {
-    wxSizerItemList::Node   *node = m_children.GetFirst();
+    wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
     while (node)
     {
         wxSizerItem     *item = node->GetData();
     while (node)
     {
         wxSizerItem     *item = node->GetData();
@@ -861,7 +1184,7 @@ bool wxSizer::IsShown( size_t index ) const
 //---------------------------------------------------------------------------
 
 wxGridSizer::wxGridSizer( int rows, int cols, int vgap, int hgap )
 //---------------------------------------------------------------------------
 
 wxGridSizer::wxGridSizer( int rows, int cols, int vgap, int hgap )
-    : m_rows( rows )
+    : m_rows( ( cols == 0 && rows == 0 ) ? 1 : rows )
     , m_cols( cols )
     , m_vgap( vgap )
     , m_hgap( hgap )
     , m_cols( cols )
     , m_vgap( vgap )
     , m_hgap( hgap )
@@ -869,7 +1192,7 @@ wxGridSizer::wxGridSizer( int rows, int cols, int vgap, int hgap )
 }
 
 wxGridSizer::wxGridSizer( int cols, int vgap, int hgap )
 }
 
 wxGridSizer::wxGridSizer( int cols, int vgap, int hgap )
-    : m_rows( 0 )
+    : m_rows( cols == 0 ? 1 : 0 )
     , m_cols( cols )
     , m_vgap( vgap )
     , m_hgap( hgap )
     , m_cols( cols )
     , m_vgap( vgap )
     , m_hgap( hgap )
@@ -923,7 +1246,7 @@ void wxGridSizer::RecalcSizes()
             int i = r * ncols + c;
             if (i < nitems)
             {
             int i = r * ncols + c;
             if (i < nitems)
             {
-                wxSizerItemList::Node   *node = m_children.Item( i );
+                wxSizerItemList::compatibility_iterator node = m_children.Item( i );
 
                 wxASSERT_MSG( node, _T("Failed to find SizerItemList node") );
 
 
                 wxASSERT_MSG( node, _T("Failed to find SizerItemList node") );
 
@@ -937,15 +1260,15 @@ void wxGridSizer::RecalcSizes()
 
 wxSize wxGridSizer::CalcMin()
 {
 
 wxSize wxGridSizer::CalcMin()
 {
-    int nitems, nrows, ncols;
-    if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
-        return wxSize(10, 10);
+    int nrows, ncols;
+    if ( CalcRowsCols(nrows, ncols) == 0 )
+        return wxSize();
 
     // Find the max width and height for any component
     int w = 0;
     int h = 0;
 
 
     // Find the max width and height for any component
     int w = 0;
     int h = 0;
 
-    wxSizerItemList::Node   *node = m_children.GetFirst();
+    wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
     while (node)
     {
         wxSizerItem     *item = node->GetData();
     while (node)
     {
         wxSizerItem     *item = node->GetData();
@@ -964,7 +1287,7 @@ wxSize wxGridSizer::CalcMin()
 void wxGridSizer::SetItemBounds( wxSizerItem *item, int x, int y, int w, int h )
 {
     wxPoint pt( x,y );
 void wxGridSizer::SetItemBounds( wxSizerItem *item, int x, int y, int w, int h )
 {
     wxPoint pt( x,y );
-    wxSize sz( item->CalcMin() );
+    wxSize sz( item->GetMinSizeWithBorder() );
     int flag = item->GetFlag();
 
     if ((flag & wxEXPAND) || (flag & wxSHAPED))
     int flag = item->GetFlag();
 
     if ((flag & wxEXPAND) || (flag & wxSHAPED))
@@ -1023,166 +1346,133 @@ void wxFlexGridSizer::RecalcSizes()
     if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
         return;
 
     if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
         return;
 
-    wxSize sz( GetSize() );
-    wxSize minsz( CalcMin() );
-    wxPoint pt( GetPosition() );
-    int    delta;
-    size_t idx, num;
-    wxArrayInt temp;
-    wxArrayInt temp_proportions;
-    int sum_proportions = 0;
-    int growable_space = 0;
+    const wxPoint pt(GetPosition());
+    const wxSize sz(GetSize());
+
+    AdjustForGrowables(sz);
 
 
-    // what to do with the rows? by default, resize them proportionally
-    if ( (m_flexDirection & wxVERTICAL) ||
-            (m_growMode == wxFLEX_GROWMODE_SPECIFIED) )
+    wxSizerItemList::const_iterator i = m_children.begin();
+    const wxSizerItemList::const_iterator end = m_children.end();
+
+    int y = 0;
+    for ( int r = 0; r < nrows; r++ )
     {
     {
-        // Transfer only those rows into temp which exist in the sizer
-        // ignoring the superfluous ones. This prevents a segfault when
-        // calling AddGrowableRow( 3 ) if the sizer only has 2 rows.
-        for (idx = 0; idx < m_growableRows.GetCount(); idx++)
+        if ( m_rowHeights[r] == -1 )
         {
         {
-            if (m_growableRows[idx] < nrows)
+            // this row is entirely hidden, skip it
+            for ( int c = 0; c < ncols; c++ )
             {
             {
-                temp.Add( m_growableRows[idx] );
-                temp_proportions.Add( m_growableRowsProportions[idx] );
-                sum_proportions += m_growableRowsProportions[idx];
-                growable_space += m_rowHeights[ temp[idx] ];
+                if ( i == end )
+                    return;
+
+                ++i;
             }
             }
+
+            continue;
         }
 
         }
 
-        num = temp.GetCount();
+        const int hrow = m_rowHeights[r];
+        int h = sz.y - y; // max remaining height, don't overflow it
+        if ( hrow < h )
+            h = hrow;
 
 
-        if ((num > 0) && (sz.y > minsz.y))
+        int x = 0;
+        for ( int c = 0; c < ncols && i != end; c++, ++i )
         {
         {
-            for (idx = 0; idx < num; idx++)
-            {
-                delta = (sz.y - minsz.y);
-                if (sum_proportions == 0)
-                    delta = (delta/num) + m_rowHeights[ temp[idx] ];
-                else
-                    delta = ((delta+growable_space)*temp_proportions[idx])/
-                                                     sum_proportions;
-                m_rowHeights[ temp[idx] ] = delta;
-            }
-        }
-        temp.Empty();
-        temp_proportions.Empty();
-               sum_proportions = 0;
-               growable_space = 0;
-    }
-    else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.y > minsz.y) )
-    {
-        // rounding problem?
-        for ( int row = 0; row < nrows; ++row )
-            m_rowHeights[ row ] = sz.y / nrows;
-    }
+            const int wcol = m_colWidths[c];
 
 
-    // the same logic as above but for the columns
-    if ( (m_flexDirection & wxHORIZONTAL) ||
-            (m_growMode == wxFLEX_GROWMODE_SPECIFIED) )
-    {
-        // See above
-        for (idx = 0; idx < m_growableCols.GetCount(); idx++)
-        {
-            if (m_growableCols[idx] < ncols)
-            {
-                temp.Add( m_growableCols[idx] );
-                temp_proportions.Add( m_growableColsProportions[idx] );
-                sum_proportions += m_growableColsProportions[idx];
-                growable_space += m_colWidths[idx];
-            }
-        }
+            if ( wcol == -1 )
+                continue;
 
 
-        num = temp.GetCount();
+            int w = sz.x - x; // max possible value, ensure we don't overflow
+            if ( wcol < w )
+                w = wcol;
 
 
-        if ((num > 0) && (sz.x > minsz.x))
-        {
-            for (idx = 0; idx < num; idx++)
-            {
-                delta = (sz.x - minsz.x);
-                if (sum_proportions == 0)
-                    delta = (delta/num) + m_colWidths[ temp[idx] ];
-               else
-                    delta = ((delta+growable_space)*temp_proportions[idx])/
-                                                     sum_proportions;
-                m_colWidths[ temp[idx] ] = delta;
-            }
+            SetItemBounds(*i, pt.x + x, pt.y + y, w, h);
+
+            x += wcol + m_hgap;
         }
         }
+
+        if ( i == end )
+            return;
+
+        y += hrow + m_vgap;
     }
     }
-    else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.x > minsz.x) )
-    {
-        for ( int col=0; col < ncols; ++col )
-            m_colWidths[ col ] = sz.x / ncols;
-    }
+}
 
 
-    sz = wxSize( pt.x + sz.x, pt.y + sz.y );
+// helper function used in CalcMin() to sum up the sizes of non-hidden items
+static int SumArraySizes(const wxArrayInt& sizes, int gap)
+{
+    // Sum total minimum size, including gaps between rows/columns.
+    // -1 is used as a magic number meaning empty row/column.
+    int total = 0;
 
 
-    int x = pt.x;
-    for (int c = 0; c < ncols; c++)
+    const size_t count = sizes.size();
+    for ( size_t n = 0; n < count; n++ )
     {
     {
-        int y = pt.y;
-        for (int r = 0; r < nrows; r++)
+        if ( sizes[n] != -1 )
         {
         {
-            int i = r * ncols + c;
-            if (i < nitems)
-            {
-                wxSizerItemList::Node   *node = m_children.Item( i );
-
-                wxASSERT_MSG( node, _T("Failed to find node") );
+            if ( total )
+                total += gap; // separate from the previous column
 
 
-                int w = wxMax( 0, wxMin( m_colWidths[c], sz.x - x ) );
-                int h = wxMax( 0, wxMin( m_rowHeights[r], sz.y - y ) );
-
-                SetItemBounds( node->GetData(), x, y, w, h);
-            }
-            y = y + m_rowHeights[r] + m_vgap;
+            total += sizes[n];
         }
         }
-        x = x + m_colWidths[c] + m_hgap;
     }
     }
+
+    return total;
 }
 
 wxSize wxFlexGridSizer::CalcMin()
 {
 }
 
 wxSize wxFlexGridSizer::CalcMin()
 {
-    int     nrows,
-            ncols;
-    size_t  i, s;
+    int nrows,
+        ncols;
 
 
+    // Number of rows/columns can change as items are added or removed.
     if ( !CalcRowsCols(nrows, ncols) )
     if ( !CalcRowsCols(nrows, ncols) )
-        return wxSize(10, 10);
-
-    // We have to clear the old sizes out if any item has wxADJUST_MINSIZE
-    // set on it.  Its probably quicker to just always do it than test for
-    // that though.  At least do it before resizing the arrays, SetCount will
-    // initialise new elements to zero.
-    for( s = m_rowHeights.GetCount(), i = 0; i < s; ++i )
-        m_rowHeights[ i ] = 0;
-
-    for( s = m_colWidths.GetCount(), i = 0; i < s; ++i )
-        m_colWidths[ i ] = 0;
+        return wxSize();
+
+
+    // We have to recalculate the sizes in case the item minimum size has
+    // changed since the previous layout, or the item has been hidden using
+    // wxSizer::Show(). If all the items in a row/column are hidden, the final
+    // dimension of the row/column will be -1, indicating that the column
+    // itself is hidden.
+    m_rowHeights.assign(nrows, -1);
+    m_colWidths.assign(ncols, -1);
+
+    // n is the index of the item in left-to-right top-to-bottom order
+    size_t n = 0;
+    for ( wxSizerItemList::iterator i = m_children.begin();
+          i != m_children.end();
+          ++i, ++n )
+    {
+        wxSizerItem * const item = *i;
+        if ( item->IsShown() )
+        {
+            const wxSize sz(item->CalcMin());
 
 
-    m_rowHeights.SetCount(nrows);
-    m_colWidths.SetCount(ncols);
+            const int row = n / ncols;
+            const int col = n % ncols;
 
 
-    wxSizerItemList::Node   *node = m_children.GetFirst();
+            if ( sz.y > m_rowHeights[row] )
+                m_rowHeights[row] = sz.y;
+            if ( sz.x > m_colWidths[col] )
+                m_colWidths[col] = sz.x;
+        }
+    }
 
 
-    i = 0;
-    while (node)
-    {
-        wxSizerItem    *item = node->GetData();
-        wxSize          sz( item->CalcMin() );
-        int             row = i / ncols;
-        int             col = i % ncols;
+    AdjustForFlexDirection();
 
 
-        m_rowHeights[ row ] = wxMax( sz.y, m_rowHeights[ row ] );
-        m_colWidths[ col ] = wxMax( sz.x, m_colWidths[ col ] );
+    m_calculatedMinSize = wxSize(SumArraySizes(m_colWidths, m_hgap),
+                                 SumArraySizes(m_rowHeights, m_vgap));
 
 
-        node = node->GetNext();
-        i++;
-    }
+    return m_calculatedMinSize;
+}
 
 
-    // the logic above works when we resize flexibly in both directions but
-    // maybe this is not the case
+void wxFlexGridSizer::AdjustForFlexDirection()
+{
+    // the logic in CalcMin works when we resize flexibly in both directions
+    // but maybe this is not the case
     if ( m_flexDirection != wxBOTH )
     {
         // select the array corresponding to the direction in which we do *not*
     if ( m_flexDirection != wxBOTH )
     {
         // select the array corresponding to the direction in which we do *not*
@@ -1190,11 +1480,12 @@ wxSize wxFlexGridSizer::CalcMin()
         wxArrayInt& array = m_flexDirection == wxVERTICAL ? m_colWidths
                                                           : m_rowHeights;
 
         wxArrayInt& array = m_flexDirection == wxVERTICAL ? m_colWidths
                                                           : m_rowHeights;
 
-        const int count = array.GetCount();
+        const size_t count = array.GetCount();
 
         // find the largest value in this array
 
         // find the largest value in this array
-        int n,
-            largest = 0;
+        size_t n;
+        int largest = 0;
+
         for ( n = 0; n < count; ++n )
         {
             if ( array[n] > largest )
         for ( n = 0; n < count; ++n )
         {
             if ( array[n] > largest )
@@ -1204,31 +1495,125 @@ wxSize wxFlexGridSizer::CalcMin()
         // and now fill it with the largest value
         for ( n = 0; n < count; ++n )
         {
         // and now fill it with the largest value
         for ( n = 0; n < count; ++n )
         {
-            array[n] = largest;
+            // don't touch hidden rows
+            if ( array[n] != -1 )
+                array[n] = largest;
         }
     }
         }
     }
+}
+
+// helper of AdjustForGrowables() which is called for rows/columns separately
+//
+// parameters:
+//      delta: the extra space, we do nothing unless it's positive
+//      growable: indices or growable rows/cols in sizes array
+//      sizes: the height/widths of rows/cols to adjust
+//      proportions: proportions of the growable rows/cols or NULL if they all
+//                   should be assumed to have proportion of 1
+static void
+DoAdjustForGrowables(int delta,
+                     const wxArrayInt& growable,
+                     wxArrayInt& sizes,
+                     const wxArrayInt *proportions)
+{
+    if ( delta <= 0 )
+        return;
+
+    // total sum of proportions of all non-hidden rows
+    int sum_proportions = 0;
+
+    // number of currently shown growable rows
+    int num = 0;
+
+    const int max_idx = sizes.size();
+
+    const size_t count = growable.size();
+    size_t idx;
+    for ( idx = 0; idx < count; idx++ )
+    {
+        // Since the number of rows/columns can change as items are
+        // inserted/deleted, we need to verify at runtime that the
+        // requested growable rows/columns are still valid.
+        if ( growable[idx] >= max_idx )
+            continue;
+
+        // If all items in a row/column are hidden, that row/column will
+        // have a dimension of -1.  This causes the row/column to be
+        // hidden completely.
+        if ( sizes[growable[idx]] == -1 )
+            continue;
+
+        if ( proportions )
+            sum_proportions += (*proportions)[idx];
+
+        num++;
+    }
+
+    if ( !num )
+        return;
 
 
+    // the remaining extra free space, adjusted during each iteration
+    for ( idx = 0; idx < count; idx++ )
+    {
+        if ( growable[idx] >= max_idx )
+            continue;
 
 
-    int width = 0;
-    for (int col = 0; col < ncols; col++)
-        width += m_colWidths[ col ];
+        if ( sizes[ growable[idx] ] == -1 )
+            continue;
 
 
-    int height = 0;
-    for (int row = 0; row < nrows; row++)
-        height += m_rowHeights[ row ];
+        int cur_delta;
+        if ( sum_proportions == 0 )
+        {
+            // no growable rows -- divide extra space evenly among all
+            cur_delta = delta/num;
+            num--;
+        }
+        else // allocate extra space proportionally
+        {
+            const int cur_prop = (*proportions)[idx];
+            cur_delta = (delta*cur_prop)/sum_proportions;
+            sum_proportions -= cur_prop;
+        }
 
 
-    return wxSize( width +  (ncols-1) * m_hgap,
-                   height + (nrows-1) * m_vgap);
+        sizes[growable[idx]] += cur_delta;
+        delta -= cur_delta;
+    }
 }
 
 }
 
-void wxFlexGridSizer::AddGrowableRow( size_t idx, int proportion )
+void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz)
 {
 {
-    m_growableRows.Add( idx );
-    m_growableRowsProportions.Add( proportion );
+    if ( (m_flexDirection & wxVERTICAL) || (m_growMode != wxFLEX_GROWMODE_NONE) )
+    {
+        // pass NULL instead of proportions if the grow mode is ALL as we
+        // should treat all rows as having proportion of 1 then
+        DoAdjustForGrowables
+        (
+            sz.y - m_calculatedMinSize.y,
+            m_growableRows,
+            m_rowHeights,
+            m_growMode == wxFLEX_GROWMODE_SPECIFIED ? &m_growableRowsProportions
+                                                    : NULL
+        );
+    }
+
+    if ( (m_flexDirection & wxHORIZONTAL) || (m_growMode != wxFLEX_GROWMODE_NONE) )
+    {
+        DoAdjustForGrowables
+        (
+            sz.x - m_calculatedMinSize.x,
+            m_growableCols,
+            m_colWidths,
+            m_growMode == wxFLEX_GROWMODE_SPECIFIED ? &m_growableColsProportions
+                                                    : NULL
+        );
+    }
 }
 
 }
 
-void wxFlexGridSizer::RemoveGrowableRow( size_t WXUNUSED(idx) )
+
+void wxFlexGridSizer::AddGrowableRow( size_t idx, int proportion )
 {
 {
+    m_growableRows.Add( idx );
+    m_growableRowsProportions.Add( proportion );
 }
 
 void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
 }
 
 void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
@@ -1237,194 +1622,143 @@ void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
     m_growableColsProportions.Add( proportion );
 }
 
     m_growableColsProportions.Add( proportion );
 }
 
-void wxFlexGridSizer::RemoveGrowableCol( size_t WXUNUSED(idx) )
+// helper function for RemoveGrowableCol/Row()
+static void
+DoRemoveFromArrays(size_t idx, wxArrayInt& items, wxArrayInt& proportions)
 {
 {
+    const size_t count = items.size();
+    for ( size_t n = 0; n < count; n++ )
+    {
+        if ( (size_t)items[n] == idx )
+        {
+            items.RemoveAt(n);
+            proportions.RemoveAt(n);
+            return;
+        }
+    }
+
+    wxFAIL_MSG( _T("column/row is already not growable") );
 }
 
 }
 
-//---------------------------------------------------------------------------
-// wxBoxSizer
-//---------------------------------------------------------------------------
+void wxFlexGridSizer::RemoveGrowableCol( size_t idx )
+{
+    DoRemoveFromArrays(idx, m_growableCols, m_growableColsProportions);
+}
 
 
-wxBoxSizer::wxBoxSizer( int orient )
-    : m_orient( orient )
+void wxFlexGridSizer::RemoveGrowableRow( size_t idx )
 {
 {
+    DoRemoveFromArrays(idx, m_growableRows, m_growableRowsProportions);
 }
 
 }
 
+//---------------------------------------------------------------------------
+// wxBoxSizer
+//---------------------------------------------------------------------------
+
 void wxBoxSizer::RecalcSizes()
 {
 void wxBoxSizer::RecalcSizes()
 {
-    if (m_children.GetCount() == 0)
+    if ( m_children.empty() )
         return;
 
         return;
 
-    int delta = 0;
-    int extra = 0;
-    if (m_stretchable)
-    {
-        if (m_orient == wxHORIZONTAL)
-        {
-            delta = (m_size.x - m_fixedWidth) / m_stretchable;
-            extra = (m_size.x - m_fixedWidth) % m_stretchable;
-        }
-        else
-        {
-            delta = (m_size.y - m_fixedHeight) / m_stretchable;
-            extra = (m_size.y - m_fixedHeight) % m_stretchable;
-        }
-    }
+    // the amount of free space which we should redistribute among the
+    // stretchable items (i.e. those with non zero proportion)
+    int delta = SizeInMajorDir(m_size) - SizeInMajorDir(m_minSize);
 
 
-    wxPoint pt( m_position );
+    // the position at which we put the next child
+    wxPoint pt(m_position);
 
 
-    wxSizerItemList::Node   *node = m_children.GetFirst();
-    while (node)
+    const wxCoord totalMinorSize = SizeInMinorDir(m_size);
+
+    int totalProportion = m_totalProportion;
+    for ( wxSizerItemList::const_iterator i = m_children.begin();
+          i != m_children.end();
+          ++i )
     {
     {
-        wxSizerItem     *item = node->GetData();
+        wxSizerItem * const item = *i;
 
 
-        if (item->IsShown())
-        {
-            int weight = 1;
-            if (item->GetProportion())
-                weight = item->GetProportion();
+        if ( !item->IsShown() )
+            continue;
 
 
-            wxSize size( item->CalcMin() );
+        const wxSize sizeThis(item->GetMinSizeWithBorder());
 
 
-            if (m_orient == wxVERTICAL)
-            {
-                wxCoord height = size.y;
-                if (item->GetProportion())
-                {
-                    height = (delta * weight) + extra;
-                    extra = 0; // only the first item will get the remainder as extra size
-                }
 
 
-                wxPoint child_pos( pt );
-                wxSize  child_size( wxSize( size.x, height) );
+        // adjust the size in the major direction using the proportion
+        wxCoord majorSize = SizeInMajorDir(sizeThis);
+        const int propItem = item->GetProportion();
+        if ( propItem )
+        {
+            const int deltaItem = (delta * propItem) / totalProportion;
 
 
-                if (item->GetFlag() & (wxEXPAND | wxSHAPED))
-                    child_size.x = m_size.x;
-                else if (item->GetFlag() & wxALIGN_RIGHT)
-                    child_pos.x += m_size.x - size.x;
-                else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
-                // XXX wxCENTER is added for backward compatibility;
-                //     wxALIGN_CENTER should be used in new code
-                    child_pos.x += (m_size.x - size.x) / 2;
+            majorSize += deltaItem;
 
 
-                item->SetDimension( child_pos, child_size );
+            delta -= deltaItem;
+            totalProportion -= propItem;
+        }
 
 
-                pt.y += height;
-            }
-            else
-            {
-                wxCoord width = size.x;
-                if (item->GetProportion())
-                {
-                    width = (delta * weight) + extra;
-                    extra = 0; // only the first item will get the remainder as extra size
-                }
 
 
-                wxPoint child_pos( pt );
-                wxSize  child_size( wxSize(width, size.y) );
+        // apply the alignment in the minor direction
+        wxPoint posChild(pt);
 
 
-                if (item->GetFlag() & (wxEXPAND | wxSHAPED))
-                    child_size.y = m_size.y;
-                else if (item->GetFlag() & wxALIGN_BOTTOM)
-                    child_pos.y += m_size.y - size.y;
-                else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
-                // XXX wxCENTER is added for backward compatibility;
-                //     wxALIGN_CENTER should be used in new code
-                    child_pos.y += (m_size.y - size.y) / 2;
+        wxCoord minorSize = SizeInMinorDir(sizeThis);
+        const int flag = item->GetFlag();
+        if ( flag & (wxEXPAND | wxSHAPED) )
+        {
+            minorSize = totalMinorSize;
+        }
+        else if ( flag & (IsVertical() ? wxALIGN_RIGHT : wxALIGN_BOTTOM) )
+        {
+            PosInMinorDir(posChild) += totalMinorSize - minorSize;
+        }
+        // NB: wxCENTRE is used here only for backwards compatibility,
+        //     wxALIGN_CENTRE should be used in new code
+        else if ( flag & (wxCENTER | wxALIGN_CENTRE) )
+        {
+            PosInMinorDir(posChild) += (totalMinorSize - minorSize) / 2;
+        }
 
 
-                item->SetDimension( child_pos, child_size );
 
 
-                pt.x += width;
-            }
+        // apply RTL adjustment for horizontal sizers:
+        if ( !IsVertical() && m_containingWindow )
+        {
+            posChild.x = m_containingWindow->AdjustForLayoutDirection
+                                             (
+                                                posChild.x,
+                                                majorSize,
+                                                m_size.x
+                                             );
         }
 
         }
 
-        node = node->GetNext();
+        // finally set size of this child and advance to the next one
+        item->SetDimension(posChild, SizeFromMajorMinor(majorSize, minorSize));
+
+        PosInMajorDir(pt) += majorSize;
     }
 }
 
 wxSize wxBoxSizer::CalcMin()
 {
     }
 }
 
 wxSize wxBoxSizer::CalcMin()
 {
-    if (m_children.GetCount() == 0)
-        return wxSize(10,10);
-
-    m_stretchable = 0;
-    m_minWidth = 0;
-    m_minHeight = 0;
-    m_fixedWidth = 0;
-    m_fixedHeight = 0;
+    m_totalProportion = 0;
+    m_minSize = wxSize(0, 0);
 
 
-    // Find how long each stretch unit needs to be
-    int                      stretchSize = 1;
-    wxSizerItemList::Node   *node = m_children.GetFirst();
-
-    while (node)
+    // calculate the minimal sizes for all items and count sum of proportions
+    for ( wxSizerItemList::const_iterator i = m_children.begin();
+          i != m_children.end();
+          ++i )
     {
     {
-        wxSizerItem     *item = node->GetData();
+        wxSizerItem * const item = *i;
 
 
-        if (item->IsShown() && item->GetProportion() != 0)
-        {
-            int stretch = item->GetProportion();
-            wxSize size( item->CalcMin() );
-            int sizePerStretch;
-            // Integer division rounded up is (a + b - 1) / b
-            if (m_orient == wxHORIZONTAL)
-                sizePerStretch = ( size.x + stretch - 1 ) / stretch;
-            else
-                sizePerStretch = ( size.y + stretch - 1 ) / stretch;
-            if (sizePerStretch > stretchSize)
-                stretchSize = sizePerStretch;
-        }
-        node = node->GetNext();
-    }
-
-    // Calculate overall minimum size
-    node = m_children.GetFirst();
-    while (node)
-    {
-        wxSizerItem     *item = node->GetData();
-
-        if (item->IsShown())
-        {
-            m_stretchable += item->GetProportion();
+        if ( !item->IsShown() )
+            continue;
 
 
-            wxSize size( item->CalcMin() );
-            if (item->GetProportion() != 0)
-            {
-                if (m_orient == wxHORIZONTAL)
-                    size.x = stretchSize * item->GetProportion();
-                else
-                    size.y = stretchSize * item->GetProportion();
-            }
+        const wxSize sizeMinThis = item->CalcMin();
 
 
-            if (m_orient == wxHORIZONTAL)
-            {
-                m_minWidth += size.x;
-                m_minHeight = wxMax( m_minHeight, size.y );
-            }
-            else
-            {
-                m_minHeight += size.y;
-                m_minWidth = wxMax( m_minWidth, size.x );
-            }
+        SizeInMajorDir(m_minSize) += SizeInMajorDir(sizeMinThis);
+        if ( SizeInMinorDir(sizeMinThis) > SizeInMinorDir(m_minSize) )
+            SizeInMinorDir(m_minSize) = SizeInMinorDir(sizeMinThis);
 
 
-            if (item->GetProportion() == 0)
-            {
-                if (m_orient == wxVERTICAL)
-                {
-                    m_fixedHeight += size.y;
-                    m_fixedWidth = wxMax( m_fixedWidth, size.x );
-                }
-                else
-                {
-                    m_fixedWidth += size.x;
-                    m_fixedHeight = wxMax( m_fixedHeight, size.y );
-                }
-            }
-        }
-        node = node->GetNext();
+        m_totalProportion += item->GetProportion();
     }
 
     }
 
-    return wxSize( m_minWidth, m_minHeight );
+    return m_minSize;
 }
 
 //---------------------------------------------------------------------------
 }
 
 //---------------------------------------------------------------------------
@@ -1434,10 +1768,27 @@ wxSize wxBoxSizer::CalcMin()
 #if wxUSE_STATBOX
 
 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
 #if wxUSE_STATBOX
 
 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
-    : wxBoxSizer( orient )
-    , m_staticBox( box )
+    : wxBoxSizer( orient ),
+      m_staticBox( box )
 {
     wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
 {
     wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
+
+    // do this so that our Detach() is called if the static box is destroyed
+    // before we are
+    m_staticBox->SetContainingSizer(this);
+}
+
+wxStaticBoxSizer::wxStaticBoxSizer(int orient, wxWindow *win, const wxString& s)
+                : wxBoxSizer(orient),
+                  m_staticBox(new wxStaticBox(win, wxID_ANY, s))
+{
+    // same as above
+    m_staticBox->SetContainingSizer(this);
+}
+
+wxStaticBoxSizer::~wxStaticBoxSizer()
+{
+    delete m_staticBox;
 }
 
 static void GetStaticBoxBorders( wxStaticBox *box,
 }
 
 static void GetStaticBoxBorders( wxStaticBox *box,
@@ -1446,18 +1797,7 @@ static void GetStaticBoxBorders( wxStaticBox *box,
 {
     // this has to be done platform by platform as there is no way to
     // guess the thickness of a wxStaticBox border
 {
     // this has to be done platform by platform as there is no way to
     // guess the thickness of a wxStaticBox border
-#ifdef __WXCOCOA__
-    box->GetBordersForSizer(borderTop,borderOther);
-#else // __WXCOCOA__
-#ifdef __WXGTK__
-    if ( box->GetLabel().IsEmpty() )
-        *borderTop = 5;
-    else
-#endif // __WXGTK__
-        *borderTop = box->GetCharHeight();
-
-    *borderOther = 5;
-#endif // __WXCOCOA__
+    box->GetBordersForSizer(borderTop, borderOther);
 }
 
 void wxStaticBoxSizer::RecalcSizes()
 }
 
 void wxStaticBoxSizer::RecalcSizes()
@@ -1492,62 +1832,211 @@ wxSize wxStaticBoxSizer::CalcMin()
     return ret;
 }
 
     return ret;
 }
 
+void wxStaticBoxSizer::ShowItems( bool show )
+{
+    m_staticBox->Show( show );
+    wxBoxSizer::ShowItems( show );
+}
+
+bool wxStaticBoxSizer::Detach( wxWindow *window )
+{
+    // avoid deleting m_staticBox in our dtor if it's being detached from the
+    // sizer (which can happen because it's being already destroyed for
+    // example)
+    if ( window == m_staticBox )
+    {
+        m_staticBox = NULL;
+        return true;
+    }
+
+    return wxSizer::Detach( window );
+}
+
 #endif // wxUSE_STATBOX
 
 #endif // wxUSE_STATBOX
 
-//---------------------------------------------------------------------------
-// wxNotebookSizer
-//---------------------------------------------------------------------------
+#if wxUSE_BUTTON
+
+wxStdDialogButtonSizer::wxStdDialogButtonSizer()
+    : wxBoxSizer(wxHORIZONTAL)
+{
+    // Vertical buttons with lots of space on either side
+    // looks rubbish on WinCE, so let's not do this for now.
+    // If we are going to use vertical buttons, we should
+    // put the sizer to the right of other controls in the dialog,
+    // and that's beyond the scope of this sizer.
+#ifndef __WXWINCE__
+    bool is_pda = (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA);
+    // If we have a PDA screen, put yes/no button over
+    // all other buttons, otherwise on the left side.
+    if (is_pda)
+        m_orient = wxVERTICAL;
+#endif
 
 
-#if wxUSE_NOTEBOOK
+    m_buttonAffirmative = NULL;
+    m_buttonApply = NULL;
+    m_buttonNegative = NULL;
+    m_buttonCancel = NULL;
+    m_buttonHelp = NULL;
+}
 
 
-wxNotebookSizer::wxNotebookSizer( wxNotebook *nb )
-    : m_notebook( nb )
+void wxStdDialogButtonSizer::AddButton(wxButton *mybutton)
 {
 {
-    wxASSERT_MSG( nb, wxT("wxNotebookSizer needs a notebook") );
+    switch (mybutton->GetId())
+    {
+        case wxID_OK:
+        case wxID_YES:
+        case wxID_SAVE:
+            m_buttonAffirmative = mybutton;
+            break;
+        case wxID_APPLY:
+            m_buttonApply = mybutton;
+            break;
+        case wxID_NO:
+            m_buttonNegative = mybutton;
+            break;
+        case wxID_CANCEL:
+        case wxID_CLOSE:
+            m_buttonCancel = mybutton;
+            break;
+        case wxID_HELP:
+        case wxID_CONTEXT_HELP:
+            m_buttonHelp = mybutton;
+            break;
+        default:
+            break;
+    }
 }
 
 }
 
-void wxNotebookSizer::RecalcSizes()
+void wxStdDialogButtonSizer::SetAffirmativeButton( wxButton *button )
 {
 {
-    m_notebook->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
+    m_buttonAffirmative = button;
 }
 
 }
 
-wxSize wxNotebookSizer::CalcMin()
+void wxStdDialogButtonSizer::SetNegativeButton( wxButton *button )
 {
 {
-    wxSize sizeBorder = m_notebook->CalcSizeFromPage(wxSize(0, 0));
+    m_buttonNegative = button;
+}
 
 
-    sizeBorder.x += 5;
-    sizeBorder.y += 5;
+void wxStdDialogButtonSizer::SetCancelButton( wxButton *button )
+{
+    m_buttonCancel = button;
+}
 
 
-    if (m_notebook->GetChildren().GetCount() == 0)
-    {
-        return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
-    }
+void wxStdDialogButtonSizer::Realize()
+{
+#ifdef __WXMAC__
+        Add(0, 0, 0, wxLEFT, 6);
+        if (m_buttonHelp)
+            Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 6);
 
 
-    int maxX = 0;
-    int maxY = 0;
+        if (m_buttonNegative){
+            // HIG POLICE BULLETIN - destructive buttons need extra padding
+            // 24 pixels on either side
+            Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 12);
+        }
 
 
-    wxWindowList::Node *node = m_notebook->GetChildren().GetFirst();
-    while (node)
-    {
-        wxWindow *item = node->GetData();
-        wxSizer *itemsizer = item->GetSizer();
+        // extra whitespace between help/negative and cancel/ok buttons
+        Add(0, 0, 1, wxEXPAND, 0);
 
 
-        if (itemsizer)
-        {
-            wxSize subsize( itemsizer->CalcMin() );
+        if (m_buttonCancel){
+            Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 6);
+            // Cancel or help should be default
+            // m_buttonCancel->SetDefaultButton();
+        }
 
 
-            if (subsize.x > maxX)
-                maxX = subsize.x;
-            if (subsize.y > maxY)
-                maxY = subsize.y;
+        // Ugh, Mac doesn't really have apply dialogs, so I'll just
+        // figure the best place is between Cancel and OK
+        if (m_buttonApply)
+            Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 6);
+
+        if (m_buttonAffirmative){
+            Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT, 6);
+
+            if (m_buttonAffirmative->GetId() == wxID_SAVE){
+                // these buttons have set labels under Mac so we should use them
+                m_buttonAffirmative->SetLabel(_("Save"));
+                if (m_buttonNegative)
+                    m_buttonNegative->SetLabel(_("Don't Save"));
+            }
         }
 
         }
 
-        node = node->GetNext();
-    }
+        // Extra space around and at the right
+        Add(12, 24);
+#elif defined(__WXGTK20__)
+        Add(0, 0, 0, wxLEFT, 9);
+        if (m_buttonHelp)
+            Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
 
 
-    return wxSize( maxX, maxY ) + sizeBorder;
-}
+        // extra whitespace between help and cancel/ok buttons
+        Add(0, 0, 1, wxEXPAND, 0);
+
+        if (m_buttonNegative){
+            Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
+        }
 
 
-#endif // wxUSE_NOTEBOOK
+        // according to HIG, in explicit apply windows the order is: 
+        // [ Help                     Apply   Cancel   OK ]
+        if (m_buttonApply)
+            Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
+
+        if (m_buttonCancel){
+            Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
+            // Cancel or help should be default
+            // m_buttonCancel->SetDefaultButton();
+        }
+
+        if (m_buttonAffirmative)
+            Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT, 6);
+#elif defined(__WXMSW__)
+        // Windows
+
+        // right-justify buttons
+        Add(0, 0, 1, wxEXPAND, 0);
+
+        if (m_buttonAffirmative){
+            Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonAffirmative->ConvertDialogToPixels(wxSize(2, 0)).x);
+        }
+
+        if (m_buttonNegative){
+            Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonNegative->ConvertDialogToPixels(wxSize(2, 0)).x);
+        }
+
+        if (m_buttonCancel){
+            Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonCancel->ConvertDialogToPixels(wxSize(2, 0)).x);
+        }
+        if (m_buttonApply)
+            Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonApply->ConvertDialogToPixels(wxSize(2, 0)).x);
+
+        if (m_buttonHelp)
+            Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonHelp->ConvertDialogToPixels(wxSize(2, 0)).x);
+#else
+        // GTK+1 and any other platform
+
+        // Add(0, 0, 0, wxLEFT, 5); // Not sure what this was for but it unbalances the dialog
+        if (m_buttonHelp)
+            Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonHelp->ConvertDialogToPixels(wxSize(4, 0)).x);
+
+        // extra whitespace between help and cancel/ok buttons
+        Add(0, 0, 1, wxEXPAND, 0);
+
+        if (m_buttonApply)
+            Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonApply->ConvertDialogToPixels(wxSize(4, 0)).x);
+
+        if (m_buttonAffirmative){
+            Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonAffirmative->ConvertDialogToPixels(wxSize(4, 0)).x);
+        }
+
+        if (m_buttonNegative){
+            Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonNegative->ConvertDialogToPixels(wxSize(4, 0)).x);
+        }
+
+        if (m_buttonCancel){
+            Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonCancel->ConvertDialogToPixels(wxSize(4, 0)).x);
+            // Cancel or help should be default
+            // m_buttonCancel->SetDefaultButton();
+        }
+
+#endif
+}
 
 
-// vi:sts=4:sw=4:et
+#endif // wxUSE_BUTTON