]> git.saurik.com Git - wxWidgets.git/blobdiff - tests/events/evthandler.cpp
Applied patch #15540: wxRichTextTable: crashes due to an invalid focus object (dghart)
[wxWidgets.git] / tests / events / evthandler.cpp
index b6de4733738e528cb41bb9fe29dd8c32005d19d4..1496f4c196d7e7e71fde16c836dd9b65330fb3a0 100644 (file)
@@ -3,7 +3,6 @@
 // Purpose:     Test the new event types and wxEvtHandler-methods
 // Author:      Peter Most
 // Created:     2009-01-24
-// RCS-ID:      $Id$
 // Copyright:   (c) 2009 Peter Most
 ///////////////////////////////////////////////////////////////////////////////
 
     #pragma hdrstop
 #endif
 
-#ifndef WX_PRECOMP
-#endif // WX_PRECOMP
-
 #include "wx/event.h"
 
+// ----------------------------------------------------------------------------
+// test events and their handlers
+// ----------------------------------------------------------------------------
 
-// --------------------------------------------------------------------------
-// test class
-// --------------------------------------------------------------------------
+const wxEventType LegacyEventType = wxNewEventType();
 
-class EvtHandlerTestCase : public CppUnit::TestCase
+class MyEvent;
+wxDEFINE_EVENT(MyEventType, MyEvent);
+
+class MyEvent : public wxEvent
 {
 public:
-    EvtHandlerTestCase() {}
+    MyEvent() : wxEvent(0, MyEventType) { }
 
-private:
-    CPPUNIT_TEST_SUITE( EvtHandlerTestCase );
-        CPPUNIT_TEST( TestConnectCompilation );
-        CPPUNIT_TEST( TestEventFunctorCompare );
-    CPPUNIT_TEST_SUITE_END();
+    virtual wxEvent *Clone() const { return new MyEvent; }
+};
 
-    void TestConnectCompilation();
-    void TestEventFunctorCompare();
+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))
 
-    DECLARE_NO_COPY_CLASS(EvtHandlerTestCase)
+class AnotherEvent : public wxEvent
+{
 };
 
-// register in the unnamed registry so that these tests are run by default
-CPPUNIT_TEST_SUITE_REGISTRATION( EvtHandlerTestCase );
+namespace
+{
 
-// also include in it's own registry so that these tests can be run alone
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( EvtHandlerTestCase, "EvtHandlerTestCase" );
+struct Called
+{
+    Called() { Reset(); }
+
+    void Reset()
+    {
+        function =
+        functor =
+        method =
+        smethod = false;
+    }
+
+    bool function,
+         functor,
+         method,
+         smethod;
+} g_called;
+
+void GlobalOnMyEvent(MyEvent&)
+{
+    g_called.function = true;
+}
+
+void GlobalOnEvent(wxEvent&)
+{
+    g_called.function = true;
+}
 
-const wxEventType EVT_LEGACY = wxNewEventType();
+#ifdef TEST_INVALID_BIND_GLOBAL
+void GlobalOnAnotherEvent(AnotherEvent&);
+#endif
 
-class MyEvent : public wxEvent
+void GlobalOnIdle(wxIdleEvent&)
+{
+    g_called.function = true;
+}
+
+struct MyFunctor
 {
+    void operator()(MyEvent &) { g_called.functor = true; }
 };
 
-wxDEFINE_EVENT( EVT_EVENT, MyEvent )
+struct IdleFunctor
+{
+    void operator()(wxIdleEvent &) { g_called.functor = true; }
+};
 
-// An arbitrary functor:
+class MyHandler : public wxEvtHandler
+{
+public:
+    static void StaticOnMyEvent(MyEvent &) { g_called.smethod = true; }
+    static void StaticOnAnotherEvent(AnotherEvent &);
+    static void StaticOnIdle(wxIdleEvent&) { g_called.smethod = true; }
+
+    void OnMyEvent(MyEvent&) { g_called.method = true; }
+    void OnEvent(wxEvent&) { g_called.method = true; }
+    void OnAnotherEvent(AnotherEvent&);
+    void OnIdle(wxIdleEvent&) { g_called.method = true; }
+};
 
-class MyFunctor
+// we can also handle events in classes not deriving from wxEvtHandler
+struct MySink
 {
-    public:
-        void operator () ( MyEvent & )
-        { }
+    void OnMyEvent(MyEvent&) { g_called.method = true; }
+    void OnEvent(wxEvent&) { g_called.method = true; }
+    void OnIdle(wxIdleEvent&) { g_called.method = true; }
+};
+
+// also test event table compilation
+class MyClassWithEventTable : public wxEvtHandler
+{
+public:
+    void OnMyEvent(MyEvent&) { g_called.method = true; }
+    void OnEvent(wxEvent&) { g_called.method = true; }
+    void OnAnotherEvent(AnotherEvent&);
+    void OnIdle(wxIdleEvent&) { g_called.method = true; }
 
-        bool operator == ( const MyFunctor & ) const
-        { return ( true ); }
+private:
+    DECLARE_EVENT_TABLE()
 };
 
+BEGIN_EVENT_TABLE(MyClassWithEventTable, wxEvtHandler)
+    EVT_IDLE(MyClassWithEventTable::OnIdle)
 
-class MyHandler : public wxEvtHandler
+    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()
+
+} // anonymous namespace
+
+
+// --------------------------------------------------------------------------
+// test class
+// --------------------------------------------------------------------------
+
+class EvtHandlerTestCase : public CppUnit::TestCase
 {
-    public:
-        void handleMethod( MyEvent & )
-        { }
+public:
+    EvtHandlerTestCase() {}
 
-        static void handleFunction( MyEvent & )
-        { }
+private:
+    CPPUNIT_TEST_SUITE( EvtHandlerTestCase );
+        CPPUNIT_TEST( BuiltinConnect );
+        CPPUNIT_TEST( LegacyConnect );
+        CPPUNIT_TEST( DisconnectWildcard );
+        CPPUNIT_TEST( AutoDisconnect );
+#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 handleEvent( wxEvent & )
-        { }
+    void BuiltinConnect();
+    void LegacyConnect();
+    void DisconnectWildcard();
+    void AutoDisconnect();
+#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
+    // they're used so many times
+    MyHandler handler;
+    MyEvent e;
 
+    DECLARE_NO_COPY_CLASS(EvtHandlerTestCase)
 };
 
