X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0b108d1006326e32f6734ef5c179b7ee7fa453e2..c437b3f4e47b74715a2f2385d4862972babd7802:/src/common/docview.cpp diff --git a/src/common/docview.cpp b/src/common/docview.cpp index db24f276be..c00db551ce 100644 --- a/src/common/docview.cpp +++ b/src/common/docview.cpp @@ -60,6 +60,7 @@ #include "wx/vector.h" #include "wx/scopedarray.h" #include "wx/scopedptr.h" +#include "wx/except.h" #if wxUSE_STD_IOSTREAM #include "wx/ioswrap.h" @@ -663,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(); @@ -774,11 +794,15 @@ wxDocTemplate::~wxDocTemplate() // Tries to dynamically construct an object of the right class. wxDocument *wxDocTemplate::CreateDocument(const wxString& path, long flags) { + // InitDocument() is supposed to delete the document object if its + // initialization fails so don't use wxScopedPtr<> here: this is fragile + // but unavoidable because the default implementation uses CreateView() + // which may -- or not -- create a wxView and if it does create it and its + // initialization fails then the view destructor will delete the document + // (via RemoveView()) and as we can't distinguish between the two cases we + // just have to assume that it always deletes it in case of failure wxDocument * const doc = DoCreateDocument(); - // VZ: this code doesn't delete doc if InitDocument() (i.e. doc->OnCreate()) - // fails, is this intentional? - return doc && InitDocument(doc, path, flags) ? doc : NULL; } @@ -1307,15 +1331,18 @@ wxDocument *wxDocManager::CreateDocument(const wxString& pathOrig, long flags) docNew->SetDocumentName(temp->GetDocumentName()); docNew->SetDocumentTemplate(temp); - // call the appropriate function depending on whether we're creating a new - // file or opening an existing one - if ( !(flags & wxDOC_NEW ? docNew->OnNewDocument() - : docNew->OnOpenDocument(path)) ) + wxTRY { - // Document is implicitly deleted by DeleteAllViews - docNew->DeleteAllViews(); - return NULL; + // call the appropriate function depending on whether we're creating a + // new file or opening an existing one + if ( !(flags & wxDOC_NEW ? docNew->OnNewDocument() + : docNew->OnOpenDocument(path)) ) + { + docNew->DeleteAllViews(); + return NULL; + } } + wxCATCH_ALL( docNew->DeleteAllViews(); throw; ) // add the successfully opened file to MRU, but only if we're going to be // able to reopen it successfully later which requires the template for @@ -1809,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; }