]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/wincmn.cpp
applying patch, closes #13045
[wxWidgets.git] / src / common / wincmn.cpp
index 031712592b76b163131661d4b449506a7e2a1553..ff653cb8309226b19215708bde9456183bde331a 100644 (file)
@@ -620,20 +620,13 @@ void wxWindowBase::DoCentre(int dir)
 // fits the window around the children
 void wxWindowBase::Fit()
 {
-    if ( !GetChildren().empty() )
-    {
-        SetSize(GetBestSize());
-    }
-    //else: do nothing if we have no children
+    SetSize(GetBestSize());
 }
 
 // fits virtual size (ie. scrolled area etc.) around children
 void wxWindowBase::FitInside()
 {
-    if ( GetChildren().GetCount() > 0 )
-    {
-        SetVirtualSize( GetBestVirtualSize() );
-    }
+    SetVirtualSize( GetBestVirtualSize() );
 }
 
 // On Mac, scrollbars are explicitly children.
@@ -906,14 +899,19 @@ wxSize wxWindowBase::GetBestSize() const
     // it to be used
     wxSize size = DoGetBestClientSize();
     if ( size != wxDefaultSize )
-    {
         size += DoGetBorderSize();
+    else
+        size = DoGetBestSize();
 
-        CacheBestSize(size);
-        return size;
-    }
+    // Ensure that the best size is at least as large as min size.
+    size.IncTo(GetMinSize());
+
+    // And not larger than max size.
+    size.DecToIfSpecified(GetMaxSize());
 
-    return DoGetBestSize();
+    // Finally cache result and return.
+    CacheBestSize(size);
+    return size;
 }
 
 int wxWindowBase::GetBestHeight(int width) const
@@ -938,12 +936,16 @@ void wxWindowBase::SetMinSize(const wxSize& minSize)
 {
     m_minWidth = minSize.x;
     m_minHeight = minSize.y;
+
+    InvalidateBestSize();
 }
 
 void wxWindowBase::SetMaxSize(const wxSize& maxSize)
 {
     m_maxWidth = maxSize.x;
     m_maxHeight = maxSize.y;
+
+    InvalidateBestSize();
 }
 
 void wxWindowBase::SetInitialSize(const wxSize& size)
@@ -1315,6 +1317,20 @@ void wxWindowBase::RemoveChild(wxWindowBase *child)
     child->SetParent(NULL);
 }
 
+void wxWindowBase::SetParent(wxWindowBase *parent)
+{
+    // This assert catches typos which may result in using "this" instead of
+    // "parent" when creating the window. This doesn't happen often but when it
+    // does the results are unpleasant because the program typically just
+    // crashes when due to a stack overflow or something similar and this
+    // assert doesn't cost much (OTOH doing a more general check that the
+    // parent is not one of our children would be more expensive and probably
+    // not worth it).
+    wxASSERT_MSG( parent != this, wxS("Can't use window as its own parent") );
+
+    m_parent = (wxWindow *)parent;
+}
+
 bool wxWindowBase::Reparent(wxWindowBase *newParent)
 {
     wxWindow *oldParent = GetParent();
@@ -1975,95 +1991,163 @@ void wxWindowBase::MakeModal(bool modal)
 }
 #endif // WXWIN_COMPATIBILITY_2_8
 
