]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/sizer.cpp
avoid conflict between wxBookCtrlBase::DoSetSelection() and the derived classes;...
[wxWidgets.git] / src / common / sizer.cpp
index b59463514639771a5578fbe1906a7ea69316c1ff..a691f6431c5af175f8741d922e325819d515c421 100644 (file)
     #pragma hdrstop
 #endif
 
+#include "wx/sizer.h"
+
 #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/sizer.h"
-#include "wx/utils.h"
-#include "wx/statbox.h"
-#include "wx/settings.h"
 #include "wx/listimpl.cpp"
 
 #if WXWIN_COMPATIBILITY_2_4
@@ -351,6 +354,11 @@ void wxSizerItem::SetDimension( const wxPoint& pos_, const wxSize& size_ )
         size.y -= m_border;
     }
 
+    if (size.x < 0)
+        size.x = 0;
+    if (size.y < 0)
+        size.y = 0;
+
     m_rect = wxRect(pos, size);
 
     switch ( m_kind )
@@ -505,6 +513,29 @@ wxSizerItem* wxSizer::Insert( size_t index, wxSizerItem *item )
     return item;
 }
 
+void wxSizer::SetContainingWindow(wxWindow *win)
+{
+    if ( win == m_containingWindow )
+        return;
+
+    m_containingWindow = win;
+
+    // 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 ( sizer )
+        {
+            sizer->SetContainingWindow(win);
+        }
+    }
+}
+
 #if WXWIN_COMPATIBILITY_2_6
 bool wxSizer::Remove( wxWindow *window )
 {
@@ -620,6 +651,80 @@ bool wxSizer::Detach( int index )
     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->GetWindow()->SetContainingSizer( NULL );
+            item->SetWindow(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)
+        {
+            wxSizer *old = item->GetSizer();
+            item->SetSizer(newsz);
+            delete old;
+            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
@@ -1152,7 +1257,7 @@ wxSize wxGridSizer::CalcMin()
 {
     int nrows, ncols;
     if ( CalcRowsCols(nrows, ncols) == 0 )
-        return wxSize(10, 10);
+        return wxSize();
 
     // Find the max width and height for any component
     int w = 0;
@@ -1277,7 +1382,7 @@ wxSize wxFlexGridSizer::CalcMin()
 
     // Number of rows/columns can change as items are added or removed.
     if ( !CalcRowsCols(nrows, ncols) )
-        return wxSize(10, 10);
+        return wxSize();
 
     m_rowHeights.SetCount(nrows);
     m_colWidths.SetCount(ncols);
@@ -1480,20 +1585,38 @@ void wxFlexGridSizer::AddGrowableRow( size_t idx, int proportion )
     m_growableRowsProportions.Add( proportion );
 }
 
-void wxFlexGridSizer::RemoveGrowableRow( size_t idx )
-{
-    m_growableRows.Remove( idx );
-}
-
 void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
 {
     m_growableCols.Add( idx );
     m_growableColsProportions.Add( proportion );
 }
 
+// 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") );
+}
+
 void wxFlexGridSizer::RemoveGrowableCol( size_t idx )
 {
-    m_growableCols.Remove( idx );
+    DoRemoveFromArrays(idx, m_growableCols, m_growableColsProportions);
+}
+
+void wxFlexGridSizer::RemoveGrowableRow( size_t idx )
+{
+    DoRemoveFromArrays(idx, m_growableRows, m_growableRowsProportions);
 }
 
 //---------------------------------------------------------------------------
@@ -1578,6 +1701,16 @@ void wxBoxSizer::RecalcSizes()
                 //     wxALIGN_CENTER should be used in new code
                     child_pos.y += (m_size.y - size.y) / 2;
 
+                if ( m_containingWindow )
+                {
+                    child_pos.x = m_containingWindow->AdjustForLayoutDirection
+                                                      (
+                                                        child_pos.x,
+                                                        width,
+                                                        m_size.x
+                                                      );
+                }
+
                 item->SetDimension( child_pos, child_size );
 
                 pt.x += width;
@@ -1591,7 +1724,7 @@ void wxBoxSizer::RecalcSizes()
 wxSize wxBoxSizer::CalcMin()
 {
     if (m_children.GetCount() == 0)
-        return wxSize(10,10);
+        return wxSize();
 
     m_stretchable = 0;
     m_minWidth = 0;
@@ -1697,16 +1830,27 @@ wxSize wxBoxSizer::CalcMin()
 #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") );
+
+    // 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,
@@ -1756,6 +1900,20 @@ void wxStaticBoxSizer::ShowItems( bool 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
 
 #if wxUSE_BUTTON