? gtk+
? gtk+.diff
? tests/testbuildable
? tests/testbuilder
? tests/testgrouping
? tests/testnouiprint
? tests/testprint
Index: gtk/Makefile.am
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/Makefile.am,v
retrieving revision 1.306
diff -u -d -p -r1.306 Makefile.am
--- gtk/Makefile.am	5 May 2006 16:07:49 -0000	1.306
+++ gtk/Makefile.am	11 May 2006 00:00:45 -0000
@@ -135,6 +135,8 @@ gtk_public_h_sources =          \
 	gtkbin.h		\
 	gtkbindings.h		\
 	gtkbox.h		\
+	gtkbuilder.h		\
+	gtkbuildable.h		\
 	gtkbutton.h		\
 	gtkcalendar.h		\
 	gtkcelleditable.h	\
@@ -323,6 +325,7 @@ gtk_semi_private_h_sources =    \
 
 # GTK+ header files that don't get installed
 gtk_private_h_sources =		\
+	gtkbuilderprivate.h	\
 	gtkdndcursors.h		\
 	gtkentryprivate.h	\
 	gtkfilechooserdefault.h	\
@@ -377,6 +380,9 @@ gtk_c_sources =                 \
 	gtkbin.c		\
 	gtkbindings.c		\
 	gtkbox.c		\
+	gtkbuildable.c		\
+	gtkbuilder.c		\
+	gtkbuilderparser.c	\
 	gtkbutton.c		\
 	gtkcalendar.c		\
 	gtkcelleditable.c	\
Index: gtk/gtk.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtk.h,v
retrieving revision 1.84
diff -u -d -p -r1.84 gtk.h
--- gtk/gtk.h	21 Apr 2006 15:09:28 -0000	1.84
+++ gtk/gtk.h	11 May 2006 00:00:45 -0000
@@ -45,6 +45,7 @@
 #include <gtk/gtkbin.h>
 #include <gtk/gtkbindings.h>
 #include <gtk/gtkbox.h>
+#include <gtk/gtkbuildable.h>
 #include <gtk/gtkbutton.h>
 #include <gtk/gtkcalendar.h>
 #include <gtk/gtkcelllayout.h>
Index: gtk/gtk.symbols
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtk.symbols,v
retrieving revision 1.104
diff -u -d -p -r1.104 gtk.symbols
--- gtk/gtk.symbols	9 May 2006 04:36:42 -0000	1.104
+++ gtk/gtk.symbols	11 May 2006 00:00:50 -0000
@@ -454,6 +454,32 @@ gtk_button_set_use_underline
 #endif
 #endif
 
+#if IN_HEADER(__GTK_BUILDABLE_H__)
+#if IN_FILE(__GTK_BUILDABLE_C__)
+gtk_buildable_get_type G_GNUC_CONST
+gtk_buildable_add
+gtk_buildable_get_name
+gtk_buildable_set_name
+gtk_buildable_set_property
+gtk_buildable_set_child_property
+gtk_buildable_construct_child
+gtk_buildable_custom_tag_end
+gtk_buildable_custom_tag_start
+#endif
+#endif
+
+#if IN_HEADER(__GTK_BUILDER_H__)
+#if IN_FILE(__GTK_BUILDER_C__)
+gtk_builder_get_type G_GNUC_CONST
+gtk_builder_new
+gtk_builder_new_from_buffer
+gtk_builder_get_name
+gtk_builder_get_object
+gtk_builder_get_objects
+gtk_builder_signal_autoconnect
+#endif
+#endif
+
 #if IN_HEADER(__GTK_CALENDAR_H__)
 #if IN_FILE(__GTK_CALENDAR_C__)
 #ifndef GTK_DISABLE_DEPRECATED
@@ -4284,6 +4310,8 @@ gtk_tree_view_columns_autosize
 #if IN_FILE(__GTK_TYPE_UTILS_C__)
 gtk_type_class
 gtk_identifier_get_type G_GNUC_CONST
+gtk_set_value_from_string
+gtk_lazy_type_from_name
 #ifndef GTK_DISABLE_DEPRECATED
 gtk_type_enum_find_value
 gtk_type_enum_get_values
Index: gtk/gtkaction.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkaction.c,v
retrieving revision 1.65
diff -u -d -p -r1.65 gtkaction.c
--- gtk/gtkaction.c	2 May 2006 23:56:40 -0000	1.65
+++ gtk/gtkaction.c	11 May 2006 00:00:50 -0000
@@ -34,6 +34,7 @@
 #include "gtkactiongroup.h"
 #include "gtkaccellabel.h"
 #include "gtkbutton.h"
+#include "gtkbuildable.h"
 #include "gtkimage.h"
 #include "gtkimagemenuitem.h"
 #include "gtkintl.h"
@@ -107,12 +108,20 @@ enum 
 };
 
 
+/* GtkBuildable */
+static void gtk_action_buildable_init           (GtkBuildableIface *iface);
+static void gtk_action_buildable_set_name       (GtkBuildable *buildable,
+						 const gchar  *name);
+
 static GQuark      accel_path_id  = 0;
 static GQuark      quark_gtk_action_proxy  = 0;
 static const gchar accel_path_key[] = "GtkAction::accel_path";
 static const gchar gtk_action_proxy_key[] = "gtk-action";
+static GtkBuildableIface *parent_buildable_iface;
 
-G_DEFINE_TYPE (GtkAction, gtk_action, G_TYPE_OBJECT);
+G_DEFINE_TYPE_WITH_CODE (GtkAction, gtk_action, GTK_TYPE_OBJECT,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_action_buildable_init));
 
 static void gtk_action_finalize     (GObject *object);
 static void gtk_action_set_property (GObject         *object,
@@ -365,6 +374,25 @@ gtk_action_init (GtkAction *action)
   action->private_data->action_group = NULL;
 
   action->private_data->proxies = NULL;
+}
+
+static void
+gtk_action_buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->set_name = gtk_action_buildable_set_name;
+}
+
+static void
+gtk_action_buildable_set_name (GtkBuildable *buildable,
+			       const gchar  *name)
+{
+  gchar *tmp;
+  GtkAction *action = GTK_ACTION (buildable);
+  
+  tmp = action->private_data->name;
+  action->private_data->name = g_strdup (name);
+  g_free (tmp);
 }
 
 /**
Index: gtk/gtkactiongroup.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkactiongroup.c,v
retrieving revision 1.57
diff -u -d -p -r1.57 gtkactiongroup.c
--- gtk/gtkactiongroup.c	16 Mar 2006 15:53:36 -0000	1.57
+++ gtk/gtkactiongroup.c	11 May 2006 00:00:57 -0000
@@ -31,6 +31,7 @@
 #include <config.h>
 
 #include "gtkactiongroup.h"
+#include "gtkbuildable.h"
 #include "gtkiconfactory.h"
 #include "gtkstock.h"
 #include "gtktoggleaction.h"
@@ -86,6 +87,13 @@ static void       gtk_action_group_get_p
 static GtkAction *gtk_action_group_real_get_action (GtkActionGroup      *self,
 						    const gchar         *name);
 
+/* GtkBuildable */
+static void gtk_action_group_buildable_init (GtkBuildableIface *iface);
+static void gtk_action_group_buildable_add (GtkBuildable  *buildable,
+					    GObject       *child,
+					    const gchar   *type);
+static void gtk_action_group_buildable_set_name (GtkBuildable *buildable,
+						 const gchar  *name);
 
 GType
 gtk_action_group_get_type (void)
@@ -107,15 +115,26 @@ gtk_action_group_get_type (void)
         (GInstanceInitFunc) gtk_action_group_init,
       };
 
+      static const GInterfaceInfo buildable_info =
+      {
+	(GInterfaceInitFunc) gtk_action_group_buildable_init,
+	NULL,
+	NULL
+      };
+
       type = g_type_register_static (G_TYPE_OBJECT, I_("GtkActionGroup"),
 				     &type_info, 0);
-    }
 
+      g_type_add_interface_static (type,
+				   GTK_TYPE_BUILDABLE,
+				   &buildable_info);
+    }
   return type;
 }
 
 static GObjectClass *parent_class = NULL;
 static guint         action_group_signals[LAST_SIGNAL] = { 0 };
+static GtkBuildableIface *parent_buildable_iface;
 
 static void
 gtk_action_group_class_init (GtkActionGroupClass *klass)
