]> git.saurik.com Git - wxWidgets.git/blob - tests/events/propagation.cpp
Yet another fix to event propagation in scrolled windows.
[wxWidgets.git] / tests / events / propagation.cpp
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
21 #include "wx/app.h"
22 #include "wx/event.h"
23 #include "wx/scrolwin.h"
24 #include "wx/window.h"
25 #endif // WX_PRECOMP
26
27 #include "wx/scopeguard.h"
28
29 namespace
30 {
31
32 // this string will record the execution of all handlers
33 wxString g_str;
34
35 // a custom event
36 wxDEFINE_EVENT(TEST_EVT, wxCommandEvent);
37
38 // a custom event handler tracing the propagation of the events of the
39 // specified types
40 template <class Event>
41 class TestEvtHandlerBase : public wxEvtHandler
42 {
43 public:
44 TestEvtHandlerBase(wxEventType evtType, char tag)
45 : m_evtType(evtType),
46 m_tag(tag)
47 {
48 Connect(evtType,
49 static_cast<wxEventFunction>(&TestEvtHandlerBase::OnTest));
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 {
56 if ( event.GetEventType() == m_evtType )
57 g_str += 'o'; // "o" == "overridden"
58
59 return wxEvtHandler::ProcessEvent(event);
60 }
61
62 private:
63 void OnTest(wxEvent& event)
64 {
65 g_str += m_tag;
66
67 event.Skip();
68 }
69
70 const wxEventType m_evtType;
71 const char m_tag;
72
73 wxDECLARE_NO_COPY_TEMPLATE_CLASS(TestEvtHandlerBase, Event);
74 };
75
76 struct TestEvtHandler : TestEvtHandlerBase<wxCommandEvent>
77 {
78 TestEvtHandler(char tag)
79 : TestEvtHandlerBase<wxCommandEvent>(TEST_EVT, tag)
80 {
81 }
82 };
83
84 struct TestPaintEvtHandler : TestEvtHandlerBase<wxPaintEvent>
85 {
86 TestPaintEvtHandler(char tag)
87 : TestEvtHandlerBase<wxPaintEvent>(wxEVT_PAINT, tag)
88 {
89 }
90 };
91
92 // a window handling the test event
93 class TestWindow : public wxWindow
94 {
95 public:
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
103 private:
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
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
121 class TestScrollWindow : public wxScrolledWindow
122 {
123 public:
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
135 private:
136 void OnPaint(wxPaintEvent& event)
137 {
138 g_str += 'P'; // paint
139 event.Skip();
140 }
141
142 wxDECLARE_NO_COPY_CLASS(TestScrollWindow);
143 };
144
145 int DoFilterEvent(wxEvent& event)
146 {
147 if ( event.GetEventType() == TEST_EVT )
148 g_str += 'a';
149
150 return -1;
151 }
152
153 bool 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
167 class EventPropagationTestCase : public CppUnit::TestCase
168 {
169 public:
170 EventPropagationTestCase() {}
171
172 virtual void setUp();
173 virtual void tearDown();
174
175 private:
176 CPPUNIT_TEST_SUITE( EventPropagationTestCase );
177 CPPUNIT_TEST( OneHandler );
178 CPPUNIT_TEST( TwoHandlers );
179 CPPUNIT_TEST( WindowWithoutHandler );
180 CPPUNIT_TEST( WindowWithHandler );
181 CPPUNIT_TEST( ScrollWindowWithoutHandler );
182 CPPUNIT_TEST( ScrollWindowWithHandler );
183 CPPUNIT_TEST_SUITE_END();
184
185 void OneHandler();
186 void TwoHandlers();
187 void WindowWithoutHandler();
188 void WindowWithHandler();
189 void ScrollWindowWithoutHandler();
190 void ScrollWindowWithHandler();
191
192 DECLARE_NO_COPY_CLASS(EventPropagationTestCase)
193 };
194
195 // register in the unnamed registry so that these tests are run by default
196 CPPUNIT_TEST_SUITE_REGISTRATION( EventPropagationTestCase );
197
198 // also include in it's own registry so that these tests can be run alone
199 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( EventPropagationTestCase, "EventPropagationTestCase" );
200
201 void EventPropagationTestCase::setUp()
202 {
203 SetFilterEventFunc(DoFilterEvent);
204 SetProcessEventFunc(DoProcessEvent);
205
206 g_str.clear();
207 }
208
209 void EventPropagationTestCase::tearDown()
210 {
211 SetFilterEventFunc(NULL);
212 SetProcessEventFunc(NULL);
213 }
214
215 void EventPropagationTestCase::OneHandler()
216 {
217 wxCommandEvent event(TEST_EVT);
218 TestEvtHandler h1('1');
219 h1.ProcessEvent(event);
220 CPPUNIT_ASSERT_EQUAL( "oa1A", g_str );
221 }
222
223 void EventPropagationTestCase::TwoHandlers()
224 {
225 wxCommandEvent event(TEST_EVT);
226 TestEvtHandler h1('1');
227 TestEvtHandler h2('2');
228 h1.SetNextHandler(&h2);
229 h2.SetPreviousHandler(&h1);
230 h1.ProcessEvent(event);
231 CPPUNIT_ASSERT_EQUAL( "oa1o2A", g_str );
232 }
233
234 void EventPropagationTestCase::WindowWithoutHandler()
235 {
236 wxCommandEvent event(TEST_EVT);
237 TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
238 wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
239
240 TestWindow * const child = new TestWindow(parent, 'c');
241
242 child->GetEventHandler()->ProcessEvent(event);
243 CPPUNIT_ASSERT_EQUAL( "acpA", g_str );
244 }
245
246 void EventPropagationTestCase::WindowWithHandler()
247 {
248 wxCommandEvent event(TEST_EVT);
249 TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
250 wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
251
252 TestWindow * const child = new TestWindow(parent, 'c');
253
254 TestEvtHandler h1('1');
255 child->PushEventHandler(&h1);
256 wxON_BLOCK_EXIT_OBJ1( *child, wxWindow::PopEventHandler, false );
257 TestEvtHandler h2('2');
258 child->PushEventHandler(&h2);
259 wxON_BLOCK_EXIT_OBJ1( *child, wxWindow::PopEventHandler, false );
260
261 child->HandleWindowEvent(event);
262 CPPUNIT_ASSERT_EQUAL( "oa2o1cpA", g_str );
263 }
264
265 void EventPropagationTestCase::ScrollWindowWithoutHandler()
266 {
267 TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
268 wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
269
270 TestScrollWindow * const win = new TestScrollWindow(parent);
271
272 wxPaintEvent event(win->GetId());
273 win->ProcessWindowEvent(event);
274 CPPUNIT_ASSERT_EQUAL( "PD", g_str );
275
276 g_str.clear();
277 wxCommandEvent eventCmd(TEST_EVT);
278 win->HandleWindowEvent(eventCmd);
279 CPPUNIT_ASSERT_EQUAL( "apA", g_str );
280 }
281
282 void EventPropagationTestCase::ScrollWindowWithHandler()
283 {
284 TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
285 wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
286
287 TestScrollWindow * const win = new TestScrollWindow(parent);
288
289 TestPaintEvtHandler h('h');
290 win->PushEventHandler(&h);
291 wxON_BLOCK_EXIT_OBJ1( *win, wxWindow::PopEventHandler, false );
292
293 wxPaintEvent event(win->GetId());
294 win->ProcessWindowEvent(event);
295 CPPUNIT_ASSERT_EQUAL( "ohPD", g_str );
296
297 g_str.clear();
298 wxCommandEvent eventCmd(TEST_EVT);
299 win->HandleWindowEvent(eventCmd);
300 CPPUNIT_ASSERT_EQUAL( "apA", g_str );
301 }
302