diff --git a/include/wx/aui/floatpane.h b/include/wx/aui/floatpane.h index 9bbf28c476..8c73605676 100644 --- a/include/wx/aui/floatpane.h +++ b/include/wx/aui/floatpane.h @@ -21,7 +21,6 @@ #if wxUSE_AUI #include "wx/frame.h" -#include "wx/weakref.h" #if defined( __WXMSW__ ) || defined( __WXMAC__ ) || defined( __WXGTK__ ) #include "wx/minifram.h" @@ -32,6 +31,8 @@ class WXDLLIMPEXP_AUI wxAuiFloatingFrame : public wxAuiFloatingFrameBaseClass { + friend class wxAuiManager; + public: wxAuiFloatingFrame(wxWindow* parent, wxAuiManager* owner_mgr, @@ -46,6 +47,7 @@ public: wxAuiManager* GetOwnerManager() const; protected: + void SetOwnerManager(wxAuiManager* owner_mgr); virtual void OnMoveStart(); virtual void OnMoving(const wxRect& window_rect, wxDirection dir); virtual void OnMoveFinished(); @@ -68,7 +70,7 @@ private: wxSize m_last_size; wxDirection m_lastDirection; - wxWeakRef m_owner_mgr; + wxAuiManager* m_owner_mgr; wxAuiManager m_mgr; #ifndef SWIG diff --git a/include/wx/aui/framemanager.h b/include/wx/aui/framemanager.h index 8b80a6d0bc..11f3b2508f 100644 --- a/include/wx/aui/framemanager.h +++ b/include/wx/aui/framemanager.h @@ -121,6 +121,7 @@ enum wxAuiPaneInsertLevel // forwards and array declarations +class WXDLLIMPEXP_FWD_AUI wxAuiFloatingFrame; class wxAuiDockUIPart; class wxAuiPaneButton; class wxAuiPaneInfo; @@ -133,6 +134,7 @@ WX_DECLARE_USER_EXPORTED_OBJARRAY(wxAuiDockInfo, wxAuiDockInfoArray, WXDLLIMPEXP WX_DECLARE_USER_EXPORTED_OBJARRAY(wxAuiDockUIPart, wxAuiDockUIPartArray, WXDLLIMPEXP_AUI); WX_DECLARE_USER_EXPORTED_OBJARRAY(wxAuiPaneButton, wxAuiPaneButtonArray, WXDLLIMPEXP_AUI); WX_DECLARE_USER_EXPORTED_OBJARRAY(wxAuiPaneInfo, wxAuiPaneInfoArray, WXDLLIMPEXP_AUI); +WX_DEFINE_USER_EXPORTED_ARRAY_PTR(wxAuiFloatingFrame*, wxAuiFloatingFramePtrArray, class WXDLLIMPEXP_AUI); WX_DEFINE_USER_EXPORTED_ARRAY_PTR(wxAuiPaneInfo*, wxAuiPaneInfoPtrArray, class WXDLLIMPEXP_AUI); WX_DEFINE_USER_EXPORTED_ARRAY_PTR(wxAuiDockInfo*, wxAuiDockInfoPtrArray, class WXDLLIMPEXP_AUI); #endif // SWIG @@ -419,8 +421,6 @@ public: -class WXDLLIMPEXP_FWD_AUI wxAuiFloatingFrame; - class WXDLLIMPEXP_AUI wxAuiManager : public wxEvtHandler { friend class wxAuiFloatingFrame; @@ -511,6 +511,12 @@ public: protected: + // Sometimes floating frames are deleted after wxAuiManager, so we need + // to clear m_owner_mgr in the floating frame to avoid a crash. To do so, + // we register frames with wxAuiManager so it can keep track. + void RegisterFloatingFrame(wxAuiFloatingFrame* frame); + void UnregisterFloatingFrame(wxAuiFloatingFrame* frame); + void UpdateHintWindowConfig(); void DoFrameLayout(); @@ -601,6 +607,7 @@ protected: wxAuiPaneInfoArray m_panes; // array of panes structures wxAuiDockInfoArray m_docks; // array of docks structures wxAuiDockUIPartArray m_uiparts; // array of UI parts (captions, buttons, etc) + wxAuiFloatingFramePtrArray m_floating_frames; // array of floating frames int m_action; // current mouse action wxPoint m_action_start; // position where the action click started diff --git a/src/aui/floatpane.cpp b/src/aui/floatpane.cpp index f98693a9d1..ab81810d61 100644 --- a/src/aui/floatpane.cpp +++ b/src/aui/floatpane.cpp @@ -73,9 +73,11 @@ wxAuiFloatingFrame::wxAuiFloatingFrame(wxWindow* parent, wxAuiFloatingFrame::~wxAuiFloatingFrame() { // if we do not do this, then we can crash... - if (m_owner_mgr && m_owner_mgr->m_action_window == this) + if(m_owner_mgr) { - m_owner_mgr->m_action_window = NULL; + if(m_owner_mgr->m_action_window == this) + m_owner_mgr->m_action_window = NULL; + m_owner_mgr->UnregisterFloatingFrame(this); } m_mgr.UnInit(); @@ -151,6 +153,11 @@ wxAuiManager* wxAuiFloatingFrame::GetOwnerManager() const return m_owner_mgr; } +void wxAuiFloatingFrame::SetOwnerManager(wxAuiManager* owner_mgr) +{ + // we want to allow for NULL here to avoid crashing in dtor + m_owner_mgr = owner_mgr; +} void wxAuiFloatingFrame::OnSize(wxSizeEvent& event) { diff --git a/src/aui/framemanager.cpp b/src/aui/framemanager.cpp index bdde5d3f32..b4ee254fd6 100644 --- a/src/aui/framemanager.cpp +++ b/src/aui/framemanager.cpp @@ -610,6 +610,17 @@ wxAuiManager::~wxAuiManager() } #endif + // We need to remove any reference to this wxAuiManager in any of the + // wxAuiFloatingFrames associated with this manager in case they haven't + // been deleted just yet. + // We need an array copy since Unregister removes the items. + wxAuiFloatingFramePtrArray array_copy = m_floating_frames; + int i, count = array_copy.GetCount(); + for (i = 0; i < count; ++i) + { + UnregisterFloatingFrame(array_copy.Item(i)); + } + delete m_art; } @@ -617,7 +628,9 @@ wxAuiManager::~wxAuiManager() wxAuiFloatingFrame* wxAuiManager::CreateFloatingFrame(wxWindow* parent, const wxAuiPaneInfo& pane_info) { - return new wxAuiFloatingFrame(parent, this, pane_info); + wxAuiFloatingFrame* frame = new wxAuiFloatingFrame(parent, this, pane_info); + RegisterFloatingFrame(frame); + return frame; } bool wxAuiManager::CanDockPanel(const wxAuiPaneInfo & WXUNUSED(p)) @@ -627,6 +640,37 @@ bool wxAuiManager::CanDockPanel(const wxAuiPaneInfo & WXUNUSED(p)) return !(wxGetKeyState(WXK_CONTROL) || wxGetKeyState(WXK_ALT)); } +// registers a floating frame with this manager (see header) +void wxAuiManager::RegisterFloatingFrame(wxAuiFloatingFrame* frame) +{ + frame->SetOwnerManager(this); + int i, count = m_floating_frames.GetCount(); + for (i = 0; i < count; ++i) + { + wxAuiFloatingFrame* f = m_floating_frames.Item(i); + if (f == frame) + // this frame is already registered + return; + } + m_floating_frames.Add(frame); +} + +// unregisters a floating frame from this manager (see header) +void wxAuiManager::UnregisterFloatingFrame(wxAuiFloatingFrame* frame) +{ + frame->SetOwnerManager(NULL); + int i, count = m_floating_frames.GetCount(); + for (i = 0; i < count; ++i) + { + wxAuiFloatingFrame* f = m_floating_frames.Item(i); + if (f == frame) + { + m_floating_frames.Remove(f); + return; + } + } +} + // GetPane() looks up a wxAuiPaneInfo structure based // on the supplied window pointer. Upon failure, GetPane() // returns an empty wxAuiPaneInfo, a condition which can be checked