Fix event handling order in doc/view framework.

Ensure that the events are always (provided there is an open document)
processed in the following order:

1. wxDocument
2. wxView
3. wxDocManager
4. wxDocChildFrame
5. wxDocParentFrame
6. wxApp

Do this by forwarding the events from wxDocParentFrame to wxDocChildFrame
first and forward them from there to wxDocManager which -- and this part
remains unchanged -- in turn forwards them to the active wxView which finally
forwards them to wxDocument. This requires another condition in the event
handling code as we still must forward from wxDocParentFrame to wxDocManager
itself if there are no active children at all, but this is the only way to
have the same event order in all cases, whether the event is originally
received by wxDocChildFrame or wxDocParentFrame.

Document this and add a unit test verifying that things indeed work like this.

See #14314.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@73928 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2013-05-04 23:59:56 +00:00
parent 80dcb89812
commit a7c0de8a98
4 changed files with 204 additions and 10 deletions

View File

@@ -2014,6 +2014,26 @@ void wxDocManager::ActivateView(wxView *view, bool activate)
// wxDocChildFrameAnyBase
// ----------------------------------------------------------------------------
bool wxDocChildFrameAnyBase::TryProcessEvent(wxEvent& event)
{
if ( !m_childView )
{
// We must be being destroyed, don't forward events anywhere as
// m_childDocument could be invalid by now.
return false;
}
// Forward the event to the document manager which will, in turn, forward
// it to its active view which must be our m_childView.
//
// Notice that we do things in this roundabout way to guarantee the correct
// event handlers call order: first the document, then the new and then the
// document manager itself. And if we forwarded the event directly to the
// view, then the document manager would do it once again when we forwarded
// it to it.
return m_childDocument->GetDocumentManager()->ProcessEventLocally(event);
}
bool wxDocChildFrameAnyBase::CloseView(wxCloseEvent& event)
{
if ( m_childView )
@@ -2046,6 +2066,35 @@ bool wxDocChildFrameAnyBase::CloseView(wxCloseEvent& event)
// wxDocParentFrameAnyBase
// ----------------------------------------------------------------------------
bool wxDocParentFrameAnyBase::TryProcessEvent(wxEvent& event)
{
if ( !m_docManager )
return false;
// If we have an active view, its associated child frame may have
// already forwarded the event to wxDocManager, check for this:
if ( wxView* const view = m_docManager->GetAnyUsableView() )
{
// Notice that we intentionally don't use wxGetTopLevelParent() here
// because we want to check both for the case of a child "frame" (e.g.
// MDI child frame or notebook page) inside this TLW and a separate
// child TLW frame (as used in the SDI mode) here.
for ( wxWindow* win = view->GetFrame(); win; win = win->GetParent() )
{
if ( win == m_frame )
return false;
}
}
// But forward the event to wxDocManager ourselves if there are no views at
// all or if we are the frame's view ourselves.
return m_docManager->ProcessEventLocally(event);
}
// ----------------------------------------------------------------------------
// Printing support
// ----------------------------------------------------------------------------
#if wxUSE_PRINTING_ARCHITECTURE
namespace