* (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
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,
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)
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;
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)
{
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();
}