efl/src/bindings/eo_cxx/eo_event.hh

153 lines
3.4 KiB
C++

///
/// @file eo_event.hh
///
#ifndef EFL_CXX_EO_EVENT_HH
#define EFL_CXX_EO_EVENT_HH
#include <Eo.h>
#include <Ecore.h>
#include <functional>
#include <memory>
namespace efl { namespace eo {
typedef ::Eo_Callback_Priority callback_priority;
namespace callback_priorities
{
static const callback_priority before = -100;
static const callback_priority default_ = 0;
static const callback_priority after = 100;
}
struct signal_connection
{
signal_connection(std::function<void()> deleter)
: _deleter(deleter) {}
void disconnect()
{
if(_deleter)
{
_deleter();
_deleter = std::function<void()>();
}
}
private:
std::function<void()> _deleter;
friend struct scoped_signal_connection;
};
struct scoped_signal_connection
{
scoped_signal_connection(signal_connection const& other)
: _deleter(other._deleter)
{
}
~scoped_signal_connection()
{
disconnect();
}
void disconnect()
{
if(_deleter)
{
_deleter();
_deleter = std::function<void()>();
}
}
scoped_signal_connection(scoped_signal_connection&& other)
: _deleter(other._deleter)
{
other._deleter = std::function<void()>();
}
private:
std::function<void()> _deleter;
scoped_signal_connection& operator=(scoped_signal_connection const&) = delete;
scoped_signal_connection(scoped_signal_connection const&) = delete;
};
template <typename F>
struct _event_deleter
{
_event_deleter(F* data, Eo* eo, ::Eo_Event_Cb cb, Eo_Event_Description const* description)
: _data(data), _eo( ::eo_ref(eo)), _cb(cb), _description(description)
{
}
~_event_deleter()
{
::eo_unref(_eo);
}
_event_deleter(_event_deleter const& other)
: _data(other._data), _eo( ::eo_ref(other._eo)), _cb(other._cb), _description(other._description)
{}
_event_deleter& operator=(_event_deleter const& other)
{
::eo_unref( _eo);
_data = other._data;
_eo = ::eo_ref(other._eo);
_cb = other._cb;
_description = other._description;
return *this;
}
void operator()() const
{
::eo_event_callback_del(_eo, _description, _cb, _data);
::ecore_main_loop_thread_safe_call_async(&_deleter_call, _data);
}
private:
static void _deleter_call(void* data)
{
delete static_cast<F*>(data);
}
F* _data;
Eo* _eo;
::Eo_Event_Cb _cb;
Eo_Event_Description const* _description;
};
template <typename F>
signal_connection make_signal_connection(std::unique_ptr<F>& data, Eo* eo, ::Eo_Event_Cb cb, Eo_Event_Description const* description)
{
signal_connection c(_event_deleter<F>(data.get(), eo, cb, description));
data.release();
return c;
}
namespace _detail {
template <typename T, typename F>
Eina_Bool really_call_event(T& wrapper, F& f, Eo_Event_Description const& desc, void *info
, std::true_type)
{
f(wrapper, desc, info);
return true;
}
template <typename T, typename F>
Eina_Bool really_call_event(T& wrapper, F& f, Eo_Event_Description const& desc, void *info
, std::false_type)
{
return f(wrapper, desc, info);
}
template <typename T, typename F>
Eina_Bool
event_callback(void *data, ::Eo_Event const* event)
{
T wrapper(::eo_ref(event->obj));
F *f = static_cast<F*>(data);
return _detail::really_call_event(wrapper, *f, *event->desc, event->info
, std::is_void<decltype((*f)(wrapper, *event->desc, event->info))>());
}
}
} }
#endif