5
// Lluis Sanchez <lluis@xamarin.com>
7
// Copyright (c) 2011 Xamarin Inc
9
// Permission is hereby granted, free of charge, to any person obtaining a copy
10
// of this software and associated documentation files (the "Software"), to deal
11
// in the Software without restriction, including without limitation the rights
12
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
// copies of the Software, and to permit persons to whom the Software is
14
// furnished to do so, subject to the following conditions:
16
// The above copyright notice and this permission notice shall be included in
17
// all copies or substantial portions of the Software.
19
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
using System.Collections.Generic;
28
using System.Runtime.InteropServices;
30
namespace Xwt.GtkBackend
32
public class CustomTreeModel: Gtk.TreeModelImplementor
34
ITreeDataSource source;
35
Dictionary<GCHandle,TreePosition> nodeHash = new Dictionary<GCHandle,TreePosition> ();
36
Dictionary<TreePosition,GCHandle> handleHash = new Dictionary<TreePosition,GCHandle> ();
38
Gtk.TreeModelAdapter adapter;
40
public CustomTreeModel (ITreeDataSource source)
43
adapter = new Gtk.TreeModelAdapter (this);
44
colTypes = source.ColumnTypes;
46
source.NodeChanged += HandleNodeChanged;
47
source.NodeDeleted += HandleNodeDeleted;
48
source.NodeInserted += HandleNodeInserted;
49
source.NodesReordered += HandleNodesReordered;
52
public Gtk.TreeModelAdapter Store {
53
get { return adapter; }
56
public IntPtr Handle {
62
Gtk.TreeIter IterFromNode (TreePosition node)
65
if (!handleHash.TryGetValue (node, out gch)) {
66
gch = GCHandle.Alloc (node);
67
handleHash [node] = gch;
68
nodeHash [gch] = node;
70
Gtk.TreeIter result = Gtk.TreeIter.Zero;
71
result.UserData = (IntPtr)gch;
75
TreePosition NodeFromIter (Gtk.TreeIter iter)
78
GCHandle gch = (GCHandle)iter.UserData;
79
nodeHash.TryGetValue (gch, out node);
83
#region TreeModelImplementor implementation
85
void HandleNodesReordered (object sender, TreeNodeOrderEventArgs e)
87
Gtk.TreeIter it = IterFromNode (e.Node);
88
adapter.EmitRowsReordered (GetPath (it), it, e.ChildrenOrder);
91
void HandleNodeInserted (object sender, TreeNodeEventArgs e)
93
Gtk.TreeIter it = IterFromNode (e.Node);
94
adapter.EmitRowInserted (GetPath (it), it);
97
void HandleNodeDeleted (object sender, TreeNodeChildEventArgs e)
100
adapter.EmitRowDeleted (new Gtk.TreePath (new int[] { e.ChildIndex }));
102
Gtk.TreeIter it = IterFromNode (e.Node);
103
var p = GetPath (it);
104
int[] idx = new int [p.Indices.Length + 1];
105
p.Indices.CopyTo (idx, 0);
106
idx [idx.Length - 1] = e.ChildIndex;
107
adapter.EmitRowDeleted (new Gtk.TreePath (idx));
111
void HandleNodeChanged (object sender, TreeNodeEventArgs e)
113
Gtk.TreeIter it = IterFromNode (e.Node);
114
adapter.EmitRowChanged (GetPath (it), it);
117
public GLib.GType GetColumnType (int index)
119
return (GLib.GType) colTypes [index];
122
public bool GetIter (out Gtk.TreeIter iter, Gtk.TreePath path)
124
iter = Gtk.TreeIter.Zero;
125
TreePosition pos = null;
126
int[] indices = path.Indices;
127
if (indices.Length == 0)
129
for (int n=0; n<indices.Length; n++) {
130
pos = source.GetChild (pos, indices [n]);
134
iter = IterFromNode (pos);
138
public Gtk.TreePath GetPath (Gtk.TreeIter iter)
140
TreePosition pos = NodeFromIter (iter);
141
List<int> idx = new List<int> ();
142
while (pos != null) {
143
var parent = source.GetParent (pos);
144
idx.Add (GetIndex (parent, pos));
148
return new Gtk.TreePath (idx.ToArray ());
151
int GetIndex (TreePosition parent, TreePosition pos)
155
var c = source.GetChild (parent, n);
158
if (c == pos || c.Equals(pos))
164
public void GetValue (Gtk.TreeIter iter, int column, ref GLib.Value value)
166
TreePosition pos = NodeFromIter (iter);
167
var v = source.GetValue (pos, column);
168
value = new GLib.Value (v);
171
public bool IterNext (ref Gtk.TreeIter iter)
173
TreePosition pos = NodeFromIter (iter);
174
TreePosition parent = source.GetParent (pos);
175
int i = GetIndex (parent, pos);
176
pos = source.GetChild (parent, i + 1);
178
iter = IterFromNode (pos);
184
public bool IterChildren (out Gtk.TreeIter iter, Gtk.TreeIter parent)
186
iter = Gtk.TreeIter.Zero;
187
TreePosition pos = NodeFromIter (parent);
188
pos = source.GetChild (pos, 0);
190
iter = IterFromNode (pos);
196
public bool IterHasChild (Gtk.TreeIter iter)
198
TreePosition pos = NodeFromIter (iter);
199
return source.GetChildrenCount (pos) != 0;
202
public int IterNChildren (Gtk.TreeIter iter)
204
TreePosition pos = NodeFromIter (iter);
205
return source.GetChildrenCount (pos);
208
public bool IterNthChild (out Gtk.TreeIter iter, Gtk.TreeIter parent, int n)
210
iter = Gtk.TreeIter.Zero;
211
TreePosition pos = NodeFromIter (parent);
212
pos = source.GetChild (pos, n);
214
iter = IterFromNode (pos);
220
public bool IterParent (out Gtk.TreeIter iter, Gtk.TreeIter child)
222
iter = Gtk.TreeIter.Zero;
223
TreePosition pos = NodeFromIter (iter);
224
pos = source.GetParent (pos);
226
iter = IterFromNode (pos);
232
public void RefNode (Gtk.TreeIter iter)
236
public void UnrefNode (Gtk.TreeIter iter)
240
public Gtk.TreeModelFlags Flags {
242
return Gtk.TreeModelFlags.ItersPersist;
246
public int NColumns {
248
return colTypes.Length;