@@ -269,6 +288,31 @@ gtk_action_group_init (GtkActionGroup *s
   self->private_data->translate_func = NULL;
   self->private_data->translate_data = NULL;
   self->private_data->translate_notify = NULL;
+}
+
+static void
+gtk_action_group_buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->add = gtk_action_group_buildable_add;
+  iface->set_name = gtk_action_group_buildable_set_name;
+}
+
+static void
+gtk_action_group_buildable_add (GtkBuildable  *buildable,
+				GObject       *child,
+				const gchar   *type)
+{
+  gtk_action_group_add_action (GTK_ACTION_GROUP (buildable),
+			       GTK_ACTION (child));
+}
+
+static void
+gtk_action_group_buildable_set_name (GtkBuildable *buildable,
+				     const gchar  *name)
+{
+  GtkActionGroup *self = GTK_ACTION_GROUP (buildable);
+  self->private_data->name = g_strdup (name);
 }
 
 /**
Index: gtk/gtkbuildable.c
===================================================================
RCS file: gtk/gtkbuildable.c
diff -N gtk/gtkbuildable.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gtk/gtkbuildable.c	11 May 2006 00:00:57 -0000
@@ -0,0 +1,237 @@
+/* gtkbuildable.c
+ * Copyright (C) 2006 Async Open Source
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include <config.h>
+#include "gtkbuildable.h"
+#include "gtktypeutils.h"
+#include "gtkintl.h"
+#include "gtkalias.h"
+
+GType
+gtk_buildable_get_type (void)
+{
+  static GType buildable_type = 0;
+
+  if (! buildable_type)
+    {
+      static const GTypeInfo buildable_info =
+      {
+	sizeof (GtkBuildableIface), /* class_size */
+	NULL,           /* base_init */
+	NULL,		/* base_finalize */
+	NULL,
+	NULL		/* class_finalize */
+      };
+
+      buildable_type =
+	g_type_register_static (G_TYPE_INTERFACE, I_("GtkBuildable"),
+				&buildable_info, 0);
+
+    }
+
+  return buildable_type;
+}
+
+/**
+ * gtk_buildable_set_name:
+ * @buildable: A #GtkBuildable
+ * 
+ **/
+void
+gtk_buildable_set_name (GtkBuildable *buildable,
+			const gchar *name)
+{
+  GtkBuildableIface *iface;
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+
+  if (iface->set_name)
+    (* iface->set_name) (buildable, name);
+  
+  g_object_set_data_full (G_OBJECT (buildable),
+			  "gtk-buildable-name",
+			  g_strdup (name),
+			  g_free);
+}
+
+/**
+ * gtk_buildable_get_name:
+ * @buildable: A #GtkBuildable
+ * 
+ **/
+const gchar *
+gtk_buildable_get_name (GtkBuildable *buildable)
+{
+  return (const gchar*)g_object_get_data (G_OBJECT (buildable),
+					  "gtk-buildable-name");
+}
+
+/**
+ * gtk_buildable_add:
+ * @buildable: A #GtkBuildable
+ * 
+ **/
+void
+gtk_buildable_add (GtkBuildable *buildable,
+		   GObject      *child,
+		   const gchar  *type)
+{
+  GtkBuildableIface *iface;
+
+  g_return_if_fail (GTK_IS_BUILDABLE (buildable));
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+
+  g_return_if_fail (iface != NULL);
+  g_return_if_fail (iface->add != NULL);
+  
+  (* iface->add) (buildable, child, type);
+}
+
+/**
+ * gtk_buildable_set_child_property:
+ * @buildable: A #GtkBuildable
+ * 
+ **/
+void
+gtk_buildable_set_child_property (GtkBuildable *buildable,
+				  GObject      *child,
+				  const gchar  *name,
+				  const gchar  *value)
+{
+  GtkBuildableIface *iface;
+
+  g_return_if_fail (GTK_IS_BUILDABLE (buildable));
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+
+  g_return_if_fail (iface != NULL);
+  g_return_if_fail (iface->set_child_property != NULL);
+
+  (* iface->set_child_property) (buildable, child, name, value);
+}
+
+/**
+ * gtk_buildable_set_child_property:
+ * @buildable: A #GtkBuildable
+ * 
+ **/
+gboolean
+gtk_buildable_set_property (GtkBuildable *buildable,
+			    const gchar  *name,
+			    const gchar  *value)
+{
+  GtkBuildableIface *iface;
+  GParamSpec *pspec;
+  GValue gvalue = { 0, };
+
+  g_return_val_if_fail (GTK_IS_BUILDABLE (buildable), FALSE);
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+
+  g_return_val_if_fail (iface != NULL, FALSE);
+
+  if (iface->set_property)
+    {
+      if (!((* iface->set_property) (buildable, name, value)))
+	return TRUE;
+    }
+     
+  pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (buildable), name);
+  if (!pspec)
+    {
+      g_warning ("%s does not have a property called %s",
+		 g_type_name (G_OBJECT_TYPE (buildable)), name);
+      return FALSE;
+    }
+
+  if (!gtk_set_value_from_string (G_PARAM_SPEC_VALUE_TYPE (pspec), value, &gvalue))
+    {
+      g_warning ("Could not set property %s of %s to %s",
+		 name, g_type_name (G_OBJECT_TYPE (buildable)), value);
+      return FALSE;
+    }
+  
+  g_object_set_property (G_OBJECT (buildable), name, &gvalue);
+  g_value_unset (&gvalue);
+  
+  return TRUE;
+}
+
+/**
+ * gtk_buildable_construct_child
+ * @buildable: A #GtkBuildable
+ * @name: 
+ * 
+ **/
+GObject *
+gtk_buildable_construct_child (GtkBuildable *buildable,
+			       const gchar  *name)
+{
+  GtkBuildableIface *iface;
+
+  g_return_val_if_fail (GTK_IS_BUILDABLE (buildable), NULL);
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+
+  g_return_val_if_fail (iface != NULL, NULL);
+  g_return_val_if_fail (iface->construct_child != NULL, NULL);
+
+  return (* iface->construct_child) (buildable, name);
+}
+
+gboolean
+gtk_buildable_custom_tag_start (GtkBuildable  *buildable,
+				const gchar   *tagname,
+				GMarkupParser *parser,
+				gpointer      *data)
+{
+  GtkBuildableIface *iface;
+
+  g_return_val_if_fail (GTK_IS_BUILDABLE (buildable), FALSE);
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+
+  g_return_val_if_fail (iface != NULL, FALSE);
+  g_return_val_if_fail (iface->custom_tag_start != NULL, FALSE);
+
+  return (* iface->custom_tag_start) (buildable, tagname, parser, data);
+}
+
+void
+gtk_buildable_custom_tag_end (GtkBuildable        *buildable,
+			      GtkBuilder          *builder,
+			      const gchar         *tagname,
+			      gpointer             data)
+{
+  GtkBuildableIface *iface;
+
+  g_return_if_fail (GTK_IS_BUILDABLE (buildable));
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+
+  g_return_if_fail (iface != NULL);
+  g_return_if_fail (iface->custom_tag_end != NULL);
+
+  (* iface->custom_tag_end) (buildable, builder, tagname, data);
+}
+
+#define __GTK_BUILDABLE_C__
+#include "gtkaliasdef.c"
Index: gtk/gtkbuildable.h
===================================================================
RCS file: gtk/gtkbuildable.h
diff -N gtk/gtkbuildable.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gtk/gtkbuildable.h	11 May 2006 00:00:57 -0000
@@ -0,0 +1,96 @@
+/* gtkbuildable.h
+ * Copyright (C) 2006 Async Open Source
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_BUILDABLE_H__
+#define __GTK_BUILDABLE_H__
+
+#include <glib/gmarkup.h>
+#include <gtk/gtkbuilder.h>
+#include <gtk/gtktypeutils.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_BUILDABLE            (gtk_buildable_get_type ())
+#define GTK_BUILDABLE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_BUILDABLE, GtkBuildable))
+#define GTK_BUILDABLE_CLASS(obj)      (G_TYPE_CHECK_CLASS_CAST ((obj), GTK_TYPE_BUILDABLE, GtkBuildableIface))
+#define GTK_IS_BUILDABLE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_BUILDABLE))
+#define GTK_BUILDABLE_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GTK_TYPE_BUILDABLE, GtkBuildableIface))
+
+typedef struct _GtkBuildable      GtkBuildable; /* Dummy typedef */
+typedef struct _GtkBuildableIface GtkBuildableIface;
+
+struct _GtkBuildableIface
+{
+  GTypeInterface g_iface;
+
+  /* virtual table */
+  void     (* set_name)           (GtkBuildable *buildable,
+				   const gchar  *name);
+  void     (* add)                (GtkBuildable *buildable,
+				   GObject      *child,
+				   const gchar  *type);
+  gboolean (* set_property)       (GtkBuildable *buildable,
+				   const gchar  *name,
+				   const gchar  *value);
+  void     (* set_child_property) (GtkBuildable *buildable,
+				   GObject      *child,
+				   const gchar  *name,
+				   const gchar  *value);
+  GObject *(* construct_child)    (GtkBuildable *buildable,
+				   const gchar  *name);
+  gboolean (* custom_tag_start)   (GtkBuildable *buildable,
+				   const gchar  *tagname,
+				   GMarkupParser *parser,
+				   gpointer     *data);
+  void     (* custom_tag_end)     (GtkBuildable *buildable,
+				   GtkBuilder   *builder,
+				   const gchar  *tagname,
+				   gpointer      data);
+};
+
+
+GType     gtk_buildable_get_type              (void) G_GNUC_CONST;
+
+void      gtk_buildable_set_name              (GtkBuildable        *buildable,
+					       const gchar         *name);
+const gchar * gtk_buildable_get_name          (GtkBuildable        *buildable);
+void      gtk_buildable_add                   (GtkBuildable        *buildable,
+					       GObject             *child,
+					       const gchar         *type);
+gboolean  gtk_buildable_set_property          (GtkBuildable        *buildable,
+					       const gchar         *name,
+					       const gchar         *value);
+void      gtk_buildable_set_child_property    (GtkBuildable        *buildable,
+					       GObject             *child,
+					       const gchar         *name,
+					       const gchar         *value);
+GObject * gtk_buildable_construct_child       (GtkBuildable        *buildable,
+					       const gchar         *name);
+gboolean  gtk_buildable_custom_tag_start      (GtkBuildable        *buildable,
+					       const gchar         *tagname,
+					       GMarkupParser       *parser,
+					       gpointer            *data);
+void      gtk_buildable_custom_tag_end        (GtkBuildable        *buildable,
+					       GtkBuilder          *builder,
+					       const gchar         *tagname,
+					       gpointer             data);
+						  
+G_END_DECLS
+
+#endif /* __GTK_BUILDABLE_H__ */
Index: gtk/gtkbuilder.c
===================================================================
RCS file: gtk/gtkbuilder.c
diff -N gtk/gtkbuilder.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gtk/gtkbuilder.c	11 May 2006 00:00:57 -0000
@@ -0,0 +1,697 @@
+/* gtkbuilder.c
+ * Copyright (C) 2006 Async Open Source
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <config.h>
+#include "gtk.h"
+#include "gtkbuilder.h"
+#include "gtkbuilderprivate.h"
+#include "gtkintl.h"
+#include "gtkalias.h"
+
+static void gtk_builder_class_init     (GtkBuilderClass     *klass);
+static void gtk_builder_init           (GtkBuilder          *builder);
+static void gtk_builder_finalize       (GObject         *object);
+static void gtk_builder_set_property   (GObject         *object,
+					guint            prop_id,
+					const GValue    *value,
+					GParamSpec      *pspec);
+static void gtk_builder_get_property   (GObject         *object,
+					guint            prop_id,
+					GValue          *value,
+					GParamSpec      *pspec);
+
+enum {
+  PROP_0,
+  PROP_FILENAME,
+  PROP_DOMAIN,
+};
+
+enum {
+  FINISH,
+  SIGNALS_NUM,
+};
+
+static guint gtk_builder_signals[SIGNALS_NUM] = { 0 };
+
+#define GTK_BUILDER_GET_PRIVATE(o)       (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_BUILDER, GtkBuilderPrivate))
+typedef struct _GtkBuilderPrivate GtkBuilderPrivate;
+
+struct _GtkBuilderPrivate
+{
+  gchar *filename;
+  gchar *domain;
+  GHashTable *objects;
+  GHashTable *delayed_properties;
+  GSList *signals;
+  GSList *visible_properties;
+  gchar *current_toplevel;
+};
+
+G_DEFINE_TYPE (GtkBuilder, gtk_builder, G_TYPE_OBJECT);
+
+static void
+gtk_builder_class_init (GtkBuilderClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->finalize = gtk_builder_finalize;
+  gobject_class->set_property = gtk_builder_set_property;
+  gobject_class->get_property = gtk_builder_get_property;
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_FILENAME,
+                                   g_param_spec_string ("filename",
+                                                        P_("Filename"),
+                                                        P_("Filename to load"),
+                                                        NULL,
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_DOMAIN,
+                                   g_param_spec_string ("domain",
+                                                        P_("Domain"),
+                                                        P_("Translation domain"),
+                                                        NULL,
+                                                        G_PARAM_READWRITE |  G_PARAM_CONSTRUCT_ONLY));
+
+  g_type_class_add_private (gobject_class, sizeof (GtkBuilderPrivate));
+
+  gtk_builder_signals[FINISH] = g_signal_new ("finish",
+					      G_TYPE_FROM_CLASS (klass),
+					      G_SIGNAL_RUN_LAST,
+					      G_STRUCT_OFFSET (GtkBuilderClass,
+							       finish),
+					      NULL, NULL,
+					      g_cclosure_marshal_VOID__VOID,
+					      G_TYPE_NONE, 0);
+}
+
+static void
+gtk_builder_init (GtkBuilder *builder)
+{
+  GtkBuilderPrivate *priv = GTK_BUILDER_GET_PRIVATE (builder);
+  priv->filename = NULL;
+  priv->domain = NULL;
+  priv->objects = g_hash_table_new (g_str_hash, g_str_equal);
+  priv->visible_properties = NULL;
+  priv->delayed_properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+						    NULL);
+}
+
+static void
+gtk_builder_finalize (GObject *object)
+{
+  GtkBuilderPrivate *priv = GTK_BUILDER_GET_PRIVATE (object);
+
+  if (priv->filename)
+    g_free (priv->filename);
+  if (priv->domain)
+    g_free (priv->domain);
+  
+  g_slist_foreach (priv->signals, (GFunc)_free_signal_info, NULL);
+  g_slist_free (priv->signals);
+  g_hash_table_foreach (priv->objects, (GHFunc)g_free, NULL);
+  g_hash_table_destroy (priv->objects);
+}
+
+static void
+gtk_builder_set_property (GObject         *object,
+			  guint            prop_id,
+			  const GValue    *value,
+			  GParamSpec      *pspec)
+{
+  GtkBuilder *builder = GTK_BUILDER (object);
+  GtkBuilderPrivate *priv = GTK_BUILDER_GET_PRIVATE (builder);
+
+  switch (prop_id)
+    {
+    case PROP_FILENAME:
+      priv->filename = g_value_dup_string (value);
+      break;
+    case PROP_DOMAIN:
+      priv->domain = g_value_dup_string (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_builder_get_property (GObject         *object,
+			  guint            prop_id,
+			  GValue          *value,
+			  GParamSpec      *pspec)
+{
+  GtkBuilder *builder = GTK_BUILDER (object);
+  GtkBuilderPrivate *priv = GTK_BUILDER_GET_PRIVATE (builder);
+
+  switch (prop_id)
+    {
+    case PROP_FILENAME:
+      g_value_set_string (value, priv->filename);
+      break;
+    case PROP_DOMAIN:
+      g_value_set_string (value, priv->domain);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+/**
+ * gtk_builder_new:
+ * @filename: 
+ * @domain: 
+ *
+ * Return value: 
+ *
+ **/
+GtkBuilder *
+gtk_builder_new (const gchar *filename,
+		 const gchar *domain)
+{
+  GtkBuilder *builder;
+
+  builder = g_object_new (GTK_TYPE_BUILDER,
+			  "filename", filename,
+			  "domain", domain,
+			  NULL);
+
+  _gtk_builder_parser_parse_filename (builder, filename, domain);
+
+  return builder;
+}
+
+/**
+ * gtk_builder_new_from_buffer:
+ * @buffer:
+ * @length: 
+ * @domain: 
+ *
+ * Return value: 
+ *
+ **/
+GtkBuilder *
+gtk_builder_new_from_buffer (const gchar *buffer,
+			     gsize length,
+			     const gchar *domain)
+{
+  GtkBuilder *builder;
+
+  builder = g_object_new (GTK_TYPE_BUILDER,
+			  "domain", domain,
+			  NULL);
+  _gtk_builder_parser_parse_buffer (builder, buffer, length, domain);
+  
+  return builder;
+}
+
+/**
+ * gtk_builder_signal_autoconnect:
+ * @buildable: a #GtkBuilder
+ *
+ * Return value: 
+ *
+ **/
+void
+gtk_builder_signal_autoconnect (GtkBuilder *builder)
+{
+  GtkBuilderPrivate *priv = GTK_BUILDER_GET_PRIVATE (builder);
+  GSList *l;
+  GObject *object;
+  GObject *other;
+  GModule *module;
+  GCallback func;
+
+  if (!priv->signals)
+    return;
+
+  module = g_module_open (NULL, 0);
+
+  for (l = priv->signals; l; l = l->next)
+    {
+      SignalInfo *signal = (SignalInfo*)l->data;
+      GConnectFlags flags = 0;
+
+      g_assert (signal != NULL);
+      g_assert (signal->name != NULL);
+
+      object = g_hash_table_lookup (priv->objects, signal->object_name);
+      g_assert (object != NULL);
+      
+      if (signal->object)
+	other = g_hash_table_lookup (priv->objects, signal->object);
+      else
+	other = NULL;
+
+      if (!g_module_symbol (module,
+			    signal->handler,
+			    (gpointer)&func))
+	{
+	  g_warning ("could not find signal handler '%s'",
+		     signal->handler);
+	  continue;
+	}
+
+      if (signal->after)
+	flags |= G_CONNECT_AFTER;
+
+      if (signal->object)
+	flags |= G_CONNECT_SWAPPED;
+
+      g_signal_connect_data (object, signal->name, func, other, NULL, flags);
+    }
+}
+
+typedef struct
+{
+  gchar *object;
+  gchar *name;
+  gchar *value;
+} DelayedProperty;
+
+static GArray *
+gtk_builder_get_parameters (GtkBuilder *builder,
+			    GType object_type,
+			    const gchar *object_name,
+			    GSList *properties)
+{
+  GtkBuilderPrivate *priv;
+  GSList *l;
+  GParamSpec *pspec;
+  GObjectClass *oclass;
+  GArray *parameters;
+  DelayedProperty *property;
+
+  priv = GTK_BUILDER_GET_PRIVATE (builder);
+  
+  oclass = g_type_class_ref (object_type);
+  g_assert (oclass != NULL);
+
+  parameters = g_array_new (FALSE, FALSE, sizeof (GParameter));
+  for (l = properties; l; l = l->next)
+    {
+      PropertyInfo *prop = (PropertyInfo*)l->data;
+      GParameter parameter = { NULL };
+      
+      pspec = g_object_class_find_property (G_OBJECT_CLASS (oclass), prop->name);
+      if (!pspec)
+	{
+	  g_print ("Unknown property: %s.%s\n",
+		   g_type_name (object_type), prop->name);
+	  continue;
+	}
+      if ((G_IS_PARAM_SPEC_OBJECT (pspec) &&
+	   !g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (pspec), GTK_TYPE_ADJUSTMENT)) ||
+	  (GTK_IS_WIDGET_CLASS (oclass) &&
+	   (!strncmp (prop->name, "has_focus", 9) ||
+	    !strncmp (prop->name, "has_default", 11))))
+	{
+	  GSList *delayed_properties;
+
+	  delayed_properties = g_hash_table_lookup (priv->delayed_properties,
+						    priv->current_toplevel);
+	  property = g_slice_new (DelayedProperty);
+	  property->object = g_strdup (object_name);
+	  property->name = g_strdup (prop->name);
+	  property->value = g_strdup (prop->data);
+	  delayed_properties = g_slist_prepend (delayed_properties, property);
+	  g_hash_table_insert (priv->delayed_properties,
+			       g_strdup (priv->current_toplevel),
+			       delayed_properties);
+	  continue;
+	}
+      if (!gtk_set_value_from_string (pspec, prop->data,
+				      &parameter.value))
+	{
+	  g_warning ("failed to set property %s.%s to %s",
+		     g_type_name (object_type), prop->name, prop->data);
+	  continue;
+	}
+
+      /*
+       * Visible properties set should not be set immediatelly, instead
+       * add them to a list and set them after the whole tree is
+       * constructed
+       */
+      if (!strncmp (prop->name, "visible", 7) &&
+	  g_value_get_boolean (&parameter.value) == TRUE)
+	{
+	  priv->visible_properties = g_slist_prepend (priv->visible_properties,
+						      g_strdup (object_name));
+	  g_value_unset (&parameter.value);
+	  continue;
+	}
+
+      parameter.name = prop->name;
+      g_array_append_val (parameters, parameter);
+    }
+
+  g_type_class_unref (oclass);
+
+  return parameters;
+}
+
+GObject *
+_gtk_builder_construct (GtkBuilder  *builder,
+			ObjectInfo  *info)
+{
+  GArray *parameters;
+  GType object_type;
+  GObject *obj;
+  GtkBuilderPrivate *priv = GTK_BUILDER_GET_PRIVATE (builder);
+  int i;
+  GSList *l;
+
+  object_type = gtk_lazy_type_from_name (info->class_name);
+  if (object_type == G_TYPE_INVALID)
+    g_error ("Invalid type: %s", info->class_name);
+
+  parameters = gtk_builder_get_parameters (builder, object_type,
+					   info->id,
+					   info->properties);
+
+  if (info->constructor)
+    {
+      GObject *constructor;
+
+      constructor = gtk_builder_get_object (builder,
+					    info->constructor);
+      if (constructor == NULL)
+	g_error ("Unknown constructor for %s: %s\n", info->id,
+		 info->constructor);
+
+      obj = gtk_buildable_construct_child (GTK_BUILDABLE (constructor),
+					   info->id);
+      g_assert (obj != NULL);
+      
+      for (i = 0; i < parameters->len; i++)
+	{
+	  GParameter *param = &g_array_index (parameters, GParameter, i);
+	  g_object_set_property (obj,
+				 param->name,
+				 &param->value);
+	}
+    }
+  else
+    {
+      obj = g_object_newv (object_type,
+			   parameters->len,
+			   (GParameter *)parameters->data);
+
+      if (gtk_debug_flags & GTK_DEBUG_BUILDER)
+	g_print ("created %s of type %s\n", info->id, info->class_name);
+    }
+  
+  for (i = 0; i < parameters->len; i++)
+    {
+      GValue *value = &g_array_index (parameters, GParameter, i).value;
+      if (gtk_debug_flags & GTK_DEBUG_BUILDER)
+	{
+	  gchar *str = g_strdup_value_contents ((const GValue*)value);
+	  g_print ("set %s: %s = %s\n",
+		   info->id,
+		   g_array_index (parameters, GParameter, i).name,
+		   str);
+	  g_free (str);
+	}
+      g_value_unset (value);
+    }
+  g_array_free (parameters, TRUE);
+
+  if (GTK_IS_BUILDABLE (obj))
+    gtk_buildable_set_name (GTK_BUILDABLE (obj), info->id);
+  
+  g_object_set_data_full (obj,
+			  "gtk-builder-name",
+			  g_strdup (info->id),
+			  g_free);
+
+  if (!info->parent)
+    {
+      if (priv->current_toplevel)
+	g_free (priv->current_toplevel);
+      priv->current_toplevel = g_strdup (info->id);
+    }
+  g_hash_table_insert (priv->objects, g_strdup (info->id), obj);
+
+  for (l = info->signals; l; l = l->next)
+    {
+      priv->signals = g_slist_prepend (priv->signals, l->data);
+    }
+
+  return g_object_ref (obj);
+}
+
+
+void
+_gtk_builder_add (GtkBuilder *builder,
+		  ChildInfo *child_info)
+{
+  GObject *object;
+  GObject *parent;
+  GSList *l;
+
+  if (!child_info)
+    return;
+  object = child_info->object;
+  if (!object)
+    return;
+
+  g_assert (object != NULL);
+  g_assert (GTK_IS_BUILDABLE (object));
+
+  if (!child_info->parent)
+    {
+      g_print ("%s: Not adding, No parent\n",
+	       gtk_widget_get_name (GTK_WIDGET (object)));
+      return;
+    }
+  parent = ((ObjectInfo*)child_info->parent)->object;
+  g_assert (parent != NULL);
+  g_assert (GTK_IS_BUILDABLE (parent));
+
+  if (gtk_debug_flags & GTK_DEBUG_BUILDER)
+    g_print ("adding %s to %s\n",
+	     gtk_builder_get_name (builder, object),
+	     gtk_builder_get_name (builder, parent));
+
+  gtk_buildable_add (GTK_BUILDABLE (parent), object, child_info->type);
+
+  child_info->packing_properties
+    = g_slist_reverse (child_info->packing_properties);
+
+  for (l = child_info->packing_properties; l; l = l->next)
+    {
+      PropertyInfo *prop = (PropertyInfo*)l->data;
+
+      if (gtk_debug_flags & GTK_DEBUG_BUILDER)
+	g_print ("child %s of %s: %s = %s\n",
+		 gtk_builder_get_name (builder, object),
+		 gtk_builder_get_name (builder, parent),
+		 prop->name, prop->data);
+     
+      gtk_buildable_set_child_property (GTK_BUILDABLE (parent),
+					object,
+					prop->name, prop->data);
+    }
+}
+
+/**
+ * gtk_builder_get_objects:
+ * @builder: a #GtkBuilder
+ * @name: name of object to get
+ *
+ * Return value: GObject or %NULL if it could not be found in the object tree.
+ *
+ **/
+GObject *
+gtk_builder_get_object (GtkBuilder *builder,
+			const gchar *name)
+{
+  GtkBuilderPrivate *priv = GTK_BUILDER_GET_PRIVATE (builder);
+
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (name != NULL, NULL);
+  
+  return g_hash_table_lookup (priv->objects, name);
+}
+
+static void
+object_add_to_list (gchar *object_id,
+		    GObject *object,
+		    GSList **list)
+{
+  *list = g_slist_append (*list, object);
+}
+
+/**
+ * gtk_builder_get_objects:
+ * @builder: a #GtkBuilder
+ *
+ * Return value: a newly-allocated #GSList containing all the objects
+ *   constructed by GtkBuilder instance.
+ *
+ **/
+GSList *
+gtk_builder_get_objects (GtkBuilder *builder)
+{
+  GtkBuilderPrivate *priv = GTK_BUILDER_GET_PRIVATE (builder);
+  GSList *objects = NULL;
+
+  g_return_val_if_fail (builder != NULL, NULL);
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
+
+  g_hash_table_foreach (priv->objects, (GHFunc)object_add_to_list, &objects);
+
+  return objects;
+}
+
+/**
+ * gtk_builder_get_objects:
+ * @builder: a #GtkBuilder
+ * @name: a GObject
+ *
+ * Return value: the name of the object, or %NULL if it was not constructed
+ *   by a GtkBuilder
+ *
+ **/
+const gchar *
+gtk_builder_get_name (GtkBuilder *builder,
+		      GObject *child)
+{
+  g_return_val_if_fail (child != NULL, NULL);
+  g_return_val_if_fail (G_IS_OBJECT (child), NULL);
+
+  return (const gchar*)g_object_get_data (G_OBJECT (child),
+					  "gtk-builder-name");
+}
+
+static void
+apply_delayed_properties (const gchar *window_name,
+			  GSList *props,
+			  GtkBuilder *builder)
+{
+  GSList *l;
+  DelayedProperty *property;
+  GObject *object;
+  GtkBuilderPrivate *priv = GTK_BUILDER_GET_PRIVATE (builder);
+  GType object_type;
+  GObjectClass *oclass;
+  GParamSpec *pspec;
+
+  g_assert (props != NULL);
+  props = g_slist_reverse (props);
+  for (l = props; l; l = l->next)
+    {
+      property = (DelayedProperty*)l->data;
+      object = g_hash_table_lookup (priv->objects, property->object);
+      g_assert (object != NULL);
+      object_type = gtk_lazy_type_from_name (G_OBJECT_TYPE_NAME (object));
+      g_assert (object_type != G_TYPE_INVALID);
+      oclass = g_type_class_ref (object_type);
+      g_assert (oclass != NULL);
+      pspec = g_object_class_find_property (G_OBJECT_CLASS (oclass),
+					    property->name);
+      if (!pspec)
+	g_warning ("Unknown property: %s.%s\n", g_type_name (object_type),
+		   property->name);
+      else
+	{
+	  if (g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (pspec), G_TYPE_OBJECT))
+	    {
+	      GObject *obj;
+
+	      obj = g_hash_table_lookup (priv->objects, property->value);
+	      if (!obj)
+		g_warning ("No object called: %s\n", property->object);
+	      else
+		g_object_set (object, property->name, obj, NULL);
+	    }
+	  else
+	    {
+	      GValue value = { 0 };
+	      
+	      if (!gtk_set_value_from_string (pspec, property->value,
+					      &value))
+		g_warning ("failed to set property %s.%s to %s",
+			   g_type_name (object_type), property->name,
+			   property->value);
+	      else
+		g_object_set_property (object, property->name, &value);
+	    }
+	}
+      g_free (property->value);
+      g_free (property->object);
+      g_free (property->name);
+      g_slice_free (DelayedProperty, property);
+      g_type_class_unref (oclass);
+    }
+  g_slist_free (props);
+}
+
+void
+_gtk_builder_finish (GtkBuilder *builder,
+		     const gchar *domain)
+{
+  GtkBuilderPrivate *priv = GTK_BUILDER_GET_PRIVATE (builder);
+  GSList *l;
+
+  if (!priv->domain)
+    priv->domain = g_strdup (domain);
+ 
+  if (priv->visible_properties)
+    {
+      priv->visible_properties = g_slist_reverse (priv->visible_properties);
+      for (l = priv->visible_properties; l; l = l->next)
+	{
+	  GtkWidget *widget;
+	  gchar *name = (gchar*)l->data;
+
+	  widget = g_hash_table_lookup (priv->objects, name);
+	  g_assert (widget != NULL);
+
+	  g_free (name);
+	  if (widget)
+	    gtk_widget_show (widget);
+	}
+      g_slist_free (priv->visible_properties);
+      priv->visible_properties = NULL;
+    }
+  if (priv->delayed_properties)
+    {
+      g_hash_table_foreach (priv->delayed_properties,
+			    (GHFunc)apply_delayed_properties, builder);
+      g_hash_table_destroy (priv->delayed_properties);
+      priv->delayed_properties = NULL;
+    }
+  g_free (priv->current_toplevel);
+  g_signal_emit (G_OBJECT (builder), gtk_builder_signals[FINISH], 0);
+}
+
+#define __GTK_BUILDER_C__
+#include "gtkaliasdef.c"
Index: gtk/gtkbuilder.h
===================================================================
RCS file: gtk/gtkbuilder.h
diff -N gtk/gtkbuilder.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gtk/gtkbuilder.h	11 May 2006 00:00:57 -0000
@@ -0,0 +1,71 @@
+/* gtkbuilder.h
+ * Copyright (C) 2006 Async Open Source
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GTK_BUILDER_H__
+#define __GTK_BUILDER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_BUILDER                 (gtk_builder_get_type ())
+#define GTK_BUILDER(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_BUILDER, GtkBuilder))
+#define GTK_BUILDER_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_BUILDER, GtkBuilderClass))
+#define GTK_IS_BUILDER(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_BUILDER))
+#define GTK_IS_BUILDER_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_BUILDER))
+#define GTK_BUILDER_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_BUILDER, GtkBuilderClass))
+
+typedef struct _GtkBuilder        GtkBuilder;
+typedef struct _GtkBuilderClass   GtkBuilderClass;
+
+struct _GtkBuilder
+{
+  GObject parent;
+};
+
+struct _GtkBuilderClass
+{
+  GObjectClass        parent_class;
+  
+
+  void (*finish) (GtkBuilder *builder);
+
+  /* Padding for future expansion */
+  void (*_gtk_reserved1) (void);
+  void (*_gtk_reserved2) (void);
+  void (*_gtk_reserved3) (void);
+  void (*_gtk_reserved4) (void);
+};
+
+
+GType          gtk_builder_get_type           (void) G_GNUC_CONST;
+GtkBuilder*    gtk_builder_new                (const gchar *filename,
+					       const gchar *domain);
+GtkBuilder*    gtk_builder_new_from_buffer    (const gchar *buffer,
+					       gsize length,
+					       const gchar *domain);
+GObject*       gtk_builder_get_object         (GtkBuilder *builder,
+					       const gchar *name);
+GSList*        gtk_builder_get_objects        (GtkBuilder *builder);
+const gchar*   gtk_builder_get_name           (GtkBuilder *builder,
+					       GObject *object);
+void           gtk_builder_signal_autoconnect (GtkBuilder *builder);
+
+G_END_DECLS
+
+#endif /* __GTK_BUILDER_H__ */
Index: gtk/gtkbuilderparser.c
===================================================================
RCS file: gtk/gtkbuilderparser.c
diff -N gtk/gtkbuilderparser.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gtk/gtkbuilderparser.c	11 May 2006 00:00:57 -0000
@@ -0,0 +1,589 @@
+/* gtkbuilderparser.c
+ * Copyright (C) 2006 Async Open Source
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <glib/gfileutils.h>
+#include <glib/gi18n.h>
+#include <glib/gmacros.h>
+#include <glib/gmessages.h>
+#include <glib/gslist.h>
+#include <glib/gstrfuncs.h>
+#include <glib-object.h>
+
+#include "gtkbuilderprivate.h"
+#include "gtkbuilder.h"
+#include "gtkbuildable.h"
+#include "gtkdebug.h"
+#include "gtktypeutils.h"
+
+static void free_property_info (PropertyInfo *info,
+				gpointer user_data);
+
+static inline void
+state_push (ParserData *data, gpointer info)
+{
+  data->stack = g_slist_prepend (data->stack, info);
+}
+
+static inline gpointer
+state_peek (ParserData *data)
+{
+  if (!data->stack)
+    return NULL;
+
+  return data->stack->data;
+}
+
+static inline gpointer
+state_pop (ParserData *data)
+{
+  gpointer old = NULL;
+
+  if (!data->stack)
+    return NULL;
+  
+  old = data->stack->data;
+  data->stack = g_slist_delete_link (data->stack, data->stack);
+  return old;
+}
+
+static ObjectInfo *
+parse_object (ParserData   *data,
+	      const gchar  *element_name,
+	      const gchar **names,
+	      const gchar **values)
+{
+  int i;
+  gchar *object_class = NULL;
+  gchar *object_id = NULL;
+  gchar *constructor = NULL;
+  ObjectInfo *info;
+  
+  for (i = 0; names[i] != NULL; i++)
+    {
+      if (!strncmp (names[i], "class", 5))
+	object_class = g_strdup (values[i]);
+      else if (!strncmp (names[i], "id", 2))
+	object_id = g_strdup (values[i]);
+      else if (!strncmp (names[i], "constructor", 11))
+	constructor = g_strdup (values[i]);
+    }
+
+  if (!object_class)
+    g_error ("<object> must have a class attribute");
+
+  if (!object_id)
+    g_error ("<object> must have an id attribute");
+
+  info = g_slice_new0 (ObjectInfo);
+  info->class_name = object_class;
+  info->id = object_id;
+  info->constructor = constructor;
+  state_push (data, info);
+  g_assert (state_peek (data) != NULL);
+  info->tag.name = element_name;
+
+  return info;
+}
+
+static void
+free_object_info (ObjectInfo *info)
+{
+  /* Do not free the signal list, the GtkBuilder takes
+     ownership of it */
+  g_slist_free (info->signals);  
+  g_slist_foreach (info->properties,
+		   (GFunc)free_property_info, NULL);
+  g_slist_free (info->properties);
+  if (info->constructor)
+    g_free (info->constructor);
+  g_free (info->class_name);
+  g_free (info->id);
+  g_slice_free (ObjectInfo, info);
+}
+
+static ChildInfo *
+parse_child (ParserData *data,
+	     const gchar  *element_name,
+	     const gchar **names,
+	     const gchar **values)
+
+{
+  ChildInfo *info;
+  guint i;
+
+  info = g_slice_new0 (ChildInfo);
+  state_push (data, info);
+  g_assert (state_peek (data) != NULL);
+  info->tag.name = element_name;
+  for (i = 0; names[i]; i++)
+    {
+      if (!strncmp (names[i], "type", 4))
+	  info->type = g_strdup (values[i]);
+    }
+  return info;
+}
+
+static void
+free_child_info (ChildInfo *info)
+{
+  g_slist_foreach (info->packing_properties,
+		   (GFunc)free_property_info, NULL);
+  g_slist_free (info->packing_properties);
+  if (info->type)
+    g_free (info->type);
+  g_slice_free (ChildInfo, info);
+}
+
+static void
+parse_property (ParserData   *data,
+		const gchar  *element_name,
+		const gchar **names,
+		const gchar **values)
+{
+  PropertyInfo *info;
+  gchar *name = NULL;
+  gboolean translatable = FALSE;
+  int i;
+
+  g_assert (data->stack != NULL);
+  
+  for (i = 0; names[i] != NULL; i++)
+    {
+      if (!strncmp (names[i], "name", 4))
+	name = g_strdup (values[i]);
+      else if (!strncmp (names[i], "translatable", 12))
+	translatable = !strncmp (values[i], "yes", 3);
+    }
+
+  if (!name)
+    g_error ("<property> needs a name");
+
+  info = g_slice_new0 (PropertyInfo);
+  info->name = name;
+  info->translatable = translatable;
+  state_push (data, info);
+
+  info->tag.name = element_name;
+}
+
+static void
+free_property_info (PropertyInfo *info,
+		    gpointer user_data)
+{
+  if (info->data)
+      g_free (info->data);
+  g_free (info->name);
+  g_slice_free (PropertyInfo, info);
+}
+
+static void
+parse_signal (ParserData   *data,
+	      const gchar  *element_name,
+	      const gchar **names,
+	      const gchar **values)
+{
+  SignalInfo *info;
+  gchar *name = NULL;
+  gchar *handler = NULL;
+  gchar *object = NULL;
+  gboolean after = FALSE;
+  int i;
+
+  g_assert (data->stack != NULL);
+  
+  for (i = 0; names[i] != NULL; i++)
+    {
+      if (!strncmp (names[i], "name", 4))
+	name = g_strdup (values[i]);
+      else if (!strncmp (names[i], "handler", 7))
+	handler = g_strdup (values[i]);
+      else if (!strncmp (names[i], "object", 6))
+	object = g_strdup (values[i]);
+      else if (!strncmp (names[i], "after", 5))
+	after = !strncmp (values[i], "yes", 3);
+    }
+
+  if (!name)
+    g_error ("<signal> needs a name");
+
+  if (!handler)
+    g_error ("<signal> needs a handler");
+
+  info = g_slice_new0 (SignalInfo);
+  info->name = name;
+  info->handler = handler;
+  info->object = object;
+  info->after = after;
+  state_push (data, info);
+
+  info->tag.name = element_name;
+}
+
+/* Called by GtkBuilder */
+void
+_free_signal_info (SignalInfo *info,
+		   gpointer user_data)
+{
+  g_free (info->name);
+  g_free (info->handler);
+  if (info->object)
+    g_free (info->object);
+  if (info->object_name)
+    g_free (info->object_name);
+  g_slice_free (SignalInfo, info);
+}
+
+static GObject *
+builder_construct (ParserData *data,
+		   ObjectInfo *object_info)
+{
+  GObject *object;
+  
+  g_assert (object_info != NULL);
+
+  if (object_info->object)
+    return object_info->object;
+      
+  object_info->properties = g_slist_reverse (object_info->properties);
+  
+  object = _gtk_builder_construct (data->builder, object_info);
+  g_assert (object != NULL);
+  g_assert (G_IS_OBJECT (object));
+
+  object_info->object = object;
+
+  return object;
+}
+
+static void
+start_element (GMarkupParseContext *context,
+	       const gchar         *element_name,
+	       const gchar        **names,
+	       const gchar        **values,
+	       gpointer             user_data,
+	       GError             **error)
+{
+  ParserData *data = (ParserData*)user_data;
+
+  if (gtk_debug_flags & GTK_DEBUG_BUILDER)
+    g_print ("<%s>\n", element_name);
+
+  if (data->subparser)
+    {
+      if (!data->subparser->start &&
+	  !strcmp (element_name, data->subparser->tagname))
+	data->subparser->start = element_name;
+
+      if (data->subparser->start)
+	{
+	  if (data->subparser->parser->start_element)
+	    {
+	      data->subparser->parser->start_element (context,
+						      element_name, names, values,
+						      data->subparser->data, error);
+	    }
+	  return;
+	}
+    }
+
+  if (!strncmp (element_name, "object", 6))
+    {
+      ChildInfo* child_info = state_peek_info (data, ChildInfo);
+      ObjectInfo *object_info;
+
+      object_info = parse_object (data, element_name, names, values);
+
+      if (child_info)
+	object_info->parent = (CommonInfo*)child_info;
+    }
+  else if (!strncmp (element_name, "child", 5))
+    {
+      ChildInfo* child_info;
+      ObjectInfo* object_info = state_peek_info (data, ObjectInfo);
+
+      child_info = parse_child (data, element_name, names, values);
+      child_info->parent = (CommonInfo*)object_info;
+      
+      object_info->object = builder_construct (data, object_info);
+    }
+  else if (!strncmp (element_name, "property", 8))
+    {
+      parse_property (data, element_name, names, values);
+    }
+  else if (!strncmp (element_name, "packing", 7))
+    {
+    }
+  else if (!strncmp (element_name, "signal", 6))
+    {
+      parse_signal (data, element_name, names, values);
+    }
+  else if (!strncmp (element_name, "glade-interface", 15))
+    {
+      int i;
+      
+      for (i = 0; names[i] != NULL; i++)
+	{
+	  if (!strncmp (names[i], "domain", 6) && !data->domain)
+	    {
+	      data->domain = g_strdup (values[i]);
+	      break;
+	    }
+	}
+    }
+  else if (!strncmp (element_name, "placeholder", 11))
+    {
+    }
+  else
+    {
+      ObjectInfo* object_info = state_peek_info (data, ObjectInfo);
+      
+      if (!strcmp (object_info->tag.name, "object"))
+	{
+	  GMarkupParser parser;
+	  SubParser *subparser;
+	  gpointer *user_data;
+	  
+	  if (!object_info->object)
+	    object_info->object = _gtk_builder_construct (data->builder,
+							  object_info);
+	  
+	  g_assert (object_info->object);
+
+	  if (!gtk_buildable_custom_tag_start (GTK_BUILDABLE (object_info->object),
+					       element_name,
+					       &parser,
+					       (gpointer*)&user_data))
+	    return;
+
+	  subparser = g_new0 (SubParser, 1);
+	  subparser->object = object_info->object;
+	  subparser->tagname = element_name;
+	  subparser->start = element_name;
+	  subparser->parser = g_memdup (&parser, sizeof (GMarkupParser));
+	  subparser->data = user_data;
+	  data->subparser = subparser;
+	  
+	  if (parser.start_element)
+	      parser.start_element (context,
+				    element_name, names, values,
+				    user_data, error);
+	}
+      else
+	{
+	  g_warning ("unhandled tag: %s\n", element_name);
+	}
+    }
+}
+
+/* Called for close tags </foo> */
+static void
+end_element (GMarkupParseContext *context,
+	     const gchar         *element_name,
+	     gpointer             user_data,
+	     GError             **error)
+{
+  ParserData *data = (ParserData*)user_data;
+  
+  if (gtk_debug_flags & GTK_DEBUG_BUILDER)
+    g_print ("</%s>\n", element_name);
+
+  if (data->subparser)
+    {
+      if (data->subparser->start)
+	{
+	  if (data->subparser->parser->end_element)
+	    data->subparser->parser->end_element (context, element_name, 
+						  data->subparser->data, error);
+	  
+	  if (!strcmp (data->subparser->start, element_name))
+	    {
+	      gtk_buildable_custom_tag_end (GTK_BUILDABLE (data->subparser->object),
+					    data->builder,
+					    element_name,
+					    data->subparser->data);
+	      g_free (data->subparser->parser);
+	      g_free (data->subparser);
+	      data->subparser = NULL;
+	    }
+	  return;
+	}
+    }
+
+  if (!strncmp (element_name, "object", 6))
+    {
+      ObjectInfo *object_info = state_pop_info (data, ObjectInfo);
+      ChildInfo* child_info = state_peek_info (data, ChildInfo);
+      
+      object_info->object = builder_construct (data, object_info);
+      
+      if (child_info)
+	child_info->object = object_info->object;
+
+      free_object_info (object_info);
+    }
+  else if (!strncmp (element_name, "property", 8))
+    {
+      PropertyInfo *prop_info = state_pop_info (data, PropertyInfo);
+      CommonInfo *info = state_peek_info (data, CommonInfo);
+
+      /* Normal properties */
+      if (!strncmp (info->tag.name, "object", 6))
+	{
+	  ObjectInfo *object_info = (ObjectInfo*)info;
+	  object_info->properties =
+	    g_slist_prepend (object_info->properties, prop_info);
+	}
+      /* Packing properties */
+      else if (!strncmp (info->tag.name, "child", 5))
+	{
+	  ChildInfo *child_info = (ChildInfo*)info;
+	  child_info->packing_properties =
+	    g_slist_prepend (child_info->packing_properties, prop_info);
+	}
+      else
+	{
+	  g_assert_not_reached ();
+	}
+    }
+  else if (!strncmp (element_name, "child", 5))
+    {
+      ChildInfo *child_info = state_pop_info (data, ChildInfo);
+
+      _gtk_builder_add (data->builder, child_info);
+
+      free_child_info (child_info);
+    }
+  else if (!strncmp (element_name, "packing", 7))
+    {
+    }
+  else if (!strncmp (element_name, "signal", 6))
+    {
+      SignalInfo *signal_info = state_pop_info (data, SignalInfo);
+      ObjectInfo *object_info = (ObjectInfo*)state_peek_info (data, CommonInfo);
+      signal_info->object_name = g_strdup (object_info->id);
+      object_info->signals =
+	g_slist_prepend (object_info->signals, signal_info);
+    }
+  else if (!strncmp (element_name, "glade-interface", 15))
+    {
+    }
+  else if (!strncmp (element_name, "placeholder", 11))
+    {
+    }
+  else
+    {
+      g_warning ("unhandled tag: %s", element_name);
+      g_assert_not_reached ();
+    }
+}
+
+/* Called for character data */
+/* text is not nul-terminated */
+static void
+text (GMarkupParseContext *context,
+      const gchar         *text,
+      gsize                text_len,
+      gpointer             user_data,
+      GError             **error)
+{
+  ParserData *data = (ParserData*)user_data;
+  CommonInfo *info;
+  
+  if (!data->stack)
+    return;
+
+  info = state_peek_info (data, CommonInfo);
+  g_assert (info != NULL);
+  
+  if (!strncmp (g_markup_parse_context_get_element (context), "property", 8))
+    {
+      PropertyInfo *prop_info = (PropertyInfo*)info;
+      
+      if (prop_info->translatable && text_len)
+	{
+	  if (data->domain)
+	    text = dgettext (text, data->domain);
+	  else
+	    text = gettext (text);
+	}
+      prop_info->data = g_strndup (text, text_len);
+    }
+}
+
+static void
+error (GMarkupParseContext *context,
+       GError              *error,
+       gpointer             user_data)
+{
+  g_message ("error: '%s'", error->message);
+}
+
+
+static const GMarkupParser parser = {
+  start_element,
+  end_element,
+  text,
+  NULL,
+  error
+};
+
+void
+_gtk_builder_parser_parse_buffer (GtkBuilder  *builder,
+				  const gchar *buffer,
+				  gsize        length,
+				  const gchar *domain)
+{
+  GMarkupParseContext *context;
+  GError *error = NULL;
+  ParserData *data;
+
+  data = g_new0 (ParserData, 1);
+  data->builder = builder;
+  if (domain)
+    data->domain = g_strdup (domain);
+  context = g_markup_parse_context_new (&parser, 0, data, NULL);
+  
+  if (!g_markup_parse_context_parse (context, buffer, length, &error))
+    {
+      g_error ("ERROR: %s", error->message);
+    }
+  g_markup_parse_context_free (context);
+  _gtk_builder_finish (builder, data->domain);
+  if (data->domain)
+    g_free (data->domain);
+  g_free (data);
+
+}
+
+void
+_gtk_builder_parser_parse_filename (GtkBuilder  *builder,
+				    const gchar *filename,
+				    const gchar *domain)
+{
+  GError *error = { NULL };
+  char *buffer;
+  unsigned length;
+    
+  if (!g_file_get_contents (filename, &buffer, &length, &error))
+    g_error ("ERROR: %s", error->message);
+
+  _gtk_builder_parser_parse_buffer (builder, buffer, length, domain);
+  g_free (buffer);
+}
Index: gtk/gtkbuilderprivate.h
===================================================================
RCS file: gtk/gtkbuilderprivate.h
diff -N gtk/gtkbuilderprivate.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gtk/gtkbuilderprivate.h	11 May 2006 00:00:57 -0000
@@ -0,0 +1,111 @@
+/* gtkbuilderparser.h
+ * Copyright (C) 2006 Async Open Source
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_BUILDER_PARSER_H__
+#define __GTK_BUILDER_PARSER_H__
+
+#include <glib/gmarkup.h>
+#include <glib/gslist.h>
+
+#include <glib-object.h>
+#include "gtkbuilder.h"
+
+typedef struct {
+  const gchar *name;
+} TagInfo;
+
+typedef struct {
+  TagInfo tag;
+} CommonInfo;
+
+typedef struct {
+  TagInfo tag;
+  gchar *class_name;
+  gchar *id;
+  gchar *constructor;
+  GSList *properties;
+  GSList *signals;
+  GObject *object;
+  CommonInfo *parent;
+
+  /* For GtkUIManager */
+  const GMarkupParser *ui_parser;
+  gpointer ui_parser_data;
+} ObjectInfo;
+
+typedef struct {
+  TagInfo tag;
+  GSList *packing_properties;
+  GObject *object;
+  CommonInfo *parent;
+  gchar *type;
+} ChildInfo;
+
+typedef struct {
+  TagInfo tag;
+  gchar *name;
+  gchar *data;
+  gboolean translatable;
+} PropertyInfo;
+
+typedef struct {
+  TagInfo tag;
+  gchar *name;
+  gchar *handler;
+  gchar *object;
+  gboolean after;
+  gchar *object_name;
+} SignalInfo;
+
+typedef struct {
+  GMarkupParser *parser;
+  const gchar *tagname;
+  const gchar *start;
+  gpointer data;
+  GObject *object;
+} SubParser;
+
+typedef struct {
+  GtkBuilder *builder;
+  gchar *domain;
+  GSList *stack; 
+  SubParser *subparser;
+} ParserData;
+
+#define state_peek_info(data, st) ((st*)state_peek(data))
+#define state_pop_info(data, st) ((st*)state_pop(data))
+
+void _gtk_builder_parser_parse_buffer (GtkBuilder *builder,
+				       const gchar *buffer,
+				       gsize length,
+				       const gchar *domain);
+void _gtk_builder_parser_parse_filename (GtkBuilder *builder,
+					 const gchar *filename,
+					 const gchar *domain);
+
+GObject * _gtk_builder_construct (GtkBuilder *builder,
+				  ObjectInfo *info);
+void      _gtk_builder_finish (GtkBuilder *builder,
+			       const gchar *domain);
+void      _gtk_builder_add (GtkBuilder *builder,
+			    ChildInfo *child_info);
+void _free_signal_info (SignalInfo *info,
+			gpointer user_data);
+
+#endif /* __GTK_BUILDER_PARSER_H__ */
Index: gtk/gtkcontainer.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkcontainer.c,v
retrieving revision 1.141
diff -u -d -p -r1.141 gtkcontainer.c
--- gtk/gtkcontainer.c	14 Dec 2005 19:39:44 -0000	1.141
+++ gtk/gtkcontainer.c	11 May 2006 00:00:57 -0000
@@ -30,6 +30,7 @@
 #include <stdlib.h>
 
 #include "gtkcontainer.h"
