diff --git a/ChangeLog b/ChangeLog index 109121063..7e6ad8b9a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-03-04 Christian Hoff + + * gtk/NodeStore.cs: reimplement NodeStore as a managed TreeModel using GInterface implementation + * gtk/glue/nodestore.c: kill + 2009-02-27 Stephane Delcroix * gdk/Gdk.metadata: @@ -10,10 +15,12 @@ * gdk/Gdk.metadata: fix GdkPixbufFormat mime_types and extensions 2009-02-24 Christian Hoff + * glib/Value.cs: Change the pad fields handling again as the previous approach didn't work on Win32. [Fixes #478578] 2009-02-17 Christian Hoff + * sample/gtk-gio/MountOperation.cs: * gtk/Builder.custom: * glib/Value.cs: Resurrect build for MS .NET Framework diff --git a/gtk/NodeCellDataFunc.cs b/gtk/NodeCellDataFunc.cs index 5c1b3b193..47c80a7ba 100644 --- a/gtk/NodeCellDataFunc.cs +++ b/gtk/NodeCellDataFunc.cs @@ -32,9 +32,9 @@ namespace Gtk { { TreeViewColumn col = (Gtk.TreeViewColumn) GLib.Object.GetObject(tree_column); CellRenderer renderer = (Gtk.CellRenderer) GLib.Object.GetObject(cell); - NodeStore store = (NodeStore) GLib.Object.GetObject(tree_model); + NodeStore.NodeStoreImplementor store = (NodeStore.NodeStoreImplementor) GLib.Object.GetObject(tree_model); TreeIter iter = TreeIter.New (iter_ptr); - managed (col, renderer, store.GetNode (iter)); + managed (col, renderer, store.GetNode (iter)); } internal GtkSharp.CellLayoutDataFuncNative NativeDelegate; diff --git a/gtk/NodeSelection.cs b/gtk/NodeSelection.cs index a05af1565..734228558 100644 --- a/gtk/NodeSelection.cs +++ b/gtk/NodeSelection.cs @@ -43,7 +43,7 @@ namespace Gtk { public bool NodeIsSelected (ITreeNode node) { - return selection.IterIsSelected (NodeView.NodeStore.GetIter (node)); + return selection.IterIsSelected (NodeView.NodeStore.Implementor.GetIter (node)); } public bool PathIsSelected (TreePath path) @@ -58,7 +58,7 @@ namespace Gtk { public void SelectNode (ITreeNode node) { - selection.SelectIter (NodeView.NodeStore.GetIter (node)); + selection.SelectIter (NodeView.NodeStore.Implementor.GetIter (node)); } public void SelectPath (TreePath path) @@ -68,8 +68,8 @@ namespace Gtk { public void SelectRange (ITreeNode begin_node, ITreeNode end_node) { - TreePath begin = NodeView.NodeStore.GetPath (begin_node); - TreePath end = NodeView.NodeStore.GetPath (end_node); + TreePath begin = NodeView.NodeStore.Implementor.GetPath (begin_node); + TreePath end = NodeView.NodeStore.Implementor.GetPath (end_node); selection.SelectRange (begin, end); } @@ -81,7 +81,7 @@ namespace Gtk { public void UnselectNode (ITreeNode node) { - selection.UnselectIter (NodeView.NodeStore.GetIter (node)); + selection.UnselectIter (NodeView.NodeStore.Implementor.GetIter (node)); } public void UnselectPath (TreePath path) @@ -96,8 +96,8 @@ namespace Gtk { public void UnselectRange (ITreeNode begin_node, ITreeNode end_node) { - TreePath begin = NodeView.NodeStore.GetPath (begin_node); - TreePath end = NodeView.NodeStore.GetPath (end_node); + TreePath begin = NodeView.NodeStore.Implementor.GetPath (begin_node); + TreePath end = NodeView.NodeStore.Implementor.GetPath (end_node); selection.UnselectRange (begin, end); } diff --git a/gtk/NodeStore.cs b/gtk/NodeStore.cs index aae89bc9d..4c2a688c2 100644 --- a/gtk/NodeStore.cs +++ b/gtk/NodeStore.cs @@ -3,6 +3,7 @@ // Author: Mike Kestner // // Copyright (c) 2003-2005 Novell, Inc. +// Copyright (c) 2009 Christian Hoff // // This program is free software; you can redistribute it and/or // modify it under the terms of version 2 of the Lesser GNU General @@ -27,171 +28,227 @@ namespace Gtk { using System.Runtime.InteropServices; public class NodeStore : GLib.Object, IEnumerable { + internal readonly NodeStoreImplementor Implementor; - class IDHashtable : Hashtable { - class IDComparer : IComparer { - public int Compare (object x, object y) - { - if ((int) x == (int) y) - return 0; - else - return 1; - } - } + public NodeStore (Type node_type) + { + Implementor = new NodeStoreImplementor (node_type); + } - class IDHashCodeProvider : IHashCodeProvider { - public int GetHashCode (object o) - { - return (int) o; + // Redirect calls to implementor class + public ITreeNode GetNode (TreePath path) { return Implementor.GetNode (path); } + public void AddNode (ITreeNode node) { Implementor.AddNode (node); } + public void AddNode (ITreeNode node, int position) { Implementor.AddNode (node, position); } + public void RemoveNode (ITreeNode node) { Implementor.RemoveNode (node); } + public void Clear () { Implementor.Clear (); } + public IEnumerator GetEnumerator () { return Implementor.GetEnumerator (); } + + internal class NodeStoreImplementor : GLib.Object, TreeModelImplementor, IEnumerable { + TreeModelAdapter model_adapter; + GLib.GType[] ctypes; + MemberInfo [] getters; + int n_cols; + bool list_only = false; + ArrayList nodes = new ArrayList (); + + public readonly int Stamp; + + public NodeStoreImplementor (Type node_type) + { + // Create a random stamp for the iters + Random RandomStampGen = new Random (); + this.Stamp = RandomStampGen.Next (int.MinValue, int.MaxValue); + + ScanType (node_type); + + model_adapter = new Gtk.TreeModelAdapter (this); + } + + void ScanType (Type type) + { + TreeNodeAttribute tna = (TreeNodeAttribute) Attribute.GetCustomAttribute (type, typeof (TreeNodeAttribute), false); + if (tna != null) + list_only = tna.ListOnly; + + ArrayList minfos = new ArrayList (); + + foreach (PropertyInfo pi in type.GetProperties ()) + foreach (TreeNodeValueAttribute attr in pi.GetCustomAttributes (typeof (TreeNodeValueAttribute), false)) + minfos.Add (pi); + + foreach (FieldInfo fi in type.GetFields ()) + foreach (TreeNodeValueAttribute attr in fi.GetCustomAttributes (typeof (TreeNodeValueAttribute), false)) + minfos.Add (fi); + + n_cols = minfos.Count; + ctypes = new GLib.GType [n_cols]; + getters = new MemberInfo [n_cols]; + + foreach (MemberInfo mi in minfos) { + foreach (TreeNodeValueAttribute attr in mi.GetCustomAttributes (typeof (TreeNodeValueAttribute), false)) { + int col = attr.Column; + + if (getters [col] != null) + throw new Exception (String.Format ("You have two TreeNodeValueAttributes with the Column={0}", col)); + + getters [col] = mi; + Type t = mi is PropertyInfo ? ((PropertyInfo) mi).PropertyType + : ((FieldInfo) mi).FieldType; + ctypes [col] = (GLib.GType) t; + } } } - public IDHashtable () : base (new IDHashCodeProvider (), new IDComparer ()) {} - } - - [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; - } - - Hashtable node_hash = new IDHashtable (); - GLib.GType[] ctypes; - MemberInfo [] getters; - int n_cols; - bool list_only = false; - ArrayList nodes = new ArrayList (); - TreeModelIfaceDelegates tree_model_iface; - - int get_flags_cb () - { - TreeModelFlags result = TreeModelFlags.ItersPersist; - if (list_only) - result |= TreeModelFlags.ListOnly; - return (int) result; - } - - int get_n_columns_cb () - { - return n_cols; - } - - IntPtr get_column_type_cb (int col) - { - try { - return ctypes [col].Val; - } catch (Exception e) { - GLib.ExceptionManager.RaiseUnhandledException (e, false); + public TreeModelFlags Flags { + get { + TreeModelFlags result = TreeModelFlags.ItersPersist; + if (list_only) + result |= TreeModelFlags.ListOnly; + return result; + } } - return IntPtr.Zero; - } + public int NColumns { + get { + return n_cols; + } + } - bool get_node_cb (out int node_idx, IntPtr path) - { - try { - if (path == IntPtr.Zero) + public GLib.GType GetColumnType (int col) + { + return ctypes [col]; + } + +#region Gtk.TreePath handling + internal TreePath GetPath (ITreeNode node) + { + TreePath path = new TreePath (); + int idx; + + while (node.Parent != null) { + idx = node.Parent.IndexOf (node); + if (idx < 0) throw new Exception ("Badly formed tree"); + path.PrependIndex (idx); + node = node.Parent; + } + idx = Nodes.IndexOf (node); + if (idx < 0) throw new Exception ("Node not found in Nodes list"); + path.PrependIndex (idx); + + path.Owned = false; + return path; + } + + public ITreeNode GetNode (TreePath path) + { + if (path == null) + throw new ArgumentNullException (); + + int[] indices = path.Indices; + + if (indices[0] >= Nodes.Count) + return null; + + ITreeNode node = Nodes [indices [0]] as ITreeNode; + int i; + for (i = 1; i < path.Depth; i++) { + if (indices [i] >= node.ChildCount) + return null; + + node = node [indices [i]]; + } + + return node; + } +#endregion + +#region Gtk.TreeIter handling + ArrayList gc_handles = new ArrayList (); + + public override void Dispose () + { + // Free all the GCHandles pointing to the iters since they won't be garbage collected + foreach (System.Runtime.InteropServices.GCHandle handle in gc_handles) + handle.Free (); + + base.Dispose (); + } + + internal void GetIter (ITreeNode node, ref TreeIter iter) + { + if (node == null) + throw new ArgumentNullException ("node"); + + iter.Stamp = this.Stamp; + GCHandle gch = GCHandle.Alloc (node); + iter.UserData = (IntPtr) gch; + gc_handles.Add (gch); + } + + public TreeIter GetIter (ITreeNode node) + { + Gtk.TreeIter result = Gtk.TreeIter.Zero; + GetIter (node, ref result); + + return result; + } + + public ITreeNode GetNode (TreeIter iter) + { + if (iter.Stamp != this.Stamp) + throw new InvalidOperationException (String.Format ("iter belongs to a different model; it's stamp is not equal to the stamp of this model({0})", this.Stamp.ToString ())); + + System.Runtime.InteropServices.GCHandle gch = (System.Runtime.InteropServices.GCHandle) iter.UserData; + return gch.Target as ITreeNode; + } + + void TreeModelImplementor.RefNode (Gtk.TreeIter iter) { } + void TreeModelImplementor.UnrefNode (Gtk.TreeIter iter) { } +#endregion + + public bool GetIter (out TreeIter iter, TreePath path) + { + if (path == null) throw new ArgumentNullException ("path"); - - TreePath treepath = new TreePath (path); - node_idx = -1; - - ITreeNode node = GetNodeAtPath (treepath); - if (node == null) + + ITreeNode node = GetNode (path); + if (node == null) { + iter = TreeIter.Zero; return false; - - node_idx = node.ID; - node_hash [node.ID] = node; - return true; - } catch (Exception e) { - GLib.ExceptionManager.RaiseUnhandledException (e, false); + } else { + iter = GetIter (node); + return true; + } } - node_idx = -1; - return false; - } - IntPtr get_path_cb (int node_idx) - { - try { - ITreeNode node = node_hash [node_idx] as ITreeNode; - if (node == null) throw new Exception ("Invalid Node ID"); - - return GetPath (node).Handle; - } catch (Exception e) { - GLib.ExceptionManager.RaiseUnhandledException (e, false); + public Gtk.TreePath GetPath (TreeIter iter) + { + return GetPath (GetNode (iter)); } - return IntPtr.Zero; - } - [DllImport("libgobject-2.0-0.dll")] - static extern void g_value_init (ref GLib.Value val, IntPtr type); + public void GetValue (Gtk.TreeIter iter, int col, ref GLib.Value val) + { + ITreeNode node = GetNode (iter); + val.Init (ctypes [col]); - void get_value_cb (int node_idx, int col, ref GLib.Value val) - { - try { - ITreeNode node = node_hash [node_idx] as ITreeNode; - if (node == null) - return; - g_value_init (ref val, ctypes [col].Val); object col_val; if (getters [col] is PropertyInfo) col_val = ((PropertyInfo) getters [col]).GetValue (node, null); else col_val = ((FieldInfo) getters [col]).GetValue (node); val.Val = col_val; - } catch (Exception e) { - GLib.ExceptionManager.RaiseUnhandledException (e, false); } - } - bool next_cb (ref int node_idx) - { - try { - ITreeNode node = node_hash [node_idx] as ITreeNode; - if (node == null) - return false; + public bool IterNext (ref TreeIter iter) + { + ITreeNode node = GetNode (iter); int idx; if (node.Parent == null) idx = Nodes.IndexOf (node); else idx = node.Parent.IndexOf (node); - + if (idx < 0) throw new Exception ("Node not found in Nodes list"); if (node.Parent == null) { @@ -203,361 +260,158 @@ namespace Gtk { return false; node = node.Parent [idx]; } - node_hash [node.ID] = node; - node_idx = node.ID; + + GetIter (node, ref iter); return true; - } catch (Exception e) { - GLib.ExceptionManager.RaiseUnhandledException (e, false); } - return false; - } - bool children_cb (out int child_idx, int parent) - { - try { - child_idx = -1; - ITreeNode node; + public bool IterChildren (out Gtk.TreeIter first_child, Gtk.TreeIter parent) + { + first_child = Gtk.TreeIter.Zero; - if (parent == -1) { + if (parent.Equals (TreeIter.Zero)) { if (Nodes.Count <= 0) return false; - node = Nodes [0] as ITreeNode; - child_idx = node.ID; - node_hash [node.ID] = node; - return true; + first_child = GetIter (Nodes [0] as ITreeNode); + } else { + ITreeNode node = GetNode (parent); + if (node.ChildCount <= 0) + return false; + + first_child = GetIter (node [0]); } - - node = node_hash [parent] as ITreeNode; - if (node == null || node.ChildCount <= 0) - return false; - - ITreeNode child = node [0]; - node_hash [child.ID] = child; - child_idx = child.ID; return true; - } catch (Exception e) { - GLib.ExceptionManager.RaiseUnhandledException (e, false); } - child_idx = -1; - return false; - } - bool has_child_cb (int node_idx) - { - try { - ITreeNode node = node_hash [node_idx] as ITreeNode; - if (node == null || node.ChildCount <= 0) - return false; - - return true; - } catch (Exception e) { - GLib.ExceptionManager.RaiseUnhandledException (e, false); + public bool IterHasChild (Gtk.TreeIter iter) + { + return IterNChildren (iter) > 0; } - return false; - } - int n_children_cb (int node_idx) - { - try { - if (node_idx == -1) + public int IterNChildren (Gtk.TreeIter iter) + { + if (iter.Equals (TreeIter.Zero)) return Nodes.Count; - - ITreeNode node = node_hash [node_idx] as ITreeNode; - if (node == null || node.ChildCount <= 0) - return 0; - - return node.ChildCount; - } catch (Exception e) { - GLib.ExceptionManager.RaiseUnhandledException (e, false); + else + return GetNode (iter).ChildCount; } - return 0; - } - bool nth_child_cb (out int child_idx, int parent, int n) - { - child_idx = -1; - try { - ITreeNode node; + public bool IterNthChild (out Gtk.TreeIter child, Gtk.TreeIter parent, int n) + { + child = TreeIter.Zero; - if (parent == -1) { + if (parent.Equals (TreeIter.Zero)) { if (Nodes.Count <= n) return false; - node = Nodes [n] as ITreeNode; - child_idx = node.ID; - node_hash [node.ID] = node; + child = GetIter (Nodes [n] as ITreeNode); + } else { + ITreeNode parent_node = GetNode (parent); + if (parent_node.ChildCount <= n) + return false; + child = GetIter (parent_node [n]); + } + return true; + } + + public bool IterParent (out Gtk.TreeIter parent, Gtk.TreeIter child) + { + parent = TreeIter.Zero; + ITreeNode child_node = GetNode (child); + + if (child_node.Parent == null) + return false; + else { + parent = GetIter (child_node.Parent); return true; } - - node = node_hash [parent] as ITreeNode; - if (node == null || node.ChildCount <= n) - return false; - - ITreeNode child = node [n]; - node_hash [child.ID] = child; - child_idx = child.ID; - return true; - } catch (Exception e) { - GLib.ExceptionManager.RaiseUnhandledException (e, false); } - return false; - } - bool parent_cb (out int parent_idx, int child) - { - parent_idx = -1; - try { - ITreeNode node = node_hash [child] as ITreeNode; - if (node == null || node.Parent == null) - return false; - - node_hash [node.Parent.ID] = node.Parent; - parent_idx = node.Parent.ID; - return true; - } catch (Exception e) { - GLib.ExceptionManager.RaiseUnhandledException (e, false); - } - return false; - } - - [DllImport("gtksharpglue-2")] - 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.children = new ChildrenDelegate (children_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); - tree_model_iface.parent = new ParentDelegate (parent_cb); - - gtksharp_node_store_set_tree_model_callbacks (Handle, ref tree_model_iface); - } - - public NodeStore (Type node_type) : base (IntPtr.Zero) - { - CreateNativeObject (new string [0], new GLib.Value [0]); - ScanType (node_type); - BuildTreeModelIface (); - } - - void ScanType (Type type) - { - TreeNodeAttribute tna = (TreeNodeAttribute) Attribute.GetCustomAttribute (type, typeof (TreeNodeAttribute), false); - if (tna != null) - list_only = tna.ListOnly; - - ArrayList minfos = new ArrayList (); - - foreach (PropertyInfo pi in type.GetProperties ()) - foreach (TreeNodeValueAttribute attr in pi.GetCustomAttributes (typeof (TreeNodeValueAttribute), false)) - minfos.Add (pi); - - foreach (FieldInfo fi in type.GetFields ()) - foreach (TreeNodeValueAttribute attr in fi.GetCustomAttributes (typeof (TreeNodeValueAttribute), false)) - minfos.Add (fi); - - ctypes = new GLib.GType [minfos.Count]; - getters = new MemberInfo [minfos.Count]; - - foreach (MemberInfo mi in minfos) { - foreach (TreeNodeValueAttribute attr in mi.GetCustomAttributes (typeof (TreeNodeValueAttribute), false)) { - int col = attr.Column; - - if (getters [col] != null) - throw new Exception (String.Format ("You have two TreeNodeValueAttributes with the Column={0}", col)); - - getters [col] = mi; - Type t = mi is PropertyInfo ? ((PropertyInfo) mi).PropertyType - : ((FieldInfo) mi).FieldType; - ctypes [col] = (GLib.GType) t; + private IList Nodes { + get { + return nodes as IList; } } - } - private IList Nodes { - get { - return nodes as IList; + private void changed_cb (object o, EventArgs args) + { + ITreeNode node = o as ITreeNode; + model_adapter.EmitRowChanged (GetPath (node), GetIter (node)); } - } - [DllImport("gtksharpglue-2")] - static extern void gtksharp_node_store_emit_row_changed (IntPtr handle, IntPtr path, int node_idx); + private void EmitRowInserted (ITreeNode node) + { + model_adapter.EmitRowInserted (GetPath (node), GetIter (node)); + for (int i = 0; i < node.ChildCount; i++) + EmitRowInserted (node [i]); + } - private void changed_cb (object o, EventArgs args) - { - ITreeNode node = o as ITreeNode; - gtksharp_node_store_emit_row_changed (Handle, get_path_cb (node.ID), node.ID); - } + private void child_added_cb (object sender, ITreeNode child) + { + AddNodeInternal (child); + EmitRowInserted (child); + } - [DllImport("gtksharpglue-2")] - static extern void gtksharp_node_store_emit_row_inserted (IntPtr handle, IntPtr path, int node_idx); - - private void EmitRowInserted (ITreeNode node) - { - gtksharp_node_store_emit_row_inserted (Handle, get_path_cb (node.ID), node.ID); - for (int i = 0; i < node.ChildCount; i++) - EmitRowInserted (node [i]); - } - - private void child_added_cb (object o, ITreeNode child) - { - AddNodeInternal (child); - EmitRowInserted (child); - } - - [DllImport("gtksharpglue-2")] - static extern void gtksharp_node_store_emit_row_deleted (IntPtr handle, IntPtr path); - - [DllImport("gtksharpglue-2")] - static extern void gtksharp_node_store_emit_row_has_child_toggled (IntPtr handle, IntPtr path, int node_idx); - - private void RemoveNodeInternal (ITreeNode node) - { - node_hash.Remove (node.ID); - for (int i = 0; i < node.ChildCount; i++) - RemoveNodeInternal (node [i]); - } - - private void child_deleted_cb (object o, ITreeNode child, int idx) - { - ITreeNode node = o as ITreeNode; + private void child_deleted_cb (object sender, ITreeNode child, int idx) + { + ITreeNode node = sender as ITreeNode; - TreePath path = new TreePath (get_path_cb (node.ID)); - TreePath child_path = path.Copy (); - child_path.AppendIndex (idx); + TreePath path = GetPath (node); + TreePath child_path = path.Copy (); + child_path.AppendIndex (idx); - RemoveNodeInternal (child); + model_adapter.EmitRowDeleted (child_path); - gtksharp_node_store_emit_row_deleted (Handle, child_path.Handle); - - if (node.ChildCount <= 0) - gtksharp_node_store_emit_row_has_child_toggled (Handle, get_path_cb (node.ID), node.ID); - } - - private void AddNodeInternal (ITreeNode node) - { - node_hash [node.ID] = node; - - node.Changed += new EventHandler (changed_cb); - node.ChildAdded += new TreeNodeAddedHandler (child_added_cb); - node.ChildRemoved += new TreeNodeRemovedHandler (child_deleted_cb); - - for (int i = 0; i < node.ChildCount; i++) - AddNodeInternal (node [i]); - } - - public void AddNode (ITreeNode node) - { - nodes.Add (node); - AddNodeInternal (node); - EmitRowInserted (node); - } - - public void AddNode (ITreeNode node, int position) - { - nodes.Insert (position, node); - AddNodeInternal (node); - EmitRowInserted (node); - } - - public void RemoveNode (ITreeNode node) - { - int idx = nodes.IndexOf (node); - if (idx < 0) - return; - nodes.Remove (node); - RemoveNodeInternal (node); - - TreePath path = new TreePath (); - path.AppendIndex (idx); - - gtksharp_node_store_emit_row_deleted (Handle, path.Handle); - } - - public void Clear () - { - while (nodes.Count > 0) - RemoveNode ((ITreeNode)nodes [0]); - - } - - private ITreeNode GetNodeAtPath (TreePath path) - { - int[] indices = path.Indices; - - if (indices[0] >= Nodes.Count) - return null; - - ITreeNode node = Nodes [indices [0]] as ITreeNode; - int i; - for (i = 1; i < path.Depth; i++) { - if (indices [i] >= node.ChildCount) - return null; - - node = node [indices [i]]; + if (node.ChildCount <= 0) + model_adapter.EmitRowHasChildToggled (GetPath (node), GetIter (node)); } - return node; - } + private void AddNodeInternal (ITreeNode node) + { + node.Changed += new EventHandler (changed_cb); + node.ChildAdded += new TreeNodeAddedHandler (child_added_cb); + node.ChildRemoved += new TreeNodeRemovedHandler (child_deleted_cb); - public ITreeNode GetNode (TreePath path) - { - if (path == null) - throw new ArgumentNullException (); - - return GetNodeAtPath (path); - } - - internal ITreeNode GetNode (TreeIter iter) - { - return node_hash [(int) iter.UserData] as ITreeNode; - } - - internal TreePath GetPath (ITreeNode node) - { - TreePath path = new TreePath (); - int idx; - - while (node.Parent != null) { - idx = node.Parent.IndexOf (node); - if (idx < 0) throw new Exception ("Badly formed tree"); - path.PrependIndex (idx); - node = node.Parent; + for (int i = 0; i < node.ChildCount; i++) + AddNodeInternal (node [i]); } - idx = Nodes.IndexOf (node); - if (idx < 0) throw new Exception ("Node not found in Nodes list"); - path.PrependIndex (idx); - path.Owned = false; - return path; - } + public void AddNode (ITreeNode node) + { + nodes.Add (node); + AddNodeInternal (node); + EmitRowInserted (node); + } - internal TreeIter GetIter (ITreeNode node) - { - TreeIter iter = new TreeIter (); - iter.UserData = new IntPtr (node.ID); - return iter; - } + public void AddNode (ITreeNode node, int position) + { + nodes.Insert (position, node); + AddNodeInternal (node); + EmitRowInserted (node); + } - [DllImport("gtksharpglue-2")] - static extern IntPtr gtksharp_node_store_get_type (); - - public static new GLib.GType GType { - get { - return new GLib.GType (gtksharp_node_store_get_type ()); + public void RemoveNode (ITreeNode node) + { + int idx = nodes.IndexOf (node); + if (idx < 0) + return; + nodes.Remove (node); + + TreePath path = new TreePath (); + path.AppendIndex (idx); + + model_adapter.EmitRowDeleted (path); + } + + public void Clear () + { + while (nodes.Count > 0) + RemoveNode ((ITreeNode)nodes [0]); + } + + public IEnumerator GetEnumerator () + { + return nodes.GetEnumerator (); } } - - public IEnumerator GetEnumerator () - { - return nodes.GetEnumerator (); - } - } + } } diff --git a/gtk/NodeView.cs b/gtk/NodeView.cs index 5f4e07790..4790d7268 100644 --- a/gtk/NodeView.cs +++ b/gtk/NodeView.cs @@ -30,27 +30,20 @@ namespace Gtk { NodeStore store; NodeSelection selection; - public NodeView (NodeStore store) : base (IntPtr.Zero) + public NodeView (NodeStore store) : base (store == null ? null : new Gtk.TreeModelAdapter (store.Implementor)) { - string[] names = { "model" }; - GLib.Value[] vals = { new GLib.Value (store) }; - CreateNativeObject (names, vals); - vals [0].Dispose (); this.store = store; } public NodeView () : base () {} - [DllImport("libgtk-win32-2.0-0.dll")] - static extern void gtk_tree_view_set_model(IntPtr raw, IntPtr model); - public NodeStore NodeStore { get { return store; } set { store = value; - gtk_tree_view_set_model (Handle, store == null ? IntPtr.Zero : store.Handle); + this.Model = store == null ? null : new Gtk.TreeModelAdapter (store.Implementor); } } diff --git a/gtk/TreeView.custom b/gtk/TreeView.custom index 70fbabb71..ed5c53447 100644 --- a/gtk/TreeView.custom +++ b/gtk/TreeView.custom @@ -25,20 +25,7 @@ [Obsolete ("Use NodeView with NodeStores")] - public TreeView (NodeStore store) : base (IntPtr.Zero) - { - if (GetType() != typeof (TreeView)) { - string[] names = new string [1]; - GLib.Value[] vals = new GLib.Value [1]; - names [0] = "model"; - vals [0] = new GLib.Value (store); - CreateNativeObject (names, vals); - vals [0].Dispose (); - return; - } - - Raw = gtk_tree_view_new_with_model (store.Handle); - } + public TreeView (NodeStore store) : this (store == null ? null : new Gtk.TreeModelAdapter (store.Implementor)) { } public Gdk.Color OddRowColor { get { diff --git a/gtk/glue/Makefile.am b/gtk/glue/Makefile.am index 7f4f0e6b8..c6bfa7a05 100644 --- a/gtk/glue/Makefile.am +++ b/gtk/glue/Makefile.am @@ -5,7 +5,6 @@ libgtksharpglue_2_la_SOURCES = \ cellrenderer.c \ clipboard.c \ container.c \ - nodestore.c \ object.c \ selectiondata.c \ statusicon.c \ diff --git a/gtk/glue/nodestore.c b/gtk/glue/nodestore.c deleted file mode 100644 index a04360a65..000000000 --- a/gtk/glue/nodestore.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * nodestore.c - * - * Copyright (c) 2003 Novell, Inc. - * - * Authors: Mike Kestner - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the Lesser GNU General - * Public License as published by the Free Software Foundation. - * - * This program 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include - -typedef GtkTreeModelFlags (* GtkSharpNodeStoreGetFlagsFunc) (void); -typedef gint (* GtkSharpNodeStoreGetNColumnsFunc) (void); -typedef GType (* GtkSharpNodeStoreGetColumnTypeFunc) (gint col); -typedef gboolean (* GtkSharpNodeStoreGetNodeFunc) (gint *node_idx, GtkTreePath *path); -typedef GtkTreePath* (* GtkSharpNodeStoreGetPathFunc) (gint node_idx); -typedef void (* GtkSharpNodeStoreGetValueFunc) (gint node_idx, gint col, GValue *value); -typedef gboolean (* GtkSharpNodeStoreIterNextFunc) (gint *node_idx); -typedef gboolean (* GtkSharpNodeStoreIterChildrenFunc) (gint *first_child, gint parent); -typedef gboolean (* GtkSharpNodeStoreIterHasChildFunc) (gint node_idx); -typedef gint (* GtkSharpNodeStoreIterNChildrenFunc) (gint node_idx); -typedef gboolean (* GtkSharpNodeStoreIterNthChildFunc) (gint *child, gint parent, gint n); -typedef gboolean (* GtkSharpNodeStoreIterParentFunc) (gint *parent, gint child); - -typedef struct _GtkSharpNodeStoreTreeModelIface { - GtkSharpNodeStoreGetFlagsFunc get_flags; - GtkSharpNodeStoreGetNColumnsFunc get_n_columns; - GtkSharpNodeStoreGetColumnTypeFunc get_column_type; - GtkSharpNodeStoreGetNodeFunc get_node; - GtkSharpNodeStoreGetPathFunc get_path; - GtkSharpNodeStoreGetValueFunc get_value; - GtkSharpNodeStoreIterNextFunc iter_next; - GtkSharpNodeStoreIterChildrenFunc iter_children; - GtkSharpNodeStoreIterHasChildFunc iter_has_child; - GtkSharpNodeStoreIterNChildrenFunc iter_n_children; - GtkSharpNodeStoreIterNthChildFunc iter_nth_child; - GtkSharpNodeStoreIterParentFunc iter_parent; -} GtkSharpNodeStoreTreeModelIface; - -typedef struct _GtkSharpNodeStore { - GObject parent; - - gint stamp; - GtkSharpNodeStoreTreeModelIface tree_model; -} GtkSharpNodeStore; - -typedef struct _GtkSharpNodeStoreClass { - GObjectClass parent; -} GtkSharpNodeStoreClass; - -GType gtksharp_node_store_get_type (void); -GObject * gtksharp_node_store_new (void); -void gtksharp_node_store_set_tree_model_callbacks (GtkSharpNodeStore *store, GtkSharpNodeStoreTreeModelIface *iface); -void gtksharp_node_store_emit_row_changed (GtkSharpNodeStore *store, GtkTreePath *path, gint node_idx); -void gtksharp_node_store_emit_row_inserted (GtkSharpNodeStore *store, GtkTreePath *path, gint node_idx); -void gtksharp_node_store_emit_row_deleted (GtkSharpNodeStore *store, GtkTreePath *path); -void gtksharp_node_store_emit_row_has_child_toggled (GtkSharpNodeStore *store, GtkTreePath *path, gint node_idx); - -static GtkTreeModelFlags -gns_get_flags (GtkTreeModel *model) -{ - GtkSharpNodeStore *store = (GtkSharpNodeStore *) model; - return store->tree_model.get_flags (); -} - -static int -gns_get_n_columns (GtkTreeModel *model) -{ - GtkSharpNodeStore *store = (GtkSharpNodeStore *) model; - return store->tree_model.get_n_columns (); -} - -static GType -gns_get_column_type (GtkTreeModel *model, int col) -{ - GtkSharpNodeStore *store = (GtkSharpNodeStore *) model; - return store->tree_model.get_column_type (col); -} - -static gboolean -gns_get_iter (GtkTreeModel *model, GtkTreeIter *iter, GtkTreePath *path) -{ - GtkSharpNodeStore *store = (GtkSharpNodeStore *) model; - gint node_idx; - - if (!store->tree_model.get_node (&node_idx, path)) - return FALSE; - - iter->stamp = store->stamp; - iter->user_data = GINT_TO_POINTER (node_idx); - return TRUE; -} - -static GtkTreePath * -gns_get_path (GtkTreeModel *model, GtkTreeIter *iter) -{ - GtkSharpNodeStore *store = (GtkSharpNodeStore *) model; - return store->tree_model.get_path (GPOINTER_TO_INT (iter->user_data)); -} - -static void -gns_get_value (GtkTreeModel *model, GtkTreeIter *iter, int col, GValue *value) -{ - GtkSharpNodeStore *store = (GtkSharpNodeStore *) model; - store->tree_model.get_value (GPOINTER_TO_INT (iter->user_data), col, value); -} - -static gboolean -gns_iter_next (GtkTreeModel *model, GtkTreeIter *iter) -{ - GtkSharpNodeStore *store = (GtkSharpNodeStore *) model; - gint node_idx; - - if (store->stamp != iter->stamp) - return FALSE; - - node_idx = GPOINTER_TO_INT (iter->user_data); - if (!store->tree_model.iter_next (&node_idx)) { - iter->stamp = -1; - return FALSE; - } - - iter->user_data = GINT_TO_POINTER (node_idx); - return TRUE; -} - -static gboolean -gns_iter_children (GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *parent) -{ - GtkSharpNodeStore *store = (GtkSharpNodeStore *) model; - gint child_idx, parent_idx; - - if (!parent) - parent_idx = -1; - else { - if (store->stamp != parent->stamp) - return FALSE; - parent_idx = GPOINTER_TO_INT (parent->user_data); - } - - if (!store->tree_model.iter_children (&child_idx, parent_idx)) - return FALSE; - - iter->stamp = store->stamp; - iter->user_data = GINT_TO_POINTER (child_idx); - return TRUE; -} - -static gboolean -gns_iter_has_child (GtkTreeModel *model, GtkTreeIter *iter) -{ - GtkSharpNodeStore *store = (GtkSharpNodeStore *) model; - return store->tree_model.iter_has_child (GPOINTER_TO_INT (iter->user_data)); -} - -static int -gns_iter_n_children (GtkTreeModel *model, GtkTreeIter *iter) -{ - GtkSharpNodeStore *store = (GtkSharpNodeStore *) model; - gint node_idx; - - if (!iter) - node_idx = -1; - else { - if (store->stamp != iter->stamp) - return 0; - node_idx = GPOINTER_TO_INT (iter->user_data); - } - - return store->tree_model.iter_n_children (node_idx); -} - -static gboolean -gns_iter_nth_child (GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *parent, int n) -{ - GtkSharpNodeStore *store = (GtkSharpNodeStore *) model; - gint child_idx, parent_idx; - - if (!parent) - parent_idx = -1; - else { - if (store->stamp != parent->stamp) - return FALSE; - parent_idx = GPOINTER_TO_INT (parent->user_data); - } - - if (!store->tree_model.iter_nth_child (&child_idx, parent_idx, n)) - return FALSE; - - iter->stamp = store->stamp; - iter->user_data = GINT_TO_POINTER (child_idx); - return TRUE; -} - -static gboolean -gns_iter_parent (GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *child) -{ - GtkSharpNodeStore *store = (GtkSharpNodeStore *) model; - gint parent; - - if (store->stamp != child->stamp) - return FALSE; - - if (!store->tree_model.iter_parent (&parent, GPOINTER_TO_INT (child->user_data))) - return FALSE; - - iter->stamp = store->stamp; - iter->user_data = GINT_TO_POINTER (parent); - return TRUE; -} - -static void -gns_tree_model_init (GtkTreeModelIface *iface) -{ - iface->get_flags = gns_get_flags; - iface->get_n_columns = gns_get_n_columns; - iface->get_column_type = gns_get_column_type; - iface->get_iter = gns_get_iter; - iface->get_path = gns_get_path; - iface->get_value = gns_get_value; - iface->iter_next = gns_iter_next; - iface->iter_children = gns_iter_children; - iface->iter_has_child = gns_iter_has_child; - iface->iter_n_children = gns_iter_n_children; - iface->iter_nth_child = gns_iter_nth_child; - iface->iter_parent = gns_iter_parent; -} - -static void -gns_class_init (GObjectClass *klass) -{ -} - - -static void -gns_init (GtkSharpNodeStore *store) -{ - store->stamp = 0; - store->tree_model.get_flags = NULL; - store->tree_model.get_n_columns = NULL; - store->tree_model.get_column_type = NULL; - store->tree_model.get_node = NULL; - store->tree_model.get_path = NULL; - store->tree_model.get_value = NULL; - store->tree_model.iter_next = NULL; - store->tree_model.iter_children = NULL; - store->tree_model.iter_has_child = NULL; - store->tree_model.iter_n_children = NULL; - store->tree_model.iter_nth_child = NULL; - store->tree_model.iter_parent = NULL; -} - -GType -gtksharp_node_store_get_type (void) -{ - static GType gns_type = 0; - - if (!gns_type) { - static const GTypeInfo gns_info = { - sizeof (GtkSharpNodeStoreClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) gns_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GtkSharpNodeStore), - 0, - (GInstanceInitFunc) gns_init }; - - static const GInterfaceInfo tree_model_info = { - (GInterfaceInitFunc) gns_tree_model_init, - NULL, - NULL }; - - gns_type = g_type_register_static (G_TYPE_OBJECT, "GtkSharpNodeStore", &gns_info, 0); - - g_type_add_interface_static (gns_type, GTK_TYPE_TREE_MODEL, &tree_model_info); - } - - return gns_type; -} - -GObject * -gtksharp_node_store_new (void) -{ - return g_object_new (gtksharp_node_store_get_type (), NULL); -} - -void -gtksharp_node_store_set_tree_model_callbacks (GtkSharpNodeStore *store, GtkSharpNodeStoreTreeModelIface *iface) -{ - store->tree_model = *iface; -} - -void -gtksharp_node_store_emit_row_changed (GtkSharpNodeStore *store, GtkTreePath *path, gint node_idx) -{ - GtkTreeIter iter; - - iter.stamp = store->stamp; - iter.user_data = GINT_TO_POINTER (node_idx); - - gtk_tree_model_row_changed (GTK_TREE_MODEL (store), path, &iter); -} - -void -gtksharp_node_store_emit_row_inserted (GtkSharpNodeStore *store, GtkTreePath *path, gint node_idx) -{ - GtkTreeIter iter; - - iter.stamp = store->stamp; - iter.user_data = GINT_TO_POINTER (node_idx); - - gtk_tree_model_row_inserted (GTK_TREE_MODEL (store), path, &iter); -} - -void -gtksharp_node_store_emit_row_deleted (GtkSharpNodeStore *store, GtkTreePath *path) -{ - gtk_tree_model_row_deleted (GTK_TREE_MODEL (store), path); -} - -void -gtksharp_node_store_emit_row_has_child_toggled (GtkSharpNodeStore *store, GtkTreePath *path, gint node_idx) -{ - GtkTreeIter iter; - - iter.stamp = store->stamp; - iter.user_data = GINT_TO_POINTER (node_idx); - - gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (store), path, &iter); -} -