1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/events/evthandler.cpp
3 // Purpose: Test the new event types and wxEvtHandler-methods
7 // Copyright: (c) 2009 Peter Most
8 ///////////////////////////////////////////////////////////////////////////////
10 // ----------------------------------------------------------------------------
12 // ----------------------------------------------------------------------------
22 // ----------------------------------------------------------------------------
23 // test events and their handlers
24 // ----------------------------------------------------------------------------
26 const wxEventType LegacyEventType
= wxNewEventType();
29 wxDEFINE_EVENT(MyEventType
, MyEvent
);
31 class MyEvent
: public wxEvent
34 MyEvent() : wxEvent(0, MyEventType
) { }
36 virtual wxEvent
*Clone() const { return new MyEvent
; }
39 typedef void (wxEvtHandler::*MyEventFunction
)(MyEvent
&);
40 #if wxEVENTS_COMPATIBILITY_2_8
41 #define MyEventHandler(func) wxEVENT_HANDLER_CAST(MyEventFunction, func)
43 #define MyEventHandler(func) &func
45 #define EVT_MYEVENT(func) \
46 wx__DECLARE_EVT0(MyEventType, MyEventHandler(func))
48 class AnotherEvent
: public wxEvent
73 void GlobalOnMyEvent(MyEvent
&)
75 g_called
.function
= true;
78 void GlobalOnAnotherEvent(AnotherEvent
&);
80 void GlobalOnIdle(wxIdleEvent
&)
82 g_called
.function
= true;
87 void operator()(MyEvent
&) { g_called
.functor
= true; }
92 void operator()(wxIdleEvent
&) { g_called
.functor
= true; }
95 class MyHandler
: public wxEvtHandler
98 static void StaticOnMyEvent(MyEvent
&) { g_called
.smethod
= true; }
99 static void StaticOnAnotherEvent(AnotherEvent
&);
100 static void StaticOnIdle(wxIdleEvent
&) { g_called
.smethod
= true; }
102 void OnMyEvent(MyEvent
&) { g_called
.method
= true; }
103 void OnEvent(wxEvent
&) { g_called
.method
= true; }
104 void OnAnotherEvent(AnotherEvent
&);
105 void OnIdle(wxIdleEvent
&) { g_called
.method
= true; }
108 // we can also handle events in classes not deriving from wxEvtHandler
111 void OnMyEvent(MyEvent
&) { g_called
.method
= true; }
112 void OnEvent(wxEvent
&) { g_called
.method
= true; }
113 void OnIdle(wxIdleEvent
&) { g_called
.method
= true; }
116 // also test event table compilation
117 class MyClassWithEventTable
: public wxEvtHandler
120 void OnMyEvent(MyEvent
&) { g_called
.method
= true; }
121 void OnEvent(wxEvent
&) { g_called
.method
= true; }
122 void OnAnotherEvent(AnotherEvent
&);
123 void OnIdle(wxIdleEvent
&) { g_called
.method
= true; }
126 DECLARE_EVENT_TABLE()
129 BEGIN_EVENT_TABLE(MyClassWithEventTable
, wxEvtHandler
)
130 EVT_IDLE(MyClassWithEventTable::OnIdle
)
132 EVT_MYEVENT(MyClassWithEventTable::OnMyEvent
)
133 #if !wxEVENTS_COMPATIBILITY_2_8
134 EVT_MYEVENT(MyClassWithEventTable::OnEvent
)
137 // this shouldn't compile:
138 //EVT_MYEVENT(MyClassWithEventTable::OnIdle)
139 //EVT_IDLE(MyClassWithEventTable::OnAnotherEvent)
142 } // anonymous namespace
145 // --------------------------------------------------------------------------
147 // --------------------------------------------------------------------------
149 class EvtHandlerTestCase
: public CppUnit::TestCase
152 EvtHandlerTestCase() {}
155 CPPUNIT_TEST_SUITE( EvtHandlerTestCase
);
156 CPPUNIT_TEST( BuiltinConnect
);
157 CPPUNIT_TEST( LegacyConnect
);
158 #if !wxEVENTS_COMPATIBILITY_2_8
159 CPPUNIT_TEST( BindFunction
);
160 CPPUNIT_TEST( BindStaticMethod
);
161 CPPUNIT_TEST( BindFunctor
);
162 CPPUNIT_TEST( BindMethod
);
163 CPPUNIT_TEST( BindMethodUsingBaseEvent
);
164 CPPUNIT_TEST( BindNonHandler
);
165 CPPUNIT_TEST( InvalidBind
);
166 #endif // !wxEVENTS_COMPATIBILITY_2_8
167 CPPUNIT_TEST_SUITE_END();
169 void BuiltinConnect();
170 void LegacyConnect();
171 #if !wxEVENTS_COMPATIBILITY_2_8
173 void BindStaticMethod();
176 void BindMethodUsingBaseEvent();
177 void BindNonHandler();
179 #endif // !wxEVENTS_COMPATIBILITY_2_8
182 // these member variables exceptionally don't use "m_" prefix because
183 // they're used so many times
187 DECLARE_NO_COPY_CLASS(EvtHandlerTestCase
)
190 // register in the unnamed registry so that these tests are run by default
191 CPPUNIT_TEST_SUITE_REGISTRATION( EvtHandlerTestCase
);
193 // also include in it's own registry so that these tests can be run alone
194 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( EvtHandlerTestCase
, "EvtHandlerTestCase" );
196 void EvtHandlerTestCase::BuiltinConnect()
198 handler
.Connect(wxEVT_IDLE
, wxIdleEventHandler(MyHandler::OnIdle
));
199 handler
.Disconnect(wxEVT_IDLE
, wxIdleEventHandler(MyHandler::OnIdle
));
201 handler
.Connect(wxEVT_IDLE
, wxIdleEventHandler(MyHandler::OnIdle
), NULL
, &handler
);
202 handler
.Disconnect(wxEVT_IDLE
, wxIdleEventHandler(MyHandler::OnIdle
), NULL
, &handler
);
204 // using casts like this is even uglier than using wxIdleEventHandler but
205 // it should still continue to work for compatibility
206 handler
.Connect(wxEVT_IDLE
, (wxObjectEventFunction
)(wxEventFunction
)&MyHandler::OnIdle
);
207 handler
.Disconnect(wxEVT_IDLE
, (wxObjectEventFunction
)(wxEventFunction
)&MyHandler::OnIdle
);
209 #if !wxEVENTS_COMPATIBILITY_2_8
210 handler
.Bind(wxEVT_IDLE
, GlobalOnIdle
);
211 handler
.Unbind(wxEVT_IDLE
, GlobalOnIdle
);
214 handler
.Bind(wxEVT_IDLE
, f
);
215 handler
.Unbind(wxEVT_IDLE
, f
);
217 handler
.Bind(wxEVT_IDLE
, &MyHandler::OnIdle
, &handler
);
218 handler
.Unbind(wxEVT_IDLE
, &MyHandler::OnIdle
, &handler
);
220 handler
.Bind(wxEVT_IDLE
, &MyHandler::StaticOnIdle
);
221 handler
.Unbind(wxEVT_IDLE
, &MyHandler::StaticOnIdle
);
222 #endif // !wxEVENTS_COMPATIBILITY_2_8
225 void EvtHandlerTestCase::LegacyConnect()
227 handler
.Connect( LegacyEventType
, (wxObjectEventFunction
)&MyHandler::OnEvent
);
228 handler
.Connect( 0, LegacyEventType
, (wxObjectEventFunction
)&MyHandler::OnEvent
);
229 handler
.Connect( 0, 0, LegacyEventType
, (wxObjectEventFunction
)&MyHandler::OnEvent
);
231 handler
.Disconnect( LegacyEventType
, (wxObjectEventFunction
)&MyHandler::OnEvent
);
232 handler
.Disconnect( 0, LegacyEventType
, (wxObjectEventFunction
)&MyHandler::OnEvent
);
233 handler
.Disconnect( 0, 0, LegacyEventType
, (wxObjectEventFunction
)&MyHandler::OnEvent
);
236 handler
.Connect( LegacyEventType
, (wxObjectEventFunction
)&MyHandler::OnEvent
, NULL
, &handler
);
237 handler
.Connect( 0, LegacyEventType
, (wxObjectEventFunction
)&MyHandler::OnEvent
, NULL
, &handler
);
238 handler
.Connect( 0, 0, LegacyEventType
, (wxObjectEventFunction
)&MyHandler::OnEvent
, NULL
, &handler
);
240 handler
.Disconnect( LegacyEventType
, (wxObjectEventFunction
)&MyHandler::OnEvent
, NULL
, &handler
);
241 handler
.Disconnect( 0, LegacyEventType
, (wxObjectEventFunction
)&MyHandler::OnEvent
, NULL
, &handler
);
242 handler
.Disconnect( 0, 0, LegacyEventType
, (wxObjectEventFunction
)&MyHandler::OnEvent
, NULL
, &handler
);
245 #if !wxEVENTS_COMPATIBILITY_2_8
247 void EvtHandlerTestCase::BindFunction()
250 handler
.Bind( MyEventType
, GlobalOnMyEvent
);
252 handler
.ProcessEvent(e
);
253 CPPUNIT_ASSERT( g_called
.function
);
254 handler
.Unbind( MyEventType
, GlobalOnMyEvent
);
256 handler
.ProcessEvent(e
);
257 CPPUNIT_ASSERT( !g_called
.function
); // check that it was disconnected
259 handler
.Bind( MyEventType
, GlobalOnMyEvent
, 0 );
260 handler
.Unbind( MyEventType
, GlobalOnMyEvent
, 0 );
262 handler
.Bind( MyEventType
, GlobalOnMyEvent
, 0, 0 );
263 handler
.Unbind( MyEventType
, GlobalOnMyEvent
, 0, 0 );
266 void EvtHandlerTestCase::BindStaticMethod()
268 // static method tests (this is same as functions but still test it just in
269 // case we hit some strange compiler bugs)
270 handler
.Bind( MyEventType
, &MyHandler::StaticOnMyEvent
);
272 handler
.ProcessEvent(e
);
273 CPPUNIT_ASSERT( g_called
.smethod
);
274 handler
.Unbind( MyEventType
, &MyHandler::StaticOnMyEvent
);
276 handler
.ProcessEvent(e
);
277 CPPUNIT_ASSERT( !g_called
.smethod
);
279 handler
.Bind( MyEventType
, &MyHandler::StaticOnMyEvent
, 0 );
280 handler
.Unbind( MyEventType
, &MyHandler::StaticOnMyEvent
, 0 );
282 handler
.Bind( MyEventType
, &MyHandler::StaticOnMyEvent
, 0, 0 );
283 handler
.Unbind( MyEventType
, &MyHandler::StaticOnMyEvent
, 0, 0 );
286 void EvtHandlerTestCase::BindFunctor()
288 // generalized functor tests
291 handler
.Bind( MyEventType
, functor
);
293 handler
.ProcessEvent(e
);
294 CPPUNIT_ASSERT( g_called
.functor
);
295 handler
.Unbind( MyEventType
, functor
);
297 handler
.ProcessEvent(e
);
298 CPPUNIT_ASSERT( !g_called
.functor
);
300 handler
.Bind( MyEventType
, functor
, 0 );
301 handler
.Unbind( MyEventType
, functor
, 0 );
303 handler
.Bind( MyEventType
, functor
, 0, 0 );
304 handler
.Unbind( MyEventType
, functor
, 0, 0 );
307 void EvtHandlerTestCase::BindMethod()
309 // class method tests
310 handler
.Bind( MyEventType
, &MyHandler::OnMyEvent
, &handler
);
312 handler
.ProcessEvent(e
);
313 CPPUNIT_ASSERT( g_called
.method
);
314 handler
.Unbind( MyEventType
, &MyHandler::OnMyEvent
, &handler
);
316 handler
.ProcessEvent(e
);
317 CPPUNIT_ASSERT( !g_called
.method
);
319 handler
.Bind( MyEventType
, &MyHandler::OnMyEvent
, &handler
, 0 );
320 handler
.Unbind( MyEventType
, &MyHandler::OnMyEvent
, &handler
, 0 );
322 handler
.Bind( MyEventType
, &MyHandler::OnMyEvent
, &handler
, 0, 0 );
323 handler
.Unbind( MyEventType
, &MyHandler::OnMyEvent
, &handler
, 0, 0 );
326 void EvtHandlerTestCase::BindMethodUsingBaseEvent()
328 // test connecting a method taking just wxEvent and not MyEvent: this
329 // should work too if we don't need any MyEvent-specific information in the
331 handler
.Bind( MyEventType
, &MyHandler::OnEvent
, &handler
);
333 handler
.ProcessEvent(e
);
334 CPPUNIT_ASSERT( g_called
.method
);
335 handler
.Unbind( MyEventType
, &MyHandler::OnEvent
, &handler
);
337 handler
.ProcessEvent(e
);
338 CPPUNIT_ASSERT( !g_called
.method
);
340 handler
.Bind( MyEventType
, &MyHandler::OnEvent
, &handler
, 0 );
341 handler
.Unbind( MyEventType
, &MyHandler::OnEvent
, &handler
, 0 );
343 handler
.Bind( MyEventType
, &MyHandler::OnEvent
, &handler
, 0, 0 );
344 handler
.Unbind( MyEventType
, &MyHandler::OnEvent
, &handler
, 0, 0 );
348 void EvtHandlerTestCase::BindNonHandler()
350 // class method tests for class not derived from wxEvtHandler
353 handler
.Bind( MyEventType
, &MySink::OnMyEvent
, &sink
);
355 handler
.ProcessEvent(e
);
356 CPPUNIT_ASSERT( g_called
.method
);
357 handler
.Unbind( MyEventType
, &MySink::OnMyEvent
, &sink
);
359 handler
.ProcessEvent(e
);
360 CPPUNIT_ASSERT( !g_called
.method
);
363 void EvtHandlerTestCase::InvalidBind()
365 // these calls shouldn't compile but we unfortunately can't check this
366 // automatically, you need to uncomment them manually and test that
367 // compilation does indeed fail
369 //handler.Bind(MyEventType, GlobalOnAnotherEvent);
370 //IdleFunctor f; handler.Bind(MyEventType, f);
371 //handler.Bind(MyEventType, &MyHandler::StaticOnAnotherEvent);
372 //handler.Bind(MyEventType, &MyHandler::OnAnotherEvent, &handler);
374 // Test that this sample (discussed on the mailing list) doesn't compile:
375 // >struct C1 : wxEvtHandler { };
376 // >struct C2 : wxEvtHandler { void OnWhatever(wxEvent&) };
378 // >c1.Connect(&C2::OnWhatever); // BOOM
381 //MyHandler myHandler;
382 //myHandler.Bind( MyEventType, &MyHandler::OnMyEvent, &mySink );
385 #endif // !wxEVENTS_COMPATIBILITY_2_8