| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478 | 
							- ///////////////////////////////////////////////////////////////////////////////
 
- // Name:        tests/events/evthandler.cpp
 
- // Purpose:     Test the new event types and wxEvtHandler-methods
 
- // Author:      Peter Most
 
- // Created:     2009-01-24
 
- // Copyright:   (c) 2009 Peter Most
 
- ///////////////////////////////////////////////////////////////////////////////
 
- // ----------------------------------------------------------------------------
 
- // headers
 
- // ----------------------------------------------------------------------------
 
- #include "testprec.h"
 
- #ifdef __BORLANDC__
 
-     #pragma hdrstop
 
- #endif
 
- #include "wx/event.h"
 
- // ----------------------------------------------------------------------------
 
- // test events and their handlers
 
- // ----------------------------------------------------------------------------
 
- const wxEventType LegacyEventType = wxNewEventType();
 
- class MyEvent;
 
- wxDEFINE_EVENT(MyEventType, MyEvent);
 
- class MyEvent : public wxEvent
 
- {
 
- public:
 
-     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
 
- {
 
- };
 
- namespace
 
- {
 
- 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;
 
- }
 
- #ifdef TEST_INVALID_BIND_GLOBAL
 
- void GlobalOnAnotherEvent(AnotherEvent&);
 
- #endif
 
- void GlobalOnIdle(wxIdleEvent&)
 
- {
 
-     g_called.function = true;
 
- }
 
- struct MyFunctor
 
- {
 
-     void operator()(MyEvent &) { g_called.functor = true; }
 
- };
 
- struct IdleFunctor
 
- {
 
-     void operator()(wxIdleEvent &) { g_called.functor = true; }
 
- };
 
- 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; }
 
- };
 
- // we can also handle events in classes not deriving from wxEvtHandler
 
- struct MySink
 
- {
 
-     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; }
 
- private:
 
-     DECLARE_EVENT_TABLE()
 
- };
 
- 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()
 
- } // anonymous namespace
 
- // --------------------------------------------------------------------------
 
- // test class
 
- // --------------------------------------------------------------------------
 
- class EvtHandlerTestCase : public CppUnit::TestCase
 
- {
 
- public:
 
-     EvtHandlerTestCase() {}
 
- 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 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)
 
- };
 
- // 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()
 
- {
 
-     handler.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle));
 
-     handler.Disconnect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle));
 
-     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);
 
- #ifdef wxHAS_EVENT_BIND
 
-     handler.Bind(wxEVT_IDLE, GlobalOnIdle);
 
-     handler.Unbind(wxEVT_IDLE, GlobalOnIdle);
 
-     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
 
- }
 
- 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( LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
 
-     handler.Disconnect( 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
 
-     handler.Disconnect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
 
-     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( 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 );
 
- }
 
- 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
 
- 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 );
 
- }
 
- 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 ));
 
- }
 
- 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 );
 
- }
 
- 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 );
 
- }
 
- 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
 
-     // 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 // wxHAS_EVENT_BIND
 
 
  |