2009-02-01 17:12:12 -05:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Name: tests/events/evthandler.cpp
|
|
|
|
// Purpose: Test the new event types and wxEvtHandler-methods
|
|
|
|
// Author: Peter Most
|
|
|
|
// Created: 2009-01-24
|
|
|
|
// Copyright: (c) 2009 Peter Most
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// headers
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#include "testprec.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "wx/event.h"
|
|
|
|
|
2009-02-02 15:38:56 -05:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// test events and their handlers
|
|
|
|
// ----------------------------------------------------------------------------
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-06 13:33:01 -05:00
|
|
|
const wxEventType LegacyEventType = wxNewEventType();
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-01 18:19:45 -05:00
|
|
|
class MyEvent;
|
2009-02-07 16:04:47 -05:00
|
|
|
wxDEFINE_EVENT(MyEventType, MyEvent);
|
2009-02-01 18:19:45 -05:00
|
|
|
|
2009-02-01 17:12:12 -05:00
|
|
|
class MyEvent : public wxEvent
|
|
|
|
{
|
2009-02-01 18:19:45 -05:00
|
|
|
public:
|
2009-02-06 13:33:01 -05:00
|
|
|
MyEvent() : wxEvent(0, MyEventType) { }
|
2009-02-01 18:19:45 -05:00
|
|
|
|
2018-09-21 13:46:49 -04:00
|
|
|
virtual wxEvent *Clone() const wxOVERRIDE { return new MyEvent; }
|
2009-02-01 17:12:12 -05:00
|
|
|
};
|
|
|
|
|
2009-02-06 16:54:09 -05:00
|
|
|
typedef void (wxEvtHandler::*MyEventFunction)(MyEvent&);
|
|
|
|
#define EVT_MYEVENT(func) \
|
2014-05-15 18:32:17 -04:00
|
|
|
wx__DECLARE_EVT0(MyEventType, &func)
|
2009-02-06 13:33:01 -05:00
|
|
|
|
2009-02-01 18:19:45 -05:00
|
|
|
class AnotherEvent : public wxEvent
|
|
|
|
{
|
|
|
|
};
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-01 18:19:45 -05:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
|
|
|
|
struct Called
|
|
|
|
{
|
|
|
|
Called() { Reset(); }
|
|
|
|
|
|
|
|
void Reset()
|
|
|
|
{
|
|
|
|
function =
|
|
|
|
functor =
|
|
|
|
method =
|
|
|
|
smethod = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool function,
|
|
|
|
functor,
|
|
|
|
method,
|
|
|
|
smethod;
|
|
|
|
} g_called;
|
|
|
|
|
|
|
|
void GlobalOnMyEvent(MyEvent&)
|
|
|
|
{
|
|
|
|
g_called.function = true;
|
|
|
|
}
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-05-02 08:52:54 -04:00
|
|
|
void GlobalOnEvent(wxEvent&)
|
|
|
|
{
|
|
|
|
g_called.function = true;
|
|
|
|
}
|
|
|
|
|
2013-07-14 21:31:40 -04:00
|
|
|
#ifdef TEST_INVALID_BIND_GLOBAL
|
2009-02-02 15:38:56 -05:00
|
|
|
void GlobalOnAnotherEvent(AnotherEvent&);
|
2013-07-14 21:31:40 -04:00
|
|
|
#endif
|
2009-02-02 15:38:56 -05:00
|
|
|
|
|
|
|
void GlobalOnIdle(wxIdleEvent&)
|
|
|
|
{
|
|
|
|
g_called.function = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct MyFunctor
|
2009-02-01 17:12:12 -05:00
|
|
|
{
|
2009-02-01 18:19:45 -05:00
|
|
|
void operator()(MyEvent &) { g_called.functor = true; }
|
2009-02-02 15:38:56 -05:00
|
|
|
};
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-02 15:38:56 -05:00
|
|
|
struct IdleFunctor
|
|
|
|
{
|
|
|
|
void operator()(wxIdleEvent &) { g_called.functor = true; }
|
2009-02-01 17:12:12 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
class MyHandler : public wxEvtHandler
|
|
|
|
{
|
2009-02-01 18:19:45 -05:00
|
|
|
public:
|
2009-02-02 15:38:56 -05:00
|
|
|
static void StaticOnMyEvent(MyEvent &) { g_called.smethod = true; }
|
|
|
|
static void StaticOnAnotherEvent(AnotherEvent &);
|
|
|
|
static void StaticOnIdle(wxIdleEvent&) { g_called.smethod = true; }
|
|
|
|
|
2009-02-01 18:19:45 -05:00
|
|
|
void OnMyEvent(MyEvent&) { g_called.method = true; }
|
2009-02-02 15:38:56 -05:00
|
|
|
void OnEvent(wxEvent&) { g_called.method = true; }
|
|
|
|
void OnAnotherEvent(AnotherEvent&);
|
|
|
|
void OnIdle(wxIdleEvent&) { g_called.method = true; }
|
2020-11-16 16:41:47 -05:00
|
|
|
|
|
|
|
void OnOverloadedHandler(wxIdleEvent&) { }
|
|
|
|
void OnOverloadedHandler(wxThreadEvent&) { }
|
2009-02-02 15:38:56 -05:00
|
|
|
};
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-02 15:38:56 -05:00
|
|
|
// we can also handle events in classes not deriving from wxEvtHandler
|
|
|
|
struct MySink
|
|
|
|
{
|
|
|
|
void OnMyEvent(MyEvent&) { g_called.method = true; }
|
2009-02-06 13:33:01 -05:00
|
|
|
void OnEvent(wxEvent&) { g_called.method = true; }
|
2009-02-02 15:38:56 -05:00
|
|
|
void OnIdle(wxIdleEvent&) { g_called.method = true; }
|
|
|
|
};
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-02 15:38:56 -05:00
|
|
|
// also test event table compilation
|
|
|
|
class MyClassWithEventTable : public wxEvtHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
void OnMyEvent(MyEvent&) { g_called.method = true; }
|
|
|
|
void OnEvent(wxEvent&) { g_called.method = true; }
|
|
|
|
void OnAnotherEvent(AnotherEvent&);
|
|
|
|
void OnIdle(wxIdleEvent&) { g_called.method = true; }
|
2020-04-09 13:48:59 -04:00
|
|
|
#ifdef wxHAS_NOEXCEPT
|
|
|
|
void OnIdleNoExcept(wxIdleEvent&) noexcept { }
|
|
|
|
#endif
|
2009-02-02 15:38:56 -05:00
|
|
|
|
|
|
|
private:
|
2015-04-23 07:49:01 -04:00
|
|
|
wxDECLARE_EVENT_TABLE();
|
2009-02-01 17:12:12 -05:00
|
|
|
};
|
|
|
|
|
2017-11-06 20:33:25 -05:00
|
|
|
// Avoid gcc warning about some of the functions defined by the expansion of
|
|
|
|
// the event table macros being unused: they are indeed unused, but we still
|
|
|
|
// want to have them to check that they compile.
|
|
|
|
wxGCC_WARNING_SUPPRESS(unused-function)
|
|
|
|
|
2015-04-23 07:49:01 -04:00
|
|
|
wxBEGIN_EVENT_TABLE(MyClassWithEventTable, wxEvtHandler)
|
2009-02-02 15:38:56 -05:00
|
|
|
EVT_IDLE(MyClassWithEventTable::OnIdle)
|
|
|
|
|
2009-02-06 13:33:01 -05:00
|
|
|
EVT_MYEVENT(MyClassWithEventTable::OnMyEvent)
|
|
|
|
EVT_MYEVENT(MyClassWithEventTable::OnEvent)
|
|
|
|
|
2020-04-09 13:48:59 -04:00
|
|
|
#ifdef wxHAS_NOEXCEPT
|
|
|
|
EVT_IDLE(MyClassWithEventTable::OnIdleNoExcept)
|
|
|
|
#endif
|
|
|
|
|
2009-02-02 15:38:56 -05:00
|
|
|
// this shouldn't compile:
|
2009-02-06 13:33:01 -05:00
|
|
|
//EVT_MYEVENT(MyClassWithEventTable::OnIdle)
|
2009-02-02 15:38:56 -05:00
|
|
|
//EVT_IDLE(MyClassWithEventTable::OnAnotherEvent)
|
2015-04-23 07:49:01 -04:00
|
|
|
wxEND_EVENT_TABLE()
|
2009-02-02 15:38:56 -05:00
|
|
|
|
2017-11-06 20:33:25 -05:00
|
|
|
wxGCC_WARNING_RESTORE(unused-function)
|
|
|
|
|
2009-02-01 18:19:45 -05:00
|
|
|
} // anonymous namespace
|
|
|
|
|
2009-02-02 15:38:56 -05:00
|
|
|
|
2020-11-16 15:03:30 -05:00
|
|
|
TEST_CASE("Event::BuiltinConnect", "[event][connect]")
|
2009-02-01 17:12:12 -05:00
|
|
|
{
|
|
|
|
MyHandler handler;
|
|
|
|
|
2009-02-02 15:38:56 -05:00
|
|
|
handler.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle));
|
|
|
|
handler.Disconnect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle));
|
|
|
|
|
|
|
|
handler.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), NULL, &handler);
|
|
|
|
handler.Disconnect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), NULL, &handler);
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-06 13:33:01 -05:00
|
|
|
// using casts like this is even uglier than using wxIdleEventHandler but
|
|
|
|
// it should still continue to work for compatibility
|
|
|
|
handler.Connect(wxEVT_IDLE, (wxObjectEventFunction)(wxEventFunction)&MyHandler::OnIdle);
|
|
|
|
handler.Disconnect(wxEVT_IDLE, (wxObjectEventFunction)(wxEventFunction)&MyHandler::OnIdle);
|
|
|
|
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind(wxEVT_IDLE, GlobalOnIdle);
|
|
|
|
handler.Unbind(wxEVT_IDLE, GlobalOnIdle);
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-02 15:38:56 -05:00
|
|
|
IdleFunctor f;
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind(wxEVT_IDLE, f);
|
|
|
|
handler.Unbind(wxEVT_IDLE, f);
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind(wxEVT_IDLE, &MyHandler::OnIdle, &handler);
|
|
|
|
handler.Unbind(wxEVT_IDLE, &MyHandler::OnIdle, &handler);
|
2009-02-02 15:38:56 -05:00
|
|
|
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind(wxEVT_IDLE, &MyHandler::StaticOnIdle);
|
|
|
|
handler.Unbind(wxEVT_IDLE, &MyHandler::StaticOnIdle);
|
2009-02-02 15:38:56 -05:00
|
|
|
}
|
|
|
|
|
2020-11-16 15:03:30 -05:00
|
|
|
TEST_CASE("Event::LegacyConnect", "[event][connect]")
|
2009-02-02 15:38:56 -05:00
|
|
|
{
|
2020-11-16 15:03:30 -05:00
|
|
|
MyHandler handler;
|
|
|
|
|
2009-02-06 13:33:01 -05:00
|
|
|
handler.Connect( LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
|
|
|
|
handler.Connect( 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
|
|
|
|
handler.Connect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-06 13:33:01 -05:00
|
|
|
handler.Disconnect( LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
|
|
|
|
handler.Disconnect( 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
|
|
|
|
handler.Disconnect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-02 15:38:56 -05:00
|
|
|
|
2009-02-06 13:33:01 -05:00
|
|
|
handler.Connect( LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
|
|
|
|
handler.Connect( 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
|
|
|
|
handler.Connect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
|
2009-02-02 15:38:56 -05:00
|
|
|
|
2009-02-06 13:33:01 -05:00
|
|
|
handler.Disconnect( LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
|
|
|
|
handler.Disconnect( 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
|
|
|
|
handler.Disconnect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
|
2009-02-02 15:38:56 -05:00
|
|
|
}
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2020-11-16 16:41:47 -05:00
|
|
|
TEST_CASE("Event::ConnectOverloaded", "[event][connect]")
|
|
|
|
{
|
|
|
|
MyHandler handler;
|
|
|
|
|
|
|
|
handler.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnOverloadedHandler));
|
|
|
|
handler.Connect(wxEVT_THREAD, wxThreadEventHandler(MyHandler::OnOverloadedHandler));
|
|
|
|
}
|
|
|
|
|
2020-11-16 15:03:30 -05:00
|
|
|
TEST_CASE("Event::DisconnectWildcard", "[event][connect][disconnect]")
|
2012-11-10 07:22:32 -05:00
|
|
|
{
|
2020-11-16 15:03:30 -05:00
|
|
|
MyHandler handler;
|
|
|
|
|
2012-11-10 07:22:32 -05:00
|
|
|
// should be able to disconnect a different handler using "wildcard search"
|
|
|
|
MyHandler sink;
|
|
|
|
wxEvtHandler source;
|
|
|
|
source.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), NULL, &sink);
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK(source.Disconnect(wxID_ANY, wxEVT_IDLE));
|
2012-11-10 07:22:32 -05:00
|
|
|
// destruction of source and sink here should properly clean up the
|
|
|
|
// wxEventConnectionRef without crashing
|
|
|
|
}
|
|
|
|
|
2020-11-16 15:03:30 -05:00
|
|
|
TEST_CASE("Event::AutoDisconnect", "[event][connect][disconnect]")
|
2012-11-10 07:22:32 -05:00
|
|
|
{
|
|
|
|
wxEvtHandler source;
|
|
|
|
{
|
|
|
|
MyHandler sink;
|
|
|
|
source.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), NULL, &sink);
|
|
|
|
// mismatched event type, so nothing should be disconnected
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK(!source.Disconnect(wxEVT_THREAD, wxIdleEventHandler(MyHandler::OnIdle), NULL, &sink));
|
2012-11-10 07:22:32 -05:00
|
|
|
}
|
|
|
|
// destruction of sink should have automatically disconnected it, so
|
|
|
|
// there should be nothing to disconnect anymore
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK(!source.Disconnect(wxID_ANY, wxEVT_IDLE));
|
2012-11-10 07:22:32 -05:00
|
|
|
}
|
|
|
|
|
2020-11-16 15:03:30 -05:00
|
|
|
TEST_CASE("Event::BindFunction", "[event][bind]")
|
2009-02-02 15:38:56 -05:00
|
|
|
{
|
2020-11-16 15:03:30 -05:00
|
|
|
MyHandler handler;
|
|
|
|
MyEvent e;
|
|
|
|
|
2009-02-02 15:38:56 -05:00
|
|
|
// function tests
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind( MyEventType, GlobalOnMyEvent );
|
2009-02-02 15:38:56 -05:00
|
|
|
g_called.Reset();
|
|
|
|
handler.ProcessEvent(e);
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK( g_called.function );
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Unbind( MyEventType, GlobalOnMyEvent );
|
2009-02-02 15:38:56 -05:00
|
|
|
g_called.Reset();
|
|
|
|
handler.ProcessEvent(e);
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK( !g_called.function ); // check that it was disconnected
|
2009-02-02 15:38:56 -05:00
|
|
|
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind( MyEventType, GlobalOnMyEvent, 0 );
|
|
|
|
handler.Unbind( MyEventType, GlobalOnMyEvent, 0 );
|
2009-02-02 15:38:56 -05:00
|
|
|
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind( MyEventType, GlobalOnMyEvent, 0, 0 );
|
|
|
|
handler.Unbind( MyEventType, GlobalOnMyEvent, 0, 0 );
|
2009-02-02 15:38:56 -05:00
|
|
|
}
|
|
|
|
|
2020-11-16 15:03:30 -05:00
|
|
|
TEST_CASE("Event::BindStaticMethod", "[event][bind]")
|
2009-02-02 15:38:56 -05:00
|
|
|
{
|
2020-11-16 15:03:30 -05:00
|
|
|
MyHandler handler;
|
|
|
|
MyEvent e;
|
|
|
|
|
2009-02-02 15:38:56 -05:00
|
|
|
// static method tests (this is same as functions but still test it just in
|
|
|
|
// case we hit some strange compiler bugs)
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind( MyEventType, &MyHandler::StaticOnMyEvent );
|
2009-02-01 18:19:45 -05:00
|
|
|
g_called.Reset();
|
|
|
|
handler.ProcessEvent(e);
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK( g_called.smethod );
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Unbind( MyEventType, &MyHandler::StaticOnMyEvent );
|
2009-02-01 18:19:45 -05:00
|
|
|
g_called.Reset();
|
|
|
|
handler.ProcessEvent(e);
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK( !g_called.smethod );
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind( MyEventType, &MyHandler::StaticOnMyEvent, 0 );
|
|
|
|
handler.Unbind( MyEventType, &MyHandler::StaticOnMyEvent, 0 );
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind( MyEventType, &MyHandler::StaticOnMyEvent, 0, 0 );
|
|
|
|
handler.Unbind( MyEventType, &MyHandler::StaticOnMyEvent, 0, 0 );
|
2009-02-02 15:38:56 -05:00
|
|
|
}
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2020-11-16 15:03:30 -05:00
|
|
|
TEST_CASE("Event::BindFunctor", "[event][bind]")
|
2009-02-02 15:38:56 -05:00
|
|
|
{
|
2020-11-16 15:03:30 -05:00
|
|
|
MyHandler handler;
|
|
|
|
MyEvent e;
|
|
|
|
|
2009-02-02 15:38:56 -05:00
|
|
|
// generalized functor tests
|
|
|
|
MyFunctor functor;
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind( MyEventType, functor );
|
2009-02-02 15:38:56 -05:00
|
|
|
g_called.Reset();
|
|
|
|
handler.ProcessEvent(e);
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK( g_called.functor );
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Unbind( MyEventType, functor );
|
2009-02-02 15:38:56 -05:00
|
|
|
g_called.Reset();
|
|
|
|
handler.ProcessEvent(e);
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK( !g_called.functor );
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind( MyEventType, functor, 0 );
|
|
|
|
handler.Unbind( MyEventType, functor, 0 );
|
2009-02-02 15:38:56 -05:00
|
|
|
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind( MyEventType, functor, 0, 0 );
|
|
|
|
handler.Unbind( MyEventType, functor, 0, 0 );
|
2009-05-02 11:28:16 -04:00
|
|
|
|
2009-05-17 06:56:14 -04:00
|
|
|
// test that a temporary functor is working as well and also test that
|
|
|
|
// unbinding a different (though equal) instance of the same functor does
|
|
|
|
// not work
|
|
|
|
MyFunctor func;
|
2009-05-02 11:28:16 -04:00
|
|
|
handler.Bind( MyEventType, MyFunctor() );
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK( !handler.Unbind( MyEventType, func ));
|
2009-05-02 11:28:16 -04:00
|
|
|
|
|
|
|
handler.Bind( MyEventType, MyFunctor(), 0 );
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK( !handler.Unbind( MyEventType, func, 0 ));
|
2009-05-02 11:28:16 -04:00
|
|
|
|
|
|
|
handler.Bind( MyEventType, MyFunctor(), 0, 0 );
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK( !handler.Unbind( MyEventType, func, 0, 0 ));
|
2009-02-02 15:38:56 -05:00
|
|
|
}
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2020-11-16 15:03:30 -05:00
|
|
|
TEST_CASE("Event::BindMethod", "[event][bind]")
|
2009-02-02 15:38:56 -05:00
|
|
|
{
|
2020-11-16 15:03:30 -05:00
|
|
|
MyHandler handler;
|
|
|
|
MyEvent e;
|
|
|
|
|
2009-02-02 15:38:56 -05:00
|
|
|
// class method tests
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind( MyEventType, &MyHandler::OnMyEvent, &handler );
|
2009-02-06 13:33:01 -05:00
|
|
|
g_called.Reset();
|
|
|
|
handler.ProcessEvent(e);
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK( g_called.method );
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Unbind( MyEventType, &MyHandler::OnMyEvent, &handler );
|
2009-02-06 13:33:01 -05:00
|
|
|
g_called.Reset();
|
|
|
|
handler.ProcessEvent(e);
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK( !g_called.method );
|
2009-02-06 13:33:01 -05:00
|
|
|
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind( MyEventType, &MyHandler::OnMyEvent, &handler, 0 );
|
|
|
|
handler.Unbind( MyEventType, &MyHandler::OnMyEvent, &handler, 0 );
|
2009-02-06 13:33:01 -05:00
|
|
|
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind( MyEventType, &MyHandler::OnMyEvent, &handler, 0, 0 );
|
|
|
|
handler.Unbind( MyEventType, &MyHandler::OnMyEvent, &handler, 0, 0 );
|
2009-02-06 13:33:01 -05:00
|
|
|
}
|
|
|
|
|
2020-11-16 15:03:30 -05:00
|
|
|
TEST_CASE("Event::BindMethodUsingBaseEvent", "[event][bind]")
|
2009-02-06 13:33:01 -05:00
|
|
|
{
|
2020-11-16 15:03:30 -05:00
|
|
|
MyHandler handler;
|
|
|
|
MyEvent e;
|
|
|
|
|
2009-02-06 13:33:01 -05:00
|
|
|
// test connecting a method taking just wxEvent and not MyEvent: this
|
|
|
|
// should work too if we don't need any MyEvent-specific information in the
|
|
|
|
// handler
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind( MyEventType, &MyHandler::OnEvent, &handler );
|
2009-02-02 15:38:56 -05:00
|
|
|
g_called.Reset();
|
|
|
|
handler.ProcessEvent(e);
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK( g_called.method );
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Unbind( MyEventType, &MyHandler::OnEvent, &handler );
|
2009-02-02 15:38:56 -05:00
|
|
|
g_called.Reset();
|
|
|
|
handler.ProcessEvent(e);
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK( !g_called.method );
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind( MyEventType, &MyHandler::OnEvent, &handler, 0 );
|
|
|
|
handler.Unbind( MyEventType, &MyHandler::OnEvent, &handler, 0 );
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind( MyEventType, &MyHandler::OnEvent, &handler, 0, 0 );
|
|
|
|
handler.Unbind( MyEventType, &MyHandler::OnEvent, &handler, 0, 0 );
|
2009-02-02 15:38:56 -05:00
|
|
|
}
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-02 15:38:56 -05:00
|
|
|
|
2020-11-16 15:03:30 -05:00
|
|
|
TEST_CASE("Event::BindFunctionUsingBaseEvent", "[event][bind]")
|
2009-05-02 08:52:54 -04:00
|
|
|
{
|
2020-11-16 15:03:30 -05:00
|
|
|
MyHandler handler;
|
|
|
|
MyEvent e;
|
|
|
|
|
2009-05-02 08:52:54 -04:00
|
|
|
// test connecting a function taking just wxEvent and not MyEvent: this
|
|
|
|
// should work too if we don't need any MyEvent-specific information in the
|
|
|
|
// handler
|
|
|
|
handler.Bind( MyEventType, GlobalOnEvent );
|
|
|
|
g_called.Reset();
|
|
|
|
handler.ProcessEvent(e);
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK( g_called.function );
|
2009-05-02 08:52:54 -04:00
|
|
|
handler.Unbind( MyEventType, GlobalOnEvent );
|
|
|
|
g_called.Reset();
|
|
|
|
handler.ProcessEvent(e);
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK( !g_called.function );
|
2009-05-02 08:52:54 -04:00
|
|
|
|
|
|
|
handler.Bind( MyEventType, GlobalOnEvent, 0 );
|
|
|
|
handler.Unbind( MyEventType, GlobalOnEvent, 0 );
|
|
|
|
|
|
|
|
handler.Bind( MyEventType, GlobalOnEvent, 0, 0 );
|
|
|
|
handler.Unbind( MyEventType, GlobalOnEvent, 0, 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-11-16 15:03:30 -05:00
|
|
|
TEST_CASE("Event::BindNonHandler", "[event][bind]")
|
2009-02-02 15:38:56 -05:00
|
|
|
{
|
2020-11-16 15:03:30 -05:00
|
|
|
MyHandler handler;
|
|
|
|
MyEvent e;
|
|
|
|
|
2009-02-02 15:38:56 -05:00
|
|
|
// class method tests for class not derived from wxEvtHandler
|
|
|
|
MySink sink;
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Bind( MyEventType, &MySink::OnMyEvent, &sink );
|
2009-02-02 15:38:56 -05:00
|
|
|
g_called.Reset();
|
|
|
|
handler.ProcessEvent(e);
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK( g_called.method );
|
2009-02-25 12:43:22 -05:00
|
|
|
handler.Unbind( MyEventType, &MySink::OnMyEvent, &sink );
|
2009-02-02 15:38:56 -05:00
|
|
|
g_called.Reset();
|
|
|
|
handler.ProcessEvent(e);
|
2020-11-16 15:03:30 -05:00
|
|
|
CHECK( !g_called.method );
|
2009-02-02 15:38:56 -05:00
|
|
|
}
|
2009-02-01 17:12:12 -05:00
|
|
|
|
2020-11-16 15:03:30 -05:00
|
|
|
TEST_CASE("Event::InvalidBind", "[event][bind]")
|
2009-02-02 15:38:56 -05:00
|
|
|
{
|
2009-02-01 18:19:45 -05:00
|
|
|
// these calls shouldn't compile but we unfortunately can't check this
|
|
|
|
// automatically, you need to uncomment them manually and test that
|
|
|
|
// compilation does indeed fail
|
2009-02-25 12:43:22 -05:00
|
|
|
|
2009-04-16 10:47:22 -04:00
|
|
|
// connecting a handler with incompatible signature shouldn't work
|
|
|
|
#ifdef TEST_INVALID_BIND_GLOBAL
|
|
|
|
handler.Bind(MyEventType, GlobalOnAnotherEvent);
|
|
|
|
#endif
|
|
|
|
#ifdef TEST_INVALID_BIND_STATIC
|
|
|
|
handler.Bind(MyEventType, &MyHandler::StaticOnAnotherEvent);
|
|
|
|
#endif
|
|
|
|
#ifdef TEST_INVALID_BIND_METHOD
|
|
|
|
handler.Bind(MyEventType, &MyHandler::OnAnotherEvent, &handler);
|
|
|
|
#endif
|
|
|
|
#ifdef TEST_INVALID_BIND_FUNCTOR
|
|
|
|
IdleFunctor f;
|
|
|
|
handler.Bind(MyEventType, f);
|
|
|
|
#endif
|
|
|
|
|
2009-04-16 17:33:37 -04:00
|
|
|
// the handler can't be omitted when calling Bind()
|
|
|
|
#ifdef TEST_INVALID_BIND_NO_HANDLER
|
|
|
|
handler.Bind(MyEventType, &MyHandler::OnMyEvent);
|
|
|
|
#endif
|
|
|
|
|
2009-04-16 10:47:22 -04:00
|
|
|
// calling a derived class method with a base class pointer must not work
|
|
|
|
#ifdef TEST_INVALID_BIND_DERIVED
|
|
|
|
struct C1 : wxEvtHandler { };
|
|
|
|
struct C2 : wxEvtHandler { void OnWhatever(wxEvent&); };
|
|
|
|
C1 c1;
|
|
|
|
c1.Bind(&C2::OnWhatever);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// using object pointer incompatible with the method must not work
|
|
|
|
#ifdef TEST_INVALID_BIND_WRONG_CLASS
|
|
|
|
MySink mySink;
|
|
|
|
MyHandler myHandler;
|
|
|
|
myHandler.Bind(MyEventType, &MyHandler::OnMyEvent, &mySink);
|
|
|
|
#endif
|
2009-02-01 17:12:12 -05:00
|
|
|
}
|
2015-11-17 09:46:38 -05:00
|
|
|
|
2015-12-08 09:22:01 -05:00
|
|
|
// Helpers for UnbindFromHandler() test, have to be declared outside of the
|
|
|
|
// function in C++98.
|
|
|
|
struct Handler1
|
2015-11-17 09:46:38 -05:00
|
|
|
{
|
2015-12-08 09:22:01 -05:00
|
|
|
void OnDontCall(MyEvent&)
|
2015-11-17 09:46:38 -05:00
|
|
|
{
|
2015-12-08 09:22:01 -05:00
|
|
|
// Although this handler is bound, the second one below is bound
|
|
|
|
// later and so will be called first and will disconnect this one
|
|
|
|
// before it has a chance to be called.
|
2020-11-16 15:03:30 -05:00
|
|
|
FAIL("shouldn't be called");
|
2015-12-08 09:22:01 -05:00
|
|
|
}
|
|
|
|
};
|
2015-11-17 09:46:38 -05:00
|
|
|
|
2015-12-08 09:22:01 -05:00
|
|
|
class Handler2
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Handler2(MyHandler& handler, Handler1& h1)
|
|
|
|
: m_handler(handler),
|
|
|
|
m_h1(h1)
|
|
|
|
{
|
|
|
|
}
|
2015-11-17 09:46:38 -05:00
|
|
|
|
2015-12-08 09:22:01 -05:00
|
|
|
void OnUnbind(MyEvent& e)
|
2015-11-17 09:46:38 -05:00
|
|
|
{
|
2015-12-08 09:22:01 -05:00
|
|
|
m_handler.Unbind(MyEventType, &Handler1::OnDontCall, &m_h1);
|
|
|
|
|
|
|
|
// Check that the now disconnected first handler is not executed.
|
|
|
|
e.Skip();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
MyHandler& m_handler;
|
|
|
|
Handler1& m_h1;
|
|
|
|
|
|
|
|
wxDECLARE_NO_COPY_CLASS(Handler2);
|
|
|
|
};
|
|
|
|
|
2020-11-16 15:03:30 -05:00
|
|
|
TEST_CASE("Event::UnbindFromHandler", "[event][bind][unbind]")
|
2015-12-08 09:22:01 -05:00
|
|
|
{
|
2020-11-16 15:03:30 -05:00
|
|
|
MyHandler handler;
|
|
|
|
MyEvent e;
|
|
|
|
|
2015-12-08 09:22:01 -05:00
|
|
|
Handler1 h1;
|
|
|
|
handler.Bind(MyEventType, &Handler1::OnDontCall, &h1);
|
2015-11-17 09:46:38 -05:00
|
|
|
|
2015-12-08 09:22:01 -05:00
|
|
|
Handler2 h2(handler, h1);
|
2015-11-17 09:46:38 -05:00
|
|
|
handler.Bind(MyEventType, &Handler2::OnUnbind, &h2);
|
|
|
|
|
|
|
|
handler.ProcessEvent(e);
|
|
|
|
}
|
2016-11-29 13:32:40 -05:00
|
|
|
|
|
|
|
// This is a compilation-time-only test: just check that a class inheriting
|
|
|
|
// from wxEvtHandler non-publicly can use Bind() with its method, this used to
|
|
|
|
// result in compilation errors.
|
|
|
|
// Note that this test will work only on C++11 compilers, so we test this only
|
|
|
|
// for such compilers.
|
2020-11-16 15:08:19 -05:00
|
|
|
#if __cplusplus >= 201103 || wxCHECK_VISUALC_VERSION(14)
|
2016-11-29 13:32:40 -05:00
|
|
|
class HandlerNonPublic : protected wxEvtHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
HandlerNonPublic()
|
|
|
|
{
|
|
|
|
Bind(wxEVT_IDLE, &HandlerNonPublic::OnIdle, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnIdle(wxIdleEvent&) { }
|
|
|
|
};
|
|
|
|
#endif // C++11
|
2020-02-10 08:08:53 -05:00
|
|
|
|
|
|
|
// Another compilation-time-only test, but this one checking that these event
|
|
|
|
// objects can't be created from outside of the library.
|
|
|
|
#ifdef TEST_INVALID_EVENT_CREATION
|
|
|
|
|
|
|
|
void TestEventCreation()
|
|
|
|
{
|
|
|
|
wxPaintEvent eventPaint;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // TEST_INVALID_EVENT_CREATION
|