[gtkmm] Add GtkContainer's child properties handling
- From: Juan R. Garcia Blanco <juanrgar src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtkmm] Add GtkContainer's child properties handling
- Date: Sat, 5 Jul 2014 10:30:33 +0000 (UTC)
commit 4442cbf5879f826d32261e486a7fc8468bc302b1
Author: Juan R. GarcĂa Blanco <juanrgar gmail com>
Date: Mon Jun 30 22:08:01 2014 +0200
Add GtkContainer's child properties handling
* gtk/gtkmm/childpropertyproxy_base.[h|cc]: New files.
* gtk/gtkmm/childpropertyproxy.[h|cc]: New files.
* gtk/gtkmm/filelist.am: Add childpropertyproxy_base.[h|cc] and
childpropertyproxy.[h|cc].
* gtk/src/container.hg: Include gtkmm/childpropertyproxy.h.
* tools/extra_defs_gen/generate_defs_gtk.cc: Add
get_child_properties(), and use it to gather information about
child properties in GtkContainer subclasses.
* tools/m4/child_property.m4: New file that expands
_CHILD_PROPERTY_PROXY macro.
* tools/m4/convert_gtkmm.m4: Include child_property.m4.
* tools/m4/filelist.am: Add child_property.m4.
gtk/gtkmm/childpropertyproxy.cc | 26 ++++
gtk/gtkmm/childpropertyproxy.h | 181 +++++++++++++++++++++++++++++
gtk/gtkmm/childpropertyproxy_base.cc | 92 +++++++++++++++
gtk/gtkmm/childpropertyproxy_base.h | 71 +++++++++++
gtk/gtkmm/filelist.am | 4 +
gtk/src/container.hg | 1 +
tools/extra_defs_gen/generate_defs_gtk.cc | 61 ++++++++++
tools/m4/child_property.m4 | 37 ++++++
tools/m4/convert_gtkmm.m4 | 1 +
tools/m4/filelist.am | 1 +
10 files changed, 475 insertions(+), 0 deletions(-)
---
diff --git a/gtk/gtkmm/childpropertyproxy.cc b/gtk/gtkmm/childpropertyproxy.cc
new file mode 100644
index 0000000..a9f5f4a
--- /dev/null
+++ b/gtk/gtkmm/childpropertyproxy.cc
@@ -0,0 +1,26 @@
+// -*- c++ -*-
+
+/* childpropertyproxy.cc
+ *
+ * Copyright 2014 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, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <gtkmm/childpropertyproxy.h>
+
+namespace Gtk
+{
+} // namespace Gtk
diff --git a/gtk/gtkmm/childpropertyproxy.h b/gtk/gtkmm/childpropertyproxy.h
new file mode 100644
index 0000000..f374efd
--- /dev/null
+++ b/gtk/gtkmm/childpropertyproxy.h
@@ -0,0 +1,181 @@
+// -*- c++ -*-
+#ifndef _GTKMM_CHILDPROPERTYPROXY_H
+#define _GTKMM_CHILDPROPERTYPROXY_H
+
+/* childpropertyproxy.h
+ *
+ * Copyright 2014 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, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <gtkmm/childpropertyproxy_base.h>
+
+
+namespace Gtk
+{
+
+/** A ChildPropertyProxy can be used to get and set the value of a GtkContainer's child property.
+ * Child properties are not specific to either the container or the contained widget, but rather
+ * to their relation.
+ * With the ChildPropertyProxy, you may use either get_value() and set_value(), or operator=()
+ * and operator PropertyType(), like in this example:
+ * @code
+ * bool first_tab_tab_expand = notebook.property_tab_expand(first_tab_widget);
+ * notebook.property_tab_expand(first_tab_widget) = true;
+ * @endcode
+ *
+ * You may also receive notification when a property's value changes on a child, by connecting
+ * to signal_changed().
+ */
+template <class T>
+class ChildPropertyProxy : public ChildPropertyProxy_Base
+{
+public:
+ typedef T PropertyType;
+
+ ChildPropertyProxy(Gtk::Container* parent, Gtk::Widget& child, const char* property_name)
+ : ChildPropertyProxy_Base(parent, child, property_name) {}
+
+ /** Set the value of this property in child.
+ * @param data The new value for the property.
+ */
+ void set_value(const PropertyType& data);
+
+ /** Get the value of this property in child.
+ * @result The current value of the property.
+ */
+ PropertyType get_value() const;
+
+ /** Set the value of this property in child back to its default value.
+ */
+ void reset_value()
+ { reset_property_(); }
+
+ ChildPropertyProxy<T>& operator=(const PropertyType& data)
+ { set_value(data); return *this; }
+
+ operator PropertyType() const
+ { return get_value(); }
+
+ SignalProxyChildProperty signal_changed();
+};
+
+
+/** See ChildPropertyProxy().
+ * This property can be written, but not read, so there is no get_value() method.
+ */
+template <class T>
+class ChildPropertyProxy_WriteOnly : public ChildPropertyProxy_Base
+{
+public:
+ typedef T PropertyType;
+
+ ChildPropertyProxy_WriteOnly(Gtk::Container* parent, Gtk::Widget& child, const char* property_name)
+ : ChildPropertyProxy_Base(parent, child, property_name) {}
+
+ /** Set the value of this property in child.
+ * @param data The new value for the property.
+ */
+ void set_value(const PropertyType& data);
+
+ /** Set the value of this property in child back to its default value.
+ */
+ void reset_value()
+ { reset_property_(); }
+
+ ChildPropertyProxy_WriteOnly<T>& operator=(const PropertyType& data)
+ { set_value(data); return *this; }
+};
+
+/** See ChildPropertyProxy().
+ * This property can be read, but not written, so there is no set_value() method.
+ */
+template <class T>
+class ChildPropertyProxy_ReadOnly : public ChildPropertyProxy_Base
+{
+public:
+ typedef T PropertyType;
+
+ //obj is const, because this should be returned by const accessors.
+ ChildPropertyProxy_ReadOnly(const Gtk::Container* parent, const Gtk::Widget& child, const char*
property_name)
+ : ChildPropertyProxy_Base(const_cast<Gtk::Container*>(parent), const_cast<Gtk::Widget&>(child),
property_name) {}
+
+ /** Get the value of this property in child.
+ * @result The current value of the property.
+ */
+ PropertyType get_value() const;
+
+ operator PropertyType() const
+ { return get_value(); }
+};
+
+
+/**** Template Implementation **********************************************/
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+template <class T>
+void ChildPropertyProxy<T>::set_value(const T& data)
+{
+ Glib::Value<T> value;
+ value.init(Glib::Value<T>::value_type());
+
+ value.set(data);
+ set_property_(value);
+}
+
+template <class T>
+T ChildPropertyProxy<T>::get_value() const
+{
+ Glib::Value<T> value;
+ value.init(Glib::Value<T>::value_type());
+
+ get_property_(value);
+ return value.get();
+}
+
+template <class T>
+SignalProxyChildProperty ChildPropertyProxy<T>::signal_changed()
+{
+ return SignalProxyChildProperty(&child_, property_name_);
+}
+
+template <class T>
+void ChildPropertyProxy_WriteOnly<T>::set_value(const T& data)
+{
+ Glib::Value<T> value;
+ value.init(Glib::Value<T>::value_type());
+
+ value.set(data);
+ set_property_(value);
+}
+
+template <class T>
+T ChildPropertyProxy_ReadOnly<T>::get_value() const
+{
+ Glib::Value<T> value;
+ value.init(Glib::Value<T>::value_type());
+
+ get_property_(value);
+ return value.get();
+}
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+} // namespace Gtk
+
+
+#endif /* _GTKMM_CHILDPROPERTYPROXY_H */
diff --git a/gtk/gtkmm/childpropertyproxy_base.cc b/gtk/gtkmm/childpropertyproxy_base.cc
new file mode 100644
index 0000000..1bd5125
--- /dev/null
+++ b/gtk/gtkmm/childpropertyproxy_base.cc
@@ -0,0 +1,92 @@
+// -*- c++ -*-
+
+/* childpropertyproxy_base.cc
+ *
+ * Copyright 2014 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, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <gtkmm/childpropertyproxy_base.h>
+#include <gtkmm/container.h>
+
+#include <gtk/gtk.h>
+
+namespace Gtk
+{
+
+sigc::connection SignalProxyChildProperty::connect(const SlotType& sl)
+{
+ // Create a proxy to hold our connection info
+ // This will be deleted by destroy_notify_handler.
+ Glib::PropertyProxyConnectionNode* pConnectionNode = new Glib::PropertyProxyConnectionNode(sl,
obj_->gobj());
+
+ // connect it to gtk+
+ // pConnectionNode will be passed as the data argument to the callback.
+ // The callback will then call the virtual Object::property_change_notify() method,
+ // which will contain a switch/case statement which will examine the property name.
+ const Glib::ustring notify_signal_name = "child-notify::" + Glib::ustring(property_name_);
+ pConnectionNode->connection_id_ = g_signal_connect_data(obj_->gobj(),
+ notify_signal_name.c_str(), (GCallback)(&Glib::PropertyProxyConnectionNode::callback),
pConnectionNode,
+ &Glib::PropertyProxyConnectionNode::destroy_notify_handler,
+ G_CONNECT_AFTER);
+
+ return sigc::connection(pConnectionNode->slot_);
+}
+
+ChildPropertyProxy_Base::ChildPropertyProxy_Base(Gtk::Container* parent, Gtk::Widget& child, const char*
property_name)
+ : parent_(parent),
+ child_(child),
+ property_name_(property_name) {}
+
+ChildPropertyProxy_Base::ChildPropertyProxy_Base(const ChildPropertyProxy_Base& other)
+ : parent_(other.parent_),
+ child_(other.child_),
+ property_name_(other.property_name_) {}
+
+SignalProxyChildProperty ChildPropertyProxy_Base::signal_changed()
+{
+ return SignalProxyChildProperty(&child_, property_name_);
+}
+
+void ChildPropertyProxy_Base::set_property_(const Glib::ValueBase& value)
+{
+ gtk_container_child_set_property(parent_->gobj(), child_.gobj(), property_name_, value.gobj());
+}
+
+void ChildPropertyProxy_Base::get_property_(Glib::ValueBase& value) const
+{
+ gtk_container_child_get_property(parent_->gobj(), child_.gobj(), property_name_, value.gobj());
+}
+
+void ChildPropertyProxy_Base::reset_property_()
+{
+ // Get information about the parameter:
+ const GParamSpec *const pParamSpec =
+ gtk_container_class_find_child_property(G_OBJECT_GET_CLASS(parent_->gobj()), property_name_);
+
+ g_return_if_fail(pParamSpec != 0);
+
+ Glib::ValueBase value;
+ value.init(G_PARAM_SPEC_VALUE_TYPE(pParamSpec));
+
+ // An explicit reset is not needed, because ValueBase:init()
+ // has already initialized it to the default value for this type.
+ // value.reset();
+
+ set_property_(value);
+}
+
+} // namespace Gtk
diff --git a/gtk/gtkmm/childpropertyproxy_base.h b/gtk/gtkmm/childpropertyproxy_base.h
new file mode 100644
index 0000000..6ae0428
--- /dev/null
+++ b/gtk/gtkmm/childpropertyproxy_base.h
@@ -0,0 +1,71 @@
+// -*- c++ -*-
+#ifndef _GTKMM_CHILDPROPERTYPROXY_BASE_H
+#define _GTKMM_CHILDPROPERTYPROXY_BASE_H
+
+/* childpropertyproxy_base.h
+ *
+ * Copyright 2014 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, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/value.h>
+#include <glibmm/propertyproxy_base.h>
+#include <gtkmm/widget.h>
+
+#include <sigc++/sigc++.h>
+
+
+namespace Gtk
+{
+
+// We need to reimplement the connect() method so that it uses
+// "child-notify" as prefix for notify signal.
+class SignalProxyChildProperty : public Glib::SignalProxyProperty
+{
+public:
+ SignalProxyChildProperty(Widget* child, const char* property_name)
+ : Glib::SignalProxyProperty(child, property_name) {}
+
+ sigc::connection connect(const SlotType& sl);
+};
+
+class Container;
+
+class ChildPropertyProxy_Base
+{
+public:
+ ChildPropertyProxy_Base(Container* parent, Widget& child, const char* property_name);
+ ChildPropertyProxy_Base(const ChildPropertyProxy_Base& other);
+
+ SignalProxyChildProperty signal_changed();
+
+ Container* get_parent() const { return parent_; }
+ Widget& get_child() const { return child_; }
+ const char* get_name() const { return property_name_; }
+
+protected:
+ void set_property_(const Glib::ValueBase& value);
+ void get_property_(Glib::ValueBase& value) const;
+ void reset_property_();
+
+ Container* parent_;
+ Widget& child_;
+ const char* property_name_;
+};
+
+} // namespace Gtk
+
+#endif /* _GTKMM_CHILDPROPERTYPROXY_BASE_H */
diff --git a/gtk/gtkmm/filelist.am b/gtk/gtkmm/filelist.am
index cfe106d..337d6b2 100644
--- a/gtk/gtkmm/filelist.am
+++ b/gtk/gtkmm/filelist.am
@@ -8,6 +8,8 @@ gtkmm_files_extra_any_cc = \
accelkey.cc \
accelmap.cc \
cellrenderer_generation.cc \
+ childpropertyproxy.cc \
+ childpropertyproxy_base.cc \
listviewtext.cc \
object.cc \
radiobuttongroup.cc \
@@ -26,6 +28,8 @@ gtkmm_files_extra_any_h = \
base.h \
border.h \
cellrenderer_generation.h \
+ childpropertyproxy.h \
+ childpropertyproxy_base.h \
listviewtext.h \
object.h \
radiobuttongroup.h \
diff --git a/gtk/src/container.hg b/gtk/src/container.hg
index 99f551f..75d0989 100644
--- a/gtk/src/container.hg
+++ b/gtk/src/container.hg
@@ -18,6 +18,7 @@
#include <vector>
#include <gtkmm/widget.h>
+#include <gtkmm/childpropertyproxy.h>
_DEFS(gtkmm,gtk)
_PINCLUDE(gtkmm/private/widget_p.h)
diff --git a/tools/extra_defs_gen/generate_defs_gtk.cc b/tools/extra_defs_gen/generate_defs_gtk.cc
index 210a6f3..30fa543 100644
--- a/tools/extra_defs_gen/generate_defs_gtk.cc
+++ b/tools/extra_defs_gen/generate_defs_gtk.cc
@@ -40,6 +40,8 @@
# include <gtk/gtkunixprint.h>
#endif
+std::string get_child_properties(GType gtype);
+
int main(int argc, char** argv)
{
gtk_init(&argc, &argv);
@@ -243,5 +245,64 @@ int main(int argc, char** argv)
<< get_defs( GTK_TYPE_WIDGET )
<< get_defs( GTK_TYPE_WINDOW )
;
+
+ std::cout << get_child_properties( GTK_TYPE_BIN )
+ << get_child_properties( GTK_TYPE_BOX )
+ << get_child_properties( GTK_TYPE_FIXED )
+ << get_child_properties( GTK_TYPE_FLOW_BOX )
+ << get_child_properties( GTK_TYPE_GRID )
+ << get_child_properties( GTK_TYPE_HEADER_BAR )
+ << get_child_properties( GTK_TYPE_PANED )
+ << get_child_properties( GTK_TYPE_ICON_VIEW )
+ << get_child_properties( GTK_TYPE_LAYOUT )
+ << get_child_properties( GTK_TYPE_LIST_BOX )
+ << get_child_properties( GTK_TYPE_MENU_SHELL )
+ << get_child_properties( GTK_TYPE_NOTEBOOK )
+#ifdef GDK_WINDOWING_X11
+ << get_child_properties( GTK_TYPE_SOCKET )
+#endif
+ << get_child_properties( GTK_TYPE_STACK )
+ << get_child_properties( GTK_TYPE_TEXT_VIEW )
+ << get_child_properties( GTK_TYPE_TOOLBAR )
+ << get_child_properties( GTK_TYPE_TOOL_ITEM_GROUP )
+ << get_child_properties( GTK_TYPE_TOOL_PALETTE )
+ << get_child_properties( GTK_TYPE_TREE_VIEW )
+ ;
+
return 0;
}
+
+std::string get_child_properties(GType gtype)
+{
+ std::string strResult; std::string strObjectName = g_type_name(gtype);
+
+ //Get the list of properties:
+ GParamSpec** ppParamSpec = 0;
+ guint iCount = 0;
+ if(g_type_is_a(gtype, GTK_TYPE_CONTAINER))
+ {
+ GObjectClass* pGClass = G_OBJECT_CLASS(g_type_class_ref(gtype));
+ ppParamSpec = gtk_container_class_list_child_properties (pGClass, &iCount);
+ g_type_class_unref(pGClass);
+
+ if(!ppParamSpec)
+ {
+ strResult += ";; Warning: gtk_container_class_list_child_properties() returned NULL for " +
std::string(g_type_name(gtype)) + "\n";
+ iCount = 0;
+ }
+ }
+
+ for(guint i = 0; i < iCount; i++)
+ {
+ GParamSpec* pParamSpec = ppParamSpec[i];
+
+ if(pParamSpec && pParamSpec->owner_type == gtype)
+ {
+ strResult += get_property_with_node_name(pParamSpec, strObjectName, "define-child-property");
+ }
+ }
+
+ g_free(ppParamSpec);
+
+ return strResult;
+}
diff --git a/tools/m4/child_property.m4 b/tools/m4/child_property.m4
new file mode 100644
index 0000000..6add346
--- /dev/null
+++ b/tools/m4/child_property.m4
@@ -0,0 +1,37 @@
+dnl
+dnl
+dnl Code generation sections for GtkContainer child properties
+dnl
+dnl
+
+dnl $1 $2 $3 $4 $5 $6
+dnl _CHILD_PROPERTY_PROXY(name, name_underscored, cpp_type, proxy_suffix, deprecated, docs)
+dnl proxy_suffix could be "", "_WriteOnly" or "_ReadOnly"
+dnl The method will be const if the propertyproxy is _ReadOnly.
+dnl
+define(`_CHILD_PROPERTY_PROXY',`dnl
+dnl
+dnl Put spaces around the template parameter if necessary.
+pushdef(`__PROXY_TYPE__',`dnl
+Gtk::ChildPropertyProxy$4< _QUOTE($3) >'dnl
+)dnl
+/** $6
+ *
+ * @return A ChildPropertyProxy$4 that allows you to dnl
+ifelse($4,_ReadOnly,get,`ifelse($4,_WriteOnly,set,get or set)') the value of the property,
+ * or receive notification when the value of the property changes.
+ */
+ __PROXY_TYPE__ child_property_$2`'(ifelse($4,_ReadOnly,const ,)Gtk::Widget& child) ifelse($4,_ReadOnly,
const,);
+_PUSH(SECTION_CC_PROPERTYPROXIES)
+ifelse(`$5',,,`_DEPRECATE_IFDEF_START
+')dnl
+__PROXY_TYPE__ __CPPNAME__::child_property_$2`'(ifelse($4,_ReadOnly,const ,)Gtk::Widget& child)
ifelse($4,_ReadOnly, const,)
+{
+ return __PROXY_TYPE__`'(this, child, "$1");
+}
+ifelse(`$5',,,`_DEPRECATE_IFDEF_END
+')dnl
+
+_POP()
+popdef(`__PROXY_TYPE__')dnl
+')dnl
diff --git a/tools/m4/convert_gtkmm.m4 b/tools/m4/convert_gtkmm.m4
index 9c5353c..1c9f4e1 100644
--- a/tools/m4/convert_gtkmm.m4
+++ b/tools/m4/convert_gtkmm.m4
@@ -17,6 +17,7 @@
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
include(class_gtkobject.m4)
+include(child_property.m4)
include(convert_base.m4)
include(convert_gtk.m4)
include(convert_gdk.m4)
diff --git a/tools/m4/filelist.am b/tools/m4/filelist.am
index 9e489f2..c6196a1 100644
--- a/tools/m4/filelist.am
+++ b/tools/m4/filelist.am
@@ -18,6 +18,7 @@
files_codegen_m4 = \
class_gtkobject.m4 \
+ child_property.m4 \
convert.m4 \
convert_gdk.m4 \
convert_gtk.m4 \
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]