// destroyed
void SetDocChildFrame(wxDocChildFrameAnyBase *docChildFrame);
+ // get the associated frame, may be NULL during destruction
+ wxDocChildFrameAnyBase* GetDocChildFrame() const { return m_docChildFrame; }
+
protected:
// hook the document into event handlers chain here
virtual bool TryBefore(wxEvent& event);
m_childDocument = NULL;
m_childView = NULL;
m_win = NULL;
+ m_lastEvent = NULL;
}
// full ctor equivalent to using the default one and Create()
wxWindow *GetWindow() const { return m_win; }
+ // implementation only
+
+ // Check if this event had been just processed in this frame.
+ bool HasAlreadyProcessed(wxEvent& event) const
+ {
+ return m_lastEvent == &event;
+ }
+
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
// allows us to avoid having any virtual functions in this class
wxWindow* m_win;
+private:
+ // Pointer to the last processed event used to avoid sending the same event
+ // twice to wxDocManager, from here and from wxDocParentFrameAnyBase.
+ wxEvent* m_lastEvent;
wxDECLARE_NO_COPY_CLASS(wxDocChildFrameAnyBase);
};
// hook the document manager into event handling chain here
virtual bool TryBefore(wxEvent& event)
{
- return TryProcessEvent(event) || BaseFrame::TryBefore(event);
+ // It is important to send the event to the base class first as
+ // wxMDIParentFrame overrides its TryBefore() to send the menu events
+ // to the currently active child frame and the child must get them
+ // before our own TryProcessEvent() is executed, not afterwards.
+ return BaseFrame::TryBefore(event) || TryProcessEvent(event);
}
private:
return false;
}
+ // Store a (non-owning) pointer to the last processed event here to be able
+ // to recognize this event again if it bubbles up to the parent frame, see
+ // the code in wxDocParentFrameAnyBase::TryProcessEvent().
+ m_lastEvent = &event;
+
// Forward the event to the document manager which will, in turn, forward
// it to its active view which must be our m_childView.
//
// already forwarded the event to wxDocManager, check for this:
if ( wxView* const view = m_docManager->GetAnyUsableView() )
{
- wxWindow* win = view->GetFrame();
- if ( win && win != m_frame )
- {
- // 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 ( win = win->GetParent(); win; win = win->GetParent() )
- {
- if ( win == m_frame )
- return false;
- }
- }
- //else: This view is directly associated with the parent frame (which
- // can happen in the so called "single" mode in which only one
- // document can be opened and so is managed by the parent frame
- // itself), there can be no child frame in play so we must forward
- // the event to wxDocManager ourselves.
+ wxDocChildFrameAnyBase* const childFrame = view->GetDocChildFrame();
+ if ( childFrame && childFrame->HasAlreadyProcessed(event) )
+ 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.
+ // all or if this event hadn't been sent to the child frame previously.
return m_docManager->ProcessEventLocally(event);
}