[Gtk-sharp-list] patch: managed TreeModel impl

Vladimir Vukicevic vladimir@pobox.com
Mon, 24 May 2004 01:46:32 -0700


This is a multi-part message in MIME format.
--------------010405020209080506070209
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

Howdy,

Attached is a patch that creates a new ManagedTreeModel class, which can 
be subclassed in managed code to implement a new GtkTreeModel (look ma, 
no unmanaged glue!).  This is the first step to a ADO.NET data-bound 
TreeModel (code in progress).  Also included is a  ManagedModelDemo.cs 
demo program that implements a simple tree model.

Let me know if I can commit and/or if any changes should be made.

Thanks,
	- Vlad


--------------010405020209080506070209
Content-Type: text/plain;
 name="managed_tree_model.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="managed_tree_model.patch"

? managed_tree_model.patch
? pixelsptr.patch
? treeiter.patch
? api/Makefile
? api/generated-stamp
? glue/Makefile
? glue/Makefile.in
? gst/Makefile
? gst/generated
? gtk/ManagedTreeModel.cs
? gtk/glue/managedtreemodel.c
? sample/ManagedModelDemo.cs
Index: ChangeLog
===================================================================
RCS file: /cvs/public/gtk-sharp/ChangeLog,v
retrieving revision 1.817
diff -u -u -r1.817 ChangeLog
--- ChangeLog	22 May 2004 19:38:28 -0000	1.817
+++ ChangeLog	24 May 2004 07:55:25 -0000
@@ -1,3 +1,28 @@
+2004-05-24  Vladimir Vukicevic  <vladimir@pobox.com>
+
+	* gtk/Makefile.am, gtk/ManagedTreeModel.cs: added
+	ManagedTreeModel.cs
+
+	* sample/Makefile.am, sample/ManagedModelDemo.cs: added.
+	
+	* gtk/TreeModel.custom: commented out SetValue() methods.  These
+	are specific to ListStore and TreeStore; they should probably get
+	removed?
+	
+	* gtk/Gtk.metadata: Changed a number of TreeModel GtkIter params
+	from out to ref; also added some refs.  out doesn't really make
+	sense (for "out TreeIter iter", the compiler wants something
+	assigned to "iter" in the method body; I have no idea how this
+	works for structs)
+
+	* glib/Object.cs: changed GType property to public from
+	protected, otherwise GetType() can't find it when it does
+	the type lookup
+
+2004-05-23  Vladimir Vukicevic  <vladimir@pobox.com>
+
+	* gtk/TreeIter.custom: add accessor properties for UserData1/2/3
+
 2004-05-22  Mike Kestner  <mkestner@ximian.com>
 
 	* configure.in : require mono-0.91.99.  Sorry, but we need to
Index: glib/Object.cs
===================================================================
RCS file: /cvs/public/gtk-sharp/glib/Object.cs,v
retrieving revision 1.64
diff -u -u -r1.64 Object.cs
--- glib/Object.cs	18 May 2004 05:06:10 -0000	1.64
+++ glib/Object.cs	24 May 2004 07:55:26 -0000
@@ -190,7 +190,7 @@
 		[DllImport("glibsharpglue")]
 		private static extern IntPtr gtksharp_get_type_id (IntPtr obj);
 
-		protected static GLib.GType GType {
+		public static GLib.GType GType {
 			get {
 				return GType.Object;
 			}
Index: gtk/Gtk.metadata
===================================================================
RCS file: /cvs/public/gtk-sharp/gtk/Gtk.metadata,v
retrieving revision 1.56
diff -u -u -r1.56 Gtk.metadata
--- gtk/Gtk.metadata	10 May 2004 20:00:08 -0000	1.56
+++ gtk/Gtk.metadata	24 May 2004 07:55:26 -0000
@@ -48,19 +48,27 @@
   <attr path="/api/namespace/interface[@cname='GtkEditable']/method[@name='SetEditable']" name="name">SetIsEditable</attr>
   <attr path="/api/namespace/interface[@cname='GtkEditable']/signal[@name='DeleteText']" name="name">TextDeleted</attr>
   <attr path="/api/namespace/interface[@cname='GtkEditable']/signal[@name='InsertText']" name="name">TextInserted</attr>
-  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='GetIterFirst']/*/*[@name='iter']" name="pass_as">out</attr>
-  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='GetIterFromString']/*/*[@name='iter']" name="pass_as">out</attr>
-  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='GetIter']/*/*[@name='iter']" name="pass_as">out</attr>
+  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='GetIterFirst']/*/*[@name='iter']" name="pass_as">ref</attr>
+  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='GetIterFromString']/*/*[@name='iter']" name="pass_as">ref</attr>
+  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='GetIter']/*/*[@name='iter']" name="pass_as">ref</attr>
   <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='GetValue']/*/*[@name='value']" name="pass_as">ref</attr>
-  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='IterChildren']/*/*[@name='iter']" name="pass_as">out</attr>
-  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='IterNext']/*/*[@name='iter']" name="pass_as">out</attr>
-  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='IterNthChild']/*/*[@name='iter']" name="pass_as">out</attr>
-  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='IterParent']/*/*[@name='iter']" name="pass_as">out</attr>
+  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='IterChildren']/*/*[@name='iter']" name="pass_as">ref</attr>
+  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='IterChildren']/*/*[@name='parent']" name="pass_as">ref</attr>
+  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='IterNext']/*/*[@name='iter']" name="pass_as">ref</attr>
+  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='IterNthChild']/*/*[@name='iter']" name="pass_as">ref</attr>
+  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='IterNthChild']/*/*[@name='parent']" name="pass_as">ref</attr>
+  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='IterParent']/*/*[@name='iter']" name="pass_as">ref</attr>
   <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='RowChanged']" name="name">EmitRowChanged</attr>
   <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='RowDeleted']" name="name">EmitRowDeleted</attr>
   <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='RowHasChildToggled']" name="name">EmitRowHasChildToggled</attr>
   <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='RowInserted']" name="name">EmitRowInserted</attr>
   <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='RowsReordered']" name="name">EmitRowsReordered</attr>
+  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='GetPath']/*/*[@name='iter']" name="pass_as">ref</attr>
+  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='IterHasChild']/*/*[@name='iter']" name="pass_as">ref</attr>
+  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='IterNChildren']/*/*[@name='iter']" name="pass_as">ref</attr>
+  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='IterParent']/*/*[@name='child']" name="pass_as">ref</attr>
+  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='RefNode']/*/*[@name='iter']" name="pass_as">ref</attr>
+  <attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='UnrefNode']/*/*[@name='iter']" name="pass_as">ref</attr>
   <attr path="/api/namespace/interface[@cname='GtkTreeSortable']/method[@name='SortColumnChanged']" name="name">ChangeSortColumn</attr>
   <attr path="/api/namespace/object[@cname='GtkAccelLabel']/constructor[@cname='gtk_accel_label_new']/*/*[@name='string']" name="property_name">label</attr>
   <attr path="/api/namespace/object[@cname='GtkAdjustment']/constructor[@cname='gtk_adjustment_new']" name="hidden">1</attr>
