diff --git a/gtk/gtkbuilder.c b/gtk/gtkbuilder.c
index 9aafaad..dcd8124 100644
--- a/gtk/gtkbuilder.c
+++ b/gtk/gtkbuilder.c
@@ -60,6 +60,7 @@ struct _GtkBuilderPrivate
 {
   gchar *domain;
   GHashTable *objects;
+  GHashTable *external_objects;
   GSList *delayed_properties;
   GSList *signals;
   gchar *filename;
@@ -109,6 +110,8 @@ gtk_builder_init (GtkBuilder *builder)
   builder->priv->domain = NULL;
   builder->priv->objects = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                   g_free, g_object_unref);
+  builder->priv->external_objects = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                           g_free, g_object_unref);
 }
 
 
@@ -125,6 +128,7 @@ gtk_builder_finalize (GObject *object)
   g_free (priv->filename);
   
   g_hash_table_destroy (priv->objects);
+  g_hash_table_destroy (priv->external_objects);
 
   g_slist_foreach (priv->signals, (GFunc) _free_signal_info, NULL);
   g_slist_free (priv->signals);
@@ -352,6 +356,9 @@ gtk_builder_get_internal_child (GtkBuilder  *builder,
           obj = gtk_buildable_get_internal_child (GTK_BUILDABLE (info->object),
                                                   builder,
                                                   childname);
+      if (!obj && GTK_IS_CONTAINER (info->object))
+	obj = (GObject *)gtk_container_get_composite_child (GTK_CONTAINER (info->object), childname);
+
     };
 
   if (!obj)
