[gtk+] Add some more child property API
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] Add some more child property API
- Date: Tue, 8 Sep 2015 12:08:06 +0000 (UTC)
commit 93f8f12e3933524c86fec4c495017ce13c80b8d1
Author: Matthias Clasen <mclasen redhat com>
Date: Mon Sep 7 18:10:56 2015 -0400
Add some more child property API
Add gtk_container_install_child_properties and
gtk_container_child_notify_by_pspec to mirror te corresponding
GObject APIs.
docs/reference/gtk/gtk3-sections.txt | 2 +
gtk/gtkcontainer.c | 199 +++++++++++++++++++++++++---------
gtk/gtkcontainer.h | 9 ++
3 files changed, 161 insertions(+), 49 deletions(-)
---
diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt
index 55e4d49..1894312 100644
--- a/docs/reference/gtk/gtk3-sections.txt
+++ b/docs/reference/gtk/gtk3-sections.txt
@@ -1020,6 +1020,7 @@ gtk_container_child_set_property
gtk_container_child_get_valist
gtk_container_child_set_valist
gtk_container_child_notify
+gtk_container_child_notify_by_pspec
gtk_container_forall
gtk_container_get_border_width
gtk_container_set_border_width
@@ -1029,6 +1030,7 @@ gtk_container_set_focus_chain
gtk_container_unset_focus_chain
gtk_container_class_find_child_property
gtk_container_class_install_child_property
+gtk_container_class_install_child_properties
gtk_container_class_list_child_properties
gtk_container_class_handle_border_width
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index c0e0473..20cb4ea 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -602,6 +602,42 @@ gtk_container_buildable_add_child (GtkBuildable *buildable,
g_type_name (G_OBJECT_TYPE (child)), g_type_name (G_OBJECT_TYPE (buildable)));
}
+static inline void
+container_set_child_property (GtkContainer *container,
+ GtkWidget *child,
+ GParamSpec *pspec,
+ const GValue *value,
+ GObjectNotifyQueue *nqueue)
+{
+ GValue tmp_value = G_VALUE_INIT;
+ GtkContainerClass *class = g_type_class_peek (pspec->owner_type);
+
+ /* provide a copy to work from, convert (if necessary) and validate */
+ g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ if (!g_value_transform (value, &tmp_value))
+ g_warning ("unable to set child property `%s' of type `%s' from value of type `%s'",
+ pspec->name,
+ g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
+ G_VALUE_TYPE_NAME (value));
+ else if (g_param_value_validate (pspec, &tmp_value) && !(pspec->flags & G_PARAM_LAX_VALIDATION))
+ {
+ gchar *contents = g_strdup_value_contents (value);
+
+ g_warning ("value \"%s\" of type `%s' is invalid for property `%s' of type `%s'",
+ contents,
+ G_VALUE_TYPE_NAME (value),
+ pspec->name,
+ g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
+ g_free (contents);
+ }
+ else
+ {
+ class->set_child_property (container, child, PARAM_SPEC_PARAM_ID (pspec), &tmp_value, pspec);
+ g_object_notify_queue_add (G_OBJECT (child), nqueue, pspec);
+ }
+ g_value_unset (&tmp_value);
+}
+
static void
gtk_container_buildable_set_child_property (GtkContainer *container,
GtkBuilder *builder,
@@ -612,6 +648,7 @@ gtk_container_buildable_set_child_property (GtkContainer *container,
GParamSpec *pspec;
GValue gvalue = G_VALUE_INIT;
GError *error = NULL;
+ GObjectNotifyQueue *nqueue;
if (_gtk_widget_get_parent (child) != (GtkWidget *)container &&
!GTK_IS_ASSISTANT (container) &&
@@ -628,8 +665,14 @@ gtk_container_buildable_set_child_property (GtkContainer *container,
pspec = gtk_container_class_find_child_property (G_OBJECT_GET_CLASS (container), name);
if (!pspec)
{
- g_warning ("%s does not have a property called %s",
- g_type_name (G_OBJECT_TYPE (container)), name);
+ g_warning ("%s does not have a child property called %s",
+ G_OBJECT_TYPE_NAME (container), name);
+ return;
+ }
+ else if (!(pspec->flags & G_PARAM_WRITABLE))
+ {
+ g_warning ("Child property `%s' of container class `%s' is not writable",
+ name, G_OBJECT_TYPE_NAME (container));
return;
}
@@ -645,7 +688,13 @@ gtk_container_buildable_set_child_property (GtkContainer *container,
return;
}
- gtk_container_child_set_property (container, child, name, &gvalue);
+ g_object_ref (container);
+ g_object_ref (child);
+ nqueue = g_object_notify_queue_freeze (G_OBJECT (child), _gtk_widget_child_property_notify_context);
+ container_set_child_property (container, child, pspec, &gvalue, nqueue);
+ g_object_notify_queue_thaw (G_OBJECT (child), nqueue);
+ g_object_unref (container);
+ g_object_unref (child);
g_value_unset (&gvalue);
}
@@ -992,7 +1041,7 @@ gtk_container_child_type (GtkContainer *container)
*
* Emits a #GtkWidget::child-notify signal for the
* [child property][child-properties]
- * @child_property on widget.
+ * @child_property on the child.
*
* This is an analogue of g_object_notify() for child properties.
*
@@ -1044,6 +1093,46 @@ gtk_container_child_notify (GtkContainer *container,
g_object_unref (obj);
}
+/**
+ * gtk_container_child_notify_by_pspec:
+ * @container: the #GtkContainer
+ * @child: the child widget
+ * @pspec: the #GParamSpec of a child property instealled on
+ * the class of @container
+ *
+ * Emits a #GtkWidget::child-notify signal for the
+ * [child property][child-properties] specified by
+ * @pspec on the child.
+ *
+ * This is an analogue of g_object_notify_by_pspec() for child properties.
+ *
+ * Since: 3.18
+ */
+void
+gtk_container_child_notify_by_pspec (GtkContainer *container,
+ GtkWidget *child,
+ GParamSpec *pspec)
+{
+ GObject *obj = G_OBJECT (child);
+ GObjectNotifyQueue *nqueue;
+
+ g_return_if_fail (GTK_IS_CONTAINER (container));
+ g_return_if_fail (GTK_IS_WIDGET (child));
+ g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+
+ if (obj->ref_count == 0)
+ return;
+
+ g_object_ref (obj);
+
+ nqueue = g_object_notify_queue_freeze (obj, _gtk_widget_child_property_notify_context);
+
+ g_object_notify_queue_add (obj, nqueue, pspec);
+ g_object_notify_queue_thaw (obj, nqueue);
+
+ g_object_unref (obj);
+}
+
static inline void
container_get_child_property (GtkContainer *container,
GtkWidget *child,
@@ -1055,42 +1144,6 @@ container_get_child_property (GtkContainer *container,
class->get_child_property (container, child, PARAM_SPEC_PARAM_ID (pspec), value, pspec);
}
-static inline void
-container_set_child_property (GtkContainer *container,
- GtkWidget *child,
- GParamSpec *pspec,
- const GValue *value,
- GObjectNotifyQueue *nqueue)
-{
- GValue tmp_value = G_VALUE_INIT;
- GtkContainerClass *class = g_type_class_peek (pspec->owner_type);
-
- /* provide a copy to work from, convert (if necessary) and validate */
- g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
- if (!g_value_transform (value, &tmp_value))
- g_warning ("unable to set child property `%s' of type `%s' from value of type `%s'",
- pspec->name,
- g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
- G_VALUE_TYPE_NAME (value));
- else if (g_param_value_validate (pspec, &tmp_value) && !(pspec->flags & G_PARAM_LAX_VALIDATION))
- {
- gchar *contents = g_strdup_value_contents (value);
-
- g_warning ("value \"%s\" of type `%s' is invalid for property `%s' of type `%s'",
- contents,
- G_VALUE_TYPE_NAME (value),
- pspec->name,
- g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
- g_free (contents);
- }
- else
- {
- class->set_child_property (container, child, PARAM_SPEC_PARAM_ID (pspec), &tmp_value, pspec);
- g_object_notify_queue_add (G_OBJECT (child), nqueue, pspec);
- }
- g_value_unset (&tmp_value);
-}
-
/**
* gtk_container_child_get_valist:
* @container: a #GtkContainer
@@ -1441,6 +1494,24 @@ gtk_container_child_get (GtkContainer *container,
va_end (var_args);
}
+static inline void
+install_child_property_internal (GType g_type,
+ guint property_id,
+ GParamSpec *pspec)
+{
+ if (g_param_spec_pool_lookup (_gtk_widget_child_property_pool, pspec->name, g_type, FALSE))
+ {
+ g_warning ("Class '%s' already contains a child property named '%s'",
+ g_type_name (g_type),
+ pspec->name);
+ return;
+ }
+ g_param_spec_ref (pspec);
+ g_param_spec_sink (pspec);
+ PARAM_SPEC_SET_PARAM_ID (pspec, property_id);
+ g_param_spec_pool_insert (_gtk_widget_child_property_pool, pspec, g_type);
+}
+
/**
* gtk_container_class_install_child_property:
* @cclass: a #GtkContainerClass
@@ -1465,17 +1536,47 @@ gtk_container_class_install_child_property (GtkContainerClass *cclass,
if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
g_return_if_fail ((pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY)) == 0);
- if (g_param_spec_pool_lookup (_gtk_widget_child_property_pool, pspec->name, G_OBJECT_CLASS_TYPE (cclass),
FALSE))
+ install_child_property_internal (G_OBJECT_CLASS_TYPE (cclass), property_id, pspec);
+}
+
+/**
+ * gtk_container_class_install_child_properties:
+ * @cclass: a #GtkContainerClass
+ * @n_pspecs: the length of the #GParamSpec array
+ * @pspec: (array length=n_pspecs): the #GParamSpec array defining the new
+ * child properties
+ *
+ * Installs child properties on a container class.
+ *
+ * Since: 3.18
+ */
+void
+gtk_container_class_install_child_properties (GtkContainerClass *cclass,
+ guint n_pspecs,
+ GParamSpec **pspecs)
+{
+ gint i;
+
+ g_return_if_fail (GTK_IS_CONTAINER_CLASS (cclass));
+ g_return_if_fail (n_pspecs > 1);
+ g_return_if_fail (pspecs[0] == NULL);
+
+ /* we skip the first element of the array as it would have a 0 prop_id */
+ for (i = 1; i < n_pspecs; i++)
{
- g_warning (G_STRLOC ": class `%s' already contains a child property named `%s'",
- G_OBJECT_CLASS_NAME (cclass),
- pspec->name);
- return;
+ GParamSpec *pspec = pspecs[i];
+
+ g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+ if (pspec->flags & G_PARAM_WRITABLE)
+ g_return_if_fail (cclass->set_child_property != NULL);
+ if (pspec->flags & G_PARAM_READABLE)
+ g_return_if_fail (cclass->get_child_property != NULL);
+ g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0); /* paranoid */
+ if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
+ g_return_if_fail ((pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY)) == 0);
+
+ install_child_property_internal (G_OBJECT_CLASS_TYPE (cclass), i, pspec);
}
- g_param_spec_ref (pspec);
- g_param_spec_sink (pspec);
- PARAM_SPEC_SET_PARAM_ID (pspec, property_id);
- g_param_spec_pool_insert (_gtk_widget_child_property_pool, pspec, G_OBJECT_CLASS_TYPE (cclass));
}
/**
diff --git a/gtk/gtkcontainer.h b/gtk/gtkcontainer.h
index a3e9b66..d6cc8ed 100644
--- a/gtk/gtkcontainer.h
+++ b/gtk/gtkcontainer.h
@@ -218,6 +218,10 @@ GDK_AVAILABLE_IN_ALL
void gtk_container_class_install_child_property (GtkContainerClass *cclass,
guint property_id,
GParamSpec *pspec);
+GDK_AVAILABLE_IN_3_18
+void gtk_container_class_install_child_properties (GtkContainerClass *cclass,
+ guint n_pspecs,
+ GParamSpec **pspecs);
GDK_AVAILABLE_IN_ALL
GParamSpec* gtk_container_class_find_child_property (GObjectClass *cclass,
const gchar *property_name);
@@ -265,6 +269,11 @@ void gtk_container_child_notify (GtkContainer *container,
GtkWidget *child,
const gchar *child_property);
+GDK_AVAILABLE_IN_3_18
+void gtk_container_child_notify_by_pspec (GtkContainer *container,
+ GtkWidget *child,
+ GParamSpec *pspec);
+
/**
* GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID:
* @object: the #GObject on which set_child_property() or get_child_property()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]