Index: gtk/Makefile.am
===================================================================
RCS file: /cvs/public/gtk-sharp/gtk/Makefile.am,v
retrieving revision 1.13
diff -u -u -r1.13 Makefile.am
--- gtk/Makefile.am	14 May 2004 20:25:57 -0000	1.13
+++ gtk/Makefile.am	24 May 2004 07:55:26 -0000
@@ -23,7 +23,8 @@
 	ThreadNotify.cs			\
 	TreeNodeAttribute.cs		\
 	TreeNode.cs			\
-	TreeNodeValueAttribute.cs
+	TreeNodeValueAttribute.cs       \
+	ManagedTreeModel.cs
 
 build_sources = $(addprefix $(srcdir)/, $(sources)) AssemblyInfo.cs
 
Index: gtk/TreeIter.custom
===================================================================
RCS file: /cvs/public/gtk-sharp/gtk/TreeIter.custom,v
retrieving revision 1.3
diff -u -u -r1.3 TreeIter.custom
--- gtk/TreeIter.custom	12 Feb 2004 21:28:42 -0000	1.3
+++ gtk/TreeIter.custom	24 May 2004 07:55:26 -0000
@@ -19,3 +19,18 @@
                                 ti._user_data2 == _user_data2 &&
                                 ti._user_data3 == _user_data3;
                 }
+
+                public IntPtr UserData1 {
+                        get { return _user_data; }
+                        set { _user_data = value; }
+                }
+                
+                public IntPtr UserData2 {
+                        get { return _user_data2; }
+                        set { _user_data2 = value; }
+                }
+                
+                public IntPtr UserData3 {
+                        get { return _user_data3; }
+                        set { _user_data3 = value; }
+                }
Index: gtk/TreeModel.custom
===================================================================
RCS file: /cvs/public/gtk-sharp/gtk/TreeModel.custom,v
retrieving revision 1.2
diff -u -u -r1.2 TreeModel.custom
--- gtk/TreeModel.custom	1 Nov 2003 12:00:26 -0000	1.2
+++ gtk/TreeModel.custom	24 May 2004 07:55:26 -0000
@@ -18,6 +18,7 @@
 	/// <remarks>To be completed</remarks>
 	bool IterNthChild (out Gtk.TreeIter iter, int n);
 
+#if false
         void SetValue (Gtk.TreeIter iter, int column, bool value);
         void SetValue (Gtk.TreeIter iter, int column, double value);
 	void SetValue (Gtk.TreeIter iter, int column, int value);
@@ -25,4 +26,5 @@
 	void SetValue (Gtk.TreeIter iter, int column, float value);
 	void SetValue (Gtk.TreeIter iter, int column, uint value);
 	void SetValue (Gtk.TreeIter iter, int column, object value);
+#endif
 	object GetValue(Gtk.TreeIter iter, int column);
Index: sample/Makefile.am
===================================================================
RCS file: /cvs/public/gtk-sharp/sample/Makefile.am,v
retrieving revision 1.4
diff -u -u -r1.4 Makefile.am
--- sample/Makefile.am	14 May 2004 20:25:57 -0000	1.4
+++ sample/Makefile.am	24 May 2004 07:55:26 -0000
@@ -24,7 +24,7 @@
 VTE_ASSEMBLY=
 endif
 
