Index: configure.in
===================================================================
--- configure.in	(revision 633)
+++ configure.in	(working copy)
@@ -265,6 +265,7 @@
 AC_CONFIG_FILES([
   tests/Makefile
     tests/glibmm_value/Makefile
+    tests/glibmm_tree/Makefile
 
   examples/Makefile
     examples/markup/Makefile
Index: tests/glibmm_tree/main.cc
===================================================================
--- tests/glibmm_tree/main.cc	(revision 0)
+++ tests/glibmm_tree/main.cc	(revision 0)
@@ -0,0 +1,87 @@
+#include <iostream>
+
+#include <glibmm.h>
+
+using namespace std;
+using namespace Glib;
+
+gboolean echo(Tree::iterator i, gpointer data)
+{
+  cout << *((string*)(i->data)) << ' ';
+  return false;
+}
+
+
+int main()
+{
+  string *a = new string("a"),
+         *b = new string("b"),
+	 *c = new string("c"),
+	 *d = new string("d"),
+	 *e = new string("e"),
+	 *f = new string("f");
+
+  Tree ta(a),
+       tb(b),
+       tc(c),
+       te(e);
+
+
+  ta.insert(0, tc);
+  ta.prepend(tb);
+  ta.append_data(d);
+  tc.append(te);
+  te.prepend_data(f);
+
+  cout << "Breadth-first:" << endl;
+  ta.traverse(LEVEL_ORDER, TRAVERSE_LEAVES | TRAVERSE_NON_LEAVES, INT_MAX, echo, NULL);
+  cout << endl;
+
+  cout << "Depth-first (pre):" << endl;
+  ta.traverse(PRE_ORDER, TRAVERSE_LEAVES | TRAVERSE_NON_LEAVES, INT_MAX, echo, NULL);
+  cout << endl;
+
+  cout << "Depth-first (in):" << endl;
+  ta.traverse(IN_ORDER, TRAVERSE_LEAVES | TRAVERSE_NON_LEAVES, INT_MAX, echo, NULL);
+  cout << endl;
+
+  cout << "Depth-first (post):" << endl;
+  ta.traverse(POST_ORDER, TRAVERSE_LEAVES | TRAVERSE_NON_LEAVES, INT_MAX, echo, NULL);
+  cout << endl;
+
+  Tree *tmp = ta.find(IN_ORDER, TRAVERSE_LEAVES | TRAVERSE_NON_LEAVES, e);
+  if(NULL == tmp){ cout << *e << " not found" << endl; }
+  else{ cout << "Found " << *((string*)(tmp->data())) << endl; }
+
+  tmp = ta.find(IN_ORDER, TRAVERSE_LEAVES | TRAVERSE_NON_LEAVES, a);
+  if(NULL == tmp){ cout << *a << " not found" << endl; }
+  else{ cout << "Found " << *((string*)(tmp->data())) << endl; }
+
+  tmp = ta.find_child(TRAVERSE_LEAVES | TRAVERSE_NON_LEAVES, e);
+  if(NULL == tmp){ cout << *e << " is not a child of " << *((string*)(ta.data())) << endl; }
+  else{ cout << "Mistakenly found " << *e << " in " << *((string*)(ta.data())) << "'s children" << endl; }
+
+  tmp = ta.find_child(TRAVERSE_LEAVES | TRAVERSE_NON_LEAVES, c);
+  if(NULL == tmp){ cout << *c << " is a child of " << *((string*)(ta.data())) << endl; }
+  else{ cout << "Found " << *c << " in " << *((string*)(ta.data())) << "'s children" << endl; }
+
+  tmp = ta.root();
+  cout << "Root is " << *((string*)(tmp->data())) << endl;
+  cout << "Depth is " << tmp->max_height() << endl;
+
+  ta.unlink(tc);
+  cout << "New depth is " << tmp->max_height() << endl;
+
+  tmp = tc.root();
+  cout << "Pruned root is " << *((string*)(tmp->data())) << endl;
+  cout << "Pruned depth is " << tmp->max_height() << endl;
+
+  delete a;
+  delete b;
+  delete c;
+  delete d;
+  delete e;
+  delete f;
+
+  return 0;
+}
Index: tests/glibmm_tree/Makefile.am
===================================================================
--- tests/glibmm_tree/Makefile.am	(revision 0)
+++ tests/glibmm_tree/Makefile.am	(revision 0)
@@ -0,0 +1,7 @@
+include $(top_srcdir)/tests/Makefile.am_fragment
+
+noinst_PROGRAMS = test
+test_SOURCES = main.cc
+
+
+
Index: tests/Makefile.am
===================================================================
--- tests/Makefile.am	(revision 633)
+++ tests/Makefile.am	(working copy)
@@ -1,4 +1,4 @@
-test_dirs = glibmm_value
+test_dirs = glibmm_value glibmm_tree
 
 SUBDIRS = $(test_dirs)
 EXTRA_DIST = Makefile.am_fragment
Index: glib/src/tree.ccg
===================================================================
--- glib/src/tree.ccg	(revision 0)
+++ glib/src/tree.ccg	(revision 0)
@@ -0,0 +1,248 @@
+/* Copyright (C) 2007 Levi Bard
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stack>
+#include <deque>
+#include <glibmm/utility.h>
+
+namespace Glib
+{
+
+  Tree::Tree()
+  {
+    gobject_ = NULL;
+    owns_gobject_ = false;
+    parent_ = this;
+  }
+
+  Tree::Tree(gpointer data)
+  {
+    gobject_ = g_node_new(data);
+    owns_gobject_ = true;
+    parent_ = this;
+  }
+
+  Tree::~Tree()
+  {
+    if(this != parent_)
+    {
+      parent_->unlink(*this);
+    }
+
+    for(NodeMap::iterator i = children.begin();
+      i != children.end(); ++i)
+    {
+      delete i->second;
+    }
+
+    if(owns_gobject_)
+    {
+      g_node_destroy(gobject_);
+    }
+  }
+
+  Tree& Tree::insert(int position, Tree &node)
+  {
+    children[node.gobj()] = &node;
+    g_node_insert(gobject_, position, node.gobj());
+    node.parent(this);
+    return node;
+  }
+
+  Tree& Tree::insert_before(Tree &sibling, Tree &node)
+  {
+    children[node.gobj()] = &node;
+    g_node_insert_before(gobject_, sibling.gobj(), node.gobj());
+    node.parent(this);
+    return node;
+  }
+
+  Tree& Tree::insert_after(Tree &sibling, Tree &node)
+  {
+    children[node.gobj()] = &node;
+    g_node_insert_after(gobject_, sibling.gobj(), node.gobj());
+    node.parent(this);
+    return node;
+  }
+
+  Tree& Tree::append(Tree &node)
+  {
+    children[node.gobj()] = &node;
+    g_node_append(gobject_, node.gobj());
+    node.parent(this);
+    return node;
+  }
+
+  Tree& Tree::prepend(Tree &node)
+  {
+    children[node.gobj()] = &node;
+    g_node_prepend(gobject_, node.gobj());
+    node.parent(this);
+    return node;
+  }
+
+  Tree* Tree::insert_data(int position, gpointer data)
+  {
+    return &(insert(position, *(new Tree(data))));
+  }
+
+  Tree* Tree::insert_data_before(Tree &sibling, gpointer data)
+  {
+    return &(insert_before(sibling, *(new Tree(data))));
+  }
+
+  Tree* Tree::append_data(gpointer data)
+  {
+    return &(append(*(new Tree(data))));
+  }
+
+  Tree* Tree::prepend_data(gpointer data)
+  {
+    return &(prepend(*(new Tree(data))));
+  }
+
+  Tree* Tree::parent(Tree *newparent)
+  {
+    return (NULL == newparent)? parent_: (parent_ = newparent);
+  }
+
+  Tree* Tree::root()
+  {
+    return (this == parent_)? this: parent_->root();
+  }
+  
+  void Tree::traverse(TraverseType order, TraverseFlags flags, int max_depth, TraverseFunc func, gpointer data)
+  {
+    g_node_traverse(gobject_, (GTraverseType)order, (GTraverseFlags)flags, max_depth, func, data);
+  }
+
+  void Tree::foreach(TraverseFlags flags, ForeachFunc func, gpointer data)
+  {
+    g_node_children_foreach(gobject_, (GTraverseFlags)flags, func, data);
+  }
+
+  Tree* Tree::find_child(TraverseFlags flags, gpointer data)
+  {
+    return children[g_node_find_child(gobject_, (GTraverseFlags)flags, data)];
+  }
+
+  Tree* Tree::find(TraverseType order, TraverseFlags flags, gpointer data)
+  {
+    iterator child = g_node_find(gobject_, (GTraverseType)order, (GTraverseFlags)flags, data),
+             cursor = child;
+    if(NULL == child){ return NULL; }
+
+    unsigned int depth = g_node_depth(child) - g_node_depth(gobject_);
+    std::stack<Tree::iterator, std::deque<Tree::iterator> > stack;
+    Tree *treecursor = this;
+
+    for(unsigned int i = 0; i < depth; ++i)
+    {
+      stack.push(cursor);
+      cursor = cursor->parent;
+    }
+
+    for(;!stack.empty();stack.pop())
+    {
+      treecursor = treecursor->lookup(stack.top());
+      if(NULL == treecursor){ return NULL; }
+    }
+
+    return treecursor;
+  }
+
+  int Tree::position_of(Tree &child)
+  {
+    return g_node_child_position(gobject_, child.gobj());
+  }
+
+  Tree* Tree::first_child()
+  {
+    return children[g_node_first_child(gobject_)];
+  }
+
+  Tree* Tree::last_child()
+  {
+    return children[g_node_last_child(gobject_)];
+  }
+
+  Tree* Tree::nth_child(int n)
+  {
+    return children[g_node_nth_child(gobject_, n)];
+  }
+
+  Tree* Tree::first_sibling()
+  {
+    Tree::iterator sib = g_node_first_sibling(gobject_);
+    return (NULL == sib)? NULL: parent_->find_child(TRAVERSE_ALL, sib->data);
+  }
+
+  Tree* Tree::prev_sibling()
+  {
+    Tree::iterator sib = g_node_prev_sibling(gobject_);
+    return (NULL == sib)? NULL: parent_->find_child(TRAVERSE_ALL, sib->data);
+  }
+
+  Tree* Tree::next_sibling()
+  {
+    Tree::iterator sib = g_node_next_sibling(gobject_);
+    return (NULL == sib)? NULL: parent_->find_child(TRAVERSE_ALL, sib->data);
+  }
+
+  Tree* Tree::last_sibling()
+  {
+    Tree::iterator sib = g_node_last_sibling(gobject_);
+    return (NULL == sib)? NULL: parent_->find_child(TRAVERSE_ALL, sib->data);
+  }
+
+  bool Tree::is_leaf()
+  {
+    return G_NODE_IS_LEAF(gobject_);
+  }
+
+  bool Tree::is_root()
+  {
+    return G_NODE_IS_ROOT(gobject_);
+  }
+
+  unsigned int Tree::node_count(TraverseFlags flags)
+  {
+    return g_node_n_nodes(gobject_, (GTraverseFlags)flags);
+  }
+
+  bool Tree::is_ancestor(Tree &descendant)
+  {
+    return g_node_is_ancestor(gobject_, descendant.gobj());
+  }
+
+  void Tree::unlink(Tree &child)
+  {
+    children.erase(child.gobj());
+    child.parent(&child);
+    g_node_unlink(child.gobj());
+  }
+
+  Tree* Tree::lookup(Tree::iterator child)
+  {
+    return children[child];
+  }
+
+  Tree::iterator Tree::iter()
+  {
+    return gobject_;
+  }
+} // namespace Glib
Index: glib/src/tree.hg
===================================================================
--- glib/src/tree.hg	(revision 0)
+++ glib/src/tree.hg	(revision 0)
@@ -0,0 +1,386 @@
+/* Copyright (C) 2007 Levi Bard
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+_DEFS(glibmm,glib)
+
+#include <map>
+
+#include <glibmm/refptr.h>
+#include <glibmm/ustring.h>
+#include <glibmm/error.h>
+#include <glibmm/arrayhandle.h>
+#include <glib/gnode.h>
+#include <glib/gtree.h>
+
+namespace Glib
+{
+
+_WRAP_ENUM(TraverseFlags, GTraverseFlags, NO_GTYPE)
+_WRAP_ENUM(TraverseType, GTraverseType, NO_GTYPE)
+
+/** N-ary Trees — trees of data with any number of branches
+ *
+ * The Tree class and its associated functions provide a N-ary tree data structure, where nodes in the tree can contain arbitrary data.
+ * 
+ * To insert a node into a tree use insert(), insert_before(), append() and prepend().
+ * 
+ * To create a new node and insert it into a tree use insert_data(), insert_data_before(), append_data() and prepend_data().
+ * 
+ * To reverse the children of a node use reverse_children().
+ * 
+ * To find a node use root(), find(), find_child(), index_of(), position_of(), first_child(), last_child(), nth_child(), first_sibling(), prev_sibling(), next_sibling() or last_sibling().
+ * 
+ * To get information about a node or tree use is_leaf(), is_root(), depth(), node_count(), child_count(), is_ancestor() or max_height().
+ * 
+ * To traverse a tree, calling a function for each node visited in the traversal, use traverse() or foreach().
+ * 
+ * To remove a node or subtree from a tree use unlink().
+*/
+
+class Tree
+{
+  _CLASS_GENERIC(Tree, GNode)
+public:
+  typedef GNode* iterator;
+  typedef GNodeTraverseFunc TraverseFunc;
+  typedef GNodeForeachFunc ForeachFunc;
+  typedef std::map<GNode*,Tree*> NodeMap;
+
+  /**
+   * Creates a new GNode containing the given data. 
+   * Used to create the first node in a tree.
+   */
+  Tree();
+  Tree(gpointer data);
+  _IGNORE(g_node_new);
+
+  /**
+   * Removes the instance and its children from the tree,
+   * freeing any memory allocated.
+   */
+  virtual ~Tree();
+  _IGNORE(g_node_destroy)
+
+
+  /**
+   * Inserts a Tree beneath the parent at the given position.
+   *
+   * @param position the position to place node at, with respect to its siblings 
+   * If position is -1, node is inserted as the last child of parent
+   * @param node the Tree to insert
+   * @return the inserted Tree
+   */
+  Tree& insert(int position, Tree &node);
+  _IGNORE(g_node_insert)
+
+  /**
+   * Inserts a Tree beneath the parent before the given sibling.
+   *
+   * @param sibling the sibling Tree to place node before.
+   * @param node the Tree to insert
+   * @return the inserted Tree
+   */
+  Tree& insert_before(Tree &sibling, Tree &node);
+  _IGNORE(g_node_insert_before)
+
+  /**
+   * Inserts a Tree beneath the parent after the given sibling.
+   *
+   * @param sibling the sibling Tree to place node after.
+   * @param node the Tree to insert
+   * @return the inserted Tree
+   */
+  Tree& insert_after(Tree &sibling, Tree &node);
+  _IGNORE(g_node_insert_after)
+
+
+  /**
+   * Inserts a Tree as the last child
+   * @param node the Tree to append
+   * @return the new Tree
+   */
+  Tree& append(Tree &node);
+  _IGNORE(g_node_append)
+
+  /**
+   * Inserts a Tree as the first child
+   * @param data the data for the Tree
+   * @return the Tree
+   */
+  Tree& prepend(Tree &node);
+  _IGNORE(g_node_prepend)
+
+  /**
+   * Inserts a new Tree at the given position.
+   * @param position the position to place the new Tree at. 
+   * If position is -1, the new Tree is inserted as the last child of parent
+   * @param data the data for the new Tree
+   * @return the new Tree
+   */
+  Tree* insert_data(int position, gpointer data);
+  _IGNORE(g_node_insert_data)
+
+  /**
+   * Inserts a new Tree before the given sibling
+   * @param sibling the sibling Tree to place node before. 
+   * @param data the data for the new Tree
+   * @return the new Tree
+   */
+  Tree* insert_data_before(Tree &sibling, gpointer data);
+  _IGNORE(g_node_insert_data_before)
+
+  /**
+   * Inserts a new Tree as the last child
+   * @param data the data for the new Tree
+   * @return the new Tree
+   */
+  Tree* append_data(gpointer data);
+  _IGNORE(g_node_append_data)
+
+  /**
+   * Inserts a new Tree as the first child
+   * @param data the data for the new Tree
+   * @return the new Tree
+   */
+  Tree* prepend_data(gpointer data);
+  _IGNORE(g_node_prepend_data)
+
+  /**
+   * Reverses the order of the children
+   */
+  _WRAP_METHOD(void reverse_children(), g_node_reverse_children)
+
+  /**
+   * Returns a pointer to the root of the tree
+   * @return a pointer to the root of the tree
+   */
+  Tree* root();
+  _IGNORE(g_node_get_root)
+
+  /**
+   * Traverses a tree starting at the current node
+   * It calls the given function for each node visited. 
+   * The traversal can be halted at any point by returning TRUE from func.
+   * @param order The order in which nodes are visited: TRAVERSE_IN_ORDER, TRAVERSE_PRE_ORDER, TRAVERSE_POST_ORDER, or TRAVERSE_LEVEL_ORDER
+   * @param flags which types of children are to be visited, one of TRAVERSE_ALL, TRAVERSE_LEAVES and TRAVERSE_NON_LEAVES
+   * @param max_depth the maximum depth of the traversal. 
+   * Nodes below this depth will not be visited. 
+   * If max_depth is -1 all nodes in the tree are visited.
+   * If depth is 1, only the root is visited.
+   * If depth is 2, the root and its children are visited. And so on.
+   * @param func the function to call for each visited child
+   * @param data user data to pass to the function
+   */
+  void traverse(TraverseType order, TraverseFlags flags, int max_depth, TraverseFunc func, gpointer data);
+  _IGNORE(g_node_traverse);
+
+  /**
+   * Calls a function for each of the children of a GNode.
+   * Note that it doesn't descend beneath the child nodes.
+   * @param flags which types of children are to be visited, one of TRAVERSE_ALL, TRAVERSE_LEAVES and TRAVERSE_NON_LEAVES
+   * @param func the function to call for each visited node
+   * @param data user data to pass to the function
+   */
+  void foreach(TraverseFlags flags, ForeachFunc func, gpointer data);
+  _IGNORE(g_node_children_foreach)
+
+  /**
+   * Finds the first child of a GNode with the given data.
+   * @param flags which types of children are to be visited, one of TRAVERSE_ALL, TRAVERSE_LEAVES and TRAVERSE_NON_LEAVES
+   * @param data user data to pass to the function
+   * @return the found child, or NULL if the data is not found
+   */
+  Tree* find_child(TraverseFlags flags, gpointer data);
+  _IGNORE(g_node_find_child)
+
+  /**
+   * Finds a node in a tree
+   * @param order The order in which nodes are visited: 
+   * TRAVERSE_IN_ORDER, TRAVERSE_PRE_ORDER, TRAVERSE_POST_ORDER, or TRAVERSE_LEVEL_ORDER
+   * @param flags which types of children are to be visited, 
+   * one of TRAVERSE_ALL, TRAVERSE_LEAVES and TRAVERSE_NON_LEAVES
+   * @return the found node, or NULL if the data is not found 
+   */
+  Tree* find(TraverseType order, TraverseFlags flags, gpointer data);
+  _IGNORE(g_node_find)
+
+  /**
+   * Gets the position of the first child which contains the given data.
+   * @param data the data to find
+   * @return the index of the child which contains data, 
+   * or -1 if the data is not found 
+   */
+  _WRAP_METHOD(int index_of(gpointer data), g_node_child_index)
+
+  /**
+   * Gets the position with respect to its siblings. 
+   * child must be a child of node.
+   * The first child is numbered 0, the second 1, and so on.
+   * @param child a child
+   * @return the position of child with respect to its siblings
+   */
+  int position_of(Tree &child);
+  _IGNORE(g_node_child_position)
+
+  /**
+   * Gets the first child
+   * @return the first child, or NULL if node has no children 
+   */
+  Tree* first_child();
+  _IGNORE(g_node_first_child)
+
+  /**
+   * Gets the last child
+   * @return the last child, or NULL if node has no children 
+   */
+  Tree* last_child();
+  _IGNORE(g_node_last_child)
+
+  /**
+   * Gets the nth child
+   * @return the nth child, or NULL if n is too large
+   */
+  Tree* nth_child(int n);
+  _IGNORE(g_node_nth_child)
+
+  /**
+   * Gets the first sibling
+   * @return the first sibling, or NULL if node has no siblings
+   */
+  Tree* first_sibling();
+  _IGNORE(g_node_first_sibling)
+
+  /**
+   * Gets the prev sibling
+   * @return the prev sibling, or NULL if node has no siblings
+   */
+  Tree* prev_sibling();
+  _IGNORE(g_node_prev_sibling)
+
+  /**
+   * Gets the next sibling
+   * @return the next sibling, or NULL if node has no siblings
+   */
+  Tree* next_sibling();
+  _IGNORE(g_node_next_sibling)
+
+  /**
+   * Gets the last sibling
+   * @return the last sibling, or NULL if node has no siblings
+   */
+  Tree* last_sibling();
+  _IGNORE(g_node_last_sibling)
+
+  /**
+   * Returns true if this is a leaf node.
+   * @return true if this is a leaf node.
+   */
+  bool is_leaf();
+
+  /**
+   * Returns true if this is the root node.
+   * @return true if this is the root node.
+   */
+  bool is_root();
+
+  /**
+   * Gets the depth of this node
+   * The root node has a depth of 1.
+   * For the children of the root node the depth is 2. And so on.
+   * @return the depth of this node
+   */
+  _WRAP_METHOD(unsigned int depth(), g_node_depth)
+
+  /**
+   * Gets the number of nodes in a tree.
+   * @param flags which types of children are to be counted,
+   * one of TRAVERSE_ALL, TRAVERSE_LEAVES and TRAVERSE_NON_LEAVES
+   * @return the number of nodes in the tree
+   */
+  unsigned int node_count(TraverseFlags flags);
+  _IGNORE(g_node_n_nodes)
+
+  /**
+   * Gets the number children
+   * @return the number of children
+   */
+  _WRAP_METHOD(unsigned int child_count(), g_node_n_children)
+
+  /**
+   * Returns TRUE if this is an ancestor of descendant.
+   * This is true if this is the parent of descendant,
+   * or if this is the grandparent of descendant etc.
+   * @param descendant a node
+   * @return true if this is an ancestor of descendant
+   */
+  bool is_ancestor(Tree &descendant);
+  _IGNORE(g_node_is_ancestor)
+
+  /**
+   * Gets the maximum height of all branches beneath this node.
+   * This is the maximum distance from the node to all leaf nodes.
+   * If root has no children, 1 is returned. If root has children, 2 is returned. And so on.
+   * @return the maximum height of all branches
+   */
+  _WRAP_METHOD(unsigned int max_height(), g_node_max_height)
+
+  /**
+   * Unlinks a GNode from a tree, resulting in two separate trees.
+   */
+  void unlink(Tree &child);
+  _IGNORE(g_node_unlink)
+
+  /// Accessor for this node's iterator
+  Tree::iterator iter();
+
+  /// Accessor for this node's data
+  gpointer data(){ return (NULL == gobject_)? NULL: gobject_->data; }
+
+  /**
+   * Lookup a child by its iterator
+   * @param child the iterator of the desired child
+   * @return the child if found, else NULL
+   */
+  Tree* lookup(Tree::iterator child);
+
+  /**
+   * Accessor for this node's parent
+   * Don't use this.
+   * @param newparent A new parent for this node, 
+   * NULL to get the current parent
+   * @return the node's parent
+   */
+  Tree* parent(Tree *newparent=NULL);
+
+  /// For auto-wrapping
+  GNode*       gobj()       { return gobject_; }
+  const GNode* gobj() const { return gobject_; }
+
+  /// Leaving these unimplemented for now
+  _IGNORE(g_node_copy)
+  _IGNORE(g_node_copy_deep)
+protected:
+  GNode *gobject_;
+  bool owns_gobject_;
+
+  /// Some metadata must be stored
+  NodeMap children;
+  Tree *parent_;
+};
+
+
+} // namespace Glib
Index: glib/src/Makefile_list_of_hg.am_fragment
===================================================================
--- glib/src/Makefile_list_of_hg.am_fragment	(revision 633)
+++ glib/src/Makefile_list_of_hg.am_fragment	(working copy)
@@ -5,4 +5,4 @@
 
 files_posix_hg =
 files_win32_hg =
-files_general_hg = convert.hg date.hg fileutils.hg iochannel.hg keyfile.hg markup.hg module.hg optioncontext.hg optionentry.hg optiongroup.hg regex.hg shell.hg spawn.hg thread.hg unicode.hg
+files_general_hg = convert.hg date.hg fileutils.hg iochannel.hg keyfile.hg markup.hg module.hg optioncontext.hg optionentry.hg optiongroup.hg regex.hg shell.hg spawn.hg thread.hg tree.hg unicode.hg
Index: glib/glibmm.h
===================================================================
--- glib/glibmm.h	(revision 633)
+++ glib/glibmm.h	(working copy)
@@ -66,6 +66,7 @@
 #include <glibmm/threadpool.h>
 #include <glibmm/timer.h>
 #include <glibmm/timeval.h>
+#include <glibmm/tree.h>
 #include <glibmm/ustring.h>
 #include <glibmm/value.h>
 #include <glibmm/wrap.h>
