wxDECLARE_NO_COPY_CLASS(wxDocMDIParentFrame);
};
-/*
- * Use this instead of wxMDIChildFrame
- */
+// ----------------------------------------------------------------------------
+// An MDI document child frame: we need to define it as a class just for wxRTTI,
+// otherwise we could simply typedef it
+// ----------------------------------------------------------------------------
-class WXDLLIMPEXP_CORE wxDocMDIChildFrame: public wxMDIChildFrame
+typedef
+ wxDocChildFrameAny<wxMDIChildFrame, wxMDIParentFrame> wxDocMDIChildFrameBase;
+
+class WXDLLIMPEXP_CORE wxDocMDIChildFrame : public wxDocMDIChildFrameBase
{
public:
- wxDocMDIChildFrame();
- wxDocMDIChildFrame(wxDocument *doc, wxView *view, wxMDIParentFrame *frame, wxWindowID id,
- const wxString& title, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
- long type = wxDEFAULT_FRAME_STYLE, const wxString& name = wxFrameNameStr);
- virtual ~wxDocMDIChildFrame();
-
- bool Create(wxDocument *doc,
- wxView *view,
- wxMDIParentFrame *frame,
- wxWindowID id,
- const wxString& title,
- const wxPoint& pos = wxDefaultPosition,
- const wxSize& size = wxDefaultSize,
- long type = wxDEFAULT_FRAME_STYLE,
- const wxString& name = wxFrameNameStr);
-
- void OnActivate(wxActivateEvent& event);
- void OnCloseWindow(wxCloseEvent& event);
-
- inline wxDocument *GetDocument() const { return m_childDocument; }
- inline wxView *GetView(void) const { return m_childView; }
- inline void SetDocument(wxDocument *doc) { m_childDocument = doc; }
- inline void SetView(wxView *view) { m_childView = view; }
- bool Destroy() { m_childView = NULL; return wxMDIChildFrame::Destroy(); }
-
-protected:
- void Init();
-
- virtual bool TryBefore(wxEvent& event);
-
- wxDocument* m_childDocument;
- wxView* m_childView;
+ wxDocMDIChildFrame(wxDocument *doc,
+ wxView *view,
+ wxMDIParentFrame *parent,
+ wxWindowID id,
+ const wxString& title,
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize,
+ long style = wxDEFAULT_FRAME_STYLE,
+ const wxString& name = wxFrameNameStr)
+ : wxDocMDIChildFrameBase(doc, view,
+ parent, id, title, pos, size, style, name)
+ {
+ }
private:
- DECLARE_EVENT_TABLE()
DECLARE_CLASS(wxDocMDIChildFrame)
wxDECLARE_NO_COPY_CLASS(wxDocMDIChildFrame);
};
-#endif
- // wxUSE_MDI_ARCHITECTURE
+WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxDocMDIChildFrameBase )
+
+
+#endif // wxUSE_MDI_ARCHITECTURE
-#endif
- // _WX_DOCMDI_H_
+#endif // _WX_DOCMDI_H_
class WXDLLIMPEXP_FWD_CORE wxFileHistory;
class WXDLLIMPEXP_FWD_BASE wxConfigBase;
+class wxDocChildFrameAnyBase;
+
#if wxUSE_STD_IOSTREAM
#include "wx/iosfwrap.h"
#else
virtual wxPrintout *OnCreatePrintout();
#endif
+ // implementation only
+ // -------------------
+
+ // set the associated frame, it is used to reset its view when we're
+ // destroyed
+ void SetDocChildFrame(wxDocChildFrameAnyBase *docChildFrame)
+ {
+ m_docChildFrame = docChildFrame;
+ }
+
protected:
// hook the document into event handlers chain here
virtual bool TryBefore(wxEvent& event);
wxString m_viewTypeName;
wxWindow* m_viewFrame;
+ wxDocChildFrameAnyBase *m_docChildFrame;
+
private:
DECLARE_ABSTRACT_CLASS(wxView)
wxDECLARE_NO_COPY_CLASS(wxView);
#endif // WXWIN_COMPATIBILITY_2_6
// ----------------------------------------------------------------------------
-// A default child frame
+// Base class for child frames -- this is what wxView renders itself into
+//
+// Notice that this is a mix-in class so it doesn't derive from wxWindow, only
+// wxDocChildFrameAny does
// ----------------------------------------------------------------------------
-class WXDLLIMPEXP_CORE wxDocChildFrame : public wxFrame
+class wxDocChildFrameAnyBase
{
public:
- wxDocChildFrame(wxDocument *doc,
- wxView *view,
- wxFrame *frame,
- wxWindowID id,
- const wxString& title,
- const wxPoint& pos = wxDefaultPosition,
- const wxSize& size = wxDefaultSize,
- long type = wxDEFAULT_FRAME_STYLE,
- const wxString& name = wxFrameNameStr);
- virtual ~wxDocChildFrame(){}
+ wxDocChildFrameAnyBase(wxDocument *doc, wxView *view)
+ {
+ m_childDocument = doc;
+ m_childView = view;
- void OnActivate(wxActivateEvent& event);
- void OnCloseWindow(wxCloseEvent& event);
+ if ( view )
+ view->SetDocChildFrame(this);
+ }
wxDocument *GetDocument() const { return m_childDocument; }
wxView *GetView() const { return m_childView; }
void SetDocument(wxDocument *doc) { m_childDocument = doc; }
void SetView(wxView *view) { m_childView = view; }
- bool Destroy() { m_childView = NULL; return wxFrame::Destroy(); }
protected:
- // hook the child view into event handlers chain here
- virtual bool TryBefore(wxEvent& event);
+ // 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
+ // a chance to process the message before the frame event handlers are used
+ bool TryProcessEvent(wxEvent& event)
+ {
+ return m_childView && m_childView->ProcessEventHere(event);
+ }
+
+ // called from EVT_CLOSE handler in the frame: check if we can close and do
+ // cleanup if so; veto the event otherwise
+ bool CloseView(wxCloseEvent& event);
+
wxDocument* m_childDocument;
wxView* m_childView;
+ wxDECLARE_NO_COPY_CLASS(wxDocChildFrameAnyBase);
+};
+
+// ----------------------------------------------------------------------------
+// Template implementing child frame concept using the given wxFrame-like class
+//
+// This is used to define wxDocChildFrame and wxDocMDIChildFrame: ChildFrame is
+// a wxFrame or wxMDIChildFrame (although in theory it could be any wxWindow-
+// derived class as long as it provided a ctor with the same signature as
+// wxFrame and OnActivate() method) and ParentFrame is either wxFrame or
+// wxMDIParentFrame.
+// ----------------------------------------------------------------------------
+
+template <class ChildFrame, class ParentFrame>
+class WXDLLIMPEXP_CORE wxDocChildFrameAny : public ChildFrame,
+ public wxDocChildFrameAnyBase
+{
+public:
+ typedef ChildFrame BaseClass;
+
+ // ctor for a frame showing the given view of the specified document
+ wxDocChildFrameAny(wxDocument *doc,
+ wxView *view,
+ ParentFrame *parent,
+ wxWindowID id,
+ const wxString& title,
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize,
+ long style = wxDEFAULT_FRAME_STYLE,
+ const wxString& name = wxFrameNameStr)
+ : BaseClass(parent, id, title, pos, size, style, name),
+ wxDocChildFrameAnyBase(doc, view)
+ {
+ if ( view )
+ view->SetFrame(this);
+
+ this->Connect(wxEVT_ACTIVATE,
+ wxActivateEventHandler(wxDocChildFrameAny::OnActivate));
+ this->Connect(wxEVT_CLOSE_WINDOW,
+ wxCloseEventHandler(wxDocChildFrameAny::OnCloseWindow));
+ }
+
+ virtual bool Destroy()
+ {
+ // FIXME: why exactly do we do this? to avoid activation events during
+ // destructions maybe?
+ m_childView = NULL;
+ return BaseClass::Destroy();
+ }
+
+protected:
+ // hook the child view into event handlers chain here
+ virtual bool TryBefore(wxEvent& event)
+ {
+ return TryProcessEvent(event) || BaseClass::TryBefore(event);
+ }
+
+private:
+ void OnActivate(wxActivateEvent& event)
+ {
+ BaseClass::OnActivate(event);
+
+ if ( m_childView )
+ m_childView->Activate(event.GetActive());
+ }
+
+ void OnCloseWindow(wxCloseEvent& event)
+ {
+ if ( CloseView(event) )
+ Destroy();
+ //else: vetoed
+ }
+
+ wxDECLARE_NO_COPY_TEMPLATE_CLASS_2(wxDocChildFrameAny,
+ ChildFrame, ParentFrame);
+};
+
+// ----------------------------------------------------------------------------
+// A default child frame: we need to define it as a class just for wxRTTI,
+// otherwise we could simply typedef it
+// ----------------------------------------------------------------------------
+
+typedef wxDocChildFrameAny<wxFrame, wxFrame> wxDocChildFrameBase;
+
+class WXDLLIMPEXP_CORE wxDocChildFrame : public wxDocChildFrameBase
+{
+public:
+ wxDocChildFrame(wxDocument *doc,
+ wxView *view,
+ wxFrame *parent,
+ wxWindowID id,
+ const wxString& title,
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize,
+ long style = wxDEFAULT_FRAME_STYLE,
+ const wxString& name = wxFrameNameStr)
+ : wxDocChildFrameBase(doc, view,
+ parent, id, title, pos, size, style, name)
+ {
+ }
+
private:
DECLARE_CLASS(wxDocChildFrame)
- DECLARE_EVENT_TABLE()
wxDECLARE_NO_COPY_CLASS(wxDocChildFrame);
};
+WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxDocChildFrameBase )
+
// ----------------------------------------------------------------------------
// A default parent frame
// ----------------------------------------------------------------------------
}
-/*
- * Default document child frame for MDI children
- */
-
IMPLEMENT_CLASS(wxDocMDIChildFrame, wxMDIChildFrame)
-BEGIN_EVENT_TABLE(wxDocMDIChildFrame, wxMDIChildFrame)
- EVT_ACTIVATE(wxDocMDIChildFrame::OnActivate)
- EVT_CLOSE(wxDocMDIChildFrame::OnCloseWindow)
-END_EVENT_TABLE()
-
-void wxDocMDIChildFrame::Init()
-{
- m_childDocument = NULL;
- m_childView = NULL;
-}
-
-wxDocMDIChildFrame::wxDocMDIChildFrame()
-{
- Init();
-}
-
-wxDocMDIChildFrame::wxDocMDIChildFrame(wxDocument *doc, wxView *view, wxMDIParentFrame *frame, wxWindowID id,
- const wxString& title, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
-{
- Init();
- Create(doc, view, frame, id, title, pos, size, style, name);
-}
-
-bool wxDocMDIChildFrame::Create(wxDocument *doc, wxView *view, wxMDIParentFrame *frame, wxWindowID id,
- const wxString& title, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
-{
- m_childDocument = doc;
- m_childView = view;
- if (wxMDIChildFrame::Create(frame, id, title, pos, size, style, name))
- {
- if (view)
- view->SetFrame(this);
- return true;
- }
-
- return false;
-}
-
-wxDocMDIChildFrame::~wxDocMDIChildFrame(void)
-{
- m_childView = NULL;
-}
-
-bool wxDocMDIChildFrame::TryBefore(wxEvent& event)
-{
- if ( m_childView && m_childView->ProcessEventHere(event) )
- return true;
-
- return wxMDIChildFrame::TryBefore(event);
-}
-
-void wxDocMDIChildFrame::OnActivate(wxActivateEvent& event)
-{
- wxMDIChildFrame::OnActivate(event);
-
- if (event.GetActive() && m_childView)
- m_childView->Activate(event.GetActive());
-}
-
-void wxDocMDIChildFrame::OnCloseWindow(wxCloseEvent& event)
-{
- // Close view but don't delete the frame while doing so!
- // ...since it will be deleted by wxWidgets if we return true.
- if (m_childView)
- {
- bool ans = event.CanVeto()
- ? m_childView->Close(false) // false means don't delete associated window
- : true; // Must delete.
-
- if (ans)
- {
- m_childView->Activate(false);
- delete m_childView;
- m_childView = NULL;
- m_childDocument = NULL;
-
- this->Destroy();
- }
- else
- event.Veto();
- }
- else
- event.Veto();
-}
-
-#endif
- // wxUSE_DOC_VIEW_ARCHITECTURE
+#endif // wxUSE_DOC_VIEW_ARCHITECTURE
m_viewDocument = NULL;
m_viewFrame = NULL;
+
+ m_docChildFrame = NULL;
}
wxView::~wxView()
{
GetDocumentManager()->ActivateView(this, false);
- m_viewDocument->RemoveView(this);
+
+ // reset our frame view first, before removing it from the document as
+ // SetView(NULL) is a simple call while RemoveView() may result in user
+ // code being executed and this user code can, for example, show a message
+ // 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 )
+ m_docChildFrame->SetView(NULL);
+
+ if ( m_viewDocument )
+ m_viewDocument->RemoveView(this);
}
bool wxView::TryBefore(wxEvent& event)
}
// ----------------------------------------------------------------------------
-// Default document child frame
+// wxDocChildFrameAnyBase
// ----------------------------------------------------------------------------
-BEGIN_EVENT_TABLE(wxDocChildFrame, wxFrame)
- EVT_ACTIVATE(wxDocChildFrame::OnActivate)
- EVT_CLOSE(wxDocChildFrame::OnCloseWindow)
-END_EVENT_TABLE()
-
-wxDocChildFrame::wxDocChildFrame(wxDocument *doc,
- wxView *view,
- wxFrame *frame,
- wxWindowID id,
- const wxString& title,
- const wxPoint& pos,
- const wxSize& size,
- long style,
- const wxString& name)
- : wxFrame(frame, id, title, pos, size, style, name)
-{
- m_childDocument = doc;
- m_childView = view;
- if (view)
- view->SetFrame(this);
-}
-
-bool wxDocChildFrame::TryBefore(wxEvent& event)
+bool wxDocChildFrameAnyBase::CloseView(wxCloseEvent& event)
{
if ( m_childView )
{
- // FIXME: why is this needed here?
- m_childView->Activate(true);
-
- if ( m_childView->ProcessEventHere(event) )
- return true;
- }
-
- return wxFrame::TryBefore(event);
-}
-
-void wxDocChildFrame::OnActivate(wxActivateEvent& event)
-{
- wxFrame::OnActivate(event);
-
- if (m_childView)
- m_childView->Activate(event.GetActive());
-}
-
-void wxDocChildFrame::OnCloseWindow(wxCloseEvent& event)
-{
- if ( !m_childView )
- return;
+ if ( event.CanVeto() && !m_childView->Close(false) )
+ {
+ event.Veto();
+ return false;
+ }
- // passing false to Close() means to not delete associated window
- if ( event.CanVeto() && !m_childView->Close(false) )
- {
- event.Veto();
- return;
+ m_childView->Activate(false);
+ delete m_childView;
+ m_childView = NULL;
}
- m_childView->Activate(false);
- delete m_childView;
- m_childView = NULL;
m_childDocument = NULL;
- Destroy();
+ return true;
}
// ----------------------------------------------------------------------------