+#include "gtkbuildable.h"
 #include "gtkprivate.h"
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
@@ -99,6 +100,18 @@ static void     gtk_container_unmap     
 static gchar* gtk_container_child_default_composite_name (GtkContainer *container,
 							  GtkWidget    *child);
 
+/* GtkBuildable */
+static void gtk_container_buildable_init           (GtkBuildableIface *iface);
+static void gtk_container_buildable_add            (GtkBuildable *buildable,
+						    GObject      *child,
+						    const gchar  *type);
+static void gtk_container_buildable_set_child_property
+                                                   (GtkBuildable *buildable,
+						    GObject      *child,
+						    const gchar  *name,
+						    const gchar  *value);
+							
+
 
 /* --- variables --- */
 static const gchar           vadjustment_key[] = "gtk-vadjustment";
@@ -108,6 +121,7 @@ static guint                 hadjustment
 static GSList	            *container_resize_queue = NULL;
 static guint                 container_signals[LAST_SIGNAL] = { 0 };
 static GtkWidgetClass       *parent_class = NULL;
+static GtkBuildableIface    *parent_buildable_iface;
 extern GParamSpecPool       *_gtk_widget_child_property_pool;
 extern GObjectNotifyContext *_gtk_widget_child_property_notify_context;
 
@@ -134,9 +148,21 @@ gtk_container_get_type (void)
 	NULL,       /* value_table */
       };
 
