1 /* propertyproxy_base.h
2  *
3  * Copyright 2002 The gtkmm Development Team
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include <glibmm/propertyproxy_base.h>
20 
21 #include <glibmm/signalproxy_connectionnode.h>
22 #include <glibmm/object.h>
23 #include <glibmm/private/object_p.h>
24 #include <utility> // For std::move()
25 
26 namespace Glib
27 {
28 
29 // PropertyProxyConnectionNode implementation:
30 
PropertyProxyConnectionNode(const sigc::slot_base & slot,GObject * gobject)31 PropertyProxyConnectionNode::PropertyProxyConnectionNode(
32   const sigc::slot_base& slot, GObject* gobject)
33 : SignalProxyConnectionNode(slot, gobject)
34 {
35 }
36 
PropertyProxyConnectionNode(sigc::slot_base && slot,GObject * gobject)37 PropertyProxyConnectionNode::PropertyProxyConnectionNode(sigc::slot_base&& slot, GObject* gobject)
38 : SignalProxyConnectionNode(std::move(slot), gobject)
39 {
40 }
41 
42 sigc::connection
connect_changed(const Glib::ustring & property_name)43 PropertyProxyConnectionNode::connect_changed(const Glib::ustring& property_name)
44 {
45   // connect it to glib
46   // 'this' will be passed as the data argument to the callback.
47   const Glib::ustring notify_signal_name = "notify::" + property_name;
48   connection_id_ = g_signal_connect_data(object_, notify_signal_name.c_str(),
49     (GCallback)(&PropertyProxyConnectionNode::callback), this,
50     &PropertyProxyConnectionNode::destroy_notify_handler, G_CONNECT_AFTER);
51 
52   return sigc::connection(slot_);
53 }
54 
callback(GObject *,GParamSpec * pspec,gpointer data)55 void PropertyProxyConnectionNode::callback(GObject*, GParamSpec* pspec, gpointer data) // static
56 {
57   if (pspec && data)
58   {
59     if (sigc::slot_base* const slot = SignalProxyBase::data_to_slot(data))
60       (*static_cast<sigc::slot<void>*>(slot))();
61   }
62 }
63 
64 // SignalProxyProperty implementation:
65 
SignalProxyProperty(Glib::ObjectBase * obj,const gchar * property_name)66 SignalProxyProperty::SignalProxyProperty(Glib::ObjectBase* obj, const gchar* property_name)
67 : SignalProxyBase(obj), property_name_(property_name)
68 {
69 }
70 
~SignalProxyProperty()71 SignalProxyProperty::~SignalProxyProperty() noexcept
72 {
73 }
74 
75 sigc::connection
connect(const SlotType & slot)76 SignalProxyProperty::connect(const SlotType& slot)
77 {
78   // Create a proxy to hold our connection info
79   // This will be deleted by destroy_notify_handler.
80   auto pConnectionNode = new PropertyProxyConnectionNode(slot, obj_->gobj());
81 
82   // connect it to glib
83   // pConnectionNode will be passed as the data argument to the callback.
84   return pConnectionNode->connect_changed(property_name_);
85 }
86 
87 sigc::connection
connect(SlotType && slot)88 SignalProxyProperty::connect(SlotType&& slot)
89 {
90   // Create a proxy to hold our connection info
91   // This will be deleted by destroy_notify_handler.
92   auto pConnectionNode = new PropertyProxyConnectionNode(std::move(slot), obj_->gobj());
93 
94   // connect it to glib
95   // pConnectionNode will be passed as the data argument to the callback.
96   return pConnectionNode->connect_changed(property_name_);
97 }
98 
99 // PropertyProxy_Base implementation:
100 
PropertyProxy_Base(ObjectBase * obj,const char * property_name)101 PropertyProxy_Base::PropertyProxy_Base(ObjectBase* obj, const char* property_name)
102 : obj_(obj), property_name_(property_name)
103 {
104 }
105 
PropertyProxy_Base(const PropertyProxy_Base & other)106 PropertyProxy_Base::PropertyProxy_Base(const PropertyProxy_Base& other)
107 : obj_(other.obj_), property_name_(other.property_name_)
108 {
109 }
110 
111 SignalProxyProperty
signal_changed()112 PropertyProxy_Base::signal_changed()
113 {
114   return SignalProxyProperty(obj_, property_name_);
115 }
116 
117 void
set_property_(const Glib::ValueBase & value)118 PropertyProxy_Base::set_property_(const Glib::ValueBase& value)
119 {
120   g_object_set_property(obj_->gobj(), property_name_, value.gobj());
121 }
122 
123 void
get_property_(Glib::ValueBase & value) const124 PropertyProxy_Base::get_property_(Glib::ValueBase& value) const
125 {
126   g_object_get_property(obj_->gobj(), property_name_, value.gobj());
127 }
128 
129 void
reset_property_()130 PropertyProxy_Base::reset_property_()
131 {
132   // Get information about the parameter:
133   const GParamSpec* const pParamSpec =
134     g_object_class_find_property(G_OBJECT_GET_CLASS(obj_->gobj()), property_name_);
135 
136   g_return_if_fail(pParamSpec != nullptr);
137 
138   Glib::ValueBase value;
139   value.init(G_PARAM_SPEC_VALUE_TYPE(pParamSpec));
140 
141   // An explicit reset is not needed, because ValueBase:init()
142   // has already initialized it to the default value for this type.
143   // value.reset();
144 
145   g_object_set_property(obj_->gobj(), property_name_, value.gobj());
146 }
147 
148 } // namespace Glib
149