+#if wxUSE_VALIDATORS
+
+namespace
+{
+
+// This class encapsulates possibly recursive iteration on window children done
+// by Validate() and TransferData{To,From}Window() and allows to avoid code
+// duplication in all three functions.
+class ValidationTraverserBase
+{
+public:
+    wxEXPLICIT ValidationTraverserBase(wxWindowBase* win)
+        : m_win(static_cast<wxWindow*>(win))
+    {
+    }
+
+    // Traverse all the direct children calling OnDo() on them and also all
+    // grandchildren if wxWS_EX_VALIDATE_RECURSIVELY is used, calling
+    // OnRecurse() for them.
+    bool DoForAllChildren()
+    {
+        const bool recurse = m_win->HasExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
+
+        wxWindowList& children = m_win->GetChildren();
+        for ( wxWindowList::iterator i = children.begin();
+              i != children.end();
+              ++i )
+        {
+            wxWindow* const child = static_cast<wxWindow*>(*i);
+            wxValidator* const validator = child->GetValidator();
+            if ( validator && !OnDo(validator) )
+            {
+                return false;
+            }
+
+            // Notice that validation should never recurse into top level
+            // children, e.g. some other dialog which might happen to be
+            // currently shown.
+            if ( recurse && !child->IsTopLevel() && !OnRecurse(child) )
+            {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+protected:
+    // Called for each child, validator is guaranteed to be non-NULL.
+    virtual bool OnDo(wxValidator* validator) = 0;
+
+    // Called for each child if we need to recurse into its children.
+    virtual bool OnRecurse(wxWindow* child) = 0;
+
+
+    // The window whose children we're traversing.
+    wxWindow* const m_win;
+
+    wxDECLARE_NO_COPY_CLASS(ValidationTraverserBase);
+};
+
+} // anonymous namespace
+
+#endif // wxUSE_VALIDATORS
+
 bool wxWindowBase::Validate()
 {
 #if wxUSE_VALIDATORS
-    bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
-
-    wxWindowList::compatibility_iterator node;
-    for ( node = m_children.GetFirst(); node; node = node->GetNext() )
+    class ValidateTraverser : public ValidationTraverserBase
     {
-        wxWindowBase *child = node->GetData();
-        wxValidator *validator = child->GetValidator();
-        if ( validator && !validator->Validate((wxWindow *)this) )
+    public:
+        wxEXPLICIT ValidateTraverser(wxWindowBase* win)
+            : ValidationTraverserBase(win)
         {
-            return false;
         }
 
-        if ( recurse && !child->Validate() )
+        virtual bool OnDo(wxValidator* validator)
         {
-            return false;
+            return validator->Validate(m_win);
         }
-    }
-#endif // wxUSE_VALIDATORS
 
+        virtual bool OnRecurse(wxWindow* child)
+        {
+            return child->Validate();
+        }
+    };
+
+    return ValidateTraverser(this).DoForAllChildren();
+#else // !wxUSE_VALIDATORS
     return true;
+#endif // wxUSE_VALIDATORS/!wxUSE_VALIDATORS
 }
 
 bool wxWindowBase::TransferDataToWindow()
 {
 #if wxUSE_VALIDATORS
-    bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
-
-    wxWindowList::compatibility_iterator node;
-    for ( node = m_children.GetFirst(); node; node = node->GetNext() )
+    class DataToWindowTraverser : public ValidationTraverserBase
     {
-        wxWindowBase *child = node->GetData();
-        wxValidator *validator = child->GetValidator();
-        if ( validator && !validator->TransferToWindow() )
+    public:
+        wxEXPLICIT DataToWindowTraverser(wxWindowBase* win)
+            : ValidationTraverserBase(win)
         {
-            wxLogWarning(_("Could not transfer data to window"));
-#if wxUSE_LOG
-            wxLog::FlushActive();
-#endif // wxUSE_LOG
-
-            return false;
         }
 
-        if ( recurse )
+        virtual bool OnDo(wxValidator* validator)
         {
-            if ( !child->TransferDataToWindow() )
+            if ( !validator->TransferToWindow() )
             {
-                // warning already given
+                wxLogWarning(_("Could not transfer data to window"));
+#if wxUSE_LOG
+                wxLog::FlushActive();
+#endif // wxUSE_LOG
+
                 return false;
             }
+
+            return true;
         }
-    }
-#endif // wxUSE_VALIDATORS
 
+        virtual bool OnRecurse(wxWindow* child)
+        {
+            return child->TransferDataToWindow();
+        }
+    };
+
+    return DataToWindowTraverser(this).DoForAllChildren();
+#else // !wxUSE_VALIDATORS
     return true;
+#endif // wxUSE_VALIDATORS/!wxUSE_VALIDATORS
 }
 
 bool wxWindowBase::TransferDataFromWindow()
 {
 #if wxUSE_VALIDATORS
-    bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
-
-    wxWindowList::compatibility_iterator node;
-    for ( node = m_children.GetFirst(); node; node = node->GetNext() )
+    class DataFromWindowTraverser : public ValidationTraverserBase
     {
-        wxWindow *child = node->GetData();
-        wxValidator *validator = child->GetValidator();
-        if ( validator && !validator->TransferFromWindow() )
+    public:
+        DataFromWindowTraverser(wxWindowBase* win)
+            : ValidationTraverserBase(win)
         {
-            // nop warning here because the application is supposed to give
-            // one itself - we don't know here what might have gone wrongly
+        }
 
-            return false;
+        virtual bool OnDo(wxValidator* validator)
+        {
+            return validator->TransferFromWindow();
         }
 
-        if ( recurse )
+        virtual bool OnRecurse(wxWindow* child)
         {
-            if ( !child->TransferDataFromWindow() )
-            {
-                // warning already given
-                return false;
-            }
+            return child->TransferDataFromWindow();
         }
-    }
-#endif // wxUSE_VALIDATORS
+    };
 
+    return DataFromWindowTraverser(this).DoForAllChildren();
+#else // !wxUSE_VALIDATORS
     return true;
+#endif // wxUSE_VALIDATORS/!wxUSE_VALIDATORS
 }
 
 void wxWindowBase::InitDialog()
@@ -2247,7 +2331,7 @@ void wxWindowBase::UnsetConstraints(wxLayoutConstraints *c)
 {
     if ( c )
     {
-        if ( c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
+        if ( c->left.GetOtherWindow() && (c->left.GetOtherWindow() != this) )
             c->left.GetOtherWindow()->RemoveConstraintReference(this);
         if ( c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
             c->top.GetOtherWindow()->RemoveConstraintReference(this);