-void EvtHandlerTestCase::TestConnectCompilation()
+// register in the unnamed registry so that these tests are run by default
+CPPUNIT_TEST_SUITE_REGISTRATION( EvtHandlerTestCase );
+
+// also include in its own registry so that these tests can be run alone
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( EvtHandlerTestCase, "EvtHandlerTestCase" );
+
+void EvtHandlerTestCase::BuiltinConnect()
 {
-    // Test that connecting the 'legacy' events still compiles:
+    handler.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle));
+    handler.Disconnect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle));
 
-    MyHandler handler;
+    handler.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), NULL, &handler);
+    handler.Disconnect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), NULL, &handler);
+
+    // 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);
 
-    handler.Connect( EVT_LEGACY, (wxObjectEventFunction)&MyHandler::handleEvent, NULL, &handler );
-    handler.Connect( 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::handleEvent, NULL, &handler );
-    handler.Connect( 0, 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::handleEvent, NULL, &handler );
+#ifdef wxHAS_EVENT_BIND
+    handler.Bind(wxEVT_IDLE, GlobalOnIdle);
+    handler.Unbind(wxEVT_IDLE, GlobalOnIdle);
 
-    handler.Disconnect( EVT_LEGACY, (wxObjectEventFunction)&MyHandler::handleEvent, NULL, &handler );
-    handler.Disconnect( 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::handleEvent, NULL, &handler );
-    handler.Disconnect( 0, 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::handleEvent, NULL, &handler );
+    IdleFunctor f;
+    handler.Bind(wxEVT_IDLE, f);
+    handler.Unbind(wxEVT_IDLE, f);
 
+    handler.Bind(wxEVT_IDLE, &MyHandler::OnIdle, &handler);
+    handler.Unbind(wxEVT_IDLE, &MyHandler::OnIdle, &handler);
 
+    handler.Bind(wxEVT_IDLE, &MyHandler::StaticOnIdle);
+    handler.Unbind(wxEVT_IDLE, &MyHandler::StaticOnIdle);
+#endif // wxHAS_EVENT_BIND
+}
 
-    handler.Connect( EVT_LEGACY, (wxObjectEventFunction)&MyHandler::handleEvent );
-    handler.Connect( 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::handleEvent );
-    handler.Connect( 0, 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::handleEvent );
+void EvtHandlerTestCase::LegacyConnect()
+{
+    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::handleEvent );
-    handler.Disconnect( 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::handleEvent );
-    handler.Disconnect( 0, 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::handleEvent );
+    handler.Disconnect( LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
+    handler.Disconnect( 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
+    handler.Disconnect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
 
-    // Call (and therefore instantiate) all Connect() variants to detect template
-    // errors:
 
-#if !wxEVENTS_COMPATIBILITY_2_8
+    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.Connect( EVT_EVENT, &MyHandler::handleFunction );
-    handler.Connect( 0, EVT_EVENT, &MyHandler::handleFunction );
-    handler.Connect( 0, 0, EVT_EVENT, &MyHandler::handleFunction );
+    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 );
+}
 