-TARGETS = custom-cellrenderer.exe gtk-hello-world.exe button.exe calendar.exe subclass.exe menu.exe size.exe scribble.exe treeviewdemo.exe managedtreeviewdemo.exe testdnd.exe $(GNOME_TARGETS) $(GLADE_TARGETS) $(VTE_TARGETS)
+TARGETS = custom-cellrenderer.exe gtk-hello-world.exe button.exe calendar.exe subclass.exe menu.exe size.exe scribble.exe treeviewdemo.exe managedtreeviewdemo.exe managedmodeldemo.exe testdnd.exe $(GNOME_TARGETS) $(GLADE_TARGETS) $(VTE_TARGETS)
 
 assemblies=../glib/glib-sharp.dll ../pango/pango-sharp.dll ../atk/atk-sharp.dll ../gdk/gdk-sharp.dll ../gtk/gtk-sharp.dll $(GNOME_ASSEMBLY) $(GLADE_ASSEMBLY) $(VTE_ASSEMBLY)
 references=$(addprefix -r , $(assemblies))
@@ -71,6 +71,9 @@
 managedtreeviewdemo.exe: $(srcdir)/ManagedTreeViewDemo.cs $(assemblies)
 	$(CSC)  -out:managedtreeviewdemo.exe $(references) $(srcdir)/ManagedTreeViewDemo.cs
 
+managedmodeldemo.exe: $(srcdir)/ManagedModelDemo.cs $(assemblies)
+	$(CSC)  -out:managedmodeldemo.exe $(references) $(srcdir)/ManagedModelDemo.cs
+
 glade-viewer.exe: $(srcdir)/GladeViewer.cs $(assemblies)
 	$(CSC)  -out:glade-viewer.exe $(references) $(srcdir)/GladeViewer.cs
 
@@ -109,4 +112,6 @@
 	CairoSample.cs			\
 	TestDnd.cs			\
 	VteTest.cs			\
-	CustomCellRenderer.cs
+	CustomCellRenderer.cs		\
+	ManagedModelDemo.cs
+
Index: sample/ManagedTreeViewDemo.cs
===================================================================
RCS file: /cvs/public/gtk-sharp/sample/ManagedTreeViewDemo.cs,v
retrieving revision 1.4
diff -u -u -r1.4 ManagedTreeViewDemo.cs
--- sample/ManagedTreeViewDemo.cs	12 Mar 2004 21:18:10 -0000	1.4
+++ sample/ManagedTreeViewDemo.cs	24 May 2004 07:55:26 -0000
@@ -23,11 +23,16 @@
 
 		private static void PopulateStore ()
 		{
+			bool first = true;
 			store = new ListStore (typeof (Pair));
 			string[] combs = {"foo", "bar", "baz", "quux"};
 			foreach (string a in combs) {
 				foreach (string b in combs) {
-					store.AppendValues (new Pair (a, b));
+					Gtk.TreeIter ti = store.AppendValues (new Pair (a, b));
+					if (first) {
+						cellIter = ti;
+						first = false;
+					}
 				}
 			}
 		}
@@ -48,6 +53,7 @@
 		{
 			Application.Init ();
 
+			cellVal = 0;
 			PopulateStore ();
 
 			Window win = new Window ("TreeView demo");
@@ -61,18 +67,31 @@
 			TreeView tv = new TreeView (store);
 			tv.HeadersVisible = true;
 
-			tv.AppendColumn ("One", new CellRendererText (), new TreeCellDataFunc (CellDataA));
+			Gtk.CellRendererText crt1, crt2;
+			crt1 = new CellRendererText();
+			crt1.Editable = true;
+			tv.AppendColumn ("One", crt1, new TreeCellDataFunc (CellDataA));
 			tv.AppendColumn ("Two", new CellRendererText (), new TreeCellDataFunc (CellDataB));
 
 			sw.Add (tv);
 			win.ShowAll ();
 
+			GLib.Timeout.Add (500, new GLib.TimeoutHandler (UpdateCell));
 			Application.Run ();
 		}
 
 		private static void DeleteCB (System.Object o, DeleteEventArgs args)
 		{
 			Application.Quit ();
+		}
+
+		private static Gtk.TreeIter cellIter;
+		private static int cellVal;
+		private static bool UpdateCell ()
+		{
+			cellVal++;
+			store.SetValue (cellIter, 0, new Pair(Convert.ToString(cellVal), Convert.ToString(cellVal)));
+			return true;
 		}
 	}
 }