+      static const GInterfaceInfo buildable_info =
+      {
+	(GInterfaceInitFunc) gtk_container_buildable_init,
+	NULL,
+	NULL
+      };
+
       container_type =
 	g_type_register_static (GTK_TYPE_WIDGET, I_("GtkContainer"), 
 				&container_info, G_TYPE_FLAG_ABSTRACT);
+
+      g_type_add_interface_static (container_type,
+				   GTK_TYPE_BUILDABLE,
+				   &buildable_info);
+
     }
 
   return container_type;
@@ -258,6 +284,63 @@ gtk_container_class_init (GtkContainerCl
 		  _gtk_marshal_VOID__OBJECT,
 		  G_TYPE_NONE, 1,
 		  GTK_TYPE_WIDGET);
+}
+
+static void
+gtk_container_buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->add = gtk_container_buildable_add;
+  iface->set_child_property = gtk_container_buildable_set_child_property;
+}
+
+static void
+gtk_container_buildable_add (GtkBuildable  *buildable,
+			     GObject       *child,
+			     const gchar   *type)
+{
+  g_return_if_fail (GTK_IS_WIDGET (child));
+     
+  gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
+}
+
+static void
+gtk_container_buildable_set_child_property (GtkBuildable *buildable,
+					    GObject      *child,
+					    const gchar  *name,
+					    const gchar  *value)
+{
+  GParamSpec *pspec;
+  GValue gvalue = { 0, };
+
+  g_return_if_fail (buildable != NULL);
+  g_return_if_fail (GTK_IS_CONTAINER (buildable));
+  g_return_if_fail (child != NULL);
+  g_return_if_fail (GTK_IS_WIDGET (child));
+
+  pspec = gtk_container_class_find_child_property
+    (G_OBJECT_GET_CLASS (buildable), name);
+  if (!pspec)
+    {
+      g_warning ("%s does not have a property called %s",
+		 g_type_name (G_OBJECT_TYPE (buildable)), name);
+      return;
+    }
+
+  if (!gtk_set_value_from_string (G_PARAM_SPEC_VALUE_TYPE(pspec),
+				  value, &gvalue))
+    {
+      g_warning ("Could not read property %s:%s with value %s of type %s",
+		 g_type_name (G_OBJECT_TYPE (buildable)),
+		 name,
+		 value,
+		 g_type_name (G_PARAM_SPEC_VALUE_TYPE(pspec)));
+      return;
+    }
+  gtk_container_child_set_property (GTK_CONTAINER (buildable),
+				    GTK_WIDGET (child),
+				    name, &gvalue);
+  g_value_unset (&gvalue);
 }
 
 /**
Index: gtk/gtkdebug.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkdebug.h,v
retrieving revision 1.23
diff -u -d -p -r1.23 gtkdebug.h
--- gtk/gtkdebug.h	19 Oct 2004 18:45:41 -0000	1.23
+++ gtk/gtkdebug.h	11 May 2006 00:00:57 -0000
@@ -41,7 +41,8 @@ typedef enum {
   GTK_DEBUG_MULTIHEAD   = 1 << 6,
   GTK_DEBUG_MODULES     = 1 << 7,
   GTK_DEBUG_GEOMETRY    = 1 << 8,
-  GTK_DEBUG_ICONTHEME   = 1 << 9
+  GTK_DEBUG_ICONTHEME   = 1 << 9,
+  GTK_DEBUG_BUILDER     = 1 << 10
 } GtkDebugFlag;
 
 #ifdef G_ENABLE_DEBUG
Index: gtk/gtkexpander.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkexpander.c,v
retrieving revision 1.27
diff -u -d -p -r1.27 gtkexpander.c
--- gtk/gtkexpander.c	2 May 2006 23:56:40 -0000	1.27
+++ gtk/gtkexpander.c	11 May 2006 00:01:07 -0000
@@ -22,10 +22,11 @@
  */
 
 #include <config.h>
