X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6164f93ca283074f4a0209ede0bc3fef3c68d996..48889bca6f8b2504f78c0f47b32f5e95c64d915d:/samples/event/event.cpp diff --git a/samples/event/event.cpp b/samples/event/event.cpp index 15895cf038..3cc8c01e55 100644 --- a/samples/event/event.cpp +++ b/samples/event/event.cpp @@ -1,11 +1,11 @@ ///////////////////////////////////////////////////////////////////////////// // Name: event.cpp -// Purpose: wxWindows sample demonstrating different event usage +// Purpose: wxWidgets sample demonstrating different event usage // Author: Vadim Zeitlin // Modified by: // Created: 31.01.01 // RCS-ID: $Id$ -// Copyright: (c) 2001 Vadim Zeitlin +// Copyright: (c) 2001-2009 Vadim Zeitlin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -17,13 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ - // DO NOT use event.cpp here, it breaks statics initialization in - // src/common/event.cpp and nothing works at all then! - #pragma implementation "eventsample.cpp" - #pragma interface "eventsample.cpp" -#endif - // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" @@ -32,11 +25,31 @@ #endif // for all others, include the necessary headers (this file is usually all you -// need because it includes almost all "standard" wxWindows headers) +// need because it includes almost all "standard" wxWidgets headers) #ifndef WX_PRECOMP #include "wx/wx.h" #endif +#ifndef __WXMSW__ + #include "../sample.xpm" +#endif + +// ---------------------------------------------------------------------------- +// event constants +// ---------------------------------------------------------------------------- + +// define a custom event type (we don't need a separate declaration here but +// usually you would use a matching wxDECLARE_EVENT in a header) +wxDEFINE_EVENT(wxEVT_MY_CUSTOM_COMMAND, wxCommandEvent); + +// it may also be convenient to define an event table macro for this event type +#define EVT_MY_CUSTOM_COMMAND(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_MY_CUSTOM_COMMAND, id, wxID_ANY, \ + wxCommandEventHandler(fn), \ + (wxObject *) NULL \ + ), + // ---------------------------------------------------------------------------- // private classes // ---------------------------------------------------------------------------- @@ -64,20 +77,52 @@ public: void OnQuit(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); +#ifdef wxHAS_EVENT_BIND + void OnBind(wxCommandEvent& event); +#endif // wxHAS_EVENT_BIND void OnConnect(wxCommandEvent& event); void OnDynamic(wxCommandEvent& event); void OnPushEventHandler(wxCommandEvent& event); void OnPopEventHandler(wxCommandEvent& event); void OnTest(wxCommandEvent& event); + void OnFireCustom(wxCommandEvent& event); + void OnProcessCustom(wxCommandEvent& event); + void OnUpdateUIPop(wxUpdateUIEvent& event); -protected: +private: + // symbolic names for the status bar fields + enum + { + Status_Main = 0, + Status_Dynamic, + Status_Push + }; + + void UpdateDynamicStatus(bool on) + { +#if wxUSE_STATUSBAR + if ( on ) + { + SetStatusText("You can now use \"Dynamic\" item in the menu"); + SetStatusText("Dynamic: on", Status_Dynamic); + } + else + { + SetStatusText("You can no more use \"Dynamic\" item in the menu"); + SetStatusText("Dynamic: off", Status_Dynamic); + } +#endif // wxUSE_STATUSBAR + } + // number of pushed event handlers - size_t m_nPush; + unsigned m_nPush; -private: - // any class wishing to process wxWindows events must use this macro + // the button to whose event we connect dynamically + wxButton *m_btnDynamic; + + // any class wishing to process wxWidgets events must use this macro DECLARE_EVENT_TABLE() }; @@ -97,7 +142,7 @@ public: } private: - size_t m_level; + unsigned m_level; DECLARE_EVENT_TABLE() }; @@ -112,46 +157,50 @@ enum // menu items Event_Quit = 1, Event_About, + Event_Bind, Event_Connect, Event_Dynamic, Event_Push, Event_Pop, + Event_Custom, Event_Test }; -// status bar fields -enum -{ - Status_Main = 0, - Status_Dynamic, - Status_Push -}; - // ---------------------------------------------------------------------------- -// event tables and other macros for wxWindows +// event tables and other macros for wxWidgets // ---------------------------------------------------------------------------- -// the event tables connect the wxWindows events with the functions (event +// 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 // simple menu events like this the static method is much simpler. BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(Event_Quit, MyFrame::OnQuit) EVT_MENU(Event_About, MyFrame::OnAbout) +#ifdef wxHAS_EVENT_BIND + EVT_MENU(Event_Bind, MyFrame::OnBind) +#endif // wxHAS_EVENT_BIND EVT_MENU(Event_Connect, MyFrame::OnConnect) + EVT_MENU(Event_Custom, MyFrame::OnFireCustom) EVT_MENU(Event_Test, MyFrame::OnTest) EVT_MENU(Event_Push, MyFrame::OnPushEventHandler) EVT_MENU(Event_Pop, MyFrame::OnPopEventHandler) EVT_UPDATE_UI(Event_Pop, MyFrame::OnUpdateUIPop) + + EVT_MY_CUSTOM_COMMAND(wxID_ANY, MyFrame::OnProcessCustom) + + // 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) END_EVENT_TABLE() BEGIN_EVENT_TABLE(MyEvtHandler, wxEvtHandler) EVT_MENU(Event_Test, MyEvtHandler::OnTest) END_EVENT_TABLE() -// Create a new application object: this macro will allow wxWindows to create +// Create a new application object: this macro will allow wxWidgets to create // the application object during program execution (it's better than using a // static object for many reasons) and also declares the accessor function // wxGetApp() which will return the reference of the right type (i.e. MyApp and @@ -169,18 +218,21 @@ IMPLEMENT_APP(MyApp) // 'Main program' equivalent: the program execution "starts" here bool MyApp::OnInit() { + if ( !wxApp::OnInit() ) + return false; + // create the main application window - MyFrame *frame = new MyFrame("Event wxWindows Sample", - wxPoint(50, 50), wxSize(450, 340)); + MyFrame *frame = new MyFrame(_T("Event wxWidgets Sample"), + wxPoint(50, 50), wxSize(600, 340)); // and show it (the frames, unlike simple controls, are not shown when // created initially) - frame->Show(TRUE); + frame->Show(true); // success: wxApp::OnRun() will be called which will enter the main message - // loop and the application will run. If we returned FALSE here, the + // loop and the application will run. If we returned false here, the // application would exit immediately. - return TRUE; + return true; } // ---------------------------------------------------------------------------- @@ -189,43 +241,65 @@ bool MyApp::OnInit() // frame constructor MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) - : wxFrame((wxFrame *)NULL, -1, title, pos, size) + : wxFrame(NULL, wxID_ANY, title, pos, size) { + SetIcon(wxICON(sample)); + + // init members + m_nPush = 0; + m_btnDynamic = NULL; + // create a menu bar wxMenu *menuFile = new wxMenu; - menuFile->Append(Event_About, "&About...\tCtrl-A", "Show about dialog"); + menuFile->Append(Event_About, _T("&About...\tCtrl-A"), _T("Show about dialog")); menuFile->AppendSeparator(); - menuFile->Append(Event_Quit, "E&xit\tAlt-X", "Quit this program"); + menuFile->Append(Event_Quit, _T("E&xit\tAlt-X"), _T("Quit this program")); wxMenu *menuEvent = new wxMenu; - menuEvent->Append(Event_Connect, "&Connect\tCtrl-C", - "Connect or disconnect the dynamic event handler", - TRUE /* checkable */); - menuEvent->Append(Event_Dynamic, "&Dynamic event\tCtrl-D", - "Dynamic event sample - only works after Connect"); +#ifdef wxHAS_EVENT_BIND + menuEvent->AppendCheckItem(Event_Bind, "&Bind\tCtrl-B", + "Bind or unbind a dynamic event handler"); +#endif // wxHAS_EVENT_BIND + menuEvent->AppendCheckItem(Event_Connect, _T("&Connect\tCtrl-C"), + _T("Connect or disconnect the dynamic event handler")); + menuEvent->Append(Event_Dynamic, _T("&Dynamic event\tCtrl-D"), + _T("Dynamic event sample - only works after Connect")); menuEvent->AppendSeparator(); - menuEvent->Append(Event_Push, "&Push event handler\tCtrl-P", - "Push event handler for test event"); - menuEvent->Append(Event_Pop, "P&op event handler\tCtrl-O", - "Pop event handler for test event"); - menuEvent->Append(Event_Test, "Test event\tCtrl-T", - "Test event processed by pushed event handler"); + menuEvent->Append(Event_Push, _T("&Push event handler\tCtrl-P"), + _T("Push event handler for test event")); + menuEvent->Append(Event_Pop, _T("P&op event handler\tCtrl-O"), + _T("Pop event handler for test event")); + menuEvent->Append(Event_Test, _T("Test event\tCtrl-T"), + _T("Test event processed by pushed event handler")); + menuEvent->AppendSeparator(); + menuEvent->Append(Event_Custom, _T("Fire c&ustom event\tCtrl-U"), + _T("Generate a custom event")); // now append the freshly created menu to the menu bar... wxMenuBar *menuBar = new wxMenuBar(); - menuBar->Append(menuFile, "&File"); - menuBar->Append(menuEvent, "&Event"); + menuBar->Append(menuFile, _T("&File")); + menuBar->Append(menuEvent, _T("&Event")); // ... and attach this menu bar to the frame SetMenuBar(menuBar); #if wxUSE_STATUSBAR CreateStatusBar(3); - SetStatusText("Welcome to wxWindows event sample"); + SetStatusText(_T("Welcome to wxWidgets event sample")); SetStatusText(_T("Dynamic: off"), Status_Dynamic); SetStatusText(_T("Push count: 0"), Status_Push); #endif // wxUSE_STATUSBAR + + wxPanel * const panel = new wxPanel(this); + wxSizer * const sizer = new wxBoxSizer(wxHORIZONTAL); + const wxSizerFlags centreY(wxSizerFlags().Centre().Border()); + sizer->Add(new wxStaticText(panel, wxID_ANY, + "This button will only work if its handler is dynamically connected"), + centreY); + m_btnDynamic = new wxButton(panel, Event_Dynamic, "&Dynamic button"); + sizer->Add(m_btnDynamic, centreY); + panel->SetSizer(sizer); } MyFrame::~MyFrame() @@ -234,7 +308,7 @@ MyFrame::~MyFrame() // crashes! while ( m_nPush-- != 0 ) { - PopEventHandler(TRUE /* delete handler */); + PopEventHandler(true /* delete handler */); } } @@ -244,48 +318,89 @@ MyFrame::~MyFrame() void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) { - // TRUE is to force the frame to close - Close(TRUE); + // true is to force the frame to close + Close(true); } void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { - wxMessageBox(_T("Event sample shows different ways of using events\n" - "© 2001 Vadim Zeitlin"), - _T("About Event Sample"), wxOK | wxICON_INFORMATION, this); + wxMessageBox("Event sample shows different ways of using events\n" + "(c) 2001-2009 Vadim Zeitlin", + "About wxWidgets Event Sample", + wxOK | wxICON_INFORMATION, this); } // ---------------------------------------------------------------------------- // dynamic event handling stuff // ---------------------------------------------------------------------------- -void MyFrame::OnDynamic(wxCommandEvent& WXUNUSED(event)) +void MyFrame::OnDynamic(wxCommandEvent& event) { - wxMessageBox(_T("This is a dynamic event handler which can be connected " - "and disconnected during run-time."), - _T("Dynamic Event Handler"), wxOK | wxICON_INFORMATION, this); + wxString origin; + if ( event.GetEventObject() == this ) + origin = "menu item"; + else if ( event.GetEventObject() == m_btnDynamic ) + origin = "button"; + else + origin = "unknown event source"; + + wxMessageBox + ( + "This message box is shown from the dynamically connected " + "event handler in response to event generated by " + origin, + "wxWidgets Event Sample", wxOK | wxICON_INFORMATION, this + ); } -void MyFrame::OnConnect(wxCommandEvent& event) +#ifdef wxHAS_EVENT_BIND + +void MyFrame::OnBind(wxCommandEvent& event) { if ( event.IsChecked() ) { - // disconnect - Connect(Event_Dynamic, -1, wxEVT_COMMAND_MENU_SELECTED, - (wxObjectEventFunction) - (wxEventFunction) - (wxCommandEventFunction)&MyFrame::OnDynamic); - - SetStatusText(_T("You can now use \"Dynamic\" item in the menu")); - SetStatusText(_T("Dynamic: on"), Status_Dynamic); + // as we bind directly to the button, there is no need to use an id + // here: the button will only ever get its own events + m_btnDynamic->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MyFrame::OnDynamic, + this); + + // but we do need the id for the menu command as the frame gets all of + // them + Bind(wxEVT_COMMAND_MENU_SELECTED, &MyFrame::OnDynamic, this, + Event_Dynamic); } - else // connect + else // disconnect { - Disconnect(Event_Dynamic, -1, wxEVT_COMMAND_MENU_SELECTED); + m_btnDynamic->Unbind(wxEVT_COMMAND_BUTTON_CLICKED, + &MyFrame::OnDynamic, this); + Unbind(wxEVT_COMMAND_MENU_SELECTED, &MyFrame::OnDynamic, this, + Event_Dynamic); + } + + UpdateDynamicStatus(event.IsChecked()); +} + +#endif // wxHAS_EVENT_BIND - SetStatusText(_T("You can no more use \"Dynamic\" item in the menu")); - SetStatusText(_T("Dynamic: off"), Status_Dynamic); +void MyFrame::OnConnect(wxCommandEvent& event) +{ + if ( event.IsChecked() ) + { + m_btnDynamic->Connect(wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler(MyFrame::OnDynamic), + NULL, this); + Connect(Event_Dynamic, wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MyFrame::OnDynamic)); } + else // disconnect + { + m_btnDynamic->Disconnect(wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler(MyFrame::OnDynamic), + NULL, this); + Disconnect(Event_Dynamic, wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MyFrame::OnDynamic)); + } + + UpdateDynamicStatus(event.IsChecked()); } // ---------------------------------------------------------------------------- @@ -296,20 +411,24 @@ void MyFrame::OnPushEventHandler(wxCommandEvent& WXUNUSED(event)) { PushEventHandler(new MyEvtHandler(++m_nPush)); +#if wxUSE_STATUSBAR SetStatusText(wxString::Format(_T("Push count: %u"), m_nPush), Status_Push); +#endif // wxUSE_STATUSBAR } void MyFrame::OnPopEventHandler(wxCommandEvent& WXUNUSED(event)) { wxCHECK_RET( m_nPush, _T("this command should be disabled!") ); - PopEventHandler(TRUE /* delete handler */); + PopEventHandler(true /* delete handler */); m_nPush--; +#if wxUSE_STATUSBAR SetStatusText(wxString::Format(_T("Push count: %u"), m_nPush), Status_Push); +#endif // wxUSE_STATUSBAR } -void MyFrame::OnTest(wxCommandEvent& event) +void MyFrame::OnTest(wxCommandEvent& WXUNUSED(event)) { wxLogMessage(_T("This is the test event handler in the main frame")); } @@ -319,3 +438,19 @@ void MyFrame::OnUpdateUIPop(wxUpdateUIEvent& event) event.Enable( m_nPush > 0 ); } +// ---------------------------------------------------------------------------- +// custom event methods +// ---------------------------------------------------------------------------- + +void MyFrame::OnFireCustom(wxCommandEvent& WXUNUSED(event)) +{ + wxCommandEvent eventCustom(wxEVT_MY_CUSTOM_COMMAND); + + wxPostEvent(this, eventCustom); +} + +void MyFrame::OnProcessCustom(wxCommandEvent& WXUNUSED(event)) +{ + wxLogMessage(_T("Got a custom event!")); +} +