X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f3ff831f3be88834579fc9a0ce17f24745650faf..3c01c5951189e13b8b4a5d7b288b54d4a57a30f8:/tests/events/evthandler.cpp diff --git a/tests/events/evthandler.cpp b/tests/events/evthandler.cpp index 137fe3e6e2..366fb8e775 100644 --- a/tests/events/evthandler.cpp +++ b/tests/events/evthandler.cpp @@ -23,19 +23,28 @@ // test events and their handlers // ---------------------------------------------------------------------------- -const wxEventType EVT_LEGACY = wxNewEventType(); +const wxEventType LegacyEventType = wxNewEventType(); class MyEvent; -wxDEFINE_EVENT( EVT_MYEVENT, MyEvent ) +wxDEFINE_EVENT(MyEventType, MyEvent); class MyEvent : public wxEvent { public: - MyEvent() : wxEvent(0, EVT_MYEVENT) { } + MyEvent() : wxEvent(0, MyEventType) { } virtual wxEvent *Clone() const { return new MyEvent; } }; +typedef void (wxEvtHandler::*MyEventFunction)(MyEvent&); +#ifndef wxHAS_EVENT_BIND + #define MyEventHandler(func) wxEVENT_HANDLER_CAST(MyEventFunction, func) +#else + #define MyEventHandler(func) &func +#endif +#define EVT_MYEVENT(func) \ + wx__DECLARE_EVT0(MyEventType, MyEventHandler(func)) + class AnotherEvent : public wxEvent { }; @@ -66,6 +75,11 @@ void GlobalOnMyEvent(MyEvent&) g_called.function = true; } +void GlobalOnEvent(wxEvent&) +{ + g_called.function = true; +} + void GlobalOnAnotherEvent(AnotherEvent&); void GlobalOnIdle(wxIdleEvent&) @@ -100,6 +114,7 @@ public: struct MySink { void OnMyEvent(MyEvent&) { g_called.method = true; } + void OnEvent(wxEvent&) { g_called.method = true; } void OnIdle(wxIdleEvent&) { g_called.method = true; } }; @@ -119,7 +134,13 @@ private: BEGIN_EVENT_TABLE(MyClassWithEventTable, wxEvtHandler) EVT_IDLE(MyClassWithEventTable::OnIdle) + EVT_MYEVENT(MyClassWithEventTable::OnMyEvent) +#ifdef wxHAS_EVENT_BIND + EVT_MYEVENT(MyClassWithEventTable::OnEvent) +#endif + // this shouldn't compile: + //EVT_MYEVENT(MyClassWithEventTable::OnIdle) //EVT_IDLE(MyClassWithEventTable::OnAnotherEvent) END_EVENT_TABLE() @@ -139,30 +160,30 @@ private: CPPUNIT_TEST_SUITE( EvtHandlerTestCase ); 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( ConnectMethodWithSink ); - CPPUNIT_TEST( ConnectNonHandler ); - CPPUNIT_TEST( StaticConnect ); - CPPUNIT_TEST( InvalidConnect ); -#endif // !wxEVENTS_COMPATIBILITY_2_8 +#ifdef wxHAS_EVENT_BIND + CPPUNIT_TEST( BindFunction ); + CPPUNIT_TEST( BindStaticMethod ); + CPPUNIT_TEST( BindFunctor ); + CPPUNIT_TEST( BindMethod ); + CPPUNIT_TEST( BindMethodUsingBaseEvent ); + CPPUNIT_TEST( BindFunctionUsingBaseEvent ); + CPPUNIT_TEST( BindNonHandler ); + CPPUNIT_TEST( InvalidBind ); +#endif // wxHAS_EVENT_BIND CPPUNIT_TEST_SUITE_END(); void BuiltinConnect(); void LegacyConnect(); -#if !wxEVENTS_COMPATIBILITY_2_8 - void ConnectFunction(); - void ConnectStaticMethod(); - void ConnectFunctor(); - void ConnectMethod(); - void ConnectMethodWithSink(); - void ConnectNonHandler(); - void StaticConnect(); - void InvalidConnect(); -#endif // !wxEVENTS_COMPATIBILITY_2_8 +#ifdef wxHAS_EVENT_BIND + void BindFunction(); + void BindStaticMethod(); + void BindFunctor(); + void BindMethod(); + void BindMethodUsingBaseEvent(); + void BindFunctionUsingBaseEvent(); + void BindNonHandler(); + void InvalidBind(); +#endif // wxHAS_EVENT_BIND // these member variables exceptionally don't use "m_" prefix because @@ -187,169 +208,241 @@ void EvtHandlerTestCase::BuiltinConnect() handler.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), NULL, &handler); handler.Disconnect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), NULL, &handler); -#if !wxEVENTS_COMPATIBILITY_2_8 - handler.Connect(wxEVT_IDLE, GlobalOnIdle); - handler.Disconnect(wxEVT_IDLE, GlobalOnIdle); + // using casts like this is even uglier than using wxIdleEventHandler but + // it should still continue to work for compatibility + handler.Connect(wxEVT_IDLE, (wxObjectEventFunction)(wxEventFunction)&MyHandler::OnIdle); + handler.Disconnect(wxEVT_IDLE, (wxObjectEventFunction)(wxEventFunction)&MyHandler::OnIdle); + +#ifdef wxHAS_EVENT_BIND + 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); -#endif // !wxEVENTS_COMPATIBILITY_2_8 + handler.Bind(wxEVT_IDLE, &MyHandler::StaticOnIdle); + handler.Unbind(wxEVT_IDLE, &MyHandler::StaticOnIdle); +#endif // wxHAS_EVENT_BIND } void EvtHandlerTestCase::LegacyConnect() { - handler.Connect( EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent ); - handler.Connect( 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent ); - handler.Connect( 0, 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent ); + handler.Connect( LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent ); + handler.Connect( 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent ); + handler.Connect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent ); - handler.Disconnect( EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent ); - handler.Disconnect( 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent ); - handler.Disconnect( 0, 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent ); + handler.Disconnect( LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent ); + handler.Disconnect( 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent ); + handler.Disconnect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent ); - handler.Connect( EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); - handler.Connect( 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); - handler.Connect( 0, 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); + handler.Connect( LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); + handler.Connect( 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); + handler.Connect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); - handler.Disconnect( EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); - handler.Disconnect( 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); - handler.Disconnect( 0, 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); + handler.Disconnect( LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); + handler.Disconnect( 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); + handler.Disconnect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); } -#if !wxEVENTS_COMPATIBILITY_2_8 +#ifdef wxHAS_EVENT_BIND -void EvtHandlerTestCase::ConnectFunction() +void EvtHandlerTestCase::BindFunction() { // function tests - handler.Connect( EVT_MYEVENT, GlobalOnMyEvent ); + handler.Bind( MyEventType, GlobalOnMyEvent ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( g_called.function ); - handler.Disconnect( EVT_MYEVENT, GlobalOnMyEvent ); + handler.Unbind( MyEventType, GlobalOnMyEvent ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( !g_called.function ); // check that it was disconnected - handler.Connect( 0, EVT_MYEVENT, GlobalOnMyEvent ); - handler.Disconnect( 0, EVT_MYEVENT, GlobalOnMyEvent ); + handler.Bind( MyEventType, GlobalOnMyEvent, 0 ); + handler.Unbind( MyEventType, GlobalOnMyEvent, 0 ); - handler.Connect( 0, 0, EVT_MYEVENT, GlobalOnMyEvent ); - handler.Disconnect( 0, 0, EVT_MYEVENT, 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( EVT_MYEVENT, &MyHandler::StaticOnMyEvent ); + handler.Bind( MyEventType, &MyHandler::StaticOnMyEvent ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( g_called.smethod ); - handler.Disconnect( EVT_MYEVENT, &MyHandler::StaticOnMyEvent ); + handler.Unbind( MyEventType, &MyHandler::StaticOnMyEvent ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( !g_called.smethod ); - handler.Connect( 0, EVT_MYEVENT, &MyHandler::StaticOnMyEvent ); - handler.Disconnect( 0, EVT_MYEVENT, &MyHandler::StaticOnMyEvent ); + handler.Bind( MyEventType, &MyHandler::StaticOnMyEvent, 0 ); + handler.Unbind( MyEventType, &MyHandler::StaticOnMyEvent, 0 ); - handler.Connect( 0, 0, EVT_MYEVENT, &MyHandler::StaticOnMyEvent ); - handler.Disconnect( 0, 0, EVT_MYEVENT, &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( EVT_MYEVENT, functor ); + handler.Bind( MyEventType, functor ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( g_called.functor ); - handler.Disconnect( EVT_MYEVENT, functor ); + handler.Unbind( MyEventType, functor ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( !g_called.functor ); - handler.Connect( 0, EVT_MYEVENT, functor ); - handler.Disconnect( 0, EVT_MYEVENT, functor ); + handler.Bind( MyEventType, functor, 0 ); + handler.Unbind( MyEventType, functor, 0 ); + + handler.Bind( MyEventType, functor, 0, 0 ); + handler.Unbind( MyEventType, functor, 0, 0 ); + + // test that a temporary functor is working as well and also test that + // unbinding a different (though equal) instance of the same functor does + // not work + MyFunctor func; + handler.Bind( MyEventType, MyFunctor() ); + CPPUNIT_ASSERT( !handler.Unbind( MyEventType, func )); + + handler.Bind( MyEventType, MyFunctor(), 0 ); + CPPUNIT_ASSERT( !handler.Unbind( MyEventType, func, 0 )); - handler.Connect( 0, 0, EVT_MYEVENT, functor ); - handler.Disconnect( 0, 0, EVT_MYEVENT, functor ); + handler.Bind( MyEventType, MyFunctor(), 0, 0 ); + CPPUNIT_ASSERT( !handler.Unbind( MyEventType, func, 0, 0 )); } -void EvtHandlerTestCase::ConnectMethod() +void EvtHandlerTestCase::BindMethod() { // class method tests - handler.Connect( EVT_MYEVENT, &MyHandler::OnMyEvent ); + handler.Bind( MyEventType, &MyHandler::OnMyEvent, &handler ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( g_called.method ); - handler.Disconnect( EVT_MYEVENT, &MyHandler::OnMyEvent ); + handler.Unbind( MyEventType, &MyHandler::OnMyEvent, &handler ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( !g_called.method ); - handler.Connect( 0, EVT_MYEVENT, &MyHandler::OnMyEvent ); - handler.Disconnect( 0, EVT_MYEVENT, &MyHandler::OnMyEvent ); + handler.Bind( MyEventType, &MyHandler::OnMyEvent, &handler, 0 ); + handler.Unbind( MyEventType, &MyHandler::OnMyEvent, &handler, 0 ); - handler.Connect( 0, 0, EVT_MYEVENT, &MyHandler::OnMyEvent ); - handler.Disconnect( 0, 0, EVT_MYEVENT, &MyHandler::OnMyEvent ); + handler.Bind( MyEventType, &MyHandler::OnMyEvent, &handler, 0, 0 ); + handler.Unbind( MyEventType, &MyHandler::OnMyEvent, &handler, 0, 0 ); } -void EvtHandlerTestCase::ConnectMethodWithSink() +void EvtHandlerTestCase::BindMethodUsingBaseEvent() { - handler.Connect( EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); - handler.Connect( 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); - handler.Connect( 0, 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); + // 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.Bind( MyEventType, &MyHandler::OnEvent, &handler ); + g_called.Reset(); + handler.ProcessEvent(e); + CPPUNIT_ASSERT( g_called.method ); + handler.Unbind( MyEventType, &MyHandler::OnEvent, &handler ); + g_called.Reset(); + handler.ProcessEvent(e); + CPPUNIT_ASSERT( !g_called.method ); - handler.Disconnect( EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); - handler.Disconnect( 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); - handler.Disconnect( 0, 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); + handler.Bind( MyEventType, &MyHandler::OnEvent, &handler, 0 ); + handler.Unbind( MyEventType, &MyHandler::OnEvent, &handler, 0 ); + + handler.Bind( MyEventType, &MyHandler::OnEvent, &handler, 0, 0 ); + handler.Unbind( MyEventType, &MyHandler::OnEvent, &handler, 0, 0 ); } -void EvtHandlerTestCase::ConnectNonHandler() + +void EvtHandlerTestCase::BindFunctionUsingBaseEvent() +{ + // test connecting a function taking just wxEvent and not MyEvent: this + // should work too if we don't need any MyEvent-specific information in the + // handler + handler.Bind( MyEventType, GlobalOnEvent ); + g_called.Reset(); + handler.ProcessEvent(e); + CPPUNIT_ASSERT( g_called.function ); + handler.Unbind( MyEventType, GlobalOnEvent ); + g_called.Reset(); + handler.ProcessEvent(e); + CPPUNIT_ASSERT( !g_called.function ); + + handler.Bind( MyEventType, GlobalOnEvent, 0 ); + handler.Unbind( MyEventType, GlobalOnEvent, 0 ); + + handler.Bind( MyEventType, GlobalOnEvent, 0, 0 ); + handler.Unbind( MyEventType, GlobalOnEvent, 0, 0 ); +} + + + +void EvtHandlerTestCase::BindNonHandler() { // class method tests for class not derived from wxEvtHandler MySink sink; - handler.Connect( EVT_MYEVENT, &MySink::OnMyEvent, NULL, &sink ); + handler.Bind( MyEventType, &MySink::OnMyEvent, &sink ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( g_called.method ); - handler.Disconnect( EVT_MYEVENT, &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, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); - wxEvtHandler::Connect( &handler, 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); - wxEvtHandler::Connect( &handler, 0, 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); - - wxEvtHandler::Disconnect( &handler, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); - wxEvtHandler::Disconnect( &handler, 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); - wxEvtHandler::Disconnect( &handler, 0, 0, EVT_MYEVENT, &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(EVT_MYEVENT, GlobalOnAnotherEvent); - //IdleFunctor f; handler.Connect(EVT_MYEVENT, f); - //handler.Connect(EVT_MYEVENT, &MyHandler::StaticOnAnotherEvent); - //handler.Connect(EVT_MYEVENT, &MyHandler::OnAnotherEvent); + + // connecting a handler with incompatible signature shouldn't work +#ifdef TEST_INVALID_BIND_GLOBAL + handler.Bind(MyEventType, GlobalOnAnotherEvent); +#endif +#ifdef TEST_INVALID_BIND_STATIC + handler.Bind(MyEventType, &MyHandler::StaticOnAnotherEvent); +#endif +#ifdef TEST_INVALID_BIND_METHOD + handler.Bind(MyEventType, &MyHandler::OnAnotherEvent, &handler); +#endif +#ifdef TEST_INVALID_BIND_FUNCTOR + IdleFunctor f; + handler.Bind(MyEventType, f); +#endif + + // the handler can't be omitted when calling Bind() +#ifdef TEST_INVALID_BIND_NO_HANDLER + handler.Bind(MyEventType, &MyHandler::OnMyEvent); +#endif + + // calling a derived class method with a base class pointer must not work +#ifdef TEST_INVALID_BIND_DERIVED + struct C1 : wxEvtHandler { }; + struct C2 : wxEvtHandler { void OnWhatever(wxEvent&); }; + C1 c1; + c1.Bind(&C2::OnWhatever); +#endif + + // using object pointer incompatible with the method must not work +#ifdef TEST_INVALID_BIND_WRONG_CLASS + MySink mySink; + MyHandler myHandler; + myHandler.Bind(MyEventType, &MyHandler::OnMyEvent, &mySink); +#endif } -#endif // !wxEVENTS_COMPATIBILITY_2_8 +#endif // wxHAS_EVENT_BIND