From ada1ff0dbcd973c0a4630318599eb469dd6e3fb6 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 9 Mar 2009 19:53:49 +0000 Subject: [PATCH] close the associated frame if the view is deleted directly to avoid leaving zombie frames floating around git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@59455 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/docview.h | 20 +++++++++++--------- src/common/docview.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/include/wx/docview.h b/include/wx/docview.h index 0ff527c403..610dd0c6f6 100644 --- a/include/wx/docview.h +++ b/include/wx/docview.h @@ -248,10 +248,7 @@ public: // set the associated frame, it is used to reset its view when we're // destroyed - void SetDocChildFrame(wxDocChildFrameAnyBase *docChildFrame) - { - m_docChildFrame = docChildFrame; - } + void SetDocChildFrame(wxDocChildFrameAnyBase *docChildFrame); protected: // hook the document into event handlers chain here @@ -523,7 +520,8 @@ inline size_t wxDocManager::GetNoHistoryFiles() const class WXDLLIMPEXP_CORE wxDocChildFrameAnyBase { public: - wxDocChildFrameAnyBase(wxDocument *doc, wxView *view) + wxDocChildFrameAnyBase(wxDocument *doc, wxView *view, wxWindow *win) + : m_win(win) { m_childDocument = doc; m_childView = view; @@ -537,6 +535,8 @@ public: void SetDocument(wxDocument *doc) { m_childDocument = doc; } void SetView(wxView *view) { m_childView = view; } + wxWindow *GetWindow() const { return m_win; } + protected: // we're not a wxEvtHandler but we provide this wxEvtHandler-like function // which is called from TryBefore() of the derived classes to give our view @@ -554,6 +554,11 @@ protected: wxDocument* m_childDocument; wxView* m_childView; + // the associated window: having it here is not terribly elegant but it + // allows us to avoid having any virtual functions in this class + wxWindow * const m_win; + + wxDECLARE_NO_COPY_CLASS(wxDocChildFrameAnyBase); }; @@ -585,11 +590,8 @@ public: long style = wxDEFAULT_FRAME_STYLE, const wxString& name = wxFrameNameStr) : BaseClass(parent, id, title, pos, size, style, name), - wxDocChildFrameAnyBase(doc, view) + wxDocChildFrameAnyBase(doc, view, this) { - if ( view ) - view->SetFrame(this); - this->Connect(wxEVT_ACTIVATE, wxActivateEventHandler(wxDocChildFrameAny::OnActivate)); this->Connect(wxEVT_CLOSE_WINDOW, diff --git a/src/common/docview.cpp b/src/common/docview.cpp index 8262d0b362..c00db551ce 100644 --- a/src/common/docview.cpp +++ b/src/common/docview.cpp @@ -664,12 +664,31 @@ wxView::~wxView() // box which would result in an activation event for m_docChildFrame and so // could reactivate the view being destroyed -- unless we reset it first if ( m_docChildFrame && m_docChildFrame->GetView() == this ) + { + // prevent it from doing anything with us m_docChildFrame->SetView(NULL); + // it doesn't make sense to leave the frame alive if its associated + // view doesn't exist any more so unconditionally close it as well + // + // notice that we only get here if m_docChildFrame is non-NULL in the + // first place and it will be always NULL if we're deleted because our + // frame was closed, so this only catches the case of directly deleting + // the view, as it happens if its creation fails in wxDocTemplate:: + // CreateView() for example + m_docChildFrame->GetWindow()->Destroy(); + } + if ( m_viewDocument ) m_viewDocument->RemoveView(this); } +void wxView::SetDocChildFrame(wxDocChildFrameAnyBase *docChildFrame) +{ + SetFrame(docChildFrame ? docChildFrame->GetWindow() : NULL); + m_docChildFrame = docChildFrame; +} + bool wxView::TryBefore(wxEvent& event) { wxDocument * const doc = GetDocument(); @@ -1817,6 +1836,13 @@ bool wxDocChildFrameAnyBase::CloseView(wxCloseEvent& event) } m_childView->Activate(false); + + // it is important to reset m_childView frame pointer to NULL before + // deleting it because while normally it is the frame which deletes the + // view when it's closed, the view also closes the frame if it is + // deleted directly not by us as indicated by its doc child frame + // pointer still being set + m_childView->SetDocChildFrame(NULL); delete m_childView; m_childView = NULL; } -- 2.45.2