diff options
author | Juan Pablo Ugarte <juanpablougarte@gmail.com> | 2012-12-10 14:53:53 -0300 |
---|---|---|
committer | Juan Pablo Ugarte <juanpablougarte@gmail.com> | 2012-12-10 14:53:53 -0300 |
commit | a3e4fa3809e9281f9dc7e10f37e89e86e0fd219a (patch) | |
tree | d8f9f04c4ecfc3878f4892b723b695c9783d8d92 /gtk | |
parent | d8fae21b1c989027b96f471665d7195b355d7cdf (diff) | |
download | gtk+-a3e4fa3809e9281f9dc7e10f37e89e86e0fd219a.tar.gz |
Added new function gtk_builder_expose_object() based on the original work by
Marco Diego Aurélio Mesquita on bug #447972
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/gtkbuilder.c | 88 | ||||
-rw-r--r-- | gtk/gtkbuilder.h | 3 | ||||
-rw-r--r-- | gtk/tests/builder.c | 51 |
3 files changed, 118 insertions, 24 deletions
diff --git a/gtk/gtkbuilder.c b/gtk/gtkbuilder.c index bf7592291b..9923bc257f 100644 --- a/gtk/gtkbuilder.c +++ b/gtk/gtkbuilder.c @@ -123,12 +123,14 @@ * (can be specified by their name, nick or integer value), flags (can be * specified by their name, nick, integer value, optionally combined with "|", * e.g. "GTK_VISIBLE|GTK_REALIZED") and colors (in a format understood by - * gdk_color_parse()). Objects can be referred to by their name. Pixbufs can be - * specified as a filename of an image file to load. In general, GtkBuilder - * allows forward references to objects — an object doesn't have to be - * constructed before it can be referred to. The exception to this rule is that - * an object has to be constructed before it can be used as the value of a - * construct-only property. + * gdk_color_parse()). Pixbufs can be specified as a filename of an image file to load. + * Objects can be referred to by their name and by default refer to objects declared + * in the local xml fragment and objects exposed via gtk_builder_expose_object(). + * + * In general, GtkBuilder allows forward references to objects &mdash declared + * in the local xml; an object doesn't have to be constructed before it can be referred to. + * The exception to this rule is that an object has to be constructed before + * it can be used as the value of a construct-only property. * * Signal handlers are set up with the <signal> element. The "name" * attribute specifies the name of the signal, and the "handler" attribute @@ -574,6 +576,24 @@ gtk_builder_get_internal_child (GtkBuilder *builder, return obj; } +static inline void +object_set_name (GObject *object, const gchar *name) +{ + if (GTK_IS_BUILDABLE (object)) + gtk_buildable_set_name (GTK_BUILDABLE (object), name); + else + g_object_set_data_full (object, "gtk-builder-name", g_strdup (name), g_free); +} + +void +_gtk_builder_add_object (GtkBuilder *builder, + const gchar *id, + GObject *object) +{ + object_set_name (object, id); + g_hash_table_insert (builder->priv->objects, g_strdup (id), g_object_ref (object)); +} + GObject * _gtk_builder_construct (GtkBuilder *builder, ObjectInfo *info, @@ -703,30 +723,17 @@ _gtk_builder_construct (GtkBuilder *builder, g_value_unset (¶m->value); } g_array_free (parameters, TRUE); - - if (GTK_IS_BUILDABLE (obj)) - gtk_buildable_set_name (buildable, info->id); - else - g_object_set_data_full (obj, - "gtk-builder-name", - g_strdup (info->id), - g_free); - /* we already own a reference to obj. put it in the hash table. */ - g_hash_table_insert (builder->priv->objects, g_strdup (info->id), obj); + /* put it in the hash table. */ + _gtk_builder_add_object (builder, info->id, obj); + + /* we already own a reference to obj. */ + g_object_unref (obj); return obj; } void -_gtk_builder_add_object (GtkBuilder *builder, - const gchar *id, - GObject *object) -{ - g_hash_table_insert (builder->priv->objects, g_strdup (id), g_object_ref (object)); -} - -void _gtk_builder_add (GtkBuilder *builder, ChildInfo *child_info) { @@ -1340,6 +1347,39 @@ gtk_builder_get_translation_domain (GtkBuilder *builder) return builder->priv->domain; } +/** + * gtk_builder_expose_object: + * @builder: a #GtkBuilder + * @name: the name of the object exposed to the builder + * @object: the object to expose + * + * Add @object to the @builder object pool so it can be referenced just like any + * other object built by builder. + * + * To make this function even more useful a new special entry point element + * <external-object> is defined. It is similar to <object> but has + * to reference an external object exposed with this function. + * This way you can change properties and even add children to an + * external object using builder, not just reference it. + * + * Since: 3.8 + **/ +void +gtk_builder_expose_object (GtkBuilder *builder, + const gchar *name, + GObject *object) +{ + g_return_if_fail (GTK_IS_BUILDER (builder)); + g_return_if_fail (name && name[0]); + g_return_if_fail (gtk_builder_get_object (builder, name) == NULL); + + object_set_name (object, name); + g_hash_table_insert (builder->priv->objects, + g_strdup (name), + g_object_ref (object)); +} + + typedef struct { GModule *module; gpointer data; diff --git a/gtk/gtkbuilder.h b/gtk/gtkbuilder.h index 60b358a28c..a10359b6e5 100644 --- a/gtk/gtkbuilder.h +++ b/gtk/gtkbuilder.h @@ -141,6 +141,9 @@ guint gtk_builder_add_objects_from_string (GtkBuilder *builder, GObject* gtk_builder_get_object (GtkBuilder *builder, const gchar *name); GSList* gtk_builder_get_objects (GtkBuilder *builder); +void gtk_builder_expose_object (GtkBuilder *builder, + const gchar *name, + GObject *object); void gtk_builder_connect_signals (GtkBuilder *builder, gpointer user_data); void gtk_builder_connect_signals_full (GtkBuilder *builder, diff --git a/gtk/tests/builder.c b/gtk/tests/builder.c index d5a3d1ffc2..5e086a577f 100644 --- a/gtk/tests/builder.c +++ b/gtk/tests/builder.c @@ -2715,6 +2715,56 @@ test_level_bar (void) g_object_unref (builder); } +static GObject *external_object = NULL, *external_object_swapped = NULL; + +void +on_button_clicked (GtkButton *button, GObject *data) +{ + external_object = data; +} + +void +on_button_clicked_swapped (GObject *data, GtkButton *button) +{ + external_object_swapped = data; +} + +static void +test_expose_object (void) +{ + GtkBuilder *builder; + GError *error = NULL; + GtkWidget *image; + GObject *obj; + const gchar buffer[] = + "<interface>" + " <object class=\"GtkButton\" id=\"button\">" + " <property name=\"image\">external_image</property>" + " <signal name=\"clicked\" handler=\"on_button_clicked\" object=\"builder\" swapped=\"no\"/>" + " <signal name=\"clicked\" handler=\"on_button_clicked_swapped\" object=\"builder\"/>" + " </object>" + "</interface>"; + + image = gtk_image_new (); + builder = gtk_builder_new (); + gtk_builder_expose_object (builder, "external_image", G_OBJECT (image)); + gtk_builder_expose_object (builder, "builder", G_OBJECT (builder)); + gtk_builder_add_from_string (builder, buffer, -1, &error); + g_assert (error == NULL); + + obj = gtk_builder_get_object (builder, "button"); + g_assert (GTK_IS_BUTTON (obj)); + + g_assert (gtk_button_get_image (GTK_BUTTON (obj)) == image); + + /* Connect signals and fake clicked event */ + gtk_builder_connect_signals (builder, NULL); + gtk_button_clicked (GTK_BUTTON (obj)); + + g_assert (external_object == G_OBJECT (builder)); + g_assert (external_object_swapped == G_OBJECT (builder)); +} + int main (int argc, char **argv) { @@ -2763,6 +2813,7 @@ main (int argc, char **argv) g_test_add_func ("/Builder/MessageDialog", test_message_dialog); g_test_add_func ("/Builder/GMenu", test_gmenu); g_test_add_func ("/Builder/LevelBar", test_level_bar); + g_test_add_func ("/Builder/Expose Object", test_expose_object); return g_test_run(); } |