-
+#include <string.h>
 #include "gtkexpander.h"
 
 #include "gtklabel.h"
+#include "gtkbuildable.h"
 #include "gtkcontainer.h"
 #include "gtkmarshalers.h"
 #include "gtkmain.h"
@@ -126,7 +127,17 @@ static void gtk_expander_activate (GtkEx
 static void get_expander_bounds (GtkExpander  *expander,
 				 GdkRectangle *rect);
 
-G_DEFINE_TYPE (GtkExpander, gtk_expander, GTK_TYPE_BIN);
+/* GtkBuildable */
+static void gtk_expander_buildable_init           (GtkBuildableIface *iface);
+static void gtk_expander_buildable_add            (GtkBuildable *buildable,
+						   GObject      *child,
+						   const gchar  *type);
+
+static GtkBuildableIface    *parent_buildable_iface;
+
+G_DEFINE_TYPE_WITH_CODE (GtkExpander, gtk_expander, GTK_TYPE_BIN,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_expander_buildable_init));
 
 static void
 gtk_expander_class_init (GtkExpanderClass *klass)
@@ -275,6 +286,26 @@ gtk_expander_init (GtkExpander *expander
 
   gtk_drag_dest_set (GTK_WIDGET (expander), 0, NULL, 0, 0);
   gtk_drag_dest_set_track_motion (GTK_WIDGET (expander), TRUE);
+}
+
+static void
+gtk_expander_buildable_add (GtkBuildable  *buildable,
+			    GObject       *child,
+			    const gchar   *type)
+{
+  if (!type)
+    gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
+  else if (!strcmp (type, "label"))
+    gtk_expander_set_label_widget (GTK_EXPANDER (buildable), GTK_WIDGET (child));
+  else
+    g_warning ("Invalid type specified: `%s'", type);
+}
+
+static void
+gtk_expander_buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->add = gtk_expander_buildable_add;
 }
 
 static void
Index: gtk/gtkframe.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkframe.c,v
retrieving revision 1.61
diff -u -d -p -r1.61 gtkframe.c
--- gtk/gtkframe.c	2 May 2006 23:56:41 -0000	1.61
+++ gtk/gtkframe.c	11 May 2006 00:01:07 -0000
@@ -31,6 +31,7 @@
 #include "gtkprivate.h"
 #include "gtkintl.h"
 #include "gtkalias.h"
+#include "gtkbuildable.h"
 
 #define LABEL_PAD 1
 #define LABEL_SIDE_PAD 2
@@ -72,8 +73,18 @@ static void gtk_frame_compute_child_allo
 						     GtkAllocation *child_allocation);
 static void gtk_frame_real_compute_child_allocation (GtkFrame      *frame,
 						     GtkAllocation *child_allocation);
+/* GtkBuildable */
+static void gtk_frame_buildable_init                (GtkBuildableIface *iface);
+static void gtk_frame_buildable_add                 (GtkBuildable *buildable,
+						     GObject      *child,
+						     const gchar  *type);
+
+static GtkBuildableIface    *parent_buildable_iface;
+
+G_DEFINE_TYPE_WITH_CODE (GtkFrame, gtk_frame, GTK_TYPE_BIN,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_frame_buildable_init));
 
-G_DEFINE_TYPE (GtkFrame, gtk_frame, GTK_TYPE_BIN);
 
 static void
 gtk_frame_class_init (GtkFrameClass *class)
@@ -147,6 +158,26 @@ gtk_frame_class_init (GtkFrameClass *cla
   container_class->forall = gtk_frame_forall;
 
   class->compute_child_allocation = gtk_frame_real_compute_child_allocation;
+}
+
+static void
+gtk_frame_buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->add = gtk_frame_buildable_add;
+}
+
+static void
+gtk_frame_buildable_add (GtkBuildable *buildable,
+			 GObject      *child,
+			 const gchar  *type)
+{
+  if (type && !strcmp (type, "label"))
+    gtk_frame_set_label_widget (GTK_FRAME (buildable), GTK_WIDGET (child));
+  else if (!type)
+    gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
+  else
+    g_warning ("Invalid type specified: `%s'", type);
 }
 
 static void
Index: gtk/gtkliststore.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkliststore.c,v
retrieving revision 1.118
diff -u -d -p -r1.118 gtkliststore.c
--- gtk/gtkliststore.c	2 May 2006 23:56:41 -0000	1.118
+++ gtk/gtkliststore.c	11 May 2006 00:01:31 -0000
@@ -25,6 +25,7 @@
 #include "gtktreedatalist.h"
 #include "gtktreednd.h"
 #include "gtksequence.h"
+#include "gtkbuildable.h"
 #include "gtkintl.h"
 #include "gtkalias.h"
 
@@ -35,6 +36,7 @@ static void         gtk_list_store_tree_
 static void         gtk_list_store_drag_source_init(GtkTreeDragSourceIface *iface);
 static void         gtk_list_store_drag_dest_init  (GtkTreeDragDestIface   *iface);
 static void         gtk_list_store_sortable_init   (GtkTreeSortableIface   *iface);
+static void         gtk_list_store_buildable_init  (GtkBuildableIface      *iface);
 static void         gtk_list_store_finalize        (GObject           *object);
 static GtkTreeModelFlags gtk_list_store_get_flags  (GtkTreeModel      *tree_model);
 static gint         gtk_list_store_get_n_columns   (GtkTreeModel      *tree_model);
@@ -115,6 +117,16 @@ static void     gtk_list_store_set_defau
 static gboolean gtk_list_store_has_default_sort_func (GtkTreeSortable        *sortable);
 
 
+/* buildable */
+static gboolean gtk_list_store_buildable_custom_tag_start (GtkBuildable *buildable,
+							   const gchar  *tagname,
+							   GMarkupParser *parser,
+							   gpointer     *data);
+static void     gtk_list_store_buildable_custom_tag_end (GtkBuildable        *buildable,
+							 GtkBuilder          *builder,
+							 const gchar         *tagname,
+							 gpointer             data);
+
 G_DEFINE_TYPE_WITH_CODE (GtkListStore, gtk_list_store, G_TYPE_OBJECT,
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
 						gtk_list_store_tree_model_init)
@@ -123,7 +135,9 @@ G_DEFINE_TYPE_WITH_CODE (GtkListStore, g
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST,
 						gtk_list_store_drag_dest_init)
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
-						gtk_list_store_sortable_init));
+						gtk_list_store_sortable_init)
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_list_store_buildable_init));
 
 static void
 gtk_list_store_class_init (GtkListStoreClass *class)
@@ -177,6 +191,13 @@ gtk_list_store_sortable_init (GtkTreeSor
   iface->has_default_sort_func = gtk_list_store_has_default_sort_func;
 }
 