--- /dev/null	2004-02-23 13:02:56.000000000 -0800
+++ gtk/ManagedTreeModel.cs	2004-05-24 01:36:19.737673976 -0700
@@ -0,0 +1,533 @@
+//
+// ManagedTreeModel.cs
+//
+// Managed framework for implementing TreeModels
+//
+// Author(s): Vladimir Vukicevic  <vladimir@pobox.com>
+
+namespace Gtk {
+  using System;
+  using System.Collections;
+  using System.Runtime.InteropServices;
+
+  public abstract class ManagedTreeModel : GLib.Object, TreeModel {
+
+    //
+    // TreeModel interface
+    //
+
+    //
+    // These are things that can be overriden by subclasses
+    //
+
+    public virtual Gtk.TreeModelFlags Flags {
+      get {
+	return (Gtk.TreeModelFlags) 0;
+      }
+    }
+
+    public abstract int NColumns { get; }
+
+    public abstract System.Type ColumnType (int index);
+
+    public virtual GLib.GType GetColumnType (int index) {
+      return GLibSharp.TypeConverter.LookupType (ColumnType (index));
+    }
+
+    public abstract bool GetIter (ref Gtk.TreeIter iter, Gtk.TreePath path);
+
+    public abstract Gtk.TreePath GetPath (ref Gtk.TreeIter iter);
+
+    public abstract object GetValue (Gtk.TreeIter iter, int column);
+
+    public virtual void GetValue (Gtk.TreeIter iter, int column, ref GLib.Value value) {
+      object o = GetValue (iter, column);
+      if (o == null) {
+	value.Init (GLib.GType.Invalid);
+	return;
+      }
+      GLib.GType ctype = GLibSharp.TypeConverter.LookupType (o.GetType());
+      value.Init (ctype);
+      value.Val = o;
+    }
+
+    public abstract bool IterNext (ref Gtk.TreeIter iter);
+
+    public virtual bool IterHasChild (ref Gtk.TreeIter iter) {
+      return false;
+    }
+
+    public virtual bool IterChildren (ref Gtk.TreeIter iter, ref Gtk.TreeIter parent) {
+      iter.UserData1 = IntPtr.Zero;
+      return false;
+    }
+
+    public virtual int IterNChildren (ref Gtk.TreeIter iter) {
+      return 0;
+    }
+
+    public virtual bool IterNthChild (ref Gtk.TreeIter iter, ref Gtk.TreeIter parent, int n) {
+      iter.UserData1 = IntPtr.Zero;
+      return false;
+    }
+
+    public virtual bool IterParent (ref Gtk.TreeIter iter, ref Gtk.TreeIter child) {
+      iter.UserData1 = IntPtr.Zero;
+      return false;
+    }
+
+    public virtual void RefNode (ref Gtk.TreeIter iter) {
+      // nothing
+    }
+
+    public virtual void UnrefNode (ref Gtk.TreeIter iter) {
+      // nothing
+    }
+
+    // events
+
+    public event Gtk.RowChangedHandler RowChanged {
+      add {
+	System.ComponentModel.EventHandlerList event_list = AfterHandlers;
+	Hashtable signals = AfterSignals;
+	if (value.Method.GetCustomAttributes (typeof(GLib.ConnectBeforeAttribute), false).Length > 0) {
+	  event_list = BeforeHandlers;
+	  signals = BeforeSignals;
+	}
+
+	if (signals["row_changed"] == null)
+	  signals["row_changed"] = new GtkSharp.voidObjectTreePathTreeIterSignal
+	    (this, "row_changed", value, System.Type.GetType("Gtk.RowChangedHandler,gtk-sharp"), 0);
+	else
+	  ((GLib.SignalCallback) signals["row_changed"]).AddDelegate (value);
+
+	event_list.AddHandler("row_changed", value);
+      }
+
+      remove {
+	sigRemovalHelper (value, "row_changed");
+      }
+    }
+
+    public event Gtk.RowDeletedHandler RowDeleted {
+      add {
+	System.ComponentModel.EventHandlerList event_list = AfterHandlers;
+	Hashtable signals = AfterSignals;
+	if (value.Method.GetCustomAttributes (typeof(GLib.ConnectBeforeAttribute), false).Length > 0) {
+	  event_list = BeforeHandlers;
+	  signals = BeforeSignals;
+	}
+
+	if (signals["row_deleted"] == null)
+	  signals["row_deleted"] = new GtkSharp.voidObjectTreePathSignal
+	    (this, "row_deleted", value, System.Type.GetType("Gtk.RowDeletedHandler,gtk-sharp"), 0);
+	else
+	  ((GLib.SignalCallback) signals["row_deleted"]).AddDelegate (value);
+
+	event_list.AddHandler("row_deleted", value);
+      }
+
+      remove {
+	sigRemovalHelper (value, "row_deleted");
+      }
+    }
+
+    public event Gtk.RowHasChildToggledHandler RowHasChildToggled {
+      add {
+	System.ComponentModel.EventHandlerList event_list = AfterHandlers;
+	Hashtable signals = AfterSignals;
+	if (value.Method.GetCustomAttributes (typeof(GLib.ConnectBeforeAttribute), false).Length > 0) {
+	  event_list = BeforeHandlers;
+	  signals = BeforeSignals;
+	}
+
+	if (signals["row_has_child_toggled"] == null)
+	  signals["row_has_child_toggled"] = new GtkSharp.voidObjectTreePathTreeIterSignal
+	    (this, "row_has_child_toggled", value, System.Type.GetType("Gtk.RowHasChildToggledHandler,gtk-sharp"), 0);
+	else
+	  ((GLib.SignalCallback) signals["row_has_child_toggled"]).AddDelegate (value);
+
+	event_list.AddHandler("row_has_child_toggled", value);
+      }
+
+      remove {
+	sigRemovalHelper (value, "row_has_child_toggled");
+      }
+    }
+
+    public event Gtk.RowInsertedHandler RowInserted {
+      add {
+	System.ComponentModel.EventHandlerList event_list = AfterHandlers;
+	Hashtable signals = AfterSignals;
+	if (value.Method.GetCustomAttributes (typeof(GLib.ConnectBeforeAttribute), false).Length > 0) {
+	  event_list = BeforeHandlers;
+	  signals = BeforeSignals;
+	}
+
+	if (signals["row_inserted"] == null)
+	  signals["row_inserted"] = new GtkSharp.voidObjectTreePathTreeIterSignal
+	    (this, "row_inserted", value, System.Type.GetType("Gtk.RowInsertedHandler,gtk-sharp"), 0);
+	else
+	  ((GLib.SignalCallback) signals["row_inserted"]).AddDelegate (value);
+
+	event_list.AddHandler("row_inserted", value);
+      }
+
+      remove {
+	sigRemovalHelper (value, "row_inserted");
+      }
+    }
+
+    public event Gtk.RowsReorderedHandler RowsReordered {
+      add {
+	System.ComponentModel.EventHandlerList event_list = AfterHandlers;
+	Hashtable signals = AfterSignals;
+	if (value.Method.GetCustomAttributes (typeof(GLib.ConnectBeforeAttribute), false).Length > 0) {
+	  event_list = BeforeHandlers;
+	  signals = BeforeSignals;
+	}
+
+	if (signals["rows_reordered"] == null)
+	  signals["rows_reordered"] = new GtkSharp.voidObjectTreePathTreeIterintSignal
+	    (this, "rows_reordered", value, System.Type.GetType("Gtk.RowsReorderedHandler,gtk-sharp"), 0);
+	else
+	  ((GLib.SignalCallback) signals["rows_reordered"]).AddDelegate (value);
+
+	event_list.AddHandler("rows_reordered", value);
+      }
+
+      remove {
+	sigRemovalHelper (value, "rows_reordered");
+      }
+    }
+
+    private void sigRemovalHelper (Delegate d, string signame) {
+      System.ComponentModel.EventHandlerList event_list = AfterHandlers;
+      Hashtable signals = AfterSignals;
+      if (d.Method.GetCustomAttributes(typeof(GLib.ConnectBeforeAttribute), false).Length > 0) {
+	event_list = BeforeHandlers;
+	signals = BeforeSignals;
+      }
+      GLib.SignalCallback cb = signals[signame] as GLib.SignalCallback;
+      event_list.RemoveHandler(signame, d);
+      if (cb == null)
+	return;
+
+      cb.RemoveDelegate(d);
+
+      if (event_list["rows_reordered"] == null) {
+	signals.Remove("rows_reordered");
+	cb.Dispose ();
+      }
+    }
+
+    /*
+     * These are methods that are defined on tree_model, but are not part of the interface itself.
+     * This code is duplicated in ListStore and TreeStore, which sucks; there really should be a way
+     * to have a common ancestor for these.
+     */
+
+    [DllImport("libgtk-win32-2.0-0.dll")]
+    static extern void gtk_tree_model_get_valist(IntPtr raw, ref Gtk.TreeIter iter, IntPtr var_args);
+    
+    public void GetValist(Gtk.TreeIter iter, IntPtr var_args) {
+      gtk_tree_model_get_valist(Handle, ref iter, var_args);
+    }
+
+    [DllImport("libgtk-win32-2.0-0.dll")]
+    static extern IntPtr gtk_tree_model_get_string_from_iter(IntPtr raw, ref Gtk.TreeIter iter);
+
+    public string GetStringFromIter(Gtk.TreeIter iter) {
+      IntPtr raw_ret = gtk_tree_model_get_string_from_iter(Handle, ref iter);
+      string ret = GLib.Marshaller.PtrToStringGFree(raw_ret);
+      return ret;
+    }
+
+    [DllImport("libgtk-win32-2.0-0.dll")]
+    static extern bool gtk_tree_model_get_iter_from_string(IntPtr raw, ref Gtk.TreeIter iter, string path_string);
+
+    public bool GetIterFromString(ref Gtk.TreeIter iter, string path_string) {
+      bool raw_ret = gtk_tree_model_get_iter_from_string(Handle, ref iter, path_string);
+      bool ret = raw_ret;
+      return ret;
+    }
+
+
+    [DllImport("libgtk-win32-2.0-0.dll")]
+    static extern bool gtk_tree_model_get_iter_first(IntPtr raw, ref Gtk.TreeIter iter);
+
+    public bool GetIterFirst(ref Gtk.TreeIter iter) {
+      bool raw_ret = gtk_tree_model_get_iter_first(Handle, ref iter);
+      bool ret = raw_ret;
+      return ret;
+    }
+
+    [DllImport("libgtk-win32-2.0-0.dll")]
+    static extern void gtk_tree_model_foreach(IntPtr raw, GtkSharp.TreeModelForeachFuncNative func, IntPtr user_data);
+
+    public void Foreach(Gtk.TreeModelForeachFunc func) {
+      GtkSharp.TreeModelForeachFuncWrapper func_wrapper = null;
+      func_wrapper = new GtkSharp.TreeModelForeachFuncWrapper (func, this);
+      gtk_tree_model_foreach(Handle, func_wrapper.NativeDelegate, IntPtr.Zero);
+    }
+
+
+    /* Signal emitters */
+    [DllImport("libgtk-win32-2.0-0.dll")]
+    static extern void gtk_tree_model_row_changed(IntPtr raw, IntPtr path, ref Gtk.TreeIter iter);
+
+    public void EmitRowChanged(Gtk.TreePath path, Gtk.TreeIter iter) {
+      gtk_tree_model_row_changed(Handle, path.Handle, ref iter);
+    }
+
+    [DllImport("libgtk-win32-2.0-0.dll")]
+    static extern void gtk_tree_model_row_deleted(IntPtr raw, IntPtr path);
+
+    public void EmitRowDeleted(Gtk.TreePath path) {
+      gtk_tree_model_row_deleted(Handle, path.Handle);
+    }
+
+    [DllImport("libgtk-win32-2.0-0.dll")]
+    static extern void gtk_tree_model_row_inserted(IntPtr raw, IntPtr path, ref Gtk.TreeIter iter);
+
+    public void EmitRowInserted(Gtk.TreePath path, Gtk.TreeIter iter) {
+      gtk_tree_model_row_inserted(Handle, path.Handle, ref iter);
+    }
+
+    [DllImport("libgtk-win32-2.0-0.dll")]
+    static extern void gtk_tree_model_row_has_child_toggled(IntPtr raw, IntPtr path, ref Gtk.TreeIter iter);
+
+    public void EmitRowHasChildToggled(Gtk.TreePath path, Gtk.TreeIter iter) {
+      gtk_tree_model_row_has_child_toggled(Handle, path.Handle, ref iter);
+    }
+
+    [DllImport("libgtk-win32-2.0-0.dll")]
+    static extern void gtk_tree_model_rows_reordered(IntPtr raw, IntPtr path, ref Gtk.TreeIter iter, out int new_order);
+
+    public int EmitRowsReordered(Gtk.TreePath path, Gtk.TreeIter iter) {
+      int new_order;
+      gtk_tree_model_rows_reordered(Handle, path.Handle, ref iter, out new_order);
+      return new_order;
+    }
+
+    /* Convenience bits */
+
+    [DllImport("libgtk-win32-2.0-0.dll")]
+    static extern bool gtk_tree_model_iter_children (IntPtr raw, ref Gtk.TreeIter iter, IntPtr parent);
+
+    public bool IterChildren (ref Gtk.TreeIter iter) {
+      bool raw_ret = gtk_tree_model_iter_children (Handle, ref iter, IntPtr.Zero);
+      bool ret = raw_ret;
+      return ret;
+    }
+
+    [DllImport("libgtk-win32-2.0-0.dll")]
+    static extern int gtk_tree_model_iter_n_children (IntPtr raw, IntPtr iter);
+
+    public int IterNChildren () {
+      int raw_ret = gtk_tree_model_iter_n_children (Handle, IntPtr.Zero);
+      int ret = raw_ret;
+      return ret;
+    }
+
+    [DllImport("libgtk-win32-2.0-0.dll")]
+    static extern bool gtk_tree_model_iter_nth_child (IntPtr raw, ref Gtk.TreeIter iter, IntPtr parent, int n);
+
+    public bool IterNthChild (ref Gtk.TreeIter iter, int n) {
+      bool raw_ret = gtk_tree_model_iter_nth_child (Handle, ref iter, IntPtr.Zero, n);
+      bool ret = raw_ret;
+      return ret;
+    }
+
+    /*
+     * ManagedTreeModel impl details
+     */
+
+    internal delegate int TreeModelGetFlagsDelegate (IntPtr tree_model);
+    internal delegate int TreeModelGetNColumnsDelegate (IntPtr tree_model);
+    internal delegate IntPtr TreeModelGetColumnTypeDelegate (IntPtr tree_model, int index);
+    internal delegate bool TreeModelGetIterDelegate (IntPtr tree_model, ref TreeIter iter, IntPtr path);
+    internal delegate IntPtr /* path */ TreeModelGetPathDelegate (IntPtr tree_model, ref TreeIter iter);
+    internal delegate void TreeModelGetValueDelegate (IntPtr tree_model, ref TreeIter iter, int column, ref GLib.Value value);
+    internal delegate bool TreeModelIterNextDelegate (IntPtr tree_model, ref TreeIter iter);
+    internal delegate bool TreeModelIterChildrenDelegate (IntPtr tree_model, ref TreeIter iter, ref TreeIter parent);
+    internal delegate bool TreeModelIterHasChildDelegate (IntPtr tree_model, ref TreeIter iter);
+    internal delegate int TreeModelIterNChildrenDelegate (IntPtr tree_model, ref TreeIter iter);
+    internal delegate bool TreeModelIterNthChildDelegate (IntPtr tree_model, ref TreeIter iter, ref TreeIter parent, int n);
+    internal delegate bool TreeModelIterParentDelegate (IntPtr tree_model, ref TreeIter iter, ref TreeIter child);
+    internal delegate void TreeModelRefNodeDelegate (IntPtr tree_model, ref TreeIter iter);
+    internal delegate void TreeModelUnrefNodeDelegate (IntPtr tree_model, ref TreeIter iter);
+
+    /* This is a copy of the TreeModel interface struct */
+    internal struct TreeModelInterface {
+      /* GLib.GTypeInterface */
+      internal IntPtr g_type;
+      internal IntPtr g_instance_type;
+
+      /* GtkTreeModel */
+      /* signals */
+      internal IntPtr row_changed;
+      internal IntPtr row_inserted;
+      internal IntPtr row_has_child_toggled;
+      internal IntPtr row_deleted;
+      internal IntPtr rows_reordered;
+
+      /* vtbl */
+      internal TreeModelGetFlagsDelegate get_flags;
+      internal TreeModelGetNColumnsDelegate get_n_columns;
+      internal TreeModelGetColumnTypeDelegate get_column_type;
+      internal TreeModelGetIterDelegate get_iter;
+      internal TreeModelGetPathDelegate get_path;
+      internal TreeModelGetValueDelegate get_value;
+      internal TreeModelIterNextDelegate iter_next;
+      internal TreeModelIterChildrenDelegate iter_children;
+      internal TreeModelIterHasChildDelegate iter_has_child;
+      internal TreeModelIterNChildrenDelegate iter_n_children;
+      internal TreeModelIterNthChildDelegate iter_nth_child;
+      internal TreeModelIterParentDelegate iter_parent;
+      internal TreeModelRefNodeDelegate ref_node;
+      internal TreeModelUnrefNodeDelegate unref_node;
+    }
+
+    // internal delegate void GTreeModelInterfaceInitFuncDelegate (ref TreeModelInterface iface, IntPtr data);
+    internal delegate void GTreeModelInterfaceInitFuncDelegate (IntPtr iface, IntPtr data);
+    internal delegate void GTreeModelInterfaceFinalizeFuncDelegate (ref TreeModelInterface iface, IntPtr data);
+
+    internal struct GInterfaceInfo {
+      internal GTreeModelInterfaceInitFuncDelegate init_func;
+      internal GTreeModelInterfaceFinalizeFuncDelegate finalize_func;
+      internal IntPtr iface_data;
+    }
+
+    [DllImport("libgtk-win32-2.0-0.dll")]
+    static extern IntPtr gtk_tree_model_get_type ();
+
+    [DllImport("libgobject-2.0-0.dll")]
+    static extern void g_type_add_interface_static (IntPtr instance_type,
+						    IntPtr interface_type,
+						    ref GInterfaceInfo info);
+
+    internal static GLib.GType ManagedTreeModelGType;
+    internal static GInterfaceInfo ManagedTreeModelInterfaceInfo;
+
+    internal static GLib.GType ManagedTreeModelGetType () {
+      if (ManagedTreeModelGType.Val == IntPtr.Zero) {
+	/* register this type */
+	ManagedTreeModelGType = GLib.Object.RegisterGType (typeof(ManagedTreeModel));
+
+	/* Add the TreeModel interface */
+	ManagedTreeModelInterfaceInfo.init_func = new GTreeModelInterfaceInitFuncDelegate (tree_model_iface_init);
+	g_type_add_interface_static (ManagedTreeModelGType.Val, gtk_tree_model_get_type(), ref ManagedTreeModelInterfaceInfo);
+      }
+
+      return ManagedTreeModelGType;
+    }
+
+    // internal static void tree_model_iface_init (ref TreeModelInterface iface, IntPtr data) {
+    internal static void tree_model_iface_init (IntPtr ifaceptr, IntPtr data) {
+      TreeModelInterface iface = (TreeModelInterface) Marshal.PtrToStructure (ifaceptr, typeof(TreeModelInterface));
+
+      iface.get_flags = new TreeModelGetFlagsDelegate (TreeModelGetFlagsImpl);
+      iface.get_n_columns = new TreeModelGetNColumnsDelegate (TreeModelGetNColumnsImpl);
+      iface.get_column_type = new TreeModelGetColumnTypeDelegate (TreeModelGetColumnTypeImpl);
+      iface.get_iter = new TreeModelGetIterDelegate (TreeModelGetIterImpl);
+      iface.get_path = new TreeModelGetPathDelegate (TreeModelGetPathImpl);
+      iface.get_value = new TreeModelGetValueDelegate (TreeModelGetValueImpl);
+      iface.iter_next = new TreeModelIterNextDelegate (TreeModelIterNextImpl);
+      iface.iter_children = new TreeModelIterChildrenDelegate (TreeModelIterChildrenImpl);
+      iface.iter_has_child = new TreeModelIterHasChildDelegate (TreeModelIterHasChildImpl);
+      iface.iter_n_children = new TreeModelIterNChildrenDelegate (TreeModelIterNChildrenImpl);
+      iface.iter_nth_child = new TreeModelIterNthChildDelegate (TreeModelIterNthChildImpl);
+      iface.iter_parent = new TreeModelIterParentDelegate (TreeModelIterParentImpl);
+      iface.ref_node = new TreeModelRefNodeDelegate (TreeModelRefNodeImpl);
+      iface.unref_node = new TreeModelUnrefNodeDelegate (TreeModelUnrefNodeImpl);
+
+      Marshal.StructureToPtr (iface, ifaceptr, false);
+    }
+
+    internal static int TreeModelGetFlagsImpl (IntPtr tree_model) {
+      Gtk.TreeModel tm = (Gtk.TreeModel) GLib.Object.GetObject (tree_model, false);
+      return (int) tm.Flags;
+    }
+
+    internal static int TreeModelGetNColumnsImpl (IntPtr tree_model) {
+      Gtk.TreeModel tm = (Gtk.TreeModel) GLib.Object.GetObject (tree_model, false);
+      return tm.NColumns;
+    }
+
+    internal static IntPtr TreeModelGetColumnTypeImpl (IntPtr tree_model, int index) {
+      Gtk.TreeModel tm = (Gtk.TreeModel) GLib.Object.GetObject (tree_model, false);
+      return tm.GetColumnType (index).Val;
+    }
+
+    internal static bool TreeModelGetIterImpl (IntPtr tree_model, ref TreeIter iter, IntPtr path) {
+      Gtk.TreeModel tm = (Gtk.TreeModel) GLib.Object.GetObject (tree_model, false);
+      return tm.GetIter (ref iter, new TreePath(path));
+    }
+
+    internal static IntPtr /* path */ TreeModelGetPathImpl (IntPtr tree_model, ref TreeIter iter) {
+      Gtk.TreeModel tm = (Gtk.TreeModel) GLib.Object.GetObject (tree_model, false);
+      TreePath path = tm.GetPath (ref iter);
+      if (path == null)
+	return IntPtr.Zero;
+      return path.Handle;
+    }
+
+    internal static void TreeModelGetValueImpl (IntPtr tree_model, ref TreeIter iter, int column, ref GLib.Value value) {
+      Gtk.TreeModel tm = (Gtk.TreeModel) GLib.Object.GetObject (tree_model, false);
+      tm.GetValue (iter, column, ref value);
+    }
+
+    internal static bool TreeModelIterNextImpl (IntPtr tree_model, ref TreeIter iter) {
+      Gtk.TreeModel tm = (Gtk.TreeModel) GLib.Object.GetObject (tree_model, false);
+      return tm.IterNext (ref iter);
+    }
+
+    internal static bool TreeModelIterChildrenImpl (IntPtr tree_model, ref TreeIter iter, ref TreeIter parent) {
+      Gtk.TreeModel tm = (Gtk.TreeModel) GLib.Object.GetObject (tree_model, false);
+      return tm.IterChildren (ref iter, ref parent);
+    }
+
+    internal static bool TreeModelIterHasChildImpl (IntPtr tree_model, ref TreeIter iter) {
+      Gtk.TreeModel tm = (Gtk.TreeModel) GLib.Object.GetObject (tree_model, false);
+      return tm.IterHasChild (ref iter);
+    }
+
+    internal static int TreeModelIterNChildrenImpl (IntPtr tree_model, ref TreeIter iter) {
+      Gtk.TreeModel tm = (Gtk.TreeModel) GLib.Object.GetObject (tree_model, false);
+      return tm.IterNChildren (ref iter);
+    }
+
+    internal static bool TreeModelIterNthChildImpl (IntPtr tree_model, ref TreeIter iter, ref TreeIter parent, int n) {
+      Gtk.TreeModel tm = (Gtk.TreeModel) GLib.Object.GetObject (tree_model, false);
+      return tm.IterNthChild (ref iter, ref parent, n);
+    }
+
+    internal static bool TreeModelIterParentImpl (IntPtr tree_model, ref TreeIter iter, ref TreeIter child) {
+      Gtk.TreeModel tm = (Gtk.TreeModel) GLib.Object.GetObject (tree_model, false);
+      return tm.IterParent (ref iter, ref child);
+    }
+
+    internal static void TreeModelRefNodeImpl (IntPtr tree_model, ref TreeIter iter) {
+      Gtk.TreeModel tm = (Gtk.TreeModel) GLib.Object.GetObject (tree_model, false);
+      tm.RefNode (ref iter);
+    }
+
+    internal static void TreeModelUnrefNodeImpl (IntPtr tree_model, ref TreeIter iter) {
+      Gtk.TreeModel tm = (Gtk.TreeModel) GLib.Object.GetObject (tree_model, false);
+      tm.UnrefNode (ref iter);
+    }
+
+    public ManagedTreeModel ()
+      : base (ManagedTreeModelGetType ())
+    {
+    }
+
+    public ManagedTreeModel (IntPtr handle)
+      : base (handle)
+    {
+    }
+
+  }
+
+}
--- /dev/null	2004-02-23 13:02:56.000000000 -0800
+++ sample/ManagedModelDemo.cs	2004-05-24 01:19:11.985915992 -0700
@@ -0,0 +1,76 @@
+using System;
+
+using Gtk;
+
+public class SampleTreeModel : ManagedTreeModel {
+  public SampleTreeModel () {
+  }
+
+  public override int NColumns {
+    get {
+      return 2;
+    }
+  }
+
+  public override Type ColumnType (int index) {
+    return typeof(string);
+  }
+
+  public override bool GetIter (ref Gtk.TreeIter iter, Gtk.TreePath path) {
+    if (path == null)
+      return false;
+
+    if (path.Indices.Length != 1)
+      return false;
+
+    if (path.Indices[0] < 10) {
+      iter.UserData1 = (IntPtr) path.Indices[0];
+      return true;
+    }
+
+    return false;
+  }
+
+  public override Gtk.TreePath GetPath (ref Gtk.TreeIter iter) {
+    TreePath path = new TreePath ();
+    path.PrependIndex ((int) iter.UserData1);
+    return path;
+  }
+
+  public override object GetValue (Gtk.TreeIter iter, int column) {
+    int row = (int) iter.UserData1;
+    return String.Format ("Row {0} Column {1}", row, column);
+  }
+
+  public override bool IterNext (ref Gtk.TreeIter iter) {
+    int row = (int) iter.UserData1;
+    if (row < 10) {
+      iter.UserData1 = (IntPtr) (row + 1);
+      return true;
+    }
+    return false;
+  }
+}
+
+public class ManagedModelDemo {
+
+  public static void Main () {
+    Application.Init();
+
+    Window w = new Window("Managed Model Demo");
+    w.SetDefaultSize (500, 300);
+
+    ScrolledWindow sw = new ScrolledWindow ();
+
+    SampleTreeModel stm = new SampleTreeModel();
+    Console.WriteLine ("Stm Handle: {0}", ((int) stm.Handle).ToString("x"));
+    TreeView tv = new TreeView (stm);
+    tv.AppendColumn ("One", new Gtk.CellRendererText(), "text", 0);
+    tv.AppendColumn ("Two", new Gtk.CellRendererText(), "text", 1);
+    sw.Add (tv);
+    w.Add (sw);
+    w.ShowAll ();
+
+    Application.Run();
+  }
+}

--------------010405020209080506070209--