1 /* Copyright (C) 2002 The gtkmm Development Team
2  *
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 2.1 of the License, or (at your option) any later version.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #include <glibmm/interface.h>
18 #include <glibmm/private/interface_p.h>
19 
20 namespace Glib
21 {
22 
23 /**** Glib::Interface_Class ************************************************/
24 
25 void
add_interface(GType instance_type) const26 Interface_Class::add_interface(GType instance_type) const
27 {
28   // This check is disabled, because it checks whether any of the types's bases implement the
29   // interface, not just the specific type.
30   // if( !g_type_is_a(instance_type, gtype_) ) //For convenience, don't complain about calling this
31   // twice.
32   //{
33   const GInterfaceInfo interface_info = {
34     class_init_func_,
35     nullptr, // interface_finalize
36     nullptr, // interface_data
37   };
38 
39   g_type_add_interface_static(instance_type, gtype_, &interface_info);
40   //}
41 }
42 
43 /**** Interface Glib::Interface ********************************************/
44 
Interface(const Interface_Class & interface_class)45 Interface::Interface(const Interface_Class& interface_class)
46 {
47   // gobject_ will be set in the Object constructor.
48   // Any instantiable class that derives from Interface should also inherit from Object.
49 
50   if (custom_type_name_ && !is_anonymous_custom_())
51   {
52     if (gobject_)
53     {
54       GObjectClass* const instance_class = G_OBJECT_GET_CLASS(gobject_);
55       const GType iface_type = interface_class.get_type();
56 
57       if (!g_type_interface_peek(instance_class, iface_type))
58       {
59         void* const g_iface = g_type_default_interface_ref(iface_type);
60 
61         // Override the properties of the derived interface, if any.
62 
63         const GType custom_type = G_OBJECT_CLASS_TYPE(instance_class);
64         Class::iface_properties_type* props = static_cast<Class::iface_properties_type*>(
65           g_type_get_qdata(custom_type, Class::iface_properties_quark));
66 
67         if (!props)
68         {
69           props = new Class::iface_properties_type();
70           g_type_set_qdata(custom_type, Class::iface_properties_quark, props);
71         }
72 
73         const guint n_existing_props = props->size();
74 
75         guint n_iface_props = 0;
76         GParamSpec** iface_props = g_object_interface_list_properties(g_iface, &n_iface_props);
77 
78         for (guint p = 0; p < n_iface_props; p++)
79         {
80           GValue* g_value = g_new0(GValue, 1);
81           g_value_init(g_value, iface_props[p]->value_type);
82           g_param_value_set_default(iface_props[p], g_value);
83           props->emplace_back(g_value);
84 
85           const gchar* prop_name = g_param_spec_get_name(iface_props[p]);
86           GParamSpec* new_spec = g_param_spec_override(prop_name, iface_props[p]);
87           g_object_class_install_property(instance_class, p + 1 + n_existing_props, new_spec);
88         }
89 
90         interface_class.add_interface(custom_type);
91 
92         g_type_default_interface_unref(g_iface);
93         g_free(iface_props);
94       }
95     }
96     else // gobject_ == nullptr
97     {
98       // The GObject is not instantiated yet. Add to the stored custom interface
99       // classes, and add the interface to the GType in the Glib::Object constructor.
100       add_custom_interface_class(&interface_class);
101     }
102   }
103 }
104 
Interface(GObject * castitem)105 Interface::Interface(GObject* castitem)
106 {
107   // Connect GObject and wrapper instances.
108   ObjectBase::initialize(castitem);
109 }
110 
Interface()111 Interface::Interface()
112 {
113 }
114 
Interface(Interface && src)115 Interface::Interface(Interface&& src) noexcept
116   : sigc::trackable(std::move(src)), // not actually called because it's a virtual base
117     ObjectBase(std::move(src)) // not actually called because it's a virtual base
118 {
119   // We don't call initialize_move() because we
120   // want the derived move constructor to only cause it
121   // to be called once, so we just let it be called
122   // by the implementing class, such as Gtk::Entry (implementing Gtk::Editable
123   // and Gtk::CellEditable), via the call to Object::Object(Object&& src).
124   // ObjectBase::initialize_move(src.gobject_, &src);
125 }
126 
127 Interface&
operator =(Interface &&)128 Interface::operator=(Interface&& /* src */) noexcept
129 {
130   // We don't call ObjectBase::operator=(ObjectBase&& src) because we
131   // want the derived move assignment operator to only cause it
132   // to be called once, so we just let it be called
133   // by the implementing class, such as Gtk::Entry (implementing Gtk::Editable
134   // and Gtk::CellEditable), via the call to Object::operator=(Object&& src).
135   // ObjectBase::operator=(std::move(src));
136   return *this;
137 }
138 
~Interface()139 Interface::~Interface() noexcept
140 {
141 }
142 
143 GType
get_type()144 Interface::get_type()
145 {
146   return G_TYPE_INTERFACE;
147 }
148 
149 GType
get_base_type()150 Interface::get_base_type()
151 {
152   return G_TYPE_INTERFACE;
153 }
154 
155 RefPtr<ObjectBase>
wrap_interface(GObject * object,bool take_copy)156 wrap_interface(GObject* object, bool take_copy)
157 {
158   return Glib::RefPtr<ObjectBase>(wrap_auto(object, take_copy));
159 }
160 
161 } // namespace Glib
162