medit/moo/gpp/gobj.h

275 lines
7.6 KiB
C++

/*
* moocpp/gobj.h
*
* Copyright (C) 2004-2016 by Yevgen Muntyan <emuntyan@users.sourceforge.net>
*
* This file is part of medit. medit is free software; you can
* redistribute it and/or modify it under the terms of the
* GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License,
* or (at your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public
* License along with medit. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef __cplusplus
#error "This is a C++ header"
#endif
#include <glib-object.h>
namespace g {
namespace impl
{
class base
{
public:
virtual ~base() = default;
virtual GObject* _gobj() = 0;
};
} // namespace impl
namespace impl
{
class obj_base
{
protected:
obj_base(GObject* o);
~obj_base();
GObject* _gobj() const { return m_gobj; }
private:
GObject* m_gobj;
};
class internals_accessor;
} // namespace impl
struct obj_type_info
{
obj_type_info(GType g_type);
GType g_type;
};
struct iface_type_info
{
iface_type_info(GType g_type);
GType g_type;
};
#define MOO_GOBJ_CLASS_DECL_BASE(Self, GName, G_TYPE) \
friend class g::impl::internals_accessor; \
\
public: \
static const g::obj_type_info type_info; \
\
using g_class = GName; \
\
GName *gobj() { return reinterpret_cast<GName*>(_gobj()); } \
\
operator GName&() { return *gobj(); } \
\
static g::obj_ptr<Self> wrap_new(GName* o); \
#define MOO_GOBJ_CLASS_DECL(Self, Parent, GName, G_TYPE) \
MOO_GOBJ_CLASS_DECL_BASE(Self, GName, G_TYPE) \
protected: \
Self() = delete; \
explicit Self(GName* o) : Parent(reinterpret_cast<Parent::g_class*>(o)) {} \
GObject *_gobj() { return Parent::_gobj(); } \
#define MOO_GOBJ_IFACE_DECL(Self, GName, G_TYPE) \
friend class g::impl::internals_accessor; \
\
public: \
static const g::iface_type_info type_info; \
\
using g_iface = GName; \
\
GName *gobj() { return reinterpret_cast<GName*>(_gobj()); } \
\
operator GName&() { return *gobj(); } \
\
static g::obj_ptr<Self> wrap_new(GName* o); \
#define MOO_DECLARE_GOBJ_CLASS(Self) \
class Self; \
using Self##Ptr = g::obj_ptr<Self> \
#define MOO_DEFINE_SIMPLE_GOBJ_CLASS(Self, Parent, GSelf, G_TYPE) \
MOO_DECLARE_GOBJ_CLASS(Self); \
class Self : public Parent \
{ \
MOO_GOBJ_CLASS_DECL(Self, Parent, GSelf, G_TYPE) \
}
#define MOO_CUSTOM_GOBJ_CLASS_DECL(Self, Parent) \
friend class impl::internals_accessor; \
\
public: \
static const g::obj_type_info type_info; \
namespace impl {
template<typename T, typename RefUnref>
class ref_ptr
{
public:
ref_ptr(T* p = nullptr) : m_p(p) { if (m_p) RefUnref::ref(m_p); }
~ref_ptr() { if (m_p) RefUnref::unref(m_p); }
T* get() const { return m_p; }
T* operator->() const { return m_p; }
T& operator*() const { return *m_p; }
void reset() { *this = nullptr; }
ref_ptr(const ref_ptr& rhs) : ref_ptr(rhs.m_p) {}
ref_ptr& operator=(const ref_ptr& rhs) { *this = rhs.m_p; return *this; }
ref_ptr(ref_ptr&& rhs) : m_p(rhs.m_p) { rhs.m_p = nullptr; }
ref_ptr& operator=(ref_ptr&& rhs) { std::swap(m_p, rhs.m_p); return *this; }
ref_ptr& operator=(T* p) { if (m_p != p) { T* tmp = m_p; m_p = p; if (tmp) RefUnref::unref(tmp); if(m_p) RefUnref::ref(m_p); } return *this; }
template<typename U>
ref_ptr(U* p) : ref_ptr(static_cast<T*>(p)) {}
template<typename U>
ref_ptr& operator=(U* p) { *this = static_cast<T*>(p); return *this; }
template<typename U>
ref_ptr(const ref_ptr<U, RefUnref>& rhs) : ref_ptr(rhs.m_p) {}
template<typename U>
ref_ptr& operator=(const ref_ptr<U, RefUnref>& rhs) { *this = rhs.get(); return *this; }
template<typename U>
ref_ptr(ref_ptr<U, RefUnref>&& rhs) : m_p(rhs.m_p) { rhs.m_p = nullptr; }
template<typename U>
ref_ptr& operator=(ref_ptr<U, RefUnref>&& rhs);
private:
T* m_p;
};
class obj_ref_unref
{
public:
template<typename T>
static void ref(T* o) { g_object_ref(o->gobj()); }
template<typename T>
static void unref(T* o) { g_object_unref(o->gobj()); }
};
} // namespace impl
template<typename T>
using obj_ptr = impl::ref_ptr<T, impl::obj_ref_unref>;
///////////////////////////////////////////////////////////////////////////////////////////
//
// GObject
//
class Object;
using ObjectPtr = obj_ptr<Object>;
class Object : public impl::obj_base
{
MOO_GOBJ_CLASS_DECL_BASE(Object, GObject, G_TYPE_OBJECT)
protected:
Object() = delete;
explicit Object(GObject* o) : impl::obj_base(o) {}
public:
gulong connect(const char* detailed_signal, GCallback c_handler, void* data);
gulong connect_swapped(const char* detailed_signal, GCallback c_handler, void* data);
void signal_emit_by_name(const char* detailed_signal, ...);
void signal_emit(guint signal_id, GQuark detail, ...);
bool signal_has_handler_pending(guint signal_id, GQuark detail, bool may_be_blocked);
gulong signal_connect_closure_by_id(guint signal_id, GQuark detail, GClosure* closure, bool after);
gulong signal_connect_closure(const char* detailed_signal, GClosure* closure, bool after);
gulong signal_connect_data(const char* detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags);
void signal_handler_block(gulong handler_id);
void signal_handler_unblock(gulong handler_id);
void signal_handler_disconnect(gulong handler_id);
bool signal_handler_is_connected(gulong handler_id);
gulong signal_handler_find(GSignalMatchType mask, guint signal_id, GQuark detail, GClosure* closure, gpointer func, gpointer data);
guint signal_handlers_block_matched(GSignalMatchType mask, guint signal_id, GQuark detail, GClosure* closure, gpointer func, gpointer data);
guint signal_handlers_unblock_matched(GSignalMatchType mask, guint signal_id, GQuark detail, GClosure* closure, gpointer func, gpointer data);
guint signal_handlers_disconnect_matched(GSignalMatchType mask, guint signal_id, GQuark detail, GClosure* closure, gpointer func, gpointer data);
guint signal_handlers_disconnect_by_func(GCallback c_handler, void* data);
#if 0
void* get_data(const char* key);
void* get_data(GQuark q);
void set_data(const char* key, gpointer value, GDestroyNotify destroy = nullptr);
void set_data(GQuark q, gpointer value, GDestroyNotify destroy = nullptr);
void set_property(const char* property_name, const GValue* value);
template<typename T>
void set(const char* prop, const T& value)
{
g_object_set(gobj(), prop, cpp_vararg_value_fixer<T>::apply(value), nullptr);
}
template<typename T, typename... Args>
void set(const char* prop, const T& value, Args&&... args)
{
set(prop, value);
set(std::forward<Args>(args)...);
}
void get(const char* prop, bool& dest)
{
gboolean val;
g_object_get(gobj(), prop, &val, nullptr);
dest = val;
}
template<typename T>
void get(const char* prop, T&& dest)
{
g_object_get(gobj(), prop, cpp_vararg_dest_fixer<T>::apply(std::forward<T>(dest)), nullptr);
}
template<typename T, typename... Args>
void get(const char* prop, T&& dest, Args&&... args)
{
get(prop, std::forward<T>(dest));
get(std::forward<Args>(args)...);
}
#endif // 0
void notify(const char* property_name);
void freeze_notify();
void thaw_notify();
};
///////////////////////////////////////////////////////////////////////////////////////////
//
// GIface
//
class Iface : public impl::base
{
};
} // namespace g