/* Copyright (C) 2002 The gtkmm Development Team
*
* This library 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.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*/
#include
#include
namespace Glib
{
/**** Glib::Interface_Class ************************************************/
void
Interface_Class::add_interface(GType instance_type) const
{
#if GLIB_CHECK_VERSION(2,70,0)
// If instance_type is a final type, it has not been registered by
// Glib::Class::register_derived_type(). Don't add an interface.
if (G_TYPE_IS_FINAL(instance_type))
return;
#endif
// This check is disabled, because it checks whether any of the types's bases implement the
// interface, not just the specific type.
// if( !g_type_is_a(instance_type, gtype_) ) //For convenience, don't complain about calling this
// twice.
//{
const GInterfaceInfo interface_info = {
class_init_func_,
nullptr, // interface_finalize
nullptr, // interface_data
};
g_type_add_interface_static(instance_type, gtype_, &interface_info);
//}
}
/**** Interface Glib::Interface ********************************************/
Interface::Interface(const Interface_Class& interface_class)
{
// gobject_ will be set in the Object constructor.
// Any instantiable class that derives from Interface should also inherit from Object.
if (custom_type_name_ && !is_anonymous_custom_())
{
if (gobject_)
{
GObjectClass* const instance_class = G_OBJECT_GET_CLASS(gobject_);
const GType iface_type = interface_class.get_type();
if (!g_type_interface_peek(instance_class, iface_type))
{
void* const g_iface = g_type_default_interface_ref(iface_type);
// Override the properties of the derived interface, if any.
const GType custom_type = G_OBJECT_CLASS_TYPE(instance_class);
Class::iface_properties_type* props = static_cast(
g_type_get_qdata(custom_type, Class::iface_properties_quark));
if (!props)
{
props = new Class::iface_properties_type();
g_type_set_qdata(custom_type, Class::iface_properties_quark, props);
}
const guint n_existing_props = props->size();
guint n_iface_props = 0;
GParamSpec** iface_props = g_object_interface_list_properties(g_iface, &n_iface_props);
for (guint p = 0; p < n_iface_props; p++)
{
GValue* g_value = g_new0(GValue, 1);
g_value_init(g_value, iface_props[p]->value_type);
g_param_value_set_default(iface_props[p], g_value);
props->emplace_back(g_value);
const gchar* prop_name = g_param_spec_get_name(iface_props[p]);
GParamSpec* new_spec = g_param_spec_override(prop_name, iface_props[p]);
g_object_class_install_property(instance_class, p + 1 + n_existing_props, new_spec);
}
interface_class.add_interface(custom_type);
g_type_default_interface_unref(g_iface);
g_free(iface_props);
}
}
else // gobject_ == nullptr
{
// The GObject is not instantiated yet. Add to the stored custom interface
// classes, and add the interface to the GType in the Glib::Object constructor.
add_custom_interface_class(&interface_class);
}
}
}
Interface::Interface(GObject* castitem)
{
// Connect GObject and wrapper instances.
ObjectBase::initialize(castitem);
}
Interface::Interface()
{
}
Interface::Interface(Interface&& src) noexcept
: sigc::trackable(std::move(src)), // not actually called because it's a virtual base
ObjectBase(std::move(src)) // not actually called because it's a virtual base
{
// We don't call initialize_move() because we
// want the derived move constructor to only cause it
// to be called once, so we just let it be called
// by the implementing class, such as Gtk::Entry (implementing Gtk::Editable
// and Gtk::CellEditable), via the call to Object::Object(Object&& src).
// ObjectBase::initialize_move(src.gobject_, &src);
}
Interface&
Interface::operator=(Interface&& /* src */) noexcept
{
// We don't call ObjectBase::operator=(ObjectBase&& src) because we
// want the derived move assignment operator to only cause it
// to be called once, so we just let it be called
// by the implementing class, such as Gtk::Entry (implementing Gtk::Editable
// and Gtk::CellEditable), via the call to Object::operator=(Object&& src).
// ObjectBase::operator=(std::move(src));
return *this;
}
Interface::~Interface() noexcept
{
}
GType
Interface::get_type()
{
return G_TYPE_INTERFACE;
}
GType
Interface::get_base_type()
{
return G_TYPE_INTERFACE;
}
RefPtr
wrap_interface(GObject* object, bool take_copy)
{
return Glib::make_refptr_for_instance(wrap_auto(object, take_copy));
}
} // namespace Glib