From: Vadim Zeitlin Date: Wed, 25 Feb 2009 17:43:22 +0000 (+0000) Subject: replace templae Connect() overloads with separate Bind() method to improve compatibil... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/5293e4b7109139cc51052d57c0585716d6250b76 replace templae Connect() overloads with separate Bind() method to improve compatibility (see #10000, closes #10477) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@59134 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/event.h b/include/wx/event.h index b18f39bed8..16380fb343 100644 --- a/include/wx/event.h +++ b/include/wx/event.h @@ -126,10 +126,6 @@ extern WXDLLIMPEXP_BASE wxEventType wxNewEventType(); #define wxDECLARE_EVENT( name, type ) \ wxDECLARE_EXPORTED_EVENT( wxEMPTY_PARAMETER_VALUE, name, type ); - // Try to cast the given event handler to the correct handler type: - - #define wxEVENT_HANDLER_CAST( functype, func ) \ - ( wxObjectEventFunction )( wxEventFunction )wxStaticCastEvent( functype, &func ) #else // Define/Declare a templatized event type with the corresponding event as // a nested typedef: @@ -155,13 +151,13 @@ extern WXDLLIMPEXP_BASE wxEventType wxNewEventType(); #define wxDECLARE_EVENT( name, type ) \ wxDECLARE_EXPORTED_EVENT( wxEMPTY_PARAMETER_VALUE, name, type ); - // Don't cast the given event handler so that wxEvtHandler::Connect() sees - // the actual type: - - #define wxEVENT_HANDLER_CAST( functype, func ) \ - ( &func ) #endif +// Try to cast the given event handler to the correct handler type: + +#define wxEVENT_HANDLER_CAST( functype, func ) \ + ( wxObjectEventFunction )( wxEventFunction )wxStaticCastEvent( functype, &func ) + // Template which associates the correct event object with the event type #if !wxEVENTS_COMPATIBILITY_2_8 @@ -2977,121 +2973,44 @@ public: { return Disconnect(wxID_ANY, eventType, func, userData, eventSink); } #if !wxEVENTS_COMPATIBILITY_2_8 - // Event handling in functions (including generalized functors): - + // Bind arbitrary functor (including just a function) to an event: template - void Connect(int winid, - int lastId, - const EventTag& eventType, - Functor func) + void Bind(const EventTag& eventType, + Functor func, + int winid = wxID_ANY, + int lastId = wxID_ANY, + wxObject *userData = NULL) { DoConnect(winid, lastId, eventType, - wxNewEventFunctor(eventType, func)); - } - - template - void Connect(int winid, const EventTag& eventType, Functor func) - { Connect(winid, wxID_ANY, eventType, func); } - - template - void Connect(const EventTag& eventType, Functor func) - { Connect(wxID_ANY, eventType, func); } - - - template - bool Disconnect(int winid, - int lastId, - const EventTag& eventType, - Functor func) - { - return DoDisconnect(winid, lastId, eventType, - wxMakeEventFunctor(eventType, func)); - } - - template - bool Disconnect(int winid, const EventTag& eventType, Functor func) - { return Disconnect(winid, wxID_ANY, eventType, func); } - - template - bool Disconnect(const EventTag& eventType, Functor func) - { return Disconnect(wxID_ANY, eventType, func); } - - - - // Event handling in class methods: the object handling the event (i.e. - // this object itself by default or eventSink if specified) must be - // convertible to this class. - // - // Notice that we need to have separate overloads for the versions with and - // without eventSink because in the latter case we must check that this - // object itself derives from Class while in the former this is not - // necessarily true - - // Methods connecting/disconnecting event to this object itself - - template - void Connect(int winid, - int lastId, - const EventTag& eventType, - void (Class::*func)(EventArg&), - wxObject *userData = NULL) - { - DoConnect(winid, lastId, eventType, - wxNewEventFunctor(eventType, func, static_cast(this)), + wxNewEventFunctor(eventType, func), userData); } - template - void Connect(int winid, - const EventTag& eventType, - void (Class::*func)(EventArg&), - wxObject *userData = NULL) - { Connect(winid, wxID_ANY, eventType, func, userData); } - - template - void Connect(const EventTag& eventType, - void (Class::*func)(EventArg&), - wxObject *userData = NULL) - { Connect(wxID_ANY, eventType, func, userData); } - - template - bool Disconnect(int winid, - int lastId, - const EventTag& eventType, - void (Class::*func)(EventArg&), - wxObject *userData = NULL) + template + bool Unbind(const EventTag& eventType, + Functor func, + int winid = wxID_ANY, + int lastId = wxID_ANY, + wxObject *userData = NULL) { return DoDisconnect(winid, lastId, eventType, - wxMakeEventFunctor(eventType, func, - static_cast(this)), + wxMakeEventFunctor(eventType, func), userData); } - template - bool Disconnect(int winid, - const EventTag& eventType, - void (Class::*func)(EventArg&), - wxObject *userData = NULL) - { return Disconnect(winid, wxID_ANY, eventType, func, userData); } - - template - bool Disconnect(const EventTag& eventType, - void (Class::*func)(EventArg&), - wxObject *userData = NULL) - { return Disconnect(wxID_ANY, eventType, func, userData); } - - // Methods connecting/disconnecting event to another object + // Bind a method of a class (called on the specified eventSink which must + // be convertible to this class) object to an event: template - void Connect(int winid, - int lastId, - const EventTag& eventType, - void (Class::*func)(EventArg&), - wxObject *userData, - ObjClass *eventSink) + void Bind(const EventTag &eventType, + void (Class::*func)(EventArg &), + ObjClass *eventSink, + int winid = wxID_ANY, + int lastId = wxID_ANY, + wxObject *userData = NULL) { DoConnect(winid, lastId, eventType, wxNewEventFunctor(eventType, func, eventSink), @@ -3100,136 +3019,19 @@ public: template - void Connect(int winid, - const EventTag& eventType, - void (Class::*func)(EventArg&), - wxObject *userData, - ObjClass *eventSink) - { Connect(winid, wxID_ANY, eventType, func, userData, eventSink); } - - template - - void Connect(const EventTag& eventType, - void (Class::*func)(EventArg&), - wxObject *userData, - ObjClass *eventSink) - { Connect(wxID_ANY, eventType, func, userData, eventSink); } - - - template - - bool Disconnect(int winid, - int lastId, - const EventTag& eventType, - void (Class::*func)(EventArg&), - wxObject *userData, - ObjClass *eventSink) + bool Unbind(const EventTag &eventType, + void (Class::*func)(EventArg&), + ObjClass *eventSink, + int winid = wxID_ANY, + int lastId = wxID_ANY, + wxObject *userData = NULL ) { return DoDisconnect(winid, lastId, eventType, wxMakeEventFunctor(eventType, func, eventSink), userData); } - - template - - bool Disconnect(int winid, - const EventTag& eventType, - void (Class::*func)(EventArg&), - wxObject *userData, - ObjClass *eventSink) - { return Disconnect(winid, wxID_ANY, eventType, func, - userData, eventSink); } - - template - - bool Disconnect(const EventTag& eventType, - void (Class::*func)(EventArg&), - wxObject *userData, - ObjClass *eventSink) - { return Disconnect(wxID_ANY, eventType, func, userData, eventSink); } - - - - // Static version of Connect() which allows to specify the event source and - // event handler in a more symmetric way - template - static void Connect(ObjSource *eventSrc, - int winid, - int lastId, - const EventTag& eventType, - void (Class::*func)(EventArg&), - wxObject *userData = NULL, - ObjClass *eventSink = NULL) - { - eventSrc->Connect(winid, lastId, eventType, func, userData, eventSink); - } - - template - static void Connect(ObjSource *eventSrc, - int winid, - const EventTag& eventType, - void (Class::*func)(EventArg&), - wxObject *userData = NULL, - ObjClass *eventSink = NULL) - { - Connect(eventSrc, winid, wxID_ANY, eventType, func, userData, eventSink); - } - - template - static void Connect(ObjSource *eventSrc, - const EventTag& eventType, - void (Class::*func)(EventArg&), - wxObject *userData = NULL, - ObjClass *eventSink = NULL) - { - Connect(eventSrc, wxID_ANY, eventType, func, userData, eventSink); - } - - - template - static bool Disconnect(ObjSource *eventSrc, - int winid, - int lastId, - const EventTag& eventType, - void (Class::*func)(EventArg&), - wxObject *userData = NULL, - ObjClass *eventSink = NULL) - { - return eventSrc->Disconnect(winid, lastId, eventType, func, - userData, eventSink); - } - - template - static bool Disconnect(ObjSource *eventSrc, - int winid, - const EventTag& eventType, - void (Class::*func)(EventArg&), - wxObject *userData = NULL, - ObjClass *eventSink = NULL) - { - return Disconnect(eventSrc, winid, wxID_ANY, eventType, func, - userData, eventSink); - } - - template - static bool Disconnect(ObjSource *eventSrc, - const EventTag& eventType, - void (Class::*func)(EventArg&), - wxObject *userData = NULL, - ObjClass *eventSink = NULL) - { - return Disconnect(eventSrc, wxID_ANY, eventType, func, - userData, eventSink); - } #endif // !wxEVENTS_COMPATIBILITY_2_8 - wxList* GetDynamicEventTable() const { return m_dynamicEvents ; } // User data can be associated with each wxEvtHandler diff --git a/include/wx/persist/window.h b/include/wx/persist/window.h index 1cb6d01257..84c27ba35c 100644 --- a/include/wx/persist/window.h +++ b/include/wx/persist/window.h @@ -34,6 +34,7 @@ public: wxPersistentWindowBase(wxWindow *win) : wxPersistentObject(win) { +#if wxEVENTS_COMPATIBILITY_2_8 win->Connect ( wxEVT_DESTROY, @@ -42,6 +43,9 @@ public: NULL, this ); +#else // !wxEVENTS_COMPATIBILITY_2_8 + win->Bind(wxEVT_DESTROY, &wxPersistentWindowBase::HandleDestroy, this); +#endif // wxEVENTS_COMPATIBILITY_2_8/!wxEVENTS_COMPATIBILITY_2_8 } virtual wxString GetName() const diff --git a/tests/events/evthandler.cpp b/tests/events/evthandler.cpp index 561680de76..031a0658da 100644 --- a/tests/events/evthandler.cpp +++ b/tests/events/evthandler.cpp @@ -37,7 +37,11 @@ public: }; typedef void (wxEvtHandler::*MyEventFunction)(MyEvent&); -#define MyEventHandler(func) wxEVENT_HANDLER_CAST(MyEventFunction, func) +#if wxEVENTS_COMPATIBILITY_2_8 + #define MyEventHandler(func) wxEVENT_HANDLER_CAST(MyEventFunction, func) +#else + #define MyEventHandler(func) &func +#endif #define EVT_MYEVENT(func) \ wx__DECLARE_EVT0(MyEventType, MyEventHandler(func)) @@ -152,30 +156,26 @@ private: CPPUNIT_TEST( BuiltinConnect ); CPPUNIT_TEST( LegacyConnect ); #if !wxEVENTS_COMPATIBILITY_2_8 - CPPUNIT_TEST( ConnectFunction ); - CPPUNIT_TEST( ConnectStaticMethod ); - CPPUNIT_TEST( ConnectFunctor ); - CPPUNIT_TEST( ConnectMethod ); - CPPUNIT_TEST( ConnectMethodUsingBaseEvent ); - CPPUNIT_TEST( ConnectMethodWithSink ); - CPPUNIT_TEST( ConnectNonHandler ); - CPPUNIT_TEST( StaticConnect ); - CPPUNIT_TEST( InvalidConnect ); + CPPUNIT_TEST( BindFunction ); + CPPUNIT_TEST( BindStaticMethod ); + CPPUNIT_TEST( BindFunctor ); + CPPUNIT_TEST( BindMethod ); + CPPUNIT_TEST( BindMethodUsingBaseEvent ); + CPPUNIT_TEST( BindNonHandler ); + CPPUNIT_TEST( InvalidBind ); #endif // !wxEVENTS_COMPATIBILITY_2_8 CPPUNIT_TEST_SUITE_END(); void BuiltinConnect(); void LegacyConnect(); #if !wxEVENTS_COMPATIBILITY_2_8 - void ConnectFunction(); - void ConnectStaticMethod(); - void ConnectFunctor(); - void ConnectMethod(); - void ConnectMethodUsingBaseEvent(); - void ConnectMethodWithSink(); - void ConnectNonHandler(); - void StaticConnect(); - void InvalidConnect(); + void BindFunction(); + void BindStaticMethod(); + void BindFunctor(); + void BindMethod(); + void BindMethodUsingBaseEvent(); + void BindNonHandler(); + void InvalidBind(); #endif // !wxEVENTS_COMPATIBILITY_2_8 @@ -207,18 +207,18 @@ void EvtHandlerTestCase::BuiltinConnect() handler.Disconnect(wxEVT_IDLE, (wxObjectEventFunction)(wxEventFunction)&MyHandler::OnIdle); #if !wxEVENTS_COMPATIBILITY_2_8 - handler.Connect(wxEVT_IDLE, GlobalOnIdle); - handler.Disconnect(wxEVT_IDLE, GlobalOnIdle); + handler.Bind(wxEVT_IDLE, GlobalOnIdle); + handler.Unbind(wxEVT_IDLE, GlobalOnIdle); IdleFunctor f; - handler.Connect(wxEVT_IDLE, f); - handler.Disconnect(wxEVT_IDLE, f); + handler.Bind(wxEVT_IDLE, f); + handler.Unbind(wxEVT_IDLE, f); - handler.Connect(wxEVT_IDLE, &MyHandler::OnIdle); - handler.Disconnect(wxEVT_IDLE, &MyHandler::OnIdle); + handler.Bind(wxEVT_IDLE, &MyHandler::OnIdle, &handler); + handler.Unbind(wxEVT_IDLE, &MyHandler::OnIdle, &handler); - handler.Connect(wxEVT_IDLE, &MyHandler::StaticOnIdle); - handler.Disconnect(wxEVT_IDLE, &MyHandler::StaticOnIdle); + handler.Bind(wxEVT_IDLE, &MyHandler::StaticOnIdle); + handler.Unbind(wxEVT_IDLE, &MyHandler::StaticOnIdle); #endif // !wxEVENTS_COMPATIBILITY_2_8 } @@ -244,152 +244,142 @@ void EvtHandlerTestCase::LegacyConnect() #if !wxEVENTS_COMPATIBILITY_2_8 -void EvtHandlerTestCase::ConnectFunction() +void EvtHandlerTestCase::BindFunction() { // function tests - handler.Connect( MyEventType, GlobalOnMyEvent ); + handler.Bind( MyEventType, GlobalOnMyEvent ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( g_called.function ); - handler.Disconnect( MyEventType, GlobalOnMyEvent ); + handler.Unbind( MyEventType, GlobalOnMyEvent ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( !g_called.function ); // check that it was disconnected - handler.Connect( 0, MyEventType, GlobalOnMyEvent ); - handler.Disconnect( 0, MyEventType, GlobalOnMyEvent ); + handler.Bind( MyEventType, GlobalOnMyEvent, 0 ); + handler.Unbind( MyEventType, GlobalOnMyEvent, 0 ); - handler.Connect( 0, 0, MyEventType, GlobalOnMyEvent ); - handler.Disconnect( 0, 0, MyEventType, GlobalOnMyEvent ); + handler.Bind( MyEventType, GlobalOnMyEvent, 0, 0 ); + handler.Unbind( MyEventType, GlobalOnMyEvent, 0, 0 ); } -void EvtHandlerTestCase::ConnectStaticMethod() +void EvtHandlerTestCase::BindStaticMethod() { // static method tests (this is same as functions but still test it just in // case we hit some strange compiler bugs) - handler.Connect( MyEventType, &MyHandler::StaticOnMyEvent ); + handler.Bind( MyEventType, &MyHandler::StaticOnMyEvent ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( g_called.smethod ); - handler.Disconnect( MyEventType, &MyHandler::StaticOnMyEvent ); + handler.Unbind( MyEventType, &MyHandler::StaticOnMyEvent ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( !g_called.smethod ); - handler.Connect( 0, MyEventType, &MyHandler::StaticOnMyEvent ); - handler.Disconnect( 0, MyEventType, &MyHandler::StaticOnMyEvent ); + handler.Bind( MyEventType, &MyHandler::StaticOnMyEvent, 0 ); + handler.Unbind( MyEventType, &MyHandler::StaticOnMyEvent, 0 ); - handler.Connect( 0, 0, MyEventType, &MyHandler::StaticOnMyEvent ); - handler.Disconnect( 0, 0, MyEventType, &MyHandler::StaticOnMyEvent ); + handler.Bind( MyEventType, &MyHandler::StaticOnMyEvent, 0, 0 ); + handler.Unbind( MyEventType, &MyHandler::StaticOnMyEvent, 0, 0 ); } -void EvtHandlerTestCase::ConnectFunctor() +void EvtHandlerTestCase::BindFunctor() { // generalized functor tests MyFunctor functor; - handler.Connect( MyEventType, functor ); + handler.Bind( MyEventType, functor ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( g_called.functor ); - handler.Disconnect( MyEventType, functor ); + handler.Unbind( MyEventType, functor ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( !g_called.functor ); - handler.Connect( 0, MyEventType, functor ); - handler.Disconnect( 0, MyEventType, functor ); + handler.Bind( MyEventType, functor, 0 ); + handler.Unbind( MyEventType, functor, 0 ); - handler.Connect( 0, 0, MyEventType, functor ); - handler.Disconnect( 0, 0, MyEventType, functor ); + handler.Bind( MyEventType, functor, 0, 0 ); + handler.Unbind( MyEventType, functor, 0, 0 ); } -void EvtHandlerTestCase::ConnectMethod() +void EvtHandlerTestCase::BindMethod() { // class method tests - handler.Connect( MyEventType, &MyHandler::OnMyEvent ); + handler.Bind( MyEventType, &MyHandler::OnMyEvent, &handler ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( g_called.method ); - handler.Disconnect( MyEventType, &MyHandler::OnMyEvent ); + handler.Unbind( MyEventType, &MyHandler::OnMyEvent, &handler ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( !g_called.method ); - handler.Connect( 0, MyEventType, &MyHandler::OnMyEvent ); - handler.Disconnect( 0, MyEventType, &MyHandler::OnMyEvent ); + handler.Bind( MyEventType, &MyHandler::OnMyEvent, &handler, 0 ); + handler.Unbind( MyEventType, &MyHandler::OnMyEvent, &handler, 0 ); - handler.Connect( 0, 0, MyEventType, &MyHandler::OnMyEvent ); - handler.Disconnect( 0, 0, MyEventType, &MyHandler::OnMyEvent ); + handler.Bind( MyEventType, &MyHandler::OnMyEvent, &handler, 0, 0 ); + handler.Unbind( MyEventType, &MyHandler::OnMyEvent, &handler, 0, 0 ); } -void EvtHandlerTestCase::ConnectMethodUsingBaseEvent() +void EvtHandlerTestCase::BindMethodUsingBaseEvent() { // test connecting a method taking just wxEvent and not MyEvent: this // should work too if we don't need any MyEvent-specific information in the // handler - handler.Connect( MyEventType, &MyHandler::OnEvent ); + handler.Bind( MyEventType, &MyHandler::OnEvent, &handler ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( g_called.method ); - handler.Disconnect( MyEventType, &MyHandler::OnEvent ); + handler.Unbind( MyEventType, &MyHandler::OnEvent, &handler ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( !g_called.method ); - handler.Connect( 0, MyEventType, &MyHandler::OnEvent ); - handler.Disconnect( 0, MyEventType, &MyHandler::OnEvent ); + handler.Bind( MyEventType, &MyHandler::OnEvent, &handler, 0 ); + handler.Unbind( MyEventType, &MyHandler::OnEvent, &handler, 0 ); - handler.Connect( 0, 0, MyEventType, &MyHandler::OnEvent ); - handler.Disconnect( 0, 0, MyEventType, &MyHandler::OnEvent ); + handler.Bind( MyEventType, &MyHandler::OnEvent, &handler, 0, 0 ); + handler.Unbind( MyEventType, &MyHandler::OnEvent, &handler, 0, 0 ); } -void EvtHandlerTestCase::ConnectMethodWithSink() -{ - handler.Connect( MyEventType, &MyHandler::OnMyEvent, NULL, &handler ); - handler.Connect( 0, MyEventType, &MyHandler::OnMyEvent, NULL, &handler ); - handler.Connect( 0, 0, MyEventType, &MyHandler::OnMyEvent, NULL, &handler ); - - handler.Disconnect( MyEventType, &MyHandler::OnMyEvent, NULL, &handler ); - handler.Disconnect( 0, MyEventType, &MyHandler::OnMyEvent, NULL, &handler ); - handler.Disconnect( 0, 0, MyEventType, &MyHandler::OnMyEvent, NULL, &handler ); -} -void EvtHandlerTestCase::ConnectNonHandler() +void EvtHandlerTestCase::BindNonHandler() { // class method tests for class not derived from wxEvtHandler MySink sink; - handler.Connect( MyEventType, &MySink::OnMyEvent, NULL, &sink ); + handler.Bind( MyEventType, &MySink::OnMyEvent, &sink ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( g_called.method ); - handler.Disconnect( MyEventType, &MySink::OnMyEvent, NULL, &sink ); + handler.Unbind( MyEventType, &MySink::OnMyEvent, &sink ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( !g_called.method ); } -void EvtHandlerTestCase::StaticConnect() -{ - wxEvtHandler::Connect( &handler, MyEventType, &MyHandler::OnMyEvent, NULL, &handler ); - wxEvtHandler::Connect( &handler, 0, MyEventType, &MyHandler::OnMyEvent, NULL, &handler ); - wxEvtHandler::Connect( &handler, 0, 0, MyEventType, &MyHandler::OnMyEvent, NULL, &handler ); - - wxEvtHandler::Disconnect( &handler, MyEventType, &MyHandler::OnMyEvent, NULL, &handler ); - wxEvtHandler::Disconnect( &handler, 0, MyEventType, &MyHandler::OnMyEvent, NULL, &handler ); - wxEvtHandler::Disconnect( &handler, 0, 0, MyEventType, &MyHandler::OnMyEvent, NULL, &handler ); -} - -void EvtHandlerTestCase::InvalidConnect() +void EvtHandlerTestCase::InvalidBind() { // these calls shouldn't compile but we unfortunately can't check this // automatically, you need to uncomment them manually and test that // compilation does indeed fail - //handler.Connect(MyEventType, GlobalOnAnotherEvent); - //IdleFunctor f; handler.Connect(MyEventType, f); - //handler.Connect(MyEventType, &MyHandler::StaticOnAnotherEvent); - //handler.Connect(MyEventType, &MyHandler::OnAnotherEvent); + + //handler.Bind(MyEventType, GlobalOnAnotherEvent); + //IdleFunctor f; handler.Bind(MyEventType, f); + //handler.Bind(MyEventType, &MyHandler::StaticOnAnotherEvent); + //handler.Bind(MyEventType, &MyHandler::OnAnotherEvent, &handler); + + // Test that this sample (discussed on the mailing list) doesn't compile: + // >struct C1 : wxEvtHandler { }; + // >struct C2 : wxEvtHandler { void OnWhatever(wxEvent&) }; + // >C1 c1; + // >c1.Connect(&C2::OnWhatever); // BOOM + + //MySink mySink; + //MyHandler myHandler; + //myHandler.Bind( MyEventType, &MyHandler::OnMyEvent, &mySink ); } #endif // !wxEVENTS_COMPATIBILITY_2_8