test_gui_listctrltest.o \
test_gui_textctrltest.o \
test_gui_textentrytest.o \
+ test_gui_propagation.o \
test_gui_rawbmp.o \
test_gui_htmlwindow.o \
test_gui_guifuncs.o \
test_gui_textentrytest.o: $(srcdir)/controls/textentrytest.cpp $(TEST_GUI_ODEP)
$(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/controls/textentrytest.cpp
+test_gui_propagation.o: $(srcdir)/events/propagation.cpp $(TEST_GUI_ODEP)
+ $(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/events/propagation.cpp
+
test_gui_rawbmp.o: $(srcdir)/image/rawbmp.cpp $(TEST_GUI_ODEP)
$(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/image/rawbmp.cpp
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+// Name: tests/events/propagation.cpp
+// Purpose: Test events propagation
+// Author: Vadim Zeitlin
+// Created: 2009-01-16
+// RCS-ID: $Id$
+// Copyright: (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
+///////////////////////////////////////////////////////////////////////////////
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+#include "testprec.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#endif // WX_PRECOMP
+
+#include "wx/event.h"
+#include "wx/scopeguard.h"
+
+namespace
+{
+
+// this string will record the execution of all handlers
+wxString g_str;
+
+// a custom event
+wxDEFINE_EVENT(TEST_EVT, wxCommandEvent);
+
+// a custom event handler
+class TestEvtHandler : public wxEvtHandler
+{
+public:
+ TestEvtHandler(char tag)
+ : m_tag(tag)
+ {
+ Connect(TEST_EVT, wxCommandEventHandler(TestEvtHandler::OnTest));
+ }
+
+ // override ProcessEvent() to confirm that it is called for all event
+ // handlers in the chain
+ virtual bool ProcessEvent(wxEvent& event)
+ {
+ if ( event.GetEventType() == TEST_EVT )
+ g_str += 'o'; // "o" == "overridden"
+
+ return wxEvtHandler::ProcessEvent(event);
+ }
+
+private:
+ void OnTest(wxCommandEvent& event)
+ {
+ g_str += m_tag;
+
+ event.Skip();
+ }
+
+ const char m_tag;
+
+ DECLARE_NO_COPY_CLASS(TestEvtHandler)
+};
+
+// a window handling the test event
+class TestWindow : public wxWindow
+{
+public:
+ TestWindow(wxWindow *parent, char tag)
+ : wxWindow(parent, wxID_ANY),
+ m_tag(tag)
+ {
+ Connect(TEST_EVT, wxCommandEventHandler(TestWindow::OnTest));
+ }
+
+private:
+ void OnTest(wxCommandEvent& event)
+ {
+ g_str += m_tag;
+
+ event.Skip();
+ }
+
+ const char m_tag;
+
+ DECLARE_NO_COPY_CLASS(TestWindow)
+};
+
+int DoFilterEvent(wxEvent& event)
+{
+ if ( event.GetEventType() == TEST_EVT )
+ g_str += 'a';
+
+ return -1;
+}
+
+bool DoProcessEvent(wxEvent& event)
+{
+ if ( event.GetEventType() == TEST_EVT )
+ g_str += 'A';
+
+ return false;
+}
+
+} // anonymous namespace
+
+// --------------------------------------------------------------------------
+// test class
+// --------------------------------------------------------------------------
+
+class EventPropagationTestCase : public CppUnit::TestCase
+{
+public:
+ EventPropagationTestCase() {}
+
+ virtual void setUp();
+ virtual void tearDown();
+
+private:
+ CPPUNIT_TEST_SUITE( EventPropagationTestCase );
+ CPPUNIT_TEST( OneHandler );
+ CPPUNIT_TEST( TwoHandlers );
+ CPPUNIT_TEST( WindowWithoutHandler );
+ CPPUNIT_TEST( WindowWithHandler );
+ CPPUNIT_TEST_SUITE_END();
+
+ void OneHandler();
+ void TwoHandlers();
+ void WindowWithoutHandler();
+ void WindowWithHandler();
+
+ DECLARE_NO_COPY_CLASS(EventPropagationTestCase)
+};
+
+// register in the unnamed registry so that these tests are run by default
+CPPUNIT_TEST_SUITE_REGISTRATION( EventPropagationTestCase );
+
+// also include in it's own registry so that these tests can be run alone
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( EventPropagationTestCase, "EventPropagationTestCase" );
+
+void EventPropagationTestCase::setUp()
+{
+ SetFilterEventFunc(DoFilterEvent);
+ SetProcessEventFunc(DoProcessEvent);
+
+ g_str.clear();
+}
+
+void EventPropagationTestCase::tearDown()
+{
+ SetFilterEventFunc(NULL);
+ SetProcessEventFunc(NULL);
+}
+
+void EventPropagationTestCase::OneHandler()
+{
+ wxCommandEvent event(TEST_EVT);
+ TestEvtHandler h1('1');
+ h1.ProcessEvent(event);
+ CPPUNIT_ASSERT_EQUAL( "oa1A", g_str );
+}
+
+void EventPropagationTestCase::TwoHandlers()
+{
+ wxCommandEvent event(TEST_EVT);
+ TestEvtHandler h1('1');
+ TestEvtHandler h2('2');
+ h1.SetNextHandler(&h2);
+ h2.SetPreviousHandler(&h1);
+ h1.ProcessEvent(event);
+ CPPUNIT_ASSERT_EQUAL( "oa1o2A", g_str );
+}
+
+void EventPropagationTestCase::WindowWithoutHandler()
+{
+ wxCommandEvent event(TEST_EVT);
+ TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
+ wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
+
+ TestWindow * const child = new TestWindow(parent, 'c');
+
+ child->ProcessEvent(event);
+ CPPUNIT_ASSERT_EQUAL( "acpA", g_str );
+}
+
+void EventPropagationTestCase::WindowWithHandler()
+{
+ wxCommandEvent event(TEST_EVT);
+ TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
+ wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
+
+ TestWindow * const child = new TestWindow(parent, 'c');
+
+ TestEvtHandler h1('1');
+ child->PushEventHandler(&h1);
+ wxON_BLOCK_EXIT_OBJ0( *child, wxWindow::PopEventHandler );
+ TestEvtHandler h2('2');
+ child->PushEventHandler(&h2);
+ wxON_BLOCK_EXIT_OBJ0( *child, wxWindow::PopEventHandler );
+
+ child->HandleWindowEvent(event);
+ CPPUNIT_ASSERT_EQUAL( "oa2o1cpA", g_str );
+}
+
$(OBJS)\test_gui_listctrltest.obj \
$(OBJS)\test_gui_textctrltest.obj \
$(OBJS)\test_gui_textentrytest.obj \
+ $(OBJS)\test_gui_propagation.obj \
$(OBJS)\test_gui_rawbmp.obj \
$(OBJS)\test_gui_htmlwindow.obj \
$(OBJS)\test_gui_guifuncs.obj \
$(OBJS)\test_gui_textentrytest.obj: .\controls\textentrytest.cpp
$(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\controls\textentrytest.cpp
+$(OBJS)\test_gui_propagation.obj: .\events\propagation.cpp
+ $(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\events\propagation.cpp
+
$(OBJS)\test_gui_rawbmp.obj: .\image\rawbmp.cpp
$(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\image\rawbmp.cpp
$(OBJS)\test_gui_listctrltest.o \
$(OBJS)\test_gui_textctrltest.o \
$(OBJS)\test_gui_textentrytest.o \
+ $(OBJS)\test_gui_propagation.o \
$(OBJS)\test_gui_rawbmp.o \
$(OBJS)\test_gui_htmlwindow.o \
$(OBJS)\test_gui_guifuncs.o \
$(OBJS)\test_gui_textentrytest.o: ./controls/textentrytest.cpp
$(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $<
+$(OBJS)\test_gui_propagation.o: ./events/propagation.cpp
+ $(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $<
+
$(OBJS)\test_gui_rawbmp.o: ./image/rawbmp.cpp
$(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $<
$(OBJS)\test_gui_listctrltest.obj \
$(OBJS)\test_gui_textctrltest.obj \
$(OBJS)\test_gui_textentrytest.obj \
+ $(OBJS)\test_gui_propagation.obj \
$(OBJS)\test_gui_rawbmp.obj \
$(OBJS)\test_gui_htmlwindow.obj \
$(OBJS)\test_gui_guifuncs.obj \
$(OBJS)\test_gui_textentrytest.obj: .\controls\textentrytest.cpp
$(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\controls\textentrytest.cpp
+$(OBJS)\test_gui_propagation.obj: .\events\propagation.cpp
+ $(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\events\propagation.cpp
+
$(OBJS)\test_gui_rawbmp.obj: .\image\rawbmp.cpp
$(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\image\rawbmp.cpp
$(OBJS)\test_gui_listctrltest.obj &
$(OBJS)\test_gui_textctrltest.obj &
$(OBJS)\test_gui_textentrytest.obj &
+ $(OBJS)\test_gui_propagation.obj &
$(OBJS)\test_gui_rawbmp.obj &
$(OBJS)\test_gui_htmlwindow.obj &
$(OBJS)\test_gui_guifuncs.obj &
$(OBJS)\test_gui_textentrytest.obj : .AUTODEPEND .\controls\textentrytest.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(TEST_GUI_CXXFLAGS) $<
+$(OBJS)\test_gui_propagation.obj : .AUTODEPEND .\events\propagation.cpp
+ $(CXX) -bt=nt -zq -fo=$^@ $(TEST_GUI_CXXFLAGS) $<
+
$(OBJS)\test_gui_rawbmp.obj : .AUTODEPEND .\image\rawbmp.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(TEST_GUI_CXXFLAGS) $<
controls/listctrltest.cpp
controls/textctrltest.cpp
controls/textentrytest.cpp
+ events/propagation.cpp
image/rawbmp.cpp
html/htmlwindow.cpp
misc/guifuncs.cpp
virtual int OnRun();
virtual int OnExit();
+ // used by events propagation test
+ virtual int FilterEvent(wxEvent& event);
+ virtual bool ProcessEvent(wxEvent& event);
+
+ void SetFilterEventFunc(FilterEventFunc f) { m_filterEventFunc = f; }
+ void SetProcessEventFunc(ProcessEventFunc f) { m_processEventFunc = f; }
+
#ifdef __WXDEBUG__
virtual void OnAssertFailure(const wxChar *,
int,
bool m_detail;
bool m_timing;
vector<string> m_registries;
+
+ // event handling hooks
+ FilterEventFunc m_filterEventFunc;
+ ProcessEventFunc m_processEventFunc;
};
IMPLEMENT_APP_CONSOLE(TestApp)
: m_list(false),
m_longlist(false)
{
+ m_filterEventFunc = NULL;
+ m_processEventFunc = NULL;
}
// Init
return TestAppBase::OnCmdLineParsed(parser);
}
+// Event handling
+int TestApp::FilterEvent(wxEvent& event)
+{
+ if ( m_filterEventFunc )
+ return (*m_filterEventFunc)(event);
+
+ return TestAppBase::FilterEvent(event);
+}
+
+bool TestApp::ProcessEvent(wxEvent& event)
+{
+ if ( m_processEventFunc )
+ return (*m_processEventFunc)(event);
+
+ return TestAppBase::ProcessEvent(event);
+}
+
+extern void SetFilterEventFunc(FilterEventFunc func)
+{
+ wxGetApp().SetFilterEventFunc(func);
+}
+
+extern void SetProcessEventFunc(ProcessEventFunc func)
+{
+ wxGetApp().SetProcessEventFunc(func);
+}
+
// Run
//
int TestApp::OnRun()
# End Source File\r
# Begin Source File\r
\r
+SOURCE=.\events\propagation.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
SOURCE=.\image\rawbmp.cpp\r
# End Source File\r
# Begin Source File\r
<File\r
RelativePath=".\geometry\point.cpp">\r
</File>\r
+ <File\r
+ RelativePath=".\events\propagation.cpp">\r
+ </File>\r
<File\r
RelativePath=".\image\rawbmp.cpp">\r
</File>\r
RelativePath=".\geometry\point.cpp"\r
>\r
</File>\r
+ <File\r
+ RelativePath=".\events\propagation.cpp"\r
+ >\r
+ </File>\r
<File\r
RelativePath=".\image\rawbmp.cpp"\r
>\r
RelativePath=".\geometry\point.cpp"\r
>\r
</File>\r
+ <File\r
+ RelativePath=".\events\propagation.cpp"\r
+ >\r
+ </File>\r
<File\r
RelativePath=".\image\rawbmp.cpp"\r
>\r
#define WX_ASSERT_FAILS_WITH_ASSERT(cond) CPPUNIT_ASSERT(!(cond))
#endif
+// these functions can be used to hook into wxApp event processing and are
+// currently used by the events propagation test
+typedef int (*FilterEventFunc)(wxEvent&);
+typedef bool (*ProcessEventFunc)(wxEvent&);
+
+extern void SetFilterEventFunc(FilterEventFunc func);
+extern void SetProcessEventFunc(ProcessEventFunc func);