using System; using System.Collections; using Gtk; namespace AdaptorTest { using System; using System.Collections; using System.Reflection; using System.Runtime.InteropServices; public class ListAdaptor : GLib.Object, IEnumerable { [GLib.CDeclCallback] delegate int GetFlagsDelegate (); [GLib.CDeclCallback] delegate int GetNColumnsDelegate (); [GLib.CDeclCallback] delegate IntPtr GetColumnTypeDelegate (int col); [GLib.CDeclCallback] delegate bool GetNodeDelegate (out int node_idx, IntPtr path); [GLib.CDeclCallback] delegate IntPtr GetPathDelegate (int node_idx); [GLib.CDeclCallback] delegate void GetValueDelegate (int node_idx, int col, ref GLib.Value val); [GLib.CDeclCallback] delegate bool NextDelegate (ref int node_idx); [GLib.CDeclCallback] delegate bool ChildrenDelegate (out int child, int parent); [GLib.CDeclCallback] delegate bool HasChildDelegate (int node_idx); [GLib.CDeclCallback] delegate int NChildrenDelegate (int node_idx); [GLib.CDeclCallback] delegate bool NthChildDelegate (out int child, int parent, int n); [GLib.CDeclCallback] delegate bool ParentDelegate (out int parent, int child); [StructLayout(LayoutKind.Sequential)] struct TreeModelIfaceDelegates { public GetFlagsDelegate get_flags; public GetNColumnsDelegate get_n_columns; public GetColumnTypeDelegate get_column_type; public GetNodeDelegate get_node; public GetPathDelegate get_path; public GetValueDelegate get_value; public NextDelegate next; public ChildrenDelegate children; public HasChildDelegate has_child; public NChildrenDelegate n_children; public NthChildDelegate nth_child; public ParentDelegate parent; } IList store; TreeModelIfaceDelegates tree_model_iface; public TreeViewAdaptor TreeViewAdaptor = null; int index = 0; int get_flags_cb () { Console.WriteLine ("get_flags_cb"); TreeModelFlags result = TreeModelFlags.ItersPersist; result |= TreeModelFlags.ListOnly; return (int) result; } int get_n_columns_cb () { if (this.TreeViewAdaptor == null) return 0; Console.WriteLine ("get_n_columns_cb: " + this.TreeViewAdaptor.column_mappings.Count.ToString()); return this.TreeViewAdaptor.column_mappings.Count; } IntPtr get_column_type_cb (int col) { Console.WriteLine ("get_column_type_cb"+col.ToString()); GLib.GType type = (GLib.GType)this.TreeViewAdaptor.column_types [col]; return type.Val; } bool get_node_cb (out int node_idx, IntPtr path) { if (path == IntPtr.Zero) throw new ArgumentNullException ("path"); TreePath treepath = new TreePath (path); int i = treepath.Indices[0]; Console.WriteLine ("get_node_cb:" + i.ToString()); if (i >= this.store.Count) { node_idx = -1; return false; } this.index = i; node_idx = this.index; return true; } IntPtr get_path_cb (int node_idx) { Console.WriteLine ("get_path_cb"); TreePath path = new TreePath (); if (node_idx < 0) throw new Exception ("Node not found in Nodes list"); path.PrependIndex (node_idx); path.Owned = false; return path.Handle; } [DllImport("/usr/lib/libgobject-2.0.so")] static extern void g_value_init (ref GLib.Value val, IntPtr type); void get_value_cb (int node_idx, int col, ref GLib.Value val) { Console.WriteLine ("get_value_cb"); bool found = false; if (this.TreeViewAdaptor == null) return; object instance = this.store [node_idx]; string property = (string) this.TreeViewAdaptor.column_mappings [col]; g_value_init (ref val, get_column_type_cb (col)); object col_val; Type type = instance.GetType(); foreach (PropertyInfo pi in type.GetProperties ()) { if (pi.Name == property) { col_val = pi.GetValue (instance, null); val.Val = col_val; Console.WriteLine ("found: " + col_val.ToString()); found = true; break; } } if (!found) throw new Exception ("Invalid MappingName"); } bool next_cb (ref int node_idx) { // The iter is also the index. Console.Write ("next_cb:"+this.store.Count.ToString() + " - " + node_idx.ToString()); if (node_idx < 0 || node_idx+1 > this.store.Count) { Console.WriteLine ("false"); return false; } this.index = node_idx + 1; node_idx = this.index; Console.WriteLine ("true"); return true; } bool has_child_cb (int node_idx) { Console.WriteLine ("has_child_cb:"+ node_idx.ToString()); return false; } int n_children_cb (int node_idx) { Console.WriteLine ("n_children_cb:" + node_idx.ToString()); if (node_idx == -1) return store.Count; return -1; } bool nth_child_cb (out int child_idx, int parent, int n) { child_idx = n; Console.WriteLine ("nth_child_cb:" + child_idx.ToString() + " " + parent.ToString() + " " + n.ToString()); if (n < 0 || n > this.store.Count) return false; this.index = n; return true; } [DllImport("/usr/lib/mono/gtk-sharp-2.0/libgtksharpglue-2.so")] static extern void gtksharp_node_store_set_tree_model_callbacks (IntPtr raw, ref TreeModelIfaceDelegates cbs); private void BuildTreeModelIface () { tree_model_iface.get_flags = new GetFlagsDelegate (get_flags_cb); tree_model_iface.get_n_columns = new GetNColumnsDelegate (get_n_columns_cb); tree_model_iface.get_column_type = new GetColumnTypeDelegate (get_column_type_cb); tree_model_iface.get_node = new GetNodeDelegate (get_node_cb); tree_model_iface.get_path = new GetPathDelegate (get_path_cb); tree_model_iface.get_value = new GetValueDelegate (get_value_cb); tree_model_iface.next = new NextDelegate (next_cb); tree_model_iface.has_child = new HasChildDelegate (has_child_cb); tree_model_iface.n_children = new NChildrenDelegate (n_children_cb); tree_model_iface.nth_child = new NthChildDelegate (nth_child_cb); gtksharp_node_store_set_tree_model_callbacks (Handle, ref tree_model_iface); } public ListAdaptor (IList source) : base (IntPtr.Zero) { CreateNativeObject (new string [0], new GLib.Value [0]); BuildTreeModelIface (); this.store = source; } [DllImport("/usr/lib/mono/gtk-sharp-2.0/libgtksharpglue-2.so")] static extern IntPtr gtksharp_node_store_get_type (); public static new GLib.GType GType { get { GLib.GType t = new GLib.GType (gtksharp_node_store_get_type ()); return t; } } public IEnumerator GetEnumerator () { return this.store.GetEnumerator (); } } }