@@ -671,7 +678,64 @@ gtk_builder_add_from_file (GtkBuilder   *builder,
   g_free (builder->priv->filename);
   builder->priv->filename = g_strdup (filename);
 
-  _gtk_builder_parser_parse_buffer (builder, filename,
+  _gtk_builder_parser_parse_buffer (builder, NULL, filename,
+                                    buffer, length,
+                                    NULL,
+                                    &tmp_error);
+
+  g_free (buffer);
+
+  if (tmp_error != NULL)
+    {
+      g_propagate_error (error, tmp_error);
+      return 0;
+    }
+
+  return 1;
+}
+
+/**
+ * gtk_builder_add_to_parent_from_file:
+ * @builder: a #GtkBuilder
+ * @parent: the parent object to be assumed in context while parsing the file
+ * @filename: the name of the file to parse
+ * @error: (allow-none): return location for an error, or %NULL
+ *
+ * Like gtk_builder_add_from_file() except the format will expect
+ * <child> instead of <object> as its first elements and expose
+ * @parent in the build context, children defined in the UI fragment
+ * will be added to @parent.
+ * 
+ * Returns: A positive value on success, 0 if an error occurred
+ *
+ * Since: ...
+ **/
+guint
+gtk_builder_add_to_parent_from_file (GtkBuilder   *builder,
+				     GObject      *parent,
+				     const gchar  *filename,
+				     GError      **error)
+{
+  gchar *buffer;
+  gsize length;
+  GError *tmp_error;
+
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
+  g_return_val_if_fail (filename != NULL, 0);
+  g_return_val_if_fail (error == NULL || *error == NULL, 0);
+
+  tmp_error = NULL;
+
+  if (!g_file_get_contents (filename, &buffer, &length, &tmp_error))
+    {
+      g_propagate_error (error, tmp_error);
+      return 0;
+    }
+  
+  g_free (builder->priv->filename);
+  builder->priv->filename = g_strdup (filename);
+
+  _gtk_builder_parser_parse_buffer (builder, parent, filename,
                                     buffer, length,
                                     NULL,
                                     &tmp_error);
@@ -734,7 +798,7 @@ gtk_builder_add_objects_from_file (GtkBuilder   *builder,
   g_free (builder->priv->filename);
   builder->priv->filename = g_strdup (filename);
 
-  _gtk_builder_parser_parse_buffer (builder, filename,
+  _gtk_builder_parser_parse_buffer (builder, NULL, filename,
                                     buffer, length,
                                     object_ids,
                                     &tmp_error);
@@ -781,7 +845,56 @@ gtk_builder_add_from_string (GtkBuilder   *builder,
   g_free (builder->priv->filename);
   builder->priv->filename = g_strdup (".");
 
-  _gtk_builder_parser_parse_buffer (builder, "<input>",
+  _gtk_builder_parser_parse_buffer (builder, NULL, "<input>",
+                                    buffer, length,
+                                    NULL,
+                                    &tmp_error);
+  if (tmp_error != NULL)
+    {
+      g_propagate_error (error, tmp_error);
+      return 0;
+    }
+
+  return 1;
+}
+
+
+/**
+ * gtk_builder_add_to_parent_from_string:
+ * @builder: a #GtkBuilder
+ * @parent: the parent object to be assumed in context while parsing
+ * @buffer: the string to parse
+ * @length: the length of @buffer (may be -1 if @buffer is nul-terminated)
+ * @error: (allow-none): return location for an error, or %NULL
+ *
+ * Like gtk_builder_add_from_string() except the format will expect
+ * <child> instead of <object> as its first elements and expose
+ * @parent in the build context, children defined in the UI fragment
+ * will be added to @parent.
+ * 
+ * Returns: A positive value on success, 0 if an error occurred
+ *
+ * Since: ...
+ **/
+guint
+gtk_builder_add_to_parent_from_string (GtkBuilder   *builder,
+				       GObject      *parent,
+				       const gchar  *buffer,
+				       gsize         length,
+				       GError      **error)
+{
+  GError *tmp_error;
+
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
+  g_return_val_if_fail (buffer != NULL, 0);
+  g_return_val_if_fail (error == NULL || *error == NULL, 0);
+
+  tmp_error = NULL;
+
+  g_free (builder->priv->filename);
+  builder->priv->filename = g_strdup (".");
+
+  _gtk_builder_parser_parse_buffer (builder, parent, "<input>",
                                     buffer, length,
                                     NULL,
                                     &tmp_error);
@@ -835,7 +948,7 @@ gtk_builder_add_objects_from_string (GtkBuilder   *builder,
   g_free (builder->priv->filename);
   builder->priv->filename = g_strdup (".");
 
-  _gtk_builder_parser_parse_buffer (builder, "<input>",
+  _gtk_builder_parser_parse_buffer (builder, NULL, "<input>",
                                     buffer, length,
                                     object_ids,
                                     &tmp_error);
@@ -955,6 +1068,16 @@ typedef struct {
   gpointer data;
 } connect_args;
 
+
+void         
+gtk_builder_expose_object (GtkBuilder    *builder,
+	        	   const gchar   *symbol_name,
+			   gpointer       user_data)
+{
+  g_hash_table_insert (builder->priv->external_objects, g_strdup (symbol_name), user_data);
+}
+
+
 static void
 gtk_builder_connect_signals_default (GtkBuilder    *builder,
 				     GObject       *object,
@@ -979,7 +1102,6 @@ gtk_builder_connect_signals_default (GtkBuilder    *builder,
     g_signal_connect_data (object, signal_name, func, args->data, NULL, flags);
 }
 
-
 /**
  * gtk_builder_connect_signals:
  * @builder: a #GtkBuilder
@@ -1064,6 +1186,7 @@ gtk_builder_connect_signals_full (GtkBuilder            *builder,
   GSList *l;
   GObject *object;
   GObject *connect_object;
+  void *connect_data;
   
   g_return_if_fail (GTK_IS_BUILDER (builder));
   g_return_if_fail (func != NULL);
@@ -1084,19 +1207,40 @@ gtk_builder_connect_signals_full (GtkBuilder            *builder,
       g_assert (object != NULL);
 
       connect_object = NULL;
+      connect_data = NULL;
       
       if (signal->connect_object_name)
 	{
-	  connect_object = g_hash_table_lookup (builder->priv->objects,
-						signal->connect_object_name);
-	  if (!connect_object)
-	      g_warning ("Could not lookup object %s on signal %s of object %s",
-			 signal->connect_object_name, signal->name,
-			 signal->object_name);
-	}
-						  
-      func (builder, object, signal->name, signal->handler, 
-	    connect_object, signal->flags, user_data);
+          if (signal->external)
+            {
+               connect_data = g_hash_table_lookup (builder->priv->external_objects,
+		  		                   signal->connect_object_name);
+               if (!connect_data)
+                 {
+                   g_warning ("External %s source not exposed!\n", signal->connect_object_name);
+                 } else {
+                   /*connect_args *args = (connect_args *)user_data;
+                   args->data = connect_data;
+                   gtk_builder_connect_signals_data (builder, object, signal->name, signal->handler, 
+                                      	             signal->flags, args);*/
+		   g_object_ref(connect_data);
+                   func (builder, object, signal->name, signal->handler, 
+              	         connect_data, signal->flags, user_data);
+                 }
+            } else {
+              connect_object = g_hash_table_lookup (builder->priv->objects,
+						    signal->connect_object_name);
+              if (!connect_object)
+                g_warning ("Could not lookup object %s on signal %s of object %s.",
+  			            signal->connect_object_name, signal->name,
+			            signal->object_name);
+            }
+        }						  
+      if (connect_data == NULL)
+        {
+          func (builder, object, signal->name, signal->handler, 
+              	connect_object, signal->flags, user_data);
+        }
     }
 
   g_slist_foreach (builder->priv->signals, (GFunc)_free_signal_info, NULL);
diff --git a/gtk/gtkbuilder.h b/gtk/gtkbuilder.h
index 0f9224e..5e5b151 100644
--- a/gtk/gtkbuilder.h
+++ b/gtk/gtkbuilder.h
@@ -110,9 +110,21 @@ guint        gtk_builder_add_objects_from_string (GtkBuilder    *builder,
                                                   gsize          length,
                                                   gchar        **object_ids,
                                                   GError       **error);
+guint        gtk_builder_add_to_parent_from_file (GtkBuilder   *builder,
+						  GObject      *parent,
+						  const gchar  *filename,
+						  GError      **error);
+guint        gtk_builder_add_to_parent_from_string (GtkBuilder   *builder,
+						    GObject      *parent,
+						    const gchar  *buffer,
+						    gsize         length,
+						    GError      **error);
 GObject*     gtk_builder_get_object              (GtkBuilder    *builder,
                                                   const gchar   *name);
 GSList*      gtk_builder_get_objects             (GtkBuilder    *builder);
+void         gtk_builder_expose_object           (GtkBuilder    *builder,
+						  const gchar   *name,
+						  gpointer       user_data);
 void         gtk_builder_connect_signals         (GtkBuilder    *builder,
 						  gpointer       user_data);
 void         gtk_builder_connect_signals_full    (GtkBuilder    *builder,
diff --git a/gtk/gtkbuilderparser.c b/gtk/gtkbuilderparser.c
index b4f6855..52a5635 100644
--- a/gtk/gtkbuilderparser.c
+++ b/gtk/gtkbuilderparser.c
@@ -437,6 +437,7 @@ parse_child (ParserData   *data,
 {
   ObjectInfo* object_info;
   ChildInfo *child_info;
+  GObject  *object;
   guint i;
 
   object_info = state_peek_info (data, ObjectInfo);
@@ -461,7 +462,8 @@ parse_child (ParserData   *data,
 
   child_info->parent = (CommonInfo*)object_info;
 
-  object_info->object = builder_construct (data, object_info, error);
+  object = builder_construct (data, object_info, error);
+  object_info->object = object;
 }
 
 static void
@@ -556,6 +558,7 @@ parse_signal (ParserData   *data,
   gboolean after = FALSE;
   gboolean swapped = FALSE;
   gboolean swapped_set = FALSE;
+  gboolean external = FALSE;
   ObjectInfo *object_info;
   int i;
 
@@ -583,6 +586,11 @@ parse_signal (ParserData   *data,
 	    return;
 	  swapped_set = TRUE;
 	}
+      else if (strcmp (names[i], "external") == 0)
+	{
+	  if (!_gtk_builder_boolean_from_string (values[i], &external, error))
+	    return;
+	}
       else if (strcmp (names[i], "object") == 0)
         object = g_strdup (values[i]);
       else if (strcmp (names[i], "last_modification_time") == 0)
@@ -617,6 +625,7 @@ parse_signal (ParserData   *data,
     info->flags |= G_CONNECT_AFTER;
   if (swapped)
     info->flags |= G_CONNECT_SWAPPED;
+  info->external = external;
   info->connect_object_name = object;
   state_push (data, info);
 
@@ -1113,6 +1122,7 @@ static const GMarkupParser parser = {
 
 void
 _gtk_builder_parser_parse_buffer (GtkBuilder   *builder,
+				  GObject      *parent,
                                   const gchar  *filename,
                                   const gchar  *buffer,
                                   gsize         length,
@@ -1137,6 +1147,19 @@ _gtk_builder_parser_parse_buffer (GtkBuilder   *builder,
   data->object_ids = g_hash_table_new_full (g_str_hash, g_str_equal,
 					    (GDestroyNotify)g_free, NULL);
 
+  if (parent)
+    {
+      ObjectInfo *object_info = g_slice_new0 (ObjectInfo);
+
+
+      GTK_NOTE (BUILDER, g_print ("parsing with contextual parent info ptr %p\n", object_info));
+
+      object_info->object = parent;
+      object_info->id = g_strdup ("__container");
+      state_push (data, object_info);
+      object_info->tag.name = "object";
+    }
+
   data->requested_objects = NULL;
   if (requested_objs)
     {
diff --git a/gtk/gtkbuilderprivate.h b/gtk/gtkbuilderprivate.h
index e633a28..7fbb2b3 100644
--- a/gtk/gtkbuilderprivate.h
+++ b/gtk/gtkbuilderprivate.h
@@ -66,6 +66,7 @@ typedef struct {
   gchar *object_name;
   gchar *name;
   gchar *handler;
+  gboolean external;
   GConnectFlags flags;
   gchar *connect_object_name;
 } SignalInfo;
@@ -109,6 +110,7 @@ typedef GType (*GTypeGetFunc) (void);
 
 /* Things only GtkBuilder should use */
 void _gtk_builder_parser_parse_buffer (GtkBuilder *builder,
+				       GObject     *parent,
                                        const gchar *filename,
                                        const gchar *buffer,
                                        gsize length,
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index 6bedc86..abed747 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -67,6 +67,9 @@ static void     gtk_container_base_class_init      (GtkContainerClass *klass);
 static void     gtk_container_base_class_finalize  (GtkContainerClass *klass);
 static void     gtk_container_class_init           (GtkContainerClass *klass);
 static void     gtk_container_init                 (GtkContainer      *container);
+static GObject *gtk_container_constructor          (GType                  type,
+						    guint                  n_construct_properties,
+						    GObjectConstructParam *construct_properties);
 static void     gtk_container_destroy              (GtkObject         *object);
 static void     gtk_container_set_property         (GObject         *object,
 						    guint            prop_id,
@@ -181,6 +184,9 @@ gtk_container_base_class_init (GtkContainerClass *class)
   /* reset instance specifc class fields that don't get inherited */
   class->set_child_property = NULL;
   class->get_child_property = NULL;
+  class->template           = NULL;
+  class->template_file      = NULL;
+  class->connect_func       = NULL;
 }
 
 static void
@@ -198,6 +204,9 @@ gtk_container_base_class_finalize (GtkContainerClass *class)
       g_param_spec_unref (pspec);
     }
   g_list_free (list);
+
+  g_free (class->template);
+  g_free (class->template_file);
 }
 
 static void
@@ -212,6 +221,7 @@ gtk_container_class_init (GtkContainerClass *class)
   vadjustment_key_id = g_quark_from_static_string (vadjustment_key);
   hadjustment_key_id = g_quark_from_static_string (hadjustment_key);
   
+  gobject_class->constructor  = gtk_container_constructor;
   gobject_class->set_property = gtk_container_set_property;
   gobject_class->get_property = gtk_container_get_property;
 
@@ -1025,6 +1035,128 @@ gtk_container_class_list_child_properties (GObjectClass *cclass,
   return pspecs;
 }
 
+/**
+ * gtk_container_get_composite_child:
+ * @container: a #GtkContainer
+ * @composite_name: the name of a composite child as defined by installation of a #GtkParamSpecComposite property
+ *
+ * Retrieves a composite child by name by checking installed composite typed properties.
+ * 
+ * Returns: the composite child of @container with the name @composite_name
+ */
+GtkWidget *
+gtk_container_get_composite_child (GtkContainer *container,
+				   const gchar  *composite_name)
+{
+  GParamSpec   **pspecs;
+  guint          n_pspecs = 0, i;
+  GtkWidget     *composite_child = NULL;
+
+  g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL);
+  g_return_val_if_fail (composite_name && composite_name[0], NULL);
+
+  pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (container), &n_pspecs);
+  for (i = 0; i < n_pspecs; i++)
+    {
+      if (strcmp (pspecs[i]->name, composite_name) == 0)
+	{
+	  if (GTK_IS_PARAM_SPEC_COMPOSITE (pspecs[i]))
+	    {
+	      g_object_get (G_OBJECT (container), 
+			    composite_name, &composite_child, 
+			    NULL);
+
+	      if (composite_child)
+		g_object_unref (composite_child);
+	      else
+		g_warning ("Failed to get composite child named %s for type %s",
+			   composite_name, G_OBJECT_TYPE_NAME (container));
+	      
+	    }
+
+	  break;
+	}
+    }
+  g_free (pspecs);
+
+  return composite_child;
+}
+
+/**
+ * gtk_container_class_set_template:
+ * @container_class: a #GtkContainerClass
+ * @template: the #GtkBuilder xml fragment used to build children
+ *
+ * This is used when implementing new composite widget types
+ * to setup a UI template for instances of this type.
+ *
+ * The provided xml fragment is expected to start with <child>
+ * instead of <object> and will be parsed with a fresh instance
+ * of the implementing composite widget type in context as the 
+ * parent container.
+ * 
+ */
+void
+gtk_container_class_set_template (GtkContainerClass *container_class,
+				  const gchar       *template)
+{
+  g_return_if_fail (GTK_IS_CONTAINER_CLASS(container_class));
+  g_return_if_fail (template && template[0]);
+
+  if (container_class->template)
+    g_free (container_class->template);
+
+  container_class->template = g_strdup (template);
+
+  if (container_class->template_file)
+    container_class->template_file =
+      (g_free (container_class->template_file), NULL);
+}
+
+
+/**
+ * gtk_container_class_set_template_file:
+ * @container_class: a #GtkContainerClass
+ * @template_file: the #GtkBuilder xml file used to build children
+ *
+ * Sets a file to be used as this class's template; see gtk_container_class_set_template().
+ * 
+ */
+void
+gtk_container_class_set_template_file (GtkContainerClass *container_class,
+				       const gchar       *template_file)
+{
+  g_return_if_fail (GTK_IS_CONTAINER_CLASS(container_class));
+  g_return_if_fail (template_file && template_file[0]);
+
+  if (container_class->template_file)
+    g_free (container_class->template_file);
+
+  container_class->template_file = g_strdup (template_file);
+
+  if (container_class->template)
+    container_class->template =
+      (g_free (container_class->template), NULL);
+}
+
+/**
+ * gtk_container_class_set_connect_func:
+ * @container_class: a #GtkContainerClass
+ * @connect_func: the #GtkBuilderConnectFunc to use when connecting signals internally.
+ *
+ * Sets the function to be used when automatically connecting signals
+ * defined by this class's GtkBuilder template.
+ */
+void
+gtk_container_class_set_connect_func    (GtkContainerClass *container_class,
+					 GtkBuilderConnectFunc connect_func)
+{
+  g_return_if_fail (GTK_IS_CONTAINER_CLASS(container_class));
+  g_return_if_fail (connect_func != NULL);
+
+  container_class->connect_func = connect_func;
+}
+
 static void
 gtk_container_add_unimplemented (GtkContainer     *container,
 				 GtkWidget        *widget)
@@ -1068,6 +1200,95 @@ gtk_container_destroy (GtkObject *object)
   GTK_OBJECT_CLASS (parent_class)->destroy (object);
 }
 
+static GObject *
+gtk_container_constructor (GType                  type,
+			   guint                  n_construct_properties,
+			   GObjectConstructParam *construct_properties)
+{
+  GtkBuilder    *builder;
+  GParamSpec   **pspecs;
+  GError        *error = NULL;
+  guint          ret = 0, n_pspecs = 0, i;
+  GObject       *ret_obj;
+  GtkContainer  *container;
+  GObjectClass  *oclass;
+  GSList        *classes = NULL, *l;
+  
+  ret_obj = G_OBJECT_CLASS (parent_class)->constructor
+    (type, n_construct_properties, construct_properties);
+  
+  container = GTK_CONTAINER (ret_obj);
+
+  /* Collect an ordered list of class which have templates to build */
+  for (oclass = G_OBJECT_GET_CLASS (container);
+       GTK_IS_CONTAINER_CLASS (oclass);
+       oclass = g_type_class_peek_parent (oclass))
+    {
+
+      if (GTK_CONTAINER_CLASS (oclass)->template ||
+	  GTK_CONTAINER_CLASS (oclass)->template_file)
+	classes = g_slist_prepend (classes, oclass);
+    }
+
+  /* Build the templates for each class starting with the superclass descending */
+  for (l = classes; l; l = l->next)
+    {
+      GtkContainerClass *cclass = l->data;
+
+      builder = gtk_builder_new ();
+      gtk_builder_expose_object (builder, "container", container);
+      
+      if (cclass->template)
+	ret = gtk_builder_add_to_parent_from_string (builder, ret_obj, 
+						     cclass->template, -1, &error);
+      else
+	ret = gtk_builder_add_to_parent_from_file (builder, ret_obj, 
+						   cclass->template_file, &error);
+      
+      if (!ret)
+	{
+	  g_critical ("Unable to build GtkContainer class %s from template: %s", 
+		      G_OBJECT_TYPE_NAME (container),
+		      error->message);
+	  g_error_free (error);
+	  g_object_unref (builder);
+	  
+	  return ret_obj;
+	}
+      
+      pspecs = g_object_class_list_properties (G_OBJECT_CLASS (cclass), &n_pspecs);
+      for (i = 0; i < n_pspecs; i++)
+	{
+	  if (GTK_IS_PARAM_SPEC_COMPOSITE (pspecs[i]) &&
+	      pspecs[i]->owner_type == G_OBJECT_CLASS_TYPE (cclass))
+	    {
+	      GObject *composite_child;
+	      
+	      if ((composite_child = 
+		   gtk_builder_get_object (builder, (pspecs[i])->name)) != NULL)
+		{
+		  /* Let GObject fire a warning if there is an object type mismatch */
+		  g_object_set (container, (pspecs[i])->name, composite_child, NULL);
+		}
+	      else
+		g_critical ("Expected internal child %s not found for container class %s",
+			    (pspecs[i])->name, G_OBJECT_TYPE_NAME (container));
+	    }
+	}
+      g_free (pspecs);
+      
+      if (cclass->connect_func)
+	gtk_builder_connect_signals_full (builder, GTK_CONTAINER_GET_CLASS (container)->connect_func, container);
+      else
+	gtk_builder_connect_signals (builder, container);
+      
+      g_object_unref (builder);
+    }
+  g_slist_free (classes);
+
+  return ret_obj;
+}
+
 static void
 gtk_container_set_property (GObject         *object,
 			    guint            prop_id,
@@ -2739,5 +2960,113 @@ gtk_container_propagate_expose (GtkContainer   *container,
     }
 }
 
+/*    ---------- Declaration of GtkParamSpecComposite
+ */
+static void
+param_composite_init (GParamSpec *pspec)
+{
+  /* GtkParamSpecComposite *ospec = GTK_PARAM_SPEC_COMPOSITE (pspec); */
+}
+
+static void
+param_composite_set_default (GParamSpec *pspec,
+			  GValue     *value)
+{
+  value->data[0].v_pointer = NULL;
+}
+
+static gboolean
+param_composite_validate (GParamSpec *pspec,
+			  GValue     *value)
+{
+  GtkParamSpecComposite *ospec = GTK_PARAM_SPEC_COMPOSITE (pspec);
+  GObject               *object = value->data[0].v_pointer;
+  guint changed = 0;
+  
+  if (object && !g_value_type_compatible (G_OBJECT_TYPE (object), G_PARAM_SPEC_VALUE_TYPE (ospec)))
+    {
+      g_object_unref (object);
+      value->data[0].v_pointer = NULL;
+      changed++;
+    }
+  
+  return changed;
+}
+
+static gint
+param_composite_values_cmp (GParamSpec   *pspec,
+			    const GValue *value1,
+			    const GValue *value2)
+{
+  guint8 *p1 = value1->data[0].v_pointer;
+  guint8 *p2 = value2->data[0].v_pointer;
+
+  /* not much to compare here, try to at least provide stable lesser/greater result */
+
+  return p1 < p2 ? -1 : p1 > p2;
+}
+
+GType 
+gtk_param_composite_get_type (void)
+{
+  static GType composite_type = 0;
+
+  if (composite_type == 0)
+    {
+      static const GParamSpecTypeInfo pspec_info = {
+	sizeof (GtkParamSpecComposite), /* instance_size */
+	16,                        /* n_preallocs */
+	param_composite_init,	 /* instance_init */
+	G_TYPE_OBJECT,		 /* value_type */
+	NULL,			 /* finalize */
+	param_composite_set_default,	 /* value_set_default */
+	param_composite_validate,	 /* value_validate */
+	param_composite_values_cmp,	 /* values_cmp */
+      };
+      composite_type = 
+	g_param_type_register_static (g_intern_static_string ("GtkParamComposite"), &pspec_info);
+    }      
+  return composite_type;
+}
+
+/**
+ * gtk_param_spec_composite:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @object_type: %G_TYPE_OBJECT derived type of this property
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GtkParamSpecComposite instance specifying a %G_TYPE_OBJECT
+ * derived property, these work exactly the same as #GParamSpecObject properties
+ * except that #GtkContainer will automatically assign all properties defined
+ * as composite object properties to instances built from the composite derived
+ * class's #GtkBuilder UI template.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: a newly created parameter specification
+ */
+GParamSpec*
+gtk_param_spec_composite (const gchar *name,
+			  const gchar *nick,
+			  const gchar *blurb,
+			  GType	  object_type,
+			  GParamFlags  flags)
+{
+  GParamSpecObject *ospec;
+  
+  g_return_val_if_fail (g_type_is_a (object_type, G_TYPE_OBJECT), NULL);
+  
+  ospec = g_param_spec_internal (GTK_TYPE_PARAM_COMPOSITE,
+				 name,
+				 nick,
+				 blurb,
+				 flags);
+  G_PARAM_SPEC (ospec)->value_type = object_type;
+  
+  return G_PARAM_SPEC (ospec);
+}
+
 #define __GTK_CONTAINER_C__
 #include "gtkaliasdef.c"
diff --git a/gtk/gtkcontainer.h b/gtk/gtkcontainer.h
index 0bf30b9..a4984a3 100644
--- a/gtk/gtkcontainer.h
+++ b/gtk/gtkcontainer.h
@@ -34,10 +34,38 @@
 
 #include <gtk/gtkwidget.h>
 #include <gtk/gtkadjustment.h>
+#include <gtk/gtkbuilder.h>
 
 
 G_BEGIN_DECLS
 
+/**
+ * GTK_TYPE_PARAM_COMPOSITE:
+ * 
+ * The #GType of #GtkParamSpecComposite.
+ */
+#define	GTK_TYPE_PARAM_COMPOSITE   (gtk_param_composite_get_type())
+
+/**
+ * GTK_IS_PARAM_SPEC_COMPOSITE:
+ * @pspec: a valid #GParamSpec instance
+ * 
+ * Checks whether the given #GParamSpec is of type %GTK_TYPE_PARAM_COMPOSITE.
+ * 
+ * Returns: %TRUE on success.
+ */
+#define GTK_IS_PARAM_SPEC_COMPOSITE(pspec)				\
+  (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GTK_TYPE_PARAM_COMPOSITE))
+
+/**
+ * GTK_PARAM_SPEC_COMPOSITE:
+ * @pspec: a valid #GParamSpec instance
+ * 
+ * Casts a #GParamSpec instance into a #GtkParamSpecComposite.
+ */
+#define GTK_PARAM_SPEC_COMPOSITE(pspec)					\
+  (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GTK_TYPE_PARAM_COMPOSITE, GtkParamSpecComposite))
+
 #define GTK_TYPE_CONTAINER              (gtk_container_get_type ())
 #define GTK_CONTAINER(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CONTAINER, GtkContainer))
 #define GTK_CONTAINER_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_CONTAINER, GtkContainerClass))
@@ -48,8 +76,20 @@ G_BEGIN_DECLS
 #define GTK_IS_RESIZE_CONTAINER(widget) (GTK_IS_CONTAINER (widget) && ((GtkContainer*) (widget))->resize_mode != GTK_RESIZE_PARENT)
 
 
-typedef struct _GtkContainer	   GtkContainer;
-typedef struct _GtkContainerClass  GtkContainerClass;
+typedef struct _GtkContainer	      GtkContainer;
+typedef struct _GtkContainerClass     GtkContainerClass;
+typedef struct _GtkParamSpecComposite GtkParamSpecComposite;
+
+/**
+ * GtkParamSpecComposite:
+ * @parent_instance: private #GParamSpec portion
+ * 
+ * A #GParamSpec derived structure that contains the meta data for composite child object properties.
+ */
+struct _GtkParamSpecComposite
+{
+  GParamSpec    parent_instance;
+};
 
 struct _GtkContainer
 {
@@ -95,15 +135,23 @@ struct _GtkContainerClass
 				 GValue          *value,
 				 GParamSpec      *pspec);
 
+  gchar *GSEAL (template);
+  gchar *GSEAL (template_file);
+  GtkBuilderConnectFunc GSEAL (connect_func);
+
   /* Padding for future expansion */
   void (*_gtk_reserved1) (void);
-  void (*_gtk_reserved2) (void);
-  void (*_gtk_reserved3) (void);
-  void (*_gtk_reserved4) (void);
 };
 
 /* Application-level methods */
 
+GType       gtk_param_composite_get_type     (void) G_GNUC_CONST;
+GParamSpec *gtk_param_spec_composite         (const gchar	 *name,
+					      const gchar	 *nick,
+					      const gchar	 *blurb,
+					      GType		  object_type,
+					      GParamFlags	  flags);
+
 GType   gtk_container_get_type		 (void) G_GNUC_CONST;
 void    gtk_container_set_border_width	 (GtkContainer	   *container,
 					  guint		    border_width);
@@ -209,6 +257,17 @@ void    gtk_container_forall		     (GtkContainer *container,
 					      GtkCallback   callback,
 					      gpointer	    callback_data);
 
+GtkWidget *gtk_container_get_composite_child     (GtkContainer *container,
+						  const gchar  *composite_name);
+
+/* Class-level functions */
+void     gtk_container_class_set_template        (GtkContainerClass *container_class,
+						  const gchar       *template);
+void     gtk_container_class_set_template_file   (GtkContainerClass *container_class,
+						  const gchar       *template_file);
+void     gtk_container_class_set_connect_func    (GtkContainerClass *container_class,
+						  GtkBuilderConnectFunc connect_func);
+
 /* Non-public methods */
 void	_gtk_container_queue_resize	     (GtkContainer *container);
 void    _gtk_container_clear_resize_widgets   (GtkContainer *container);
