diff options
author | Juan Pablo Ugarte <juanpablougarte@gmail.com> | 2014-04-11 16:24:04 -0300 |
---|---|---|
committer | Juan Pablo Ugarte <juanpablougarte@gmail.com> | 2014-04-18 18:59:14 -0300 |
commit | 887fc60ccee7b9719ebb47291682e48f00609b7b (patch) | |
tree | 2bd08e04e3314d27e6280e274a2eac6ab4ced56d /gtk/gtkbuilder.c | |
parent | be9d1e0b3ba969c71db6e1b00be505bea425908b (diff) | |
download | gtk+-887fc60ccee7b9719ebb47291682e48f00609b7b.tar.gz |
Added bindings support to GtkBuilder by introducing 3 new <property> attributes "bind-source" to specify the source object of the binding "bind-property" to specify the source property and "bind-flags" to specify the binding flags (optional)
Binding an object sensitive property with a check button active property will look like this:
<object class="GtkButton" id="button">
<property name="sensitive" bind-source="checkbutton" bind-property="active"/>
</object>
This is based on the original work done by Denis Washington for his GSoC project
This closes Bug 654417 "[GSoC] Add <binding> element to GtkBuilder syntax"
Diffstat (limited to 'gtk/gtkbuilder.c')
-rw-r--r-- | gtk/gtkbuilder.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/gtk/gtkbuilder.c b/gtk/gtkbuilder.c index fe15875d17..d6a435f16b 100644 --- a/gtk/gtkbuilder.c +++ b/gtk/gtkbuilder.c @@ -134,6 +134,14 @@ * object has to be constructed before it can be used as the value of * a construct-only property. * + * It is also possible to bind a property value to another object's + * property value using the attributes + * "bind-source" to specify the source object of the binding, + * "bind-property" to specify the source property and optionally + * "bind-flags" to specify the binding flags + * Internally builder implement this using GBinding objects. + * For more information see g_object_bind_property() + * * Signal handlers are set up with the <signal> element. The “name” * attribute specifies the name of the signal, and the “handler” attribute * specifies the function to connect to the signal. By default, GTK+ tries @@ -244,6 +252,7 @@ struct _GtkBuilderPrivate GHashTable *callbacks; GSList *delayed_properties; GSList *signals; + GSList *bindings; gchar *filename; gchar *resource_prefix; GType template_type; @@ -499,6 +508,13 @@ gtk_builder_get_parameters (GtkBuilder *builder, continue; } } + else if (prop->bound && (!prop->data || *prop->data == '\0')) + { + /* Ignore properties with a binding and no value since they are + * only there for to express the binding. + */ + continue; + } else if (!gtk_builder_value_from_string (builder, pspec, prop->data, ¶meter.value, &error)) { @@ -572,6 +588,15 @@ object_set_name (GObject *object, const gchar *name) g_object_set_data_full (object, "gtk-builder-name", g_strdup (name), g_free); } +static inline const gchar * +object_get_name (GObject *object) +{ + if (GTK_IS_BUILDABLE (object)) + return gtk_buildable_get_name (GTK_BUILDABLE (object)); + else + return g_object_get_data (object, "gtk-builder-name"); +} + void _gtk_builder_add_object (GtkBuilder *builder, const gchar *id, @@ -581,6 +606,22 @@ _gtk_builder_add_object (GtkBuilder *builder, g_hash_table_insert (builder->priv->objects, g_strdup (id), g_object_ref (object)); } +static inline void +gtk_builder_take_bindings (GtkBuilder *builder, + GObject *target, + GSList *bindings) +{ + GSList *l; + + for (l = bindings; l; l = g_slist_next (l)) + { + BindingInfo *info = l->data; + info->target = target; + } + + builder->priv->bindings = g_slist_concat (builder->priv->bindings, bindings); +} + GObject * _gtk_builder_construct (GtkBuilder *builder, ObjectInfo *info, @@ -741,6 +782,9 @@ _gtk_builder_construct (GtkBuilder *builder, } g_array_free (parameters, TRUE); + if (info->bindings) + gtk_builder_take_bindings (builder, obj, info->bindings); + /* put it in the hash table. */ _gtk_builder_add_object (builder, info->id, obj); @@ -909,10 +953,46 @@ gtk_builder_apply_delayed_properties (GtkBuilder *builder) g_slist_free (props); } +static inline void +free_binding_info (gpointer data, gpointer user) +{ + BindingInfo *info = data; + g_free (info->target_property); + g_free (info->source); + g_free (info->source_property); + g_slice_free (BindingInfo, data); +} + +static inline void +gtk_builder_create_bindings (GtkBuilder *builder) +{ + GSList *l; + + for (l = builder->priv->bindings; l; l = g_slist_next (l)) + { + BindingInfo *info = l->data; + GObject *source; + + if ((source = gtk_builder_get_object (builder, info->source))) + g_object_bind_property (source, info->source_property, + info->target, info->target_property, + info->flags); + else + g_warning ("Could not find source object '%s' to bind property '%s'", + info->source, info->source_property); + + free_binding_info (info, NULL); + } + + g_slist_free (builder->priv->bindings); + builder->priv->bindings = NULL; +} + void _gtk_builder_finish (GtkBuilder *builder) { gtk_builder_apply_delayed_properties (builder); + gtk_builder_create_bindings (builder); } /** |