+void
+gtk_list_store_buildable_init (GtkBuildableIface *iface)
+{
+  iface->custom_tag_start = gtk_list_store_buildable_custom_tag_start;
+  iface->custom_tag_end = gtk_list_store_buildable_custom_tag_end;
+}
+
 static void
 gtk_list_store_init (GtkListStore *list_store)
 {
@@ -1948,6 +1969,109 @@ gtk_list_store_insert_with_valuesv (GtkL
   path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
   gtk_tree_path_free (path);
+}
+
+/* GtkBuildable custom tag implementation
+ *
+ * <columns>
+ *   <column type="..."/>
+ *   <column type="..."/>
+ * </columns>
+ */
+typedef struct {
+  GObject *object;
+  GSList *items;
+} GSListSubParserData;
+
+static void
+tree_model_start_element (GMarkupParseContext *context,
+			  const gchar         *element_name,
+			  const gchar        **names,
+			  const gchar        **values,
+			  gpointer            user_data,
+			  GError            **error)
+{
+  guint i;
+  GSListSubParserData *data = (GSListSubParserData*)user_data;
+
+  for (i = 0; names[i]; i++)
+    {
+      if (!strncmp (names[i], "type", 4))
+	data->items = g_slist_prepend (data->items, g_strdup (values[i]));
+    }
+}
+
+static const GMarkupParser tree_model_parser =
+  {
+    tree_model_start_element
+  };
+
+
+static gboolean
+gtk_list_store_buildable_custom_tag_start (GtkBuildable *buildable,
+					   const gchar  *tagname,
+					   GMarkupParser *parser,
+					   gpointer     *data)
+{
+  GSListSubParserData *parser_data;
+
+  if (!strcmp (tagname, "columns"))
+    {
+      parser_data = g_new0 (GSListSubParserData, 1);
+      parser_data->items = NULL;
+      parser_data->object = G_OBJECT (buildable);
+      
+      *parser = tree_model_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+subparser_tree_model_finish_cb (GtkBuilder *builder,
+				gpointer user_data)
+{
+  GSList *l;
+  GSListSubParserData *data = (GSListSubParserData*)user_data;
+  GType *types;
+  int i;
+  GType type;
+  
+  data->items = g_slist_reverse (data->items);
+  types = g_new0 (GType, g_slist_length (data->items));
+		  
+  for (l = data->items, i = 0; l; l = l->next, i++)
+    {
+      type = gtk_lazy_type_from_name (l->data);
+      if (type == G_TYPE_INVALID)
+	{
+	  g_warning ("Unknown type %s specified in treemodel %s",
+		     (const gchar*)l->data,
+		     gtk_buildable_get_name (GTK_BUILDABLE (data->object)));
+	  continue;
+	}
+      types[i] = type;
+
+      g_free (l->data);
+    }
+
+  gtk_list_store_set_column_types (GTK_LIST_STORE (data->object), i, types);
+
+  g_free (types);
+  g_slist_free (data->items);
+  g_free (data);
+}
+
+static void
+gtk_list_store_buildable_custom_tag_end (GtkBuildable        *buildable,
+					 GtkBuilder          *builder,
+					 const gchar         *tagname,
+					 gpointer             data)
+{
+  g_signal_connect (G_OBJECT (builder), "finish",
+		    (GCallback)subparser_tree_model_finish_cb, data);
 }
 
 #define __GTK_LIST_STORE_C__
Index: gtk/gtkmain.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmain.c,v
retrieving revision 1.276
diff -u -d -p -r1.276 gtkmain.c
--- gtk/gtkmain.c	6 Apr 2006 03:29:48 -0000	1.276
+++ gtk/gtkmain.c	11 May 2006 00:01:31 -0000
@@ -159,7 +159,8 @@ static const GDebugKey gtk_debug_keys[] 
   {"multihead", GTK_DEBUG_MULTIHEAD},
   {"modules", GTK_DEBUG_MODULES},
   {"geometry", GTK_DEBUG_GEOMETRY},
-  {"icontheme", GTK_DEBUG_ICONTHEME}
+  {"icontheme", GTK_DEBUG_ICONTHEME},
+  {"builder", GTK_DEBUG_BUILDER}
 };
 #endif /* G_ENABLE_DEBUG */
 
Index: gtk/gtknotebook.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtknotebook.c,v
retrieving revision 1.210
diff -u -d -p -r1.210 gtknotebook.c
--- gtk/gtknotebook.c	10 May 2006 15:58:48 -0000	1.210
+++ gtk/gtknotebook.c	11 May 2006 00:01:45 -0000
@@ -26,6 +26,7 @@
  */
 
 #include <config.h>
+#include <string.h>
 #include "gtknotebook.h"
 #include "gtkmain.h"
 #include "gtkmenu.h"
@@ -39,6 +40,7 @@
 #include "gtkprivate.h"
 #include "gtkalias.h"
 #include "gtkdnd.h"
+#include "gtkbuildable.h"
 
 #define SCROLL_DELAY_FACTOR   5
 #define SCROLL_THRESHOLD      12
@@ -394,13 +396,22 @@ static gboolean focus_child_in (GtkNoteb
 
 static void stop_scrolling (GtkNotebook *notebook);
 
+/* GtkBuildable */
+static void gtk_notebook_buildable_init           (GtkBuildableIface *iface);
+static void gtk_notebook_buildable_add            (GtkBuildable *buildable,
+						   GObject      *child,
+						   const gchar  *type);
+
 
 static GtkNotebookWindowCreationFunc window_creation_hook = NULL;
 static gpointer window_creation_hook_data;
 
+static GtkBuildableIface *parent_buildable_iface;
 static guint notebook_signals[LAST_SIGNAL] = { 0 };
 
-G_DEFINE_TYPE (GtkNotebook, gtk_notebook, GTK_TYPE_CONTAINER);
+G_DEFINE_TYPE_WITH_CODE (GtkNotebook, gtk_notebook, GTK_TYPE_CONTAINER,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_notebook_buildable_init));
 
 static void
 add_tab_bindings (GtkBindingSet    *binding_set,
@@ -999,6 +1010,36 @@ gtk_notebook_init (GtkNotebook *notebook
                      GDK_ACTION_MOVE);
 
   gtk_drag_dest_set_track_motion (GTK_WIDGET (notebook), TRUE);
+}
+
+static void
+gtk_notebook_buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->add = gtk_notebook_buildable_add;
+}
+
+static void
+gtk_notebook_buildable_add (GtkBuildable  *buildable,
+			    GObject       *child,
+			    const gchar   *type)
+{
+  GtkNotebook *notebook = GTK_NOTEBOOK (buildable);
+
+  if (type && !strcmp (type, "tab"))
+    {
+      GtkWidget * page;
+
+      page = gtk_notebook_get_nth_page (notebook, -1);
+      /* To set the tab label widget, we must have already a child
+       * inside the tab container. */
+      g_assert (page != NULL);
+      gtk_notebook_set_tab_label (notebook, page, GTK_WIDGET (child));
+    }
+  else if (!type)
+    gtk_notebook_append_page (notebook, GTK_WIDGET (child), NULL);
+  else
+    g_warning ("Invalid type specified: `%s'", type);
 }
 
 static gboolean
Index: gtk/gtksizegroup.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtksizegroup.c,v
retrieving revision 1.24
diff -u -d -p -r1.24 gtksizegroup.c
--- gtk/gtksizegroup.c	2 May 2006 23:56:42 -0000	1.24
+++ gtk/gtksizegroup.c	11 May 2006 00:01:45 -0000
@@ -19,11 +19,13 @@
  */
 
 #include <config.h>
+#include <string.h>
 #include "gtkcontainer.h"
 #include "gtkintl.h"
 #include "gtkprivate.h"
 #include "gtksizegroup.h"
 #include "gtkalias.h"
+#include "gtkbuildable.h"
 
 enum {
   PROP_0,
@@ -48,6 +50,27 @@ static void add_widget_to_closure (GtkWi
 				   GtkSizeGroupMode   mode,
 				   GSList           **groups,
 				   GSList           **widgets);
+static void gtk_size_group_finalize (GObject *size_group);
+
+/* GtkBuildable */
+static void gtk_size_group_buildable_init (GtkBuildableIface *iface);
+static void gtk_size_group_buildable_set_name (GtkBuildable *buildable,
+					       const gchar *name);
+static gboolean gtk_size_group_buildable_custom_tag_start (GtkBuildable  *buildable,
+						       const gchar   *tagname,
+						       GMarkupParser *parser,
+						       gpointer      *data);
+static void gtk_size_group_buildable_custom_tag_end (GtkBuildable  *buildable,
+						     GtkBuilder    *builder,
+						     const gchar   *tagname,
+						     gpointer       data);
+
+#define GTK_SIZE_GROUP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_SIZE_GROUP, GtkSizeGroupPrivate))
+
+typedef struct _GtkSizeGroupPrivate
+{
+  gchar *name;
+} GtkSizeGroupPrivate;
 
 static GQuark size_groups_quark;
 static const gchar size_groups_tag[] = "gtk-size-groups";
@@ -258,6 +281,7 @@ gtk_size_group_class_init (GtkSizeGroupC
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
+  gobject_class->finalize = gtk_size_group_finalize;
   gobject_class->set_property = gtk_size_group_set_property;
   gobject_class->get_property = gtk_size_group_get_property;
   
@@ -287,6 +311,8 @@ gtk_size_group_class_init (GtkSizeGroupC
 							 FALSE,
 							 GTK_PARAM_READWRITE));
 
+  g_type_class_add_private (gobject_class, sizeof (GtkSizeGroupPrivate));
+
   size_groups_quark = g_quark_from_static_string (size_groups_tag);
   visited_quark = g_quark_from_string (visited_tag);
 }
@@ -294,14 +320,48 @@ gtk_size_group_class_init (GtkSizeGroupC
 static void
 gtk_size_group_init (GtkSizeGroup *size_group)
 {
+  GtkSizeGroupPrivate *priv = GTK_SIZE_GROUP_GET_PRIVATE (size_group);
+
   size_group->widgets = NULL;
   size_group->mode = GTK_SIZE_GROUP_HORIZONTAL;
   size_group->have_width = 0;
   size_group->have_height = 0;
   size_group->ignore_hidden = 0;
+  priv->name = NULL;
 }
 
-G_DEFINE_TYPE (GtkSizeGroup, gtk_size_group, G_TYPE_OBJECT);
+static void
+gtk_size_group_finalize (GObject *obj)
+{
+  GtkSizeGroupPrivate *priv = GTK_SIZE_GROUP_GET_PRIVATE (obj);
+
+  if (priv->name)
+    g_free (priv->name);
+}
+
+static void
+gtk_size_group_buildable_init (GtkBuildableIface *iface)
+{
+  iface->set_name = gtk_size_group_buildable_set_name;
+  iface->custom_tag_start = gtk_size_group_buildable_custom_tag_start;
+  iface->custom_tag_end = gtk_size_group_buildable_custom_tag_end;
+}
+
+G_DEFINE_TYPE_WITH_CODE (GtkSizeGroup, gtk_size_group, G_TYPE_OBJECT,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_size_group_buildable_init));
+
+static void
+gtk_size_group_buildable_set_name (GtkBuildable *object,
+				   const gchar *name)
+{
+  GtkSizeGroupPrivate * priv;
+
+  priv = GTK_SIZE_GROUP_GET_PRIVATE (object);
+  if (priv->name)
+    g_free (priv->name);
+  priv->name = g_strdup (name);
+}
 
 static void
 gtk_size_group_set_property (GObject      *object,
@@ -794,6 +854,100 @@ _gtk_size_group_queue_resize (GtkWidget 
 {
   queue_resize_on_widget (widget, TRUE);
 }
+
+typedef struct {
+  GObject *object;
+  GSList *items;
+} GSListSubParserData;
+
+static void
+size_group_start_element (GMarkupParseContext *context,
+			  const gchar         *element_name,
+			  const gchar        **names,
+			  const gchar        **values,
+			  gpointer            user_data,
+			  GError            **error)
+{
+  guint i;
+  GSListSubParserData *data = (GSListSubParserData*)user_data;
+
+  if (!strcmp (element_name, "widget"))
+    for (i = 0; names[i]; i++)
+      if (!strncmp (names[i], "name", 4))
+	data->items = g_slist_prepend (data->items, g_strdup (values[i]));
+  else if (!strcmp (element_name, "widgets"))
+    return;
+  else
+    g_warning ("Unsupported type tag for GtkSizeGroup: %s\n",
+	       element_name);
+
+}
+
+static GMarkupParser size_group_parser =
+  {
+    size_group_start_element
+  };
+
+static gboolean
+gtk_size_group_buildable_custom_tag_start (GtkBuildable  *buildable,
+					   const gchar   *tagname,
+					   GMarkupParser *parser,
+					   gpointer      *data)
+{
+  GSListSubParserData *parser_data;
+
+  if (!strcmp (tagname, "widgets"))
+    {
+      parser_data = g_new0 (GSListSubParserData, 1);
+      parser_data->items = NULL;
+      parser_data->object = G_OBJECT (buildable);
+      
+      *parser = size_group_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+builder_finish_cb (GtkBuilder *builder,
+		   gpointer user_data)
+{
+  GSList *l;
+  GSListSubParserData *data = (GSListSubParserData*)user_data;
+  GObject *object;
+
+  data->items = g_slist_reverse (data->items);
+
+  for (l = data->items; l; l = l->next)
+    {
+      object = gtk_builder_get_object (builder, l->data);
+      if (!object)
+	{
+	  g_warning ("Unknown object %s specified in sizegroup %s",
+		     (const gchar*)l->data,
+		     gtk_buildable_get_name (GTK_BUILDABLE (data->object)));
+	  continue;
+	}
+      gtk_size_group_add_widget (GTK_SIZE_GROUP (data->object),
+				 GTK_WIDGET (object));
+      g_free (l->data);
+    }
+  g_slist_free (data->items);
+  g_free (data);
+}
+
+static void
+gtk_size_group_buildable_custom_tag_end (GtkBuildable  *buildable,
+					 GtkBuilder    *builder,
+					 const gchar   *tagname,
+					 gpointer       data)
+{
+  g_signal_connect (builder, "finish",
+		    (GCallback)builder_finish_cb, data);
+}
+
 
 #define __GTK_SIZE_GROUP_C__
 #include "gtkaliasdef.c"
Index: gtk/gtktreestore.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktreestore.c,v
retrieving revision 1.126
diff -u -d -p -r1.126 gtktreestore.c
--- gtk/gtktreestore.c	2 May 2006 23:56:43 -0000	1.126
+++ gtk/gtktreestore.c	11 May 2006 00:01:56 -0000
@@ -24,6 +24,7 @@
 #include "gtktreestore.h"
 #include "gtktreedatalist.h"
 #include "gtktreednd.h"
+#include "gtkbuildable.h"
 #include "gtkintl.h"
 #include "gtkalias.h"
 
@@ -35,6 +36,7 @@ static void         gtk_tree_store_tree_
 static void         gtk_tree_store_drag_source_init(GtkTreeDragSourceIface *iface);
 static void         gtk_tree_store_drag_dest_init  (GtkTreeDragDestIface   *iface);
 static void         gtk_tree_store_sortable_init   (GtkTreeSortableIface   *iface);
+static void         gtk_tree_store_buildable_init  (GtkBuildableIface      *iface);
 static void         gtk_tree_store_finalize        (GObject           *object);
 static GtkTreeModelFlags gtk_tree_store_get_flags  (GtkTreeModel      *tree_model);
 static gint         gtk_tree_store_get_n_columns   (GtkTreeModel      *tree_model);
@@ -115,6 +117,17 @@ static void     gtk_tree_store_set_defau
 							GtkDestroyNotify        destroy);
 static gboolean gtk_tree_store_has_default_sort_func   (GtkTreeSortable        *sortable);
 
+
+/* buildable */
+static gboolean gtk_tree_store_buildable_custom_tag_start (GtkBuildable *buildable,
+							   const gchar  *tagname,
+							   GMarkupParser *parser,
+							   gpointer     *data);
+static void     gtk_tree_store_buildable_custom_tag_end (GtkBuildable        *buildable,
+							 GtkBuilder          *builder,
+							 const gchar         *tagname,
+							 gpointer             data);
+
 static void     validate_gnode                         (GNode *node);
 
 static void     gtk_tree_store_move                    (GtkTreeStore           *tree_store,
@@ -142,7 +155,10 @@ G_DEFINE_TYPE_WITH_CODE (GtkTreeStore, g
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST,
 						gtk_tree_store_drag_dest_init)
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
-						gtk_tree_store_sortable_init));
+						gtk_tree_store_sortable_init)
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_tree_store_buildable_init)
+			 );
 
 static void
 gtk_tree_store_class_init (GtkTreeStoreClass *class)