-    handler.Disconnect( EVT_EVENT, &MyHandler::handleFunction );
-    handler.Disconnect( 0, EVT_EVENT, &MyHandler::handleFunction );
-    handler.Disconnect( 0, 0, EVT_EVENT, &MyHandler::handleFunction );
+void EvtHandlerTestCase::DisconnectWildcard()
+{
+    // should be able to disconnect a different handler using "wildcard search"
+    MyHandler sink;
+    wxEvtHandler source;
+    source.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), NULL, &sink);
+    CPPUNIT_ASSERT(source.Disconnect(wxID_ANY, wxEVT_IDLE));
+    // destruction of source and sink here should properly clean up the
+    // wxEventConnectionRef without crashing
+}
 
+void EvtHandlerTestCase::AutoDisconnect()
+{
+    wxEvtHandler source;
+    {
+        MyHandler sink;
+        source.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), NULL, &sink);
+        // mismatched event type, so nothing should be disconnected
+        CPPUNIT_ASSERT(!source.Disconnect(wxEVT_THREAD, wxIdleEventHandler(MyHandler::OnIdle), NULL, &sink));
+    }
+    // destruction of sink should have automatically disconnected it, so
+    // there should be nothing to disconnect anymore
+    CPPUNIT_ASSERT(!source.Disconnect(wxID_ANY, wxEVT_IDLE));
+}
 
+#ifdef wxHAS_EVENT_BIND
 
-    handler.Connect( EVT_EVENT, &MyHandler::handleMethod );
-    handler.Connect( 0, EVT_EVENT, &MyHandler::handleMethod );
-    handler.Connect( 0, 0, EVT_EVENT, &MyHandler::handleMethod );
+void EvtHandlerTestCase::BindFunction()
+{
+    // function tests
+    handler.Bind( MyEventType, GlobalOnMyEvent );
+    g_called.Reset();
+    handler.ProcessEvent(e);
+    CPPUNIT_ASSERT( g_called.function );
+    handler.Unbind( MyEventType, GlobalOnMyEvent );
+    g_called.Reset();
+    handler.ProcessEvent(e);
+    CPPUNIT_ASSERT( !g_called.function ); // check that it was disconnected
+
+    handler.Bind( MyEventType, GlobalOnMyEvent, 0 );
+    handler.Unbind( MyEventType, GlobalOnMyEvent, 0 );
+
+    handler.Bind( MyEventType, GlobalOnMyEvent, 0, 0 );
+    handler.Unbind( MyEventType, GlobalOnMyEvent, 0, 0 );
+}
 
-    handler.Disconnect( EVT_EVENT, &MyHandler::handleMethod );
-    handler.Disconnect( 0, EVT_EVENT, &MyHandler::handleMethod );
-    handler.Disconnect( 0, 0, EVT_EVENT, &MyHandler::handleMethod );
+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.Bind( MyEventType, &MyHandler::StaticOnMyEvent );
+    g_called.Reset();
+    handler.ProcessEvent(e);
+    CPPUNIT_ASSERT( g_called.smethod );
+    handler.Unbind( MyEventType, &MyHandler::StaticOnMyEvent );
+    g_called.Reset();
+    handler.ProcessEvent(e);
+    CPPUNIT_ASSERT( !g_called.smethod );
+
+    handler.Bind( MyEventType, &MyHandler::StaticOnMyEvent, 0 );
+    handler.Unbind( MyEventType, &MyHandler::StaticOnMyEvent, 0 );
+
+    handler.Bind( MyEventType, &MyHandler::StaticOnMyEvent, 0, 0 );
+    handler.Unbind( MyEventType, &MyHandler::StaticOnMyEvent, 0, 0 );
+}
 
