Changes to template Connect() to make it compile with MSVC7 and possible other
[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 EVT_LEGACY = wxNewEventType();
27
28 class MyEvent;
29 wxDEFINE_EVENT( EVT_MYEVENT, MyEvent )
30
31 class MyEvent : public wxEvent
32 {
33 public:
34 MyEvent() : wxEvent(0, EVT_MYEVENT) { }
35
36 virtual wxEvent *Clone() const { return new MyEvent; }
37 };
38
39 class AnotherEvent : public wxEvent
40 {
41 };
42
43 namespace
44 {
45
46 struct Called
47 {
48 Called() { Reset(); }
49
50 void Reset()
51 {
52 function =
53 functor =
54 method =
55 smethod = false;
56 }
57
58 bool function,
59 functor,
60 method,
61 smethod;
62 } g_called;
63
64 void GlobalOnMyEvent(MyEvent&)
65 {
66 g_called.function = true;
67 }
68
69 void GlobalOnAnotherEvent(AnotherEvent&);
70
71 void GlobalOnIdle(wxIdleEvent&)
72 {
73 g_called.function = true;
74 }
75
76 struct MyFunctor
77 {
78 void operator()(MyEvent &) { g_called.functor = true; }
79 };
80
81 struct IdleFunctor
82 {
83 void operator()(wxIdleEvent &) { g_called.functor = true; }
84 };
85
86 class MyHandler : public wxEvtHandler
87 {
88 public:
89 static void StaticOnMyEvent(MyEvent &) { g_called.smethod = true; }
90 static void StaticOnAnotherEvent(AnotherEvent &);
91 static void StaticOnIdle(wxIdleEvent&) { g_called.smethod = true; }
92
93 void OnMyEvent(MyEvent&) { g_called.method = true; }
94 void OnEvent(wxEvent&) { g_called.method = true; }
95 void OnAnotherEvent(AnotherEvent&);
96 void OnIdle(wxIdleEvent&) { g_called.method = true; }
97 };
98
99 // we can also handle events in classes not deriving from wxEvtHandler
100 struct MySink
101 {
102 void OnMyEvent(MyEvent&) { g_called.method = true; }
103 void OnIdle(wxIdleEvent&) { g_called.method = true; }
104 };
105
106 // also test event table compilation
107 class MyClassWithEventTable : public wxEvtHandler
108 {
109 public:
110 void OnMyEvent(MyEvent&) { g_called.method = true; }
111 void OnEvent(wxEvent&) { g_called.method = true; }
112 void OnAnotherEvent(AnotherEvent&);
113 void OnIdle(wxIdleEvent&) { g_called.method = true; }
114
115 private:
116 DECLARE_EVENT_TABLE()
117 };
118
119 BEGIN_EVENT_TABLE(MyClassWithEventTable, wxEvtHandler)
120 EVT_IDLE(MyClassWithEventTable::OnIdle)
121
122 // this shouldn't compile:
123 //EVT_IDLE(MyClassWithEventTable::OnAnotherEvent)
124 END_EVENT_TABLE()
125
126 } // anonymous namespace
127
128
129 // --------------------------------------------------------------------------
130 // test class
131 // --------------------------------------------------------------------------
132
133 class EvtHandlerTestCase : public CppUnit::TestCase
134 {
135 public:
136 EvtHandlerTestCase() {}
137
138 private:
139 CPPUNIT_TEST_SUITE( EvtHandlerTestCase );
140 CPPUNIT_TEST( BuiltinConnect );
141 CPPUNIT_TEST( LegacyConnect );
142 #if !wxEVENTS_COMPATIBILITY_2_8
143 CPPUNIT_TEST( ConnectFunction );
144 CPPUNIT_TEST( ConnectStaticMethod );
145 CPPUNIT_TEST( ConnectFunctor );
146 CPPUNIT_TEST( ConnectMethod );
147 CPPUNIT_TEST( ConnectMethodWithSink );
148 CPPUNIT_TEST( ConnectNonHandler );
149 CPPUNIT_TEST( StaticConnect );
150 CPPUNIT_TEST( InvalidConnect );
151 #endif // !wxEVENTS_COMPATIBILITY_2_8
152 CPPUNIT_TEST_SUITE_END();
153
154 void BuiltinConnect();
155 void LegacyConnect();
156 #if !wxEVENTS_COMPATIBILITY_2_8
157 void ConnectFunction();
158 void ConnectStaticMethod();
159 void ConnectFunctor();
160 void ConnectMethod();
161 void ConnectMethodWithSink();
162 void ConnectNonHandler();
163 void StaticConnect();
164 void InvalidConnect();
165 #endif // !wxEVENTS_COMPATIBILITY_2_8
166
167
168 // these member variables exceptionally don't use "m_" prefix because
169 // they're used so many times
170 MyHandler handler;
171 MyEvent e;
172
173 DECLARE_NO_COPY_CLASS(EvtHandlerTestCase)
174 };
175
176 // register in the unnamed registry so that these tests are run by default
177 CPPUNIT_TEST_SUITE_REGISTRATION( EvtHandlerTestCase );
178
179 // also include in it's own registry so that these tests can be run alone
180 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( EvtHandlerTestCase, "EvtHandlerTestCase" );
181
182 void EvtHandlerTestCase::BuiltinConnect()
183 {
184 handler.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle));
185 handler.Disconnect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle));
186
187 handler.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), NULL, &handler);
188 handler.Disconnect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), NULL, &handler);
189
190 #if !wxEVENTS_COMPATIBILITY_2_8
191 handler.Connect(wxEVT_IDLE, GlobalOnIdle);
192 handler.Disconnect(wxEVT_IDLE, GlobalOnIdle);
193
194 IdleFunctor f;
195 handler.Connect(wxEVT_IDLE, f);
196 handler.Disconnect(wxEVT_IDLE, f);
197
198 handler.Connect(wxEVT_IDLE, &MyHandler::OnIdle);
199 handler.Disconnect(wxEVT_IDLE, &MyHandler::OnIdle);
200
201 handler.Connect(wxEVT_IDLE, &MyHandler::StaticOnIdle);
202 handler.Disconnect(wxEVT_IDLE, &MyHandler::StaticOnIdle);
203 #endif // !wxEVENTS_COMPATIBILITY_2_8
204 }
205
206 void EvtHandlerTestCase::LegacyConnect()
207 {
208 handler.Connect( EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent );
209 handler.Connect( 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent );
210 handler.Connect( 0, 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent );
211
212 handler.Disconnect( EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent );
213 handler.Disconnect( 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent );
214 handler.Disconnect( 0, 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent );
215
216
217 handler.Connect( EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
218 handler.Connect( 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
219 handler.Connect( 0, 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
220
221 handler.Disconnect( EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
222 handler.Disconnect( 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
223 handler.Disconnect( 0, 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
224 }
225
226 #if !wxEVENTS_COMPATIBILITY_2_8
227
228 void EvtHandlerTestCase::ConnectFunction()
229 {
230 // function tests
231 handler.Connect( EVT_MYEVENT, GlobalOnMyEvent );
232 g_called.Reset();
233 handler.ProcessEvent(e);
234 CPPUNIT_ASSERT( g_called.function );
235 handler.Disconnect( EVT_MYEVENT, GlobalOnMyEvent );
236 g_called.Reset();
237 handler.ProcessEvent(e);
238 CPPUNIT_ASSERT( !g_called.function ); // check that it was disconnected
239
240 handler.Connect( 0, EVT_MYEVENT, GlobalOnMyEvent );
241 handler.Disconnect( 0, EVT_MYEVENT, GlobalOnMyEvent );
242
243 handler.Connect( 0, 0, EVT_MYEVENT, GlobalOnMyEvent );
244 handler.Disconnect( 0, 0, EVT_MYEVENT, GlobalOnMyEvent );
245 }
246
247 void EvtHandlerTestCase::ConnectStaticMethod()
248 {
249 // static method tests (this is same as functions but still test it just in
250 // case we hit some strange compiler bugs)
251 handler.Connect( EVT_MYEVENT, &MyHandler::StaticOnMyEvent );
252 g_called.Reset();
253 handler.ProcessEvent(e);
254 CPPUNIT_ASSERT( g_called.smethod );
255 handler.Disconnect( EVT_MYEVENT, &MyHandler::StaticOnMyEvent );
256 g_called.Reset();
257 handler.ProcessEvent(e);
258 CPPUNIT_ASSERT( !g_called.smethod );
259
260 handler.Connect( 0, EVT_MYEVENT, &MyHandler::StaticOnMyEvent );
261 handler.Disconnect( 0, EVT_MYEVENT, &MyHandler::StaticOnMyEvent );
262
263 handler.Connect( 0, 0, EVT_MYEVENT, &MyHandler::StaticOnMyEvent );
264 handler.Disconnect( 0, 0, EVT_MYEVENT, &MyHandler::StaticOnMyEvent );
265 }
266
267 void EvtHandlerTestCase::ConnectFunctor()
268 {
269 // generalized functor tests
270 MyFunctor functor;
271
272 handler.Connect( EVT_MYEVENT, functor );
273 g_called.Reset();
274 handler.ProcessEvent(e);
275 CPPUNIT_ASSERT( g_called.functor );
276 handler.Disconnect( EVT_MYEVENT, functor );
277 g_called.Reset();
278 handler.ProcessEvent(e);
279 CPPUNIT_ASSERT( !g_called.functor );
280
281 handler.Connect( 0, EVT_MYEVENT, functor );
282 handler.Disconnect( 0, EVT_MYEVENT, functor );
283
284 handler.Connect( 0, 0, EVT_MYEVENT, functor );
285 handler.Disconnect( 0, 0, EVT_MYEVENT, functor );
286 }
287
288 void EvtHandlerTestCase::ConnectMethod()
289 {
290 // class method tests
291 handler.Connect( EVT_MYEVENT, &MyHandler::OnMyEvent );
292 g_called.Reset();
293 handler.ProcessEvent(e);
294 CPPUNIT_ASSERT( g_called.method );
295 handler.Disconnect( EVT_MYEVENT, &MyHandler::OnMyEvent );
296 g_called.Reset();
297 handler.ProcessEvent(e);
298 CPPUNIT_ASSERT( !g_called.method );
299
300 handler.Connect( 0, EVT_MYEVENT, &MyHandler::OnMyEvent );
301 handler.Disconnect( 0, EVT_MYEVENT, &MyHandler::OnMyEvent );
302
303 handler.Connect( 0, 0, EVT_MYEVENT, &MyHandler::OnMyEvent );
304 handler.Disconnect( 0, 0, EVT_MYEVENT, &MyHandler::OnMyEvent );
305 }
306
307 void EvtHandlerTestCase::ConnectMethodWithSink()
308 {
309 handler.Connect( EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler );
310 handler.Connect( 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler );
311 handler.Connect( 0, 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler );
312
313 handler.Disconnect( EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler );
314 handler.Disconnect( 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler );
315 handler.Disconnect( 0, 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler );
316 }
317
318 void EvtHandlerTestCase::ConnectNonHandler()
319 {
320 // class method tests for class not derived from wxEvtHandler
321 MySink sink;
322
323 handler.Connect( EVT_MYEVENT, &MySink::OnMyEvent, NULL, &sink );
324 g_called.Reset();
325 handler.ProcessEvent(e);
326 CPPUNIT_ASSERT( g_called.method );
327 handler.Disconnect( EVT_MYEVENT, &MySink::OnMyEvent, NULL, &sink );
328 g_called.Reset();
329 handler.ProcessEvent(e);
330 CPPUNIT_ASSERT( !g_called.method );
331 }
332
333 void EvtHandlerTestCase::StaticConnect()
334 {
335 wxEvtHandler::Connect( &handler, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler );
336 wxEvtHandler::Connect( &handler, 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler );
337 wxEvtHandler::Connect( &handler, 0, 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler );
338
339 wxEvtHandler::Disconnect( &handler, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler );
340 wxEvtHandler::Disconnect( &handler, 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler );
341 wxEvtHandler::Disconnect( &handler, 0, 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler );
342 }
343
344 void EvtHandlerTestCase::InvalidConnect()
345 {
346 // these calls shouldn't compile but we unfortunately can't check this
347 // automatically, you need to uncomment them manually and test that
348 // compilation does indeed fail
349 //handler.Connect(EVT_MYEVENT, GlobalOnAnotherEvent);
350 //IdleFunctor f; handler.Connect(EVT_MYEVENT, f);
351 //handler.Connect(EVT_MYEVENT, &MyHandler::StaticOnAnotherEvent);
352 //handler.Connect(EVT_MYEVENT, &MyHandler::OnAnotherEvent);
353 }
354
355 #endif // !wxEVENTS_COMPATIBILITY_2_8