@@ -196,6 +212,13 @@ gtk_tree_store_sortable_init (GtkTreeSor
   iface->has_default_sort_func = gtk_tree_store_has_default_sort_func;
 }
 
+void
+gtk_tree_store_buildable_init (GtkBuildableIface *iface)
+{
+  iface->custom_tag_start = gtk_tree_store_buildable_custom_tag_start;
+  iface->custom_tag_end = gtk_tree_store_buildable_custom_tag_end;
+}
+
 static void
 gtk_tree_store_init (GtkTreeStore *tree_store)
 {
@@ -3111,6 +3134,109 @@ validate_gnode (GNode* node)
       validate_gnode (iter);
       iter = iter->next;
     }
+}
+
+/* GtkBuildable custom tag implementation
+ *
+ * <columns>
+ *   <column type="..."/>
+ *   <column type="..."/>
+ * </columns>
+ */
+typedef struct {
+  GObject *object;
+  GSList *items;
+} GSListSubParserData;
+
+static void
+tree_model_start_element (GMarkupParseContext *context,
+			  const gchar         *element_name,
+			  const gchar        **names,
+			  const gchar        **values,
+			  gpointer            user_data,
+			  GError            **error)
+{
+  guint i;
+  GSListSubParserData *data = (GSListSubParserData*)user_data;
+
+  for (i = 0; names[i]; i++)
+    {
+      if (!strncmp (names[i], "type", 4))
+	data->items = g_slist_prepend (data->items, g_strdup (values[i]));
+    }
+}
+
+static const GMarkupParser tree_model_parser =
+  {
+    tree_model_start_element
+  };
+
+
+static gboolean
+gtk_tree_store_buildable_custom_tag_start (GtkBuildable *buildable,
+					   const gchar  *tagname,
+					   GMarkupParser *parser,
+					   gpointer     *data)
+{
+  GSListSubParserData *parser_data;
+
+  if (!strcmp (tagname, "columns"))
+    {
+      parser_data = g_new0 (GSListSubParserData, 1);
+      parser_data->items = NULL;
+      parser_data->object = G_OBJECT (buildable);
+      
+      *parser = tree_model_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+subparser_tree_model_finish_cb (GtkBuilder *builder,
+				gpointer user_data)
+{
+  GSList *l;
+  GSListSubParserData *data = (GSListSubParserData*)user_data;
+  GType *types;
+  int i;
+  GType type;
+  
+  data->items = g_slist_reverse (data->items);
+  types = g_new0 (GType, g_slist_length (data->items));
+		  
+  for (l = data->items, i = 0; l; l = l->next, i++)
+    {
+      type = gtk_lazy_type_from_name (l->data);
+      if (type == G_TYPE_INVALID)
+	{
+	  g_warning ("Unknown type %s specified in treemodel %s",
+		     (const gchar*)l->data,
+		     gtk_buildable_get_name (GTK_BUILDABLE (data->object)));
+	  continue;
+	}
+      types[i] = type;
+
+      g_free (l->data);
+    }
+
+  gtk_tree_store_set_column_types (GTK_TREE_STORE (data->object), i, types);
+
+  g_free (types);
+  g_slist_free (data->items);
+  g_free (data);
+}
+
+static void
+gtk_tree_store_buildable_custom_tag_end (GtkBuildable        *buildable,
+					 GtkBuilder          *builder,
+					 const gchar         *tagname,
+					 gpointer             data)
+{
+  g_signal_connect (G_OBJECT (builder), "finish",
+		    (GCallback)subparser_tree_model_finish_cb, data);
 }
 
 #define __GTK_TREE_STORE_C__
Index: gtk/gtktypetable.c
===================================================================
RCS file: gtk/gtktypetable.c
diff -N gtk/gtktypetable.c
Index: gtk/gtktypeutils.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktypeutils.c,v
retrieving revision 1.79
diff -u -d -p -r1.79 gtktypeutils.c
--- gtk/gtktypeutils.c	1 Sep 2005 05:11:43 -0000	1.79
+++ gtk/gtktypeutils.c	11 May 2006 00:01:56 -0000
@@ -28,12 +28,15 @@
 
 #include <config.h>
 #include <string.h> /* strcmp */
-
+#include <stdlib.h> /* strtol, strtoul */
+#include <gdk/gdkcolor.h>
 #include "gtktypeutils.h"
+#include "gtkadjustment.h"
+#include "gtkwidget.h"
 #include "gtkobject.h"
 #include "gtkintl.h"
 #include "gtkalias.h"
-
+#include "gtk.h"
 
 /* --- functions --- */
 GtkType
@@ -199,6 +202,412 @@ gtk_type_flags_find_value (GtkType      
   return value;
 }
 
+/**
+ * gtk_enum_from_string
+ * @type: the GType for this enum type.
+ * @string: the string representation of the enum value.
+ *
+ * This helper routine is designed to be used by widget build routines to
+ * convert the string representations of enumeration values found in the
+ * XML descriptions to the integer values that can be used to configure
+ * the widget.
+ *
+ * Returns: the integer value for this enumeration, or 0 if it couldn't be
+ * found.
+ */
+static gint
+gtk_enum_from_string (GType type, const char *string)
+{
+  GEnumClass *eclass;
+  GEnumValue *ev;
+  gchar *endptr;
+  gint ret = 0;
+
+  ret = strtoul(string, &endptr, 0);
+  if (endptr != string) /* parsed a number */
+    return ret;
+
+  eclass = g_type_class_ref(type);
+  ev = g_enum_get_value_by_name(eclass, string);
+  if (!ev) ev = g_enum_get_value_by_nick(eclass, string);
+  if (ev)  ret = ev->value;
+
+  g_type_class_unref(eclass);
+
+  return ret;
+}
+
+/**
+ * gtk_flags_from_string
+ * @type: the GType for this flags type.
+ * @string: the string representation of the flags value.
+ *
+ * This helper routine is designed to be used by widget build routines
+ * to convert the string representations of flags values found in the
+ * XML descriptions to the integer values that can be used to
+ * configure the widget.  The string is composed of string names or
+ * nicknames for various flags separated by '|'.
+ *
+ * Returns: the integer value for this flags string
+ */
+static guint
+gtk_flags_from_string (GType type, const char *string)
+{
+  GFlagsClass *fclass;
+  gchar *endptr, *prevptr;
+  guint i, j, ret = 0;
+  char *flagstr;
+
+  ret = strtoul(string, &endptr, 0);
+  if (endptr != string) /* parsed a number */
+    return ret;
+
+  fclass = g_type_class_ref(type);
+
+  flagstr = g_strdup (string);
+  for (ret = i = j = 0; ; i++) {
+    gboolean eos;
+
+    eos = flagstr [i] == '\0';
+	
+    if (eos || flagstr [i] == '|') {
+      GFlagsValue *fv;
+      const char  *flag;
+      gunichar ch;
+
+      flag = &flagstr [j];
+      endptr = &flagstr [i];
+
+      if (!eos) {
+	flagstr [i++] = '\0';
+	j = i;
+      }
+
+      /* trim spaces */
+      for (;;)
+	{
+	  ch = g_utf8_get_char (flag);
+	  if (!g_unichar_isspace (ch))
+	    break;
+	  flag = g_utf8_next_char (flag);
+	}
+
+      while (endptr > flag)
+	{
+	  prevptr = g_utf8_prev_char (endptr);
+	  ch = g_utf8_get_char (prevptr);
+	  if (!g_unichar_isspace (ch))
+	    break;
+	  endptr = prevptr;
+	}
+
+      if (endptr > flag)
+	{
+	  *endptr = '\0';
+	  fv = g_flags_get_value_by_name (fclass, flag);
+
+	  if (!fv)
+	    fv = g_flags_get_value_by_nick (fclass, flag);
+
+	  if (fv)
+	    ret |= fv->value;
+	  else
+	    g_warning ("Unknown flag: '%s'", flag);
+	}
+
+      if (eos)
+	break;
+    }
+  }
+    
+  g_free (flagstr);
+
+  g_type_class_unref(fclass);
+
+  return ret;
+}
+
+/**
+ * gtk_set_value_from_string
+ * @pspec: the GParamSpec for the property
+ * @string: the string representation of the value.
+ * @value: the GValue to store the result in.
+ *
+ * This function demarshals a value from a string.  This function
+ * calls g_value_init() on the @value argument, so it need not be
+ * initialised beforehand.
+ *
+ * This function can handle char, uchar, boolean, int, uint, long,
+ * ulong, enum, flags, float, double, string, GdkColor and
+ * GtkAdjustment type values.  Support for GtkWidget type values is
+ * still to come.
+ *
+ * Returns: %TRUE on success.
+ */
+gboolean
+gtk_set_value_from_string (GParamSpec *pspec,
+			   const gchar *string,
+			   GValue *value)
+{
+  gboolean ret = TRUE;
+  GType prop_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
+
+  g_value_init (value, prop_type);
+
+  /*
+   * GParamSpecUnichar had the internal type G_TYPE_UINT,
+   * so we cannot handle this in the switch, do it separately
+   */
+  
+  if (G_IS_PARAM_SPEC_UNICHAR (pspec))
+    {
+      gunichar c;
+      c = g_utf8_get_char_validated (string, strlen (string));
+      if (c > 0)
+	g_value_set_uint (value, c);
+      return TRUE;
+    }
+  
+  switch (G_TYPE_FUNDAMENTAL (prop_type))
+    {
+    case G_TYPE_CHAR:
+      g_value_set_char (value, string[0]);
+      break;
+    case G_TYPE_UCHAR:
+      g_value_set_uchar (value, (guchar)string[0]);
+      break;
+    case G_TYPE_BOOLEAN:
+      g_value_set_boolean (value, 
+			   g_ascii_tolower (string[0]) == 't'
+			   || g_ascii_tolower (string[0]) == 'y'
+			   || strtol (string, NULL, 0));
+      break;
+    case G_TYPE_INT:
+      g_value_set_int (value, strtol (string, NULL, 0));
+      break;
+    case G_TYPE_UINT:
+      g_value_set_uint (value, strtoul (string, NULL, 0));
+      break;
+    case G_TYPE_LONG:
+      g_value_set_long (value, strtol (string, NULL, 0));
+      break;
+    case G_TYPE_ULONG:
+      g_value_set_ulong (value, strtoul (string, NULL, 0));
+      break; 
+    case G_TYPE_ENUM:
+      g_value_set_enum (value, gtk_enum_from_string (prop_type, string));
+      break;
+    case G_TYPE_FLAGS:
+      g_value_set_flags (value, gtk_flags_from_string (prop_type, string));
+      break;
+    case G_TYPE_FLOAT:
+      g_value_set_float (value, g_strtod (string, NULL));
+      break;
+    case G_TYPE_DOUBLE:
+      g_value_set_double (value, g_strtod (string, NULL));
+      break;
+    case G_TYPE_STRING:
+      g_value_set_string (value, string);
+      break;
+    case G_TYPE_BOXED:
+      if (G_VALUE_HOLDS (value, GDK_TYPE_COLOR))
+	{
+	  GdkColor colour = { 0, };
+
+	  if (gdk_color_parse (string, &colour) &&
+	      gdk_colormap_alloc_color (gtk_widget_get_default_colormap (),
+					&colour, FALSE, TRUE))
+	    {
+	      g_value_set_boxed (value, &colour);
+	    }
+	  else
+	    {
+	      g_warning ("could not parse colour name `%s'", string);
+	      ret = FALSE;
+	    }
+	}
+      else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
+	{
+	  char **vector = g_strsplit (string, "\n", 0);
+	  g_value_take_boxed (value, vector);
+	}
+      else
+	ret = FALSE;
+      break;
+    case G_TYPE_OBJECT:
+      if (G_VALUE_HOLDS (value, GTK_TYPE_ADJUSTMENT))
+	{
+	  GtkAdjustment *adj =
+	    GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 100, 1, 10, 10));
+	  gchar *ptr = (gchar *)string;
+
+	  adj->value = g_strtod (ptr, &ptr);
+	  adj->lower = g_strtod (ptr, &ptr);
+	  adj->upper = g_strtod (ptr, &ptr);
+	  adj->step_increment = g_strtod (ptr, &ptr);
+	  adj->page_increment = g_strtod (ptr, &ptr);
+	  adj->page_size = g_strtod (ptr, &ptr);
+
+	  g_value_set_object (value, adj);
+	  g_object_ref_sink (G_OBJECT (adj));
+	  g_object_unref (G_OBJECT (adj));
+	}
+#if 0
+        else if (G_VALUE_HOLDS (value, GDK_TYPE_PIXBUF))
+      {
+	gchar *filename;
+	GError *error = NULL;
+	GdkPixbuf *pixbuf;
+	
+	filename = gtk_xml_relative_file (xml, string);
+	pixbuf = gdk_pixbuf_new_from_file (filename, &error);
+	if (pixbuf)
+	  {
+	    g_value_set_object (value, pixbuf);
+	    g_object_unref (G_OBJECT (pixbuf));
+	  }
+	else
+	  {
+	    g_warning ("Error loading image: %s", error->message);
+	    g_error_free (error);
+	    ret = FALSE;
+	  }
+	g_free (filename);
+      }
+#endif
+	else
+	  ret = FALSE;
+      break;
+    default:
+      ret = FALSE;
+      break;
+    }
+
+  return ret;
+}
+
+typedef GType (*GetTypeFunc) (void);
+
+typedef struct {
+  gchar *name;
+  GetTypeFunc func;
+} BuilderTypeInfo;
+
+static const BuilderTypeInfo infos[] = {
+  /* Tested, working widgets */
+  { "GtkAction", gtk_action_get_type },
+  { "GtkActionGroup", gtk_action_group_get_type },
+  { "GtkAlignment", gtk_alignment_get_type },
+  { "GtkArrow", gtk_arrow_get_type },
+  { "GtkButton", gtk_button_get_type },
+  { "GtkCheckButton", gtk_check_button_get_type },
+  { "GtkDialog", gtk_dialog_get_type },
+  { "GtkDrawingArea", gtk_drawing_area_get_type },
+  { "GtkEventBox", gtk_event_box_get_type },
+  { "GtkEntry", gtk_entry_get_type },
+  { "GtkFontButton", gtk_font_button_get_type },
+  { "GtkHButtonBox", gtk_hbutton_box_get_type },
+  { "GtkHBox", gtk_hbox_get_type },
+  { "GtkHPaned", gtk_hpaned_get_type },
+  { "GtkHRuler", gtk_hruler_get_type },
+  { "GtkHScale", gtk_hscale_get_type },
+  { "GtkHScrollbar", gtk_hscrollbar_get_type },
+  { "GtkHSeparator", gtk_hseparator_get_type },
+  { "GtkImage", gtk_image_get_type },
+  { "GtkLabel", gtk_label_get_type },
+  { "GtkListStore", gtk_list_store_get_type },
+  { "GtkMenuBar", gtk_menu_bar_get_type },
+  { "GtkNotebook", gtk_notebook_get_type },
+  { "GtkProgressBar", gtk_progress_bar_get_type },
+  { "GtkRadioButton", gtk_radio_button_get_type },
+  { "GtkSizeGroup", gtk_size_group_get_type },
+  { "GtkScrolledWindow", gtk_scrolled_window_get_type },
+  { "GtkSpinButton", gtk_spin_button_get_type },
+  { "GtkStatusbar", gtk_statusbar_get_type },
+  { "GtkTextView", gtk_text_view_get_type },
+  { "GtkToggleAction", gtk_toggle_action_get_type },
+  { "GtkToggleButton", gtk_toggle_button_get_type },
+  { "GtkToolbar", gtk_toolbar_get_type },
+  { "GtkTreeStore", gtk_tree_store_get_type },
+  { "GtkTreeView", gtk_tree_view_get_type },
+  { "GtkTable", gtk_table_get_type },
+  { "GtkVBox", gtk_vbox_get_type },
+  { "GtkVButtonBox", gtk_vbutton_box_get_type },
+  { "GtkVScrollbar", gtk_vscrollbar_get_type },
+  { "GtkVSeparator", gtk_vseparator_get_type },
+  { "GtkViewport", gtk_viewport_get_type },
+  { "GtkVRuler", gtk_vruler_get_type },
+  { "GtkVPaned", gtk_vpaned_get_type },
+  { "GtkVScale", gtk_vscale_get_type },
+  { "GtkWindow", gtk_window_get_type },
+  { "GtkUIManager", gtk_ui_manager_get_type },
+
+  /* Widget supported by libglade that are not deprecated
+   * Needs testing before we can enable them
+   */
+#if 0
+  { "GtkAboutDialog", gtk_about_dialog_get_type },
+  { "GtkAccelLabel", gtk_accel_label_get_type },
+  { "GtkAspectFrame", gtk_aspect_frame_get_type },
+  { "GtkCalendar", gtk_calendar_get_type },
+  { "GtkColorButton", gtk_color_button_get_type },
+  { "GtkColorSelection", gtk_color_selection_get_type },
+  { "GtkColorSelectionDialog", gtk_color_selection_dialog_get_type },
+  { "GtkComboBox", gtk_combo_box_get_type },
+  { "GtkComboBoxEntry", gtk_combo_box_entry_get_type },
+  { "GtkCurve", gtk_curve_get_type },
+  { "GtkFileChooser", gtk_file_chooser_get_type },
+  { "GtkFileChooserDialog", gtk_file_chooser_dialog_get_type },
+  { "GtkFileChooserButton", gtk_file_chooser_button_get_type },
+  { "GtkFileSelection", gtk_file_selection_get_type },
+  { "GtkFixed", gtk_fixed_get_type },
+  { "GtkFontSelection", gtk_font_selection_get_type },
+  { "GtkFontSelectionDialog", gtk_font_selection_dialog_get_type },
+  { "GtkFrame", gtk_frame_get_type },
+  { "GtkGammaCurve", gtk_gamma_curve_get_type },
+  { "GtkHandleBox", gtk_handle_box_get_type },
+  { "GtkIconView", gtk_icon_view_get_type },
+  { "GtkInputDialog", gtk_input_dialog_get_type },
+  { "GtkLayout", gtk_layout_get_type },
+  { "GtkMenu", gtk_menu_get_type },
+  { "GtkMessageDialog", gtk_message_dialog_get_type },
+#endif
+
+  /* New objects, that needs to be supported */
+#if 0
+  { "GtkAssistant", gtk_assistant_get_type },
+  { "GtkInputDialog ", gtk_GtkInputDialog _get_type },
+  { "GtkLinkButton", gtk_link_button_get_type },
+  { "GtkRadioAction", gtk_GtkRadioAction_get_type },
+  { "GtkPageSetupUnixDialog", gtk_page_setup_unix_dialog_get_type },
+  { "GtkPrintUnixDialog", gtk_print_unix_dialog_get_type },
+  { "GtkRecentChooserDialog", gtk_recent_chooser_dialog_get_type },
+  { "GtkTextBuffer", gtk_text_buffer_get_type },
+  { "GtkToggleAction", gtk_GtkToggleAction_get_type },
+  { "GtkTreeModelFilter", gtk_tree_model_filter_get_type },
+  { "GtkTreeModelSort", gtk_tree_model_sort_get_type },
+  { "GtkTreeViewColumn", gtk_tree_view_column_get_type },
+#endif  
+  { NULL, NULL }
+};
+
+GType
+gtk_lazy_type_from_name (const gchar *name)
+{
+  int i;
+  GType gtype;
+  
+  gtype = g_type_from_name (name);
+  if (gtype == G_TYPE_INVALID)
+    for (i = 0; infos[i].name; i++)
+      if (!strcmp (infos[i].name, name))
+	{
+	  gtype = infos[i].func();
+	  break;
+	}
+
+  return gtype;
+}
 
 #define __GTK_TYPE_UTILS_C__
 #include "gtkaliasdef.c"
