From 7c9cc312e76950fcddb0174ae48b60c347eee8b4 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 7 Sep 2009 23:00:21 +0000 Subject: [PATCH] Show the order in which different event handlers are called. Update the event sample to define (as) many (as possible) event handlers for a test button and log messages in all of the handlers to leave a trace of the order in which they were executed. Add a pointer to this feature of the event sample to the events overview. Closes #11156. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@61852 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/doxygen/overviews/eventhandling.h | 7 +- samples/event/event.cpp | 166 ++++++++++++++++++++++++- 2 files changed, 168 insertions(+), 5 deletions(-) diff --git a/docs/doxygen/overviews/eventhandling.h b/docs/doxygen/overviews/eventhandling.h index e671bb84d0..05ad03f49a 100644 --- a/docs/doxygen/overviews/eventhandling.h +++ b/docs/doxygen/overviews/eventhandling.h @@ -428,7 +428,10 @@ in simple situations where this extra flexibility is not needed. The previous sections explain how to define event handlers but don't address the question of how exactly wxWidgets finds the handler to call for the -given event. This section describes the algorithm used in detail. +given event. This section describes the algorithm used in detail. Notice that +you may want to run the @ref page_samples_event while reading this section and +look at its code and the output when the button which can be used to test the +event handlers execution order is clicked to understand it better. When an event is received from the windowing system, wxWidgets calls wxEvtHandler::ProcessEvent() on the first event handler object belonging to the @@ -454,7 +457,7 @@ doesn't count as having handled the event and the search continues):
  • - The list of dynamically bind event handlers, i.e., those for which + The list of dynamically bound event handlers, i.e., those for which Bind<>() was called, is consulted. Notice that this is done before checking the static event table entries, so if both a dynamic and a static event handler match the same event, the static one is never going to be diff --git a/samples/event/event.cpp b/samples/event/event.cpp index d2b7679af1..1ddacb0430 100644 --- a/samples/event/event.cpp +++ b/samples/event/event.cpp @@ -34,6 +34,9 @@ #include "../sample.xpm" #endif +#include +#include + // ---------------------------------------------------------------------------- // event constants // ---------------------------------------------------------------------------- @@ -65,8 +68,56 @@ public: // initialization (doing it here and not in the ctor allows to have an error // return: if OnInit() returns false, the application terminates) virtual bool OnInit(); + + // these are regular event handlers used to highlight the events handling + // order + void OnClickDynamicHandlerApp(wxCommandEvent& event); + void OnClickStaticHandlerApp(wxCommandEvent& event); + + // we override wxConsoleApp::FilterEvent used to highlight the events + // handling order + virtual int FilterEvent(wxEvent& event); + +private: + DECLARE_EVENT_TABLE() }; +// Define a custom button used to highlight the events handling order +class MyEvtTestButton : public wxButton +{ +public: + static long BUTTON_ID; + + MyEvtTestButton(wxWindow *parent, const wxString& label) + : wxButton(parent, BUTTON_ID, label) + { + // Add a dynamic handler for this button event to button itself + Connect(wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler(MyEvtTestButton::OnClickDynamicHandler)); + } + +private: + void OnClickDynamicHandler(wxCommandEvent& event) + { + wxLogMessage("Step 3 in \"How Events are Processed\":\n" + "Button::ownDynamicHandler"); + + event.Skip(); + } + + void OnClickStaticHandler(wxCommandEvent& event) + { + wxLogMessage("Step 4 in \"How Events are Processed\":\n" + "Button::ownStaticHandler"); + + event.Skip(); + } + + DECLARE_EVENT_TABLE() +}; + +long MyEvtTestButton::BUTTON_ID = wxNewId(); + // Define a new frame type: this is going to be our main frame class MyFrame : public wxFrame { @@ -91,6 +142,11 @@ public: void OnUpdateUIPop(wxUpdateUIEvent& event); + // regular event handlers used to highlight the events handling order + void OnClickDynamicHandlerFrame(wxCommandEvent& event); + void OnClickDynamicHandlerButton(wxCommandEvent& event); + void OnClickStaticHandlerFrame(wxCommandEvent& event); + private: // symbolic names for the status bar fields enum @@ -122,6 +178,10 @@ private: // the button to whose event we connect dynamically wxButton *m_btnDynamic; + // the button used to highlight the event handlers execution order + MyEvtTestButton *m_testBtn; + + // any class wishing to process wxWidgets events must use this macro DECLARE_EVENT_TABLE() }; @@ -170,8 +230,19 @@ enum // event tables and other macros for wxWidgets // ---------------------------------------------------------------------------- -// the event tables connect the wxWidgets events with the functions (event -// handlers) which process them. It can be also done at run-time, but for the +// The event tables connect the wxWidgets events with the functions (event +// handlers) which process them. +BEGIN_EVENT_TABLE(MyApp, wxApp) + // Add a static handler for button Click event in the app + EVT_BUTTON(MyEvtTestButton::BUTTON_ID, MyApp::OnClickStaticHandlerApp) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(MyEvtTestButton, wxButton) + // Add a static handler to this button itself for its own event + EVT_BUTTON(BUTTON_ID, MyEvtTestButton::OnClickStaticHandler) +END_EVENT_TABLE() + +// This can be also done at run-time, but for the // simple menu events like this the static method is much simpler. BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(Event_Quit, MyFrame::OnQuit) @@ -194,6 +265,9 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) // the line below would also work if OnProcessCustom() were defined as // taking a wxEvent (as required by EVT_CUSTOM) and not wxCommandEvent //EVT_CUSTOM(wxEVT_MY_CUSTOM_COMMAND, wxID_ANY, MyFrame::OnProcessCustom) + + // Add a static handler in the parent frame for button event + EVT_BUTTON(MyEvtTestButton::BUTTON_ID, MyFrame::OnClickStaticHandlerFrame) END_EVENT_TABLE() BEGIN_EVENT_TABLE(MyEvtHandler, wxEvtHandler) @@ -229,12 +303,51 @@ bool MyApp::OnInit() // created initially) frame->Show(true); + // Add a dynamic handler at the application level for the test button + Connect(MyEvtTestButton::BUTTON_ID, wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler(MyApp::OnClickDynamicHandlerApp)); + // success: wxApp::OnRun() will be called which will enter the main message // loop and the application will run. If we returned false here, the // application would exit immediately. return true; } +// This is always the first to handle an event ! +int MyApp::FilterEvent(wxEvent& event) +{ + if ( event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED && + event.GetId() == MyEvtTestButton::BUTTON_ID ) + { + wxLogMessage("Step 0 in \"How Events are Processed\":\n" + "App::FilterEvent"); + } + + return wxApp::FilterEvent(event); +} + +void MyApp::OnClickDynamicHandlerApp(wxCommandEvent& event) +{ + wxLogMessage("Step 7, 3 in \"How Events are Processed\":\n" + "App::DynamicHandler_InAppTable"); + + event.Skip(); +} + +void MyApp::OnClickStaticHandlerApp(wxCommandEvent& event) +{ + wxLogMessage("Step 7, 4 in \"How Events are Processed\":\n" + "App::StaticHandler_InAppTable"); + + wxLogMessage("Button click processed, there should be no more messages " + "about handling events from the button.\n\n" + "The log below shows the order in which the handlers " + "were executed."); + wxLog::FlushActive(); + + event.Skip(); +} + // ---------------------------------------------------------------------------- // main frame // ---------------------------------------------------------------------------- @@ -292,6 +405,7 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) #endif // wxUSE_STATUSBAR wxPanel * const panel = new wxPanel(this); + wxSizer * const mainSizer = new wxBoxSizer(wxVERTICAL); wxSizer * const sizer = new wxBoxSizer(wxHORIZONTAL); const wxSizerFlags centreY(wxSizerFlags().Centre().Border()); sizer->Add(new wxStaticText(panel, wxID_ANY, @@ -299,7 +413,29 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) centreY); m_btnDynamic = new wxButton(panel, Event_Dynamic, "&Dynamic button"); sizer->Add(m_btnDynamic, centreY); - panel->SetSizer(sizer); + + mainSizer->Add(sizer, 1, wxEXPAND); + mainSizer->Add(new wxStaticLine(panel), 0, wxEXPAND); + mainSizer->Add(new wxStaticLine(panel), 0, wxEXPAND); + + m_testBtn = new MyEvtTestButton(panel, "Test Event Handlers Execution Order"); + + // After being created, an instance of MyEvtTestButton already has its own + // event handlers (see class definition); + + // Add a dynamic handler for this button event in the parent frame + Connect(m_testBtn->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler(MyFrame::OnClickDynamicHandlerFrame)); + + // Bind a method of this frame (notice "this" argument!) to the button + // itself + m_testBtn->Connect(wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler(MyFrame::OnClickDynamicHandlerButton), + NULL, + this); + + mainSizer->Add(m_testBtn); + panel->SetSizer(mainSizer); } MyFrame::~MyFrame() @@ -330,10 +466,34 @@ void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) wxOK | wxICON_INFORMATION, this); } +void MyFrame::OnClickStaticHandlerFrame(wxCommandEvent& event) +{ + wxLogMessage("Step 6, 4 in \"How Events are Processed\":\n" + "parentWin::StaticHandler_InFrameTable"); + + event.Skip(); +} + // ---------------------------------------------------------------------------- // dynamic event handling stuff // ---------------------------------------------------------------------------- +void MyFrame::OnClickDynamicHandlerFrame(wxCommandEvent& event) +{ + wxLogMessage("Step 6, 3 in \"How Events are Processed\":\n" + "parentWin::DynamicHandler_InFrameTable"); + + event.Skip(); +} + +void MyFrame::OnClickDynamicHandlerButton(wxCommandEvent& event) +{ + wxLogMessage("Step 3 in \"How Events are Processed\":\n" + "parentWin::DynamicHandler_InButtonTable"); + + event.Skip(); +} + void MyFrame::OnDynamic(wxCommandEvent& event) { wxString origin; -- 2.47.2