+void EvtHandlerTestCase::BindFunctor()
+{
+    // generalized functor tests
+    MyFunctor functor;
 
+    handler.Bind( MyEventType, functor );
+    g_called.Reset();
+    handler.ProcessEvent(e);
+    CPPUNIT_ASSERT( g_called.functor );
+    handler.Unbind( MyEventType, functor );
+    g_called.Reset();
+    handler.ProcessEvent(e);
+    CPPUNIT_ASSERT( !g_called.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.Bind( MyEventType, MyFunctor(), 0, 0 );
+    CPPUNIT_ASSERT( !handler.Unbind( MyEventType, func, 0, 0 ));
+}
 
-    handler.Connect( EVT_EVENT, &MyHandler::handleMethod, NULL, &handler );
-    handler.Connect( 0, EVT_EVENT, &MyHandler::handleMethod, NULL, &handler );
-    handler.Connect( 0, 0, EVT_EVENT, &MyHandler::handleMethod, NULL, &handler );
+void EvtHandlerTestCase::BindMethod()
+{
+    // class method tests
+    handler.Bind( MyEventType, &MyHandler::OnMyEvent, &handler );
+    g_called.Reset();
+    handler.ProcessEvent(e);
+    CPPUNIT_ASSERT( g_called.method );
+    handler.Unbind( MyEventType, &MyHandler::OnMyEvent, &handler );
+    g_called.Reset();
+    handler.ProcessEvent(e);
+    CPPUNIT_ASSERT( !g_called.method );
+
+    handler.Bind( MyEventType, &MyHandler::OnMyEvent, &handler, 0 );
+    handler.Unbind( MyEventType, &MyHandler::OnMyEvent, &handler, 0 );
+
+    handler.Bind( MyEventType, &MyHandler::OnMyEvent, &handler, 0, 0 );
+    handler.Unbind( MyEventType, &MyHandler::OnMyEvent, &handler, 0, 0 );
+}
 
-    handler.Disconnect( EVT_EVENT, &MyHandler::handleMethod, NULL, &handler );
-    handler.Disconnect( 0, EVT_EVENT, &MyHandler::handleMethod, NULL, &handler );
-    handler.Disconnect( 0, 0, EVT_EVENT, &MyHandler::handleMethod, NULL, &handler );
+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.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.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::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 );
+}
 
-    wxEvtHandler::Connect( &handler, EVT_EVENT, &MyHandler::handleMethod, NULL, &handler );
-    wxEvtHandler::Connect( &handler, 0, EVT_EVENT, &MyHandler::handleMethod, NULL, &handler );
-    wxEvtHandler::Connect( &handler, 0, 0, EVT_EVENT, &MyHandler::handleMethod, NULL, &handler );
 
-    wxEvtHandler::Disconnect( &handler, EVT_EVENT, &MyHandler::handleMethod, NULL, &handler );
-    wxEvtHandler::Disconnect( &handler, 0, EVT_EVENT, &MyHandler::handleMethod, NULL, &handler );
-    wxEvtHandler::Disconnect( &handler, 0, 0, EVT_EVENT, &MyHandler::handleMethod, NULL, &handler );
 
+void EvtHandlerTestCase::BindNonHandler()
+{
+    // class method tests for class not derived from wxEvtHandler
+    MySink sink;
+
+    handler.Bind( MyEventType, &MySink::OnMyEvent, &sink );
+    g_called.Reset();
+    handler.ProcessEvent(e);
+    CPPUNIT_ASSERT( g_called.method );
+    handler.Unbind( MyEventType, &MySink::OnMyEvent, &sink );
+    g_called.Reset();
+    handler.ProcessEvent(e);
+    CPPUNIT_ASSERT( !g_called.method );
+}
 
+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
 
-    MyFunctor functor;
+    // 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
 
-    handler.Connect( EVT_EVENT, functor );
-    handler.Connect( 0, EVT_EVENT, functor );
-    handler.Connect( 0, 0, EVT_EVENT, functor );
+    // the handler can't be omitted when calling Bind()
+#ifdef TEST_INVALID_BIND_NO_HANDLER
+    handler.Bind(MyEventType, &MyHandler::OnMyEvent);
+#endif
 
-    handler.Disconnect( EVT_EVENT, functor );
-    handler.Disconnect( 0, EVT_EVENT, functor );
-    handler.Disconnect( 0, 0, EVT_EVENT, functor );
+    // 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
-}
 
-void EvtHandlerTestCase::TestEventFunctorCompare()
-{
-//#if !wxEVENTS_COMPATIBILITY_2_8
-//    MyHandler handler1;
-//    wxEventFunctor *connectFunctor = wxNewEventFunctor( EVT_EVENT, &MyHandler::handleMethod, &handler1 );
-//    wxEventFunctor *disconnectFunctor = wxNewEventFunctor( EVT_EVENT, &MyHandler::handleMethod, &handler1 );
-//    wxEventFunctor *nullFunctor = wxNewEventFunctor( EVT_EVENT, &MyHandler::handleMethod );
-//   
-//    CPPUNIT_ASSERT( connectFunctor->Matches( *disconnectFunctor ));
-//    CPPUNIT_ASSERT( disconnectFunctor->Matches( *connectFunctor ));
-//
-//    CPPUNIT_ASSERT( connectFunctor->Matches( *nullFunctor ));
-//    CPPUNIT_ASSERT( nullFunctor->Matches( *connectFunctor ));
-//
-//    CPPUNIT_ASSERT( disconnectFunctor->Matches( *nullFunctor ));
-//    CPPUNIT_ASSERT( nullFunctor->Matches( *disconnectFunctor ));
-//#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 // wxHAS_EVENT_BIND