]> git.saurik.com Git - wxWidgets.git/blame - tests/events/propagation.cpp
Add a simple test for keyboard events generation.
[wxWidgets.git] / tests / events / propagation.cpp
CommitLineData
1649d288
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: tests/events/propagation.cpp
3// Purpose: Test events propagation
4// Author: Vadim Zeitlin
5// Created: 2009-01-16
6// RCS-ID: $Id$
7// Copyright: (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
8///////////////////////////////////////////////////////////////////////////////
9
10// ----------------------------------------------------------------------------
11// headers
12// ----------------------------------------------------------------------------
13
14#include "testprec.h"
15
16#ifdef __BORLANDC__
17 #pragma hdrstop
18#endif
19
20#ifndef WX_PRECOMP
c21dcf80
VZ
21 #include "wx/app.h"
22 #include "wx/event.h"
ce45133e 23 #include "wx/scrolwin.h"
c21dcf80 24 #include "wx/window.h"
1649d288
VZ
25#endif // WX_PRECOMP
26
1649d288
VZ
27#include "wx/scopeguard.h"
28
29namespace
30{
31
32// this string will record the execution of all handlers
33wxString g_str;
34
35// a custom event
36wxDEFINE_EVENT(TEST_EVT, wxCommandEvent);
37
ce45133e
VZ
38// a custom event handler tracing the propagation of the events of the
39// specified types
40template <class Event>
41class TestEvtHandlerBase : public wxEvtHandler
1649d288
VZ
42{
43public:
ce45133e
VZ
44 TestEvtHandlerBase(wxEventType evtType, char tag)
45 : m_evtType(evtType),
46 m_tag(tag)
1649d288 47 {
ce45133e
VZ
48 Connect(evtType,
49 static_cast<wxEventFunction>(&TestEvtHandlerBase::OnTest));
1649d288
VZ
50 }
51
52 // override ProcessEvent() to confirm that it is called for all event
53 // handlers in the chain
54 virtual bool ProcessEvent(wxEvent& event)
55 {
ce45133e 56 if ( event.GetEventType() == m_evtType )
1649d288
VZ
57 g_str += 'o'; // "o" == "overridden"
58
59 return wxEvtHandler::ProcessEvent(event);
60 }
61
62private:
ce45133e 63 void OnTest(wxEvent& event)
1649d288
VZ
64 {
65 g_str += m_tag;
66
67 event.Skip();
68 }
69
ce45133e 70 const wxEventType m_evtType;
1649d288
VZ
71 const char m_tag;
72
ce45133e
VZ
73 wxDECLARE_NO_COPY_TEMPLATE_CLASS(TestEvtHandlerBase, Event);
74};
75
76struct TestEvtHandler : TestEvtHandlerBase<wxCommandEvent>
77{
78 TestEvtHandler(char tag)
79 : TestEvtHandlerBase<wxCommandEvent>(TEST_EVT, tag)
80 {
81 }
82};
83
84struct TestPaintEvtHandler : TestEvtHandlerBase<wxPaintEvent>
85{
86 TestPaintEvtHandler(char tag)
87 : TestEvtHandlerBase<wxPaintEvent>(wxEVT_PAINT, tag)
88 {
89 }
1649d288
VZ
90};
91
92// a window handling the test event
93class TestWindow : public wxWindow
94{
95public:
96 TestWindow(wxWindow *parent, char tag)
97 : wxWindow(parent, wxID_ANY),
98 m_tag(tag)
99 {
100 Connect(TEST_EVT, wxCommandEventHandler(TestWindow::OnTest));
101 }
102
103private:
104 void OnTest(wxCommandEvent& event)
105 {
106 g_str += m_tag;
107
108 event.Skip();
109 }
110
111 const char m_tag;
112
113 DECLARE_NO_COPY_CLASS(TestWindow)
114};
115
ce45133e
VZ
116// a scroll window handling paint event: we want to have a special test case
117// for this because the event propagation is complicated even further than
118// usual here by the presence of wxScrollHelperEvtHandler in the event handlers
119// chain and the fact that OnDraw() virtual method must be called if EVT_PAINT
120// is not handled
121class TestScrollWindow : public wxScrolledWindow
122{
123public:
124 TestScrollWindow(wxWindow *parent)
125 : wxScrolledWindow(parent, wxID_ANY)
126 {
127 Connect(wxEVT_PAINT, wxPaintEventHandler(TestScrollWindow::OnPaint));
128 }
129
130 virtual void OnDraw(wxDC& WXUNUSED(dc))
131 {
132 g_str += 'D'; // draw
133 }
134
135private:
136 void OnPaint(wxPaintEvent& event)
137 {
138 g_str += 'P'; // paint
139 event.Skip();
140 }
141
142 wxDECLARE_NO_COPY_CLASS(TestScrollWindow);
143};
144
1649d288
VZ
145int DoFilterEvent(wxEvent& event)
146{
147 if ( event.GetEventType() == TEST_EVT )
148 g_str += 'a';
149
150 return -1;
151}
152
153bool DoProcessEvent(wxEvent& event)
154{
155 if ( event.GetEventType() == TEST_EVT )
156 g_str += 'A';
157
158 return false;
159}
160
161} // anonymous namespace
162
163// --------------------------------------------------------------------------
164// test class
165// --------------------------------------------------------------------------
166
167class EventPropagationTestCase : public CppUnit::TestCase
168{
169public:
170 EventPropagationTestCase() {}
171
172 virtual void setUp();
173 virtual void tearDown();
174
175private:
176 CPPUNIT_TEST_SUITE( EventPropagationTestCase );
177 CPPUNIT_TEST( OneHandler );
178 CPPUNIT_TEST( TwoHandlers );
179 CPPUNIT_TEST( WindowWithoutHandler );
180 CPPUNIT_TEST( WindowWithHandler );
bbdee10d 181 CPPUNIT_TEST( ForwardEvent );
ce45133e
VZ
182 CPPUNIT_TEST( ScrollWindowWithoutHandler );
183 CPPUNIT_TEST( ScrollWindowWithHandler );
1649d288
VZ
184 CPPUNIT_TEST_SUITE_END();
185
186 void OneHandler();
187 void TwoHandlers();
188 void WindowWithoutHandler();
189 void WindowWithHandler();
bbdee10d 190 void ForwardEvent();
ce45133e
VZ
191 void ScrollWindowWithoutHandler();
192 void ScrollWindowWithHandler();
1649d288
VZ
193
194 DECLARE_NO_COPY_CLASS(EventPropagationTestCase)
195};
196
197// register in the unnamed registry so that these tests are run by default
198CPPUNIT_TEST_SUITE_REGISTRATION( EventPropagationTestCase );
199
200// also include in it's own registry so that these tests can be run alone
201CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( EventPropagationTestCase, "EventPropagationTestCase" );
202
203void EventPropagationTestCase::setUp()
204{
205 SetFilterEventFunc(DoFilterEvent);
206 SetProcessEventFunc(DoProcessEvent);
207
208 g_str.clear();
209}
210
211void EventPropagationTestCase::tearDown()
212{
213 SetFilterEventFunc(NULL);
214 SetProcessEventFunc(NULL);
215}
216
217void EventPropagationTestCase::OneHandler()
218{
219 wxCommandEvent event(TEST_EVT);
220 TestEvtHandler h1('1');
221 h1.ProcessEvent(event);
222 CPPUNIT_ASSERT_EQUAL( "oa1A", g_str );
223}
224
225void EventPropagationTestCase::TwoHandlers()
226{
227 wxCommandEvent event(TEST_EVT);
228 TestEvtHandler h1('1');
229 TestEvtHandler h2('2');
230 h1.SetNextHandler(&h2);
231 h2.SetPreviousHandler(&h1);
232 h1.ProcessEvent(event);
233 CPPUNIT_ASSERT_EQUAL( "oa1o2A", g_str );
234}
235
236void EventPropagationTestCase::WindowWithoutHandler()
237{
238 wxCommandEvent event(TEST_EVT);
239 TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
240 wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
241
242 TestWindow * const child = new TestWindow(parent, 'c');
243
004867db 244 child->GetEventHandler()->ProcessEvent(event);
1649d288
VZ
245 CPPUNIT_ASSERT_EQUAL( "acpA", g_str );
246}
247
248void EventPropagationTestCase::WindowWithHandler()
249{
250 wxCommandEvent event(TEST_EVT);
251 TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
252 wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
253
254 TestWindow * const child = new TestWindow(parent, 'c');
255
256 TestEvtHandler h1('1');
257 child->PushEventHandler(&h1);
9ebfc963 258 wxON_BLOCK_EXIT_OBJ1( *child, wxWindow::PopEventHandler, false );
1649d288
VZ
259 TestEvtHandler h2('2');
260 child->PushEventHandler(&h2);
9ebfc963 261 wxON_BLOCK_EXIT_OBJ1( *child, wxWindow::PopEventHandler, false );
1649d288
VZ
262
263 child->HandleWindowEvent(event);
264 CPPUNIT_ASSERT_EQUAL( "oa2o1cpA", g_str );
265}
266
bbdee10d
VZ
267void EventPropagationTestCase::ForwardEvent()
268{
269 // The idea of this test is to check that the events explicitly forwarded
270 // to another event handler still get pre/post-processed as usual as this
271 // used to be broken by the fixes trying to avoid duplicate processing.
272 TestWindow * const win = new TestWindow(wxTheApp->GetTopWindow(), 'w');
273 wxON_BLOCK_EXIT_OBJ0( *win, wxWindow::Destroy );
274
275 TestEvtHandler h1('1');
276 win->PushEventHandler(&h1);
277 wxON_BLOCK_EXIT_OBJ1( *win, wxWindow::PopEventHandler, false );
278
279 class ForwardEvtHandler : public wxEvtHandler
280 {
281 public:
282 ForwardEvtHandler(wxEvtHandler& h) : m_h(&h) { }
283
284 virtual bool ProcessEvent(wxEvent& event)
285 {
286 g_str += 'f';
287
288 return m_h->ProcessEvent(event);
289 }
290
291 private:
292 wxEvtHandler *m_h;
293 } f(h1);
294
295 // First send the event directly to f.
296 wxCommandEvent event1(TEST_EVT);
297 f.ProcessEvent(event1);
298 CPPUNIT_ASSERT_EQUAL( "foa1wA", g_str );
299 g_str.clear();
300
301 // And then also test sending it to f indirectly.
302 wxCommandEvent event2(TEST_EVT);
303 TestEvtHandler h2('2');
304 h2.SetNextHandler(&f);
305 h2.ProcessEvent(event2);
306 CPPUNIT_ASSERT_EQUAL( "oa2fo1wAA", g_str );
307}
308
ce45133e
VZ
309void EventPropagationTestCase::ScrollWindowWithoutHandler()
310{
52212bcb
VZ
311 TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
312 wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
313
314 TestScrollWindow * const win = new TestScrollWindow(parent);
ce45133e 315
f009da6e 316#ifndef __WXOSX__
ce45133e
VZ
317 wxPaintEvent event(win->GetId());
318 win->ProcessWindowEvent(event);
319 CPPUNIT_ASSERT_EQUAL( "PD", g_str );
f009da6e 320#endif
52212bcb
VZ
321 g_str.clear();
322 wxCommandEvent eventCmd(TEST_EVT);
323 win->HandleWindowEvent(eventCmd);
324 CPPUNIT_ASSERT_EQUAL( "apA", g_str );
ce45133e
VZ
325}
326
327void EventPropagationTestCase::ScrollWindowWithHandler()
328{
52212bcb
VZ
329 TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
330 wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
331
332 TestScrollWindow * const win = new TestScrollWindow(parent);
ce45133e 333
15536294 334#ifndef __WXOSX__
ce45133e
VZ
335 TestPaintEvtHandler h('h');
336 win->PushEventHandler(&h);
337 wxON_BLOCK_EXIT_OBJ1( *win, wxWindow::PopEventHandler, false );
338
339 wxPaintEvent event(win->GetId());
340 win->ProcessWindowEvent(event);
341 CPPUNIT_ASSERT_EQUAL( "ohPD", g_str );
15536294 342#endif
52212bcb
VZ
343
344 g_str.clear();
345 wxCommandEvent eventCmd(TEST_EVT);
346 win->HandleWindowEvent(eventCmd);
347 CPPUNIT_ASSERT_EQUAL( "apA", g_str );
ce45133e
VZ
348}
349