]> git.saurik.com Git - wxWidgets.git/blob - tests/events/evthandler.cpp
ea866600201362f5bce3d3008b22c65cba1839ee
[wxWidgets.git] / tests / events / evthandler.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/events/evthandler.cpp
3 // Purpose: Test the new event types and wxEvtHandler-methods
4 // Author: Peter Most
5 // Created: 2009-01-24
6 // RCS-ID: $Id$
7 // Copyright: (c) 2009 Peter Most
8 ///////////////////////////////////////////////////////////////////////////////
9
10 // ----------------------------------------------------------------------------
11 // headers
12 // ----------------------------------------------------------------------------
13
14 #include "testprec.h"
15
16 #ifdef __BORLANDC__
17 #pragma hdrstop
18 #endif
19
20 #include "wx/event.h"
21
22 // ----------------------------------------------------------------------------
23 // test events and their handlers
24 // ----------------------------------------------------------------------------
25
26 const wxEventType LegacyEventType = wxNewEventType();
27
28 class MyEvent;
29 wxDEFINE_EVENT( MyEventType, MyEvent )
30
31 class MyEvent : public wxEvent
32 {
33 public:
34 MyEvent() : wxEvent(0, MyEventType) { }
35
36 virtual wxEvent *Clone() const { return new MyEvent; }
37 };
38
39 #define EVT_MYEVENT(func) wx__DECLARE_EVT0(MyEventType, &func)
40
41 class AnotherEvent : public wxEvent
42 {
43 };
44
45 namespace
46 {
47
48 struct Called
49 {
50 Called() { Reset(); }
51
52 void Reset()
53 {
54 function =
55 functor =
56 method =
57 smethod = false;
58 }
59
60 bool function,
61 functor,
62 method,
63 smethod;
64 } g_called;
65
66 void GlobalOnMyEvent(MyEvent&)
67 {
68 g_called.function = true;
69 }
70
71 void GlobalOnAnotherEvent(AnotherEvent&);
72
73 void GlobalOnIdle(wxIdleEvent&)
74 {
75 g_called.function = true;
76 }
77
78 struct MyFunctor
79 {
80 void operator()(MyEvent &) { g_called.functor = true; }
81 };
82
83 struct IdleFunctor
84 {
85 void operator()(wxIdleEvent &) { g_called.functor = true; }
86 };
87
88 class MyHandler : public wxEvtHandler
89 {
90 public:
91 static void StaticOnMyEvent(MyEvent &) { g_called.smethod = true; }
92 static void StaticOnAnotherEvent(AnotherEvent &);
93 static void StaticOnIdle(wxIdleEvent&) { g_called.smethod = true; }
94
95 void OnMyEvent(MyEvent&) { g_called.method = true; }
96 void OnEvent(wxEvent&) { g_called.method = true; }
97 void OnAnotherEvent(AnotherEvent&);
98 void OnIdle(wxIdleEvent&) { g_called.method = true; }
99 };
100
101 // we can also handle events in classes not deriving from wxEvtHandler
102 struct MySink
103 {
104 void OnMyEvent(MyEvent&) { g_called.method = true; }
105 void OnEvent(wxEvent&) { g_called.method = true; }
106 void OnIdle(wxIdleEvent&) { g_called.method = true; }
107 };
108
109 // also test event table compilation
110 class MyClassWithEventTable : public wxEvtHandler
111 {
112 public:
113 void OnMyEvent(MyEvent&) { g_called.method = true; }
114 void OnEvent(wxEvent&) { g_called.method = true; }
115 void OnAnotherEvent(AnotherEvent&);
116 void OnIdle(wxIdleEvent&) { g_called.method = true; }
117
118 private:
119 DECLARE_EVENT_TABLE()
120 };
121
122 BEGIN_EVENT_TABLE(MyClassWithEventTable, wxEvtHandler)
123 EVT_IDLE(MyClassWithEventTable::OnIdle)
124
125 EVT_MYEVENT(MyClassWithEventTable::OnMyEvent)
126 EVT_MYEVENT(MyClassWithEventTable::OnEvent)
127
128 // this shouldn't compile:
129 //EVT_MYEVENT(MyClassWithEventTable::OnIdle)
130 //EVT_IDLE(MyClassWithEventTable::OnAnotherEvent)
131 END_EVENT_TABLE()
132
133 } // anonymous namespace
134
135
136 // --------------------------------------------------------------------------
137 // test class
138 // --------------------------------------------------------------------------
139
140 class EvtHandlerTestCase : public CppUnit::TestCase
141 {
142 public:
143 EvtHandlerTestCase() {}
144
145 private:
146 CPPUNIT_TEST_SUITE( EvtHandlerTestCase );
147 CPPUNIT_TEST( BuiltinConnect );
148 CPPUNIT_TEST( LegacyConnect );
149 #if !wxEVENTS_COMPATIBILITY_2_8
150 CPPUNIT_TEST( ConnectFunction );
151 CPPUNIT_TEST( ConnectStaticMethod );
152 CPPUNIT_TEST( ConnectFunctor );
153 CPPUNIT_TEST( ConnectMethod );
154 CPPUNIT_TEST( ConnectMethodUsingBaseEvent );
155 CPPUNIT_TEST( ConnectMethodWithSink );
156 CPPUNIT_TEST( ConnectNonHandler );
157 CPPUNIT_TEST( StaticConnect );
158 CPPUNIT_TEST( InvalidConnect );
159 #endif // !wxEVENTS_COMPATIBILITY_2_8
160 CPPUNIT_TEST_SUITE_END();
161
162 void BuiltinConnect();
163 void LegacyConnect();
164 #if !wxEVENTS_COMPATIBILITY_2_8
165 void ConnectFunction();
166 void ConnectStaticMethod();
167 void ConnectFunctor();
168 void ConnectMethod();
169 void ConnectMethodUsingBaseEvent();
170 void ConnectMethodWithSink();
171 void ConnectNonHandler();
172 void StaticConnect();
173 void InvalidConnect();
174 #endif // !wxEVENTS_COMPATIBILITY_2_8
175
176
177 // these member variables exceptionally don't use "m_" prefix because
178 // they're used so many times
179 MyHandler handler;
180 MyEvent e;
181
182 DECLARE_NO_COPY_CLASS(EvtHandlerTestCase)
183 };
184
185 // register in the unnamed registry so that these tests are run by default
186 CPPUNIT_TEST_SUITE_REGISTRATION( EvtHandlerTestCase );
187
188 // also include in it's own registry so that these tests can be run alone
189 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( EvtHandlerTestCase, "EvtHandlerTestCase" );
190
191 void EvtHandlerTestCase::BuiltinConnect()
192 {
193 handler.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle));
194 handler.Disconnect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle));
195
196 handler.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), NULL, &handler);
197 handler.Disconnect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), NULL, &handler);
198
199 // using casts like this is even uglier than using wxIdleEventHandler but
200 // it should still continue to work for compatibility
201 handler.Connect(wxEVT_IDLE, (wxObjectEventFunction)(wxEventFunction)&MyHandler::OnIdle);
202 handler.Disconnect(wxEVT_IDLE, (wxObjectEventFunction)(wxEventFunction)&MyHandler::OnIdle);
203
204 #if !wxEVENTS_COMPATIBILITY_2_8
205 handler.Connect(wxEVT_IDLE, GlobalOnIdle);
206 handler.Disconnect(wxEVT_IDLE, GlobalOnIdle);
207
208 IdleFunctor f;
209 handler.Connect(wxEVT_IDLE, f);
210 handler.Disconnect(wxEVT_IDLE, f);
211
212 handler.Connect(wxEVT_IDLE, &MyHandler::OnIdle);
213 handler.Disconnect(wxEVT_IDLE, &MyHandler::OnIdle);
214
215 handler.Connect(wxEVT_IDLE, &MyHandler::StaticOnIdle);
216 handler.Disconnect(wxEVT_IDLE, &MyHandler::StaticOnIdle);
217 #endif // !wxEVENTS_COMPATIBILITY_2_8
218 }
219
220 void EvtHandlerTestCase::LegacyConnect()
221 {
222 handler.Connect( LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
223 handler.Connect( 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
224 handler.Connect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
225
226 handler.Disconnect( LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
227 handler.Disconnect( 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
228 handler.Disconnect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
229
230
231 handler.Connect( LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
232 handler.Connect( 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
233 handler.Connect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
234
235 handler.Disconnect( LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
236 handler.Disconnect( 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
237 handler.Disconnect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
238 }
239
240 #if !wxEVENTS_COMPATIBILITY_2_8
241
242 void EvtHandlerTestCase::ConnectFunction()
243 {
244 // function tests
245 handler.Connect( MyEventType, GlobalOnMyEvent );
246 g_called.Reset();
247 handler.ProcessEvent(e);
248 CPPUNIT_ASSERT( g_called.function );
249 handler.Disconnect( MyEventType, GlobalOnMyEvent );
250 g_called.Reset();
251 handler.ProcessEvent(e);
252 CPPUNIT_ASSERT( !g_called.function ); // check that it was disconnected
253
254 handler.Connect( 0, MyEventType, GlobalOnMyEvent );
255 handler.Disconnect( 0, MyEventType, GlobalOnMyEvent );
256
257 handler.Connect( 0, 0, MyEventType, GlobalOnMyEvent );
258 handler.Disconnect( 0, 0, MyEventType, GlobalOnMyEvent );
259 }
260
261 void EvtHandlerTestCase::ConnectStaticMethod()
262 {
263 // static method tests (this is same as functions but still test it just in
264 // case we hit some strange compiler bugs)
265 handler.Connect( MyEventType, &MyHandler::StaticOnMyEvent );
266 g_called.Reset();
267 handler.ProcessEvent(e);
268 CPPUNIT_ASSERT( g_called.smethod );
269 handler.Disconnect( MyEventType, &MyHandler::StaticOnMyEvent );
270 g_called.Reset();
271 handler.ProcessEvent(e);
272 CPPUNIT_ASSERT( !g_called.smethod );
273
274 handler.Connect( 0, MyEventType, &MyHandler::StaticOnMyEvent );
275 handler.Disconnect( 0, MyEventType, &MyHandler::StaticOnMyEvent );
276
277 handler.Connect( 0, 0, MyEventType, &MyHandler::StaticOnMyEvent );
278 handler.Disconnect( 0, 0, MyEventType, &MyHandler::StaticOnMyEvent );
279 }
280
281 void EvtHandlerTestCase::ConnectFunctor()
282 {
283 // generalized functor tests
284 MyFunctor functor;
285
286 handler.Connect( MyEventType, functor );
287 g_called.Reset();
288 handler.ProcessEvent(e);
289 CPPUNIT_ASSERT( g_called.functor );
290 handler.Disconnect( MyEventType, functor );
291 g_called.Reset();
292 handler.ProcessEvent(e);
293 CPPUNIT_ASSERT( !g_called.functor );
294
295 handler.Connect( 0, MyEventType, functor );
296 handler.Disconnect( 0, MyEventType, functor );
297
298 handler.Connect( 0, 0, MyEventType, functor );
299 handler.Disconnect( 0, 0, MyEventType, functor );
300 }
301
302 void EvtHandlerTestCase::ConnectMethod()
303 {
304 // class method tests
305 handler.Connect( MyEventType, &MyHandler::OnMyEvent );
306 g_called.Reset();
307 handler.ProcessEvent(e);
308 CPPUNIT_ASSERT( g_called.method );
309 handler.Disconnect( MyEventType, &MyHandler::OnMyEvent );
310 g_called.Reset();
311 handler.ProcessEvent(e);
312 CPPUNIT_ASSERT( !g_called.method );
313
314 handler.Connect( 0, MyEventType, &MyHandler::OnMyEvent );
315 handler.Disconnect( 0, MyEventType, &MyHandler::OnMyEvent );
316
317 handler.Connect( 0, 0, MyEventType, &MyHandler::OnMyEvent );
318 handler.Disconnect( 0, 0, MyEventType, &MyHandler::OnMyEvent );
319 }
320
321 void EvtHandlerTestCase::ConnectMethodUsingBaseEvent()
322 {
323 // test connecting a method taking just wxEvent and not MyEvent: this
324 // should work too if we don't need any MyEvent-specific information in the
325 // handler
326 handler.Connect( MyEventType, &MyHandler::OnEvent );
327 g_called.Reset();
328 handler.ProcessEvent(e);
329 CPPUNIT_ASSERT( g_called.method );
330 handler.Disconnect( MyEventType, &MyHandler::OnEvent );
331 g_called.Reset();
332 handler.ProcessEvent(e);
333 CPPUNIT_ASSERT( !g_called.method );
334
335 handler.Connect( 0, MyEventType, &MyHandler::OnEvent );
336 handler.Disconnect( 0, MyEventType, &MyHandler::OnEvent );
337
338 handler.Connect( 0, 0, MyEventType, &MyHandler::OnEvent );
339 handler.Disconnect( 0, 0, MyEventType, &MyHandler::OnEvent );
340 }
341
342 void EvtHandlerTestCase::ConnectMethodWithSink()
343 {
344 handler.Connect( MyEventType, &MyHandler::OnMyEvent, NULL, &handler );
345 handler.Connect( 0, MyEventType, &MyHandler::OnMyEvent, NULL, &handler );
346 handler.Connect( 0, 0, MyEventType, &MyHandler::OnMyEvent, NULL, &handler );
347
348 handler.Disconnect( MyEventType, &MyHandler::OnMyEvent, NULL, &handler );
349 handler.Disconnect( 0, MyEventType, &MyHandler::OnMyEvent, NULL, &handler );
350 handler.Disconnect( 0, 0, MyEventType, &MyHandler::OnMyEvent, NULL, &handler );
351 }
352
353 void EvtHandlerTestCase::ConnectNonHandler()
354 {
355 // class method tests for class not derived from wxEvtHandler
356 MySink sink;
357
358 handler.Connect( MyEventType, &MySink::OnMyEvent, NULL, &sink );
359 g_called.Reset();
360 handler.ProcessEvent(e);
361 CPPUNIT_ASSERT( g_called.method );
362 handler.Disconnect( MyEventType, &MySink::OnMyEvent, NULL, &sink );
363 g_called.Reset();
364 handler.ProcessEvent(e);
365 CPPUNIT_ASSERT( !g_called.method );
366 }
367
368 void EvtHandlerTestCase::StaticConnect()
369 {
370 wxEvtHandler::Connect( &handler, MyEventType, &MyHandler::OnMyEvent, NULL, &handler );
371 wxEvtHandler::Connect( &handler, 0, MyEventType, &MyHandler::OnMyEvent, NULL, &handler );
372 wxEvtHandler::Connect( &handler, 0, 0, MyEventType, &MyHandler::OnMyEvent, NULL, &handler );
373
374 wxEvtHandler::Disconnect( &handler, MyEventType, &MyHandler::OnMyEvent, NULL, &handler );
375 wxEvtHandler::Disconnect( &handler, 0, MyEventType, &MyHandler::OnMyEvent, NULL, &handler );
376 wxEvtHandler::Disconnect( &handler, 0, 0, MyEventType, &MyHandler::OnMyEvent, NULL, &handler );
377 }
378
379 void EvtHandlerTestCase::InvalidConnect()
380 {
381 // these calls shouldn't compile but we unfortunately can't check this
382 // automatically, you need to uncomment them manually and test that
383 // compilation does indeed fail
384 //handler.Connect(MyEventType, GlobalOnAnotherEvent);
385 //IdleFunctor f; handler.Connect(MyEventType, f);
386 //handler.Connect(MyEventType, &MyHandler::StaticOnAnotherEvent);
387 //handler.Connect(MyEventType, &MyHandler::OnAnotherEvent);
388 }
389
390 #endif // !wxEVENTS_COMPATIBILITY_2_8