Index: gtk/gtktypeutils.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktypeutils.h,v
retrieving revision 1.68
diff -u -d -p -r1.68 gtktypeutils.h
--- gtk/gtktypeutils.h	28 Nov 2004 07:02:27 -0000	1.68
+++ gtk/gtktypeutils.h	11 May 2006 00:01:56 -0000
@@ -230,6 +230,11 @@ struct _GtkTypeInfo
 #endif /* GTK_DISABLE_DEPRECATED */
 
 gpointer	gtk_type_class	(GtkType	 type);
+gboolean        gtk_set_value_from_string (GParamSpec *pspec,
+					   const gchar *string,
+					   GValue *value);
+GType           gtk_lazy_type_from_name   (const gchar    *name);
+
 
 #ifndef GTK_DISABLE_DEPRECATED
 
Index: gtk/gtkuimanager.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkuimanager.c,v
retrieving revision 1.100
diff -u -d -p -r1.100 gtkuimanager.c
--- gtk/gtkuimanager.c	8 May 2006 16:21:02 -0000	1.100
+++ gtk/gtkuimanager.c	11 May 2006 00:01:56 -0000
@@ -31,6 +31,7 @@
 #include <config.h>
 
 #include <string.h>
+#include "gtkbuildable.h"
 #include "gtkintl.h"
 #include "gtkmarshalers.h"
 #include "gtkmenu.h"
@@ -142,6 +143,23 @@ static void        node_prepend_ui_refer
 static void        node_remove_ui_reference       (GNode             *node,
                                                    guint              merge_id);
 
+/* GtkBuildable */
+static void gtk_ui_manager_buildable_init (GtkBuildableIface *iface);
+static void gtk_ui_manager_buildable_add (GtkBuildable  *buildable,
+					  GObject       *child,
+					  const gchar   *type);
+static GObject* gtk_ui_manager_buildable_construct_child (GtkBuildable *buildable,
+							  const gchar  *name);
+static gboolean gtk_ui_manager_buildable_custom_tag_start (GtkBuildable *buildable,
+							   const gchar  *tagname,
+							   GMarkupParser *parser,
+							   gpointer     *data);
+static void     gtk_ui_manager_buildable_custom_tag_end (GtkBuildable        *buildable,
+							 GtkBuilder          *builder,
+							 const gchar         *tagname,
+							 gpointer             data);
+
+
 
 enum 
 {
@@ -161,9 +179,12 @@ enum
   PROP_UI
 };
 
+static GtkBuildableIface *parent_buildable_iface;
 static guint ui_manager_signals[LAST_SIGNAL] = { 0 };
 
-G_DEFINE_TYPE (GtkUIManager, gtk_ui_manager, G_TYPE_OBJECT);
+G_DEFINE_TYPE_WITH_CODE (GtkUIManager, gtk_ui_manager, GTK_TYPE_OBJECT,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_ui_manager_buildable_init));
 
 static void
 gtk_ui_manager_class_init (GtkUIManagerClass *klass)
@@ -401,6 +422,50 @@ gtk_ui_manager_finalize (GObject *object
 }
 
 static void
+gtk_ui_manager_buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->add = gtk_ui_manager_buildable_add;
+  iface->construct_child = gtk_ui_manager_buildable_construct_child;
+  iface->custom_tag_start = gtk_ui_manager_buildable_custom_tag_start;
+  iface->custom_tag_end = gtk_ui_manager_buildable_custom_tag_end;
+}
+
+static void
+gtk_ui_manager_buildable_add (GtkBuildable  *buildable,
+			      GObject       *child,
+			      const gchar   *type)
+{
+  GtkUIManager *self = GTK_UI_MANAGER (buildable);
+  guint pos;
+  
+  g_return_if_fail (GTK_IS_ACTION_GROUP (child));
+
+  pos = g_list_length (self->private_data->action_groups);
+
+  gtk_ui_manager_insert_action_group (self,
+				      GTK_ACTION_GROUP (child),
+				      pos);
+}
+
+static GObject *
+gtk_ui_manager_buildable_construct_child (GtkBuildable *buildable,
+					  const gchar  *id)
+{
+  GtkWidget *widget;
+  char *name;
+
+  name = g_strdup_printf ("ui/%s", id);
+  widget = gtk_ui_manager_get_widget (GTK_UI_MANAGER (buildable), name);
+  if (!widget)
+    g_error ("Unknown ui manager child: %s\n", name);
+
+  g_free (name);
+  
+  return G_OBJECT (widget);
+}
+
+static void
 gtk_ui_manager_set_property (GObject         *object,
 			     guint            prop_id,
 			     const GValue    *value,
@@ -1453,7 +1518,7 @@ add_ui_from_string (GtkUIManager *self,
 {
   ParseContext ctx = { 0 };
   GMarkupParseContext *context;
-
+  
   ctx.state = STATE_START;
   ctx.self = self;
   ctx.current = NULL;
@@ -1467,7 +1532,7 @@ add_ui_from_string (GtkUIManager *self,
 
   if (!g_markup_parse_context_parse (context, buffer, length, error))
     goto out;
-
+  
   if (needs_root)
     if (!g_markup_parse_context_parse (context, "</ui>", -1, error))
       goto out;
@@ -1479,7 +1544,7 @@ add_ui_from_string (GtkUIManager *self,
 
   queue_update (self);
 
-  g_object_notify (G_OBJECT (self), "ui");      
+  g_object_notify (G_OBJECT (self), "ui");
 
   return ctx.merge_id;
 
@@ -2770,6 +2835,43 @@ print_node (GtkUIManager *self,
     g_string_append_printf (buffer, close_fmt, indent_level, "");
 }
 
+static gboolean
+gtk_ui_manager_buildable_custom_tag_start (GtkBuildable *buildable,
+					   const gchar  *tagname,
+					   GMarkupParser *parser,
+					   gpointer     *data)
+{
+  if (!strcmp (tagname, "ui"))
+    {
+      ParseContext *ctx;
+
+      ctx = g_new0 (ParseContext, 1);
+      ctx->state = STATE_START;
+      ctx->self = GTK_UI_MANAGER (buildable);
+      ctx->current = NULL;
+      ctx->merge_id = gtk_ui_manager_new_merge_id (GTK_UI_MANAGER (buildable));
+      
+      *data = ctx;
+      *parser = ui_parser;
+
+      return TRUE;
+    }
+
+  return FALSE;
+
+}
+
+static void
+gtk_ui_manager_buildable_custom_tag_end (GtkBuildable        *buildable,
+					 GtkBuilder          *builder,
+					 const gchar         *tagname,
+					 gpointer             data)
+{
+  queue_update (GTK_UI_MANAGER (buildable));
+  g_object_notify (G_OBJECT (buildable), "ui");      
+  g_free (data);
+}
+
 /**
  * gtk_ui_manager_get_ui:
  * @self: a #GtkUIManager
@@ -2818,6 +2920,7 @@ gtk_ui_manager_add_ui_from_file (GtkUIMa
 }
 
 #endif
+
 
 #define __GTK_UI_MANAGER_C__
 #include "gtkaliasdef.c"
Index: gtk/gtkwidget.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.c,v
retrieving revision 1.436
diff -u -d -p -r1.436 gtkwidget.c
--- gtk/gtkwidget.c	10 May 2006 14:02:20 -0000	1.436
+++ gtk/gtkwidget.c	11 May 2006 00:02:14 -0000
@@ -52,6 +52,7 @@
 #include "gtkaccessible.h"
 #include "gtktooltips.h"
 #include "gtkinvisible.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 #define WIDGET_CLASS(w)	 GTK_WIDGET_GET_CLASS (w)
@@ -222,8 +223,11 @@ static void             gtk_widget_inval
 								 GdkRegion        *region);
 static GdkScreen *      gtk_widget_get_screen_unchecked         (GtkWidget        *widget);
 static void		gtk_widget_queue_shallow_draw		(GtkWidget        *widget);
-static gboolean         gtk_widget_real_can_activate_accel      (GtkWidget *widget,
-                                                                 guint      signal_id);
+static gboolean         gtk_widget_real_can_activate_accel      (GtkWidget        *widget,
+                                                                 guint             signal_id);
+static void             gtk_widget_buildable_interface_init     (GtkBuildableIface *iface);
+static void             gtk_widget_buildable_set_name           (GtkBuildable     *buildable,
+								 const gchar      *name);
      
 static void gtk_widget_set_usize_internal (GtkWidget *widget,
 					   gint       width,
@@ -260,7 +264,9 @@ GObjectNotifyContext   *_gtk_widget_chil
 /* --- functions --- */
 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GtkWidget, gtk_widget, GTK_TYPE_OBJECT,
 				  G_IMPLEMENT_INTERFACE (ATK_TYPE_IMPLEMENTOR,
-							 gtk_widget_accessible_interface_init));
+							 gtk_widget_accessible_interface_init)
+				  G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+							 gtk_widget_buildable_interface_init));
 
 static void
 child_property_notify_dispatcher (GObject     *object,
@@ -7746,6 +7752,19 @@ gtk_widget_ref_accessible (AtkImplemento
   if (accessible)
     g_object_ref (accessible);
   return accessible;
+}
+
+static void
+gtk_widget_buildable_interface_init (GtkBuildableIface *iface)
+{
+  iface->set_name = gtk_widget_buildable_set_name;
+}
+
+static void
+gtk_widget_buildable_set_name (GtkBuildable *buildable,
+			       const gchar  *name)
+{
+  gtk_widget_set_name (GTK_WIDGET (buildable), name);
 }
 
 /**
