~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/xwt/Xwt/Xwt/TreeStore.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// 
 
2
// TreeStore.cs
 
3
//  
 
4
// Author:
 
5
//       Lluis Sanchez <lluis@xamarin.com>
 
6
// 
 
7
// Copyright (c) 2011 Xamarin Inc
 
8
// 
 
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:
 
15
// 
 
16
// The above copyright notice and this permission notice shall be included in
 
17
// all copies or substantial portions of the Software.
 
18
// 
 
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
 
25
// THE SOFTWARE.
 
26
 
 
27
 
 
28
using System;
 
29
using System.Linq;
 
30
using System.Collections.Generic;
 
31
using Xwt.Backends;
 
32
using System.ComponentModel;
 
33
 
 
34
namespace Xwt
 
35
{
 
36
        public class TreeStore: XwtComponent, ITreeDataSource
 
37
        {
 
38
                DataField[] fields;
 
39
                
 
40
                class TreeStoreBackendHost: BackendHost<TreeStore,ITreeStoreBackend>
 
41
                {
 
42
                        protected override IBackend OnCreateBackend ()
 
43
                        {
 
44
                                var b = base.OnCreateBackend ();
 
45
                                if (b == null)
 
46
                                        b = new DefaultTreeStoreBackend ();
 
47
                                ((ITreeStoreBackend)b).Initialize (Parent.fields.Select (f => f.FieldType).ToArray ());
 
48
                                return b;
 
49
                        }
 
50
                }
 
51
                
 
52
                protected override Xwt.Backends.BackendHost CreateBackendHost ()
 
53
                {
 
54
                        return new TreeStoreBackendHost ();
 
55
                }
 
56
                
 
57
                public TreeStore (params DataField[] fields)
 
58
                {
 
59
                        for (int n=0; n<fields.Length; n++) {
 
60
                                if (fields[n].Index != -1)
 
61
                                        throw new InvalidOperationException ("DataField object already belongs to another data store");
 
62
                                fields[n].Index = n;
 
63
                        }
 
64
                        this.fields = fields;
 
65
                }
 
66
                
 
67
                ITreeStoreBackend Backend {
 
68
                        get { return (ITreeStoreBackend)BackendHost.Backend; }
 
69
                }
 
70
                
 
71
                public TreeNavigator GetFirstNode ()
 
72
                {
 
73
                        var p = Backend.GetChild (null, 0);
 
74
                        return new TreeNavigator (Backend, p);
 
75
                }
 
76
                
 
77
                public TreeNavigator GetNavigatorAt (TreePosition pos)
 
78
                {
 
79
                        return new TreeNavigator (Backend, pos);
 
80
                }
 
81
                
 
82
                public TreeNavigator AddNode ()
 
83
                {
 
84
                        var pos = Backend.AddChild (null);
 
85
                        return new TreeNavigator (Backend, pos);
 
86
                }
 
87
 
 
88
                public TreeNavigator AddNode (TreePosition position)
 
89
                {
 
90
                        var pos = Backend.AddChild (position);
 
91
                        return new TreeNavigator (Backend, pos);
 
92
                }
 
93
                
 
94
                public void Clear ()
 
95
                {
 
96
                        Backend.Clear ();
 
97
                }
 
98
 
 
99
                event EventHandler<TreeNodeEventArgs> ITreeDataSource.NodeInserted {
 
100
                        add { Backend.NodeInserted += value; }
 
101
                        remove { Backend.NodeInserted -= value; }
 
102
                }
 
103
                event EventHandler<TreeNodeChildEventArgs> ITreeDataSource.NodeDeleted {
 
104
                        add { Backend.NodeDeleted += value; }
 
105
                        remove { Backend.NodeDeleted -= value; }
 
106
                }
 
107
                event EventHandler<TreeNodeEventArgs> ITreeDataSource.NodeChanged {
 
108
                        add { Backend.NodeChanged += value; }
 
109
                        remove { Backend.NodeChanged -= value; }
 
110
                }
 
111
                event EventHandler<TreeNodeOrderEventArgs> ITreeDataSource.NodesReordered {
 
112
                        add { Backend.NodesReordered += value; }
 
113
                        remove { Backend.NodesReordered -= value; }
 
114
                }
 
115
                
 
116
                TreePosition ITreeDataSource.GetChild (TreePosition pos, int index)
 
117
                {
 
118
                        return Backend.GetChild (pos, index);
 
119
                }
 
120
 
 
121
                TreePosition ITreeDataSource.GetParent (TreePosition pos)
 
122
                {
 
123
                        return Backend.GetParent (pos);
 
124
                }
 
125
 
 
126
                int ITreeDataSource.GetChildrenCount (TreePosition pos)
 
127
                {
 
128
                        return Backend.GetChildrenCount (pos);
 
129
                }
 
130
 
 
131
                object ITreeDataSource.GetValue (TreePosition pos, int column)
 
132
                {
 
133
                        return Backend.GetValue (pos, column);
 
134
                }
 
135
 
 
136
                void ITreeDataSource.SetValue (TreePosition pos, int column, object val)
 
137
                {
 
138
                        Backend.SetValue (pos, column, val);
 
139
                }
 
140
                
 
141
                Type[] ITreeDataSource.ColumnTypes {
 
142
                        get {
 
143
                                return fields.Select (f => f.FieldType).ToArray ();
 
144
                        }
 
145
                }
 
146
        }
 
147
        
 
148
        class DefaultTreeStoreBackend: ITreeStoreBackend
 
149
        {
 
150
                struct Node {
 
151
                        public object[] Data;
 
152
                        public NodeList Children;
 
153
                        public int NodeId;
 
154
                }
 
155
                
 
156
                class NodePosition: TreePosition
 
157
                {
 
158
                        public NodeList ParentList;
 
159
                        public int NodeIndex;
 
160
                        public int NodeId;
 
161
                        public int StoreVersion;
 
162
                        
 
163
                        public override bool Equals (object obj)
 
164
                        {
 
165
                                NodePosition other = (NodePosition) obj;
 
166
                                if (other == null)
 
167
                                        return false;
 
168
                                return ParentList == other.ParentList && NodeId == other.NodeId;
 
169
                        }
 
170
                        
 
171
                        public override int GetHashCode ()
 
172
                        {
 
173
                                return ParentList.GetHashCode () ^ NodeId;
 
174
                        }
 
175
                }
 
176
                
 
177
                class NodeList: List<Node>
 
178
                {
 
179
                        public NodePosition Parent;
 
180
                }
 
181
                
 
182
                Type[] columnTypes;
 
183
                NodeList rootNodes = new NodeList ();
 
184
                int version;
 
185
                int nextNodeId;
 
186
                
 
187
                public event EventHandler<TreeNodeEventArgs> NodeInserted;
 
188
                public event EventHandler<TreeNodeChildEventArgs> NodeDeleted;
 
189
                public event EventHandler<TreeNodeEventArgs> NodeChanged;
 
190
                public event EventHandler<TreeNodeOrderEventArgs> NodesReordered;
 
191
 
 
192
                public void InitializeBackend (object frontend)
 
193
                {
 
194
                }
 
195
                
 
196
                public void Initialize (Type[] columnTypes)
 
197
                {
 
198
                        this.columnTypes = columnTypes;
 
199
                }
 
200
                
 
201
                public void Clear ()
 
202
                {
 
203
                        rootNodes.Clear ();
 
204
                }
 
205
                
 
206
                NodePosition GetPosition (TreePosition pos)
 
207
                {
 
208
                        if (pos == null)
 
209
                                return null;
 
210
                        NodePosition np = (NodePosition)pos;
 
211
                        if (np.StoreVersion != version) {
 
212
                                np.NodeIndex = -1;
 
213
                                for (int i=0; i<np.ParentList.Count; i++) {
 
214
                                        if (np.ParentList [i].NodeId == np.NodeId) {
 
215
                                                np.NodeIndex = i;
 
216
                                                break;
 
217
                                        }
 
218
                                }
 
219
                                if (np.NodeIndex == -1)
 
220
                                        throw new InvalidOperationException ("Invalid node position");
 
221
                                np.StoreVersion = version;
 
222
                        }
 
223
                        return np;
 
224
                }
 
225
                
 
226
                public void SetValue (TreePosition pos, int column, object value)
 
227
                {
 
228
                        NodePosition n = GetPosition (pos);
 
229
                        Node node = n.ParentList [n.NodeIndex];
 
230
                        if (node.Data == null) {
 
231
                                node.Data = new object [columnTypes.Length];
 
232
                                n.ParentList [n.NodeIndex] = node;
 
233
                        }
 
234
                        node.Data [column] = value;
 
235
                        if (NodeChanged != null)
 
236
                                NodeChanged (this, new TreeNodeEventArgs (pos));
 
237
                }
 
238
 
 
239
                public object GetValue (TreePosition pos, int column)
 
240
                {
 
241
                        NodePosition np = GetPosition (pos);
 
242
                        Node n = np.ParentList[np.NodeIndex];
 
243
                        if (n.Data == null)
 
244
                                return null;
 
245
                        return n.Data [column];
 
246
                }
 
247
 
 
248
                public TreePosition GetChild (TreePosition pos, int index)
 
249
                {
 
250
                        if (pos == null) {
 
251
                                if (rootNodes.Count == 0)
 
252
                                        return null;
 
253
                                Node n = rootNodes[index];
 
254
                                return new NodePosition () { ParentList = rootNodes, NodeId = n.NodeId, NodeIndex = index, StoreVersion = version };
 
255
                        } else {
 
256
                                NodePosition np = GetPosition (pos);
 
257
                                Node n = np.ParentList[np.NodeIndex];
 
258
                                return new NodePosition () { ParentList = n.Children, NodeId = n.Children[index].NodeId, NodeIndex = index, StoreVersion = version };
 
259
                        }
 
260
                }
 
261
                
 
262
                public TreePosition GetNext (TreePosition pos)
 
263
                {
 
264
                        NodePosition np = GetPosition (pos);
 
265
                        if (np.NodeIndex >= np.ParentList.Count)
 
266
                                return null;
 
267
                        Node n = np.ParentList[np.NodeIndex + 1];
 
268
                        return new NodePosition () { ParentList = np.ParentList, NodeId = n.NodeId, NodeIndex = np.NodeIndex + 1, StoreVersion = version };
 
269
                }
 
270
 
 
271
                public TreePosition GetPrevious (TreePosition pos)
 
272
                {
 
273
                        NodePosition np = GetPosition (pos);
 
274
                        if (np.NodeIndex <= 0)
 
275
                                return null;
 
276
                        Node n = np.ParentList[np.NodeIndex - 1];
 
277
                        return new NodePosition () { ParentList = np.ParentList, NodeId = n.NodeId, NodeIndex = np.NodeIndex - 1, StoreVersion = version };
 
278
                }
 
279
 
 
280
                public int GetChildrenCount (TreePosition pos)
 
281
                {
 
282
                        if (pos == null)
 
283
                                return rootNodes.Count;
 
284
                        
 
285
                        NodePosition np = GetPosition (pos);
 
286
                        Node n = np.ParentList[np.NodeIndex];
 
287
                        return n.Children != null ? n.Children.Count : 0;
 
288
                }
 
289
 
 
290
                public TreePosition InsertBefore (TreePosition pos)
 
291
                {
 
292
                        NodePosition np = GetPosition (pos);
 
293
                        Node nn = new Node ();
 
294
                        nn.NodeId = nextNodeId++;
 
295
                        
 
296
                        np.ParentList.Insert (np.NodeIndex, nn);
 
297
                        version++;
 
298
                        
 
299
                        // Update the NodePosition since it is now invalid
 
300
                        np.NodeIndex++;
 
301
                        np.StoreVersion = version;
 
302
                        
 
303
                        var node = new NodePosition () { ParentList = np.ParentList, NodeId = nn.NodeId, NodeIndex = np.NodeIndex - 1, StoreVersion = version };
 
304
                        if (NodeInserted != null)
 
305
                                NodeInserted (this, new TreeNodeEventArgs (node));
 
306
                        return node;
 
307
                }
 
308
 
 
309
                public TreePosition InsertAfter (TreePosition pos)
 
310
                {
 
311
                        NodePosition np = GetPosition (pos);
 
312
                        Node nn = new Node ();
 
313
                        nn.NodeId = nextNodeId++;
 
314
                        
 
315
                        np.ParentList.Insert (np.NodeIndex + 1, nn);
 
316
                        version++;
 
317
                        
 
318
                        // Update the provided position is still valid
 
319
                        np.StoreVersion = version;
 
320
                        
 
321
                        var node = new NodePosition () { ParentList = np.ParentList, NodeId = nn.NodeId, NodeIndex = np.NodeIndex + 1, StoreVersion = version };
 
322
                        if (NodeInserted != null)
 
323
                                NodeInserted (this, new TreeNodeEventArgs (node));
 
324
                        return node;
 
325
                }
 
326
                
 
327
                public TreePosition AddChild (TreePosition pos)
 
328
                {
 
329
                        NodePosition np = GetPosition (pos);
 
330
                        
 
331
                        Node nn = new Node ();
 
332
                        nn.NodeId = nextNodeId++;
 
333
                        
 
334
                        NodeList list;
 
335
                        
 
336
                        if (pos == null) {
 
337
                                list = rootNodes;
 
338
                        } else {
 
339
                                Node n = np.ParentList [np.NodeIndex];
 
340
                                if (n.Children == null) {
 
341
                                        n.Children = new NodeList ();
 
342
                                        n.Children.Parent = new NodePosition () { ParentList = np.ParentList, NodeId = n.NodeId, NodeIndex = np.NodeIndex, StoreVersion = version };
 
343
                                        np.ParentList [np.NodeIndex] = n;
 
344
                                }
 
345
                                list = n.Children;
 
346
                        }
 
347
                        list.Add (nn);
 
348
                        version++;
 
349
                        
 
350
                        // The provided position is unafected by this change. Keep it valid.
 
351
                        if (np != null)
 
352
                                np.StoreVersion = version;
 
353
                        
 
354
                        var node = new NodePosition () { ParentList = list, NodeId = nn.NodeId, NodeIndex = list.Count - 1, StoreVersion = version };
 
355
                        if (NodeInserted != null)
 
356
                                NodeInserted (this, new TreeNodeEventArgs (node));
 
357
                        return node;
 
358
                }
 
359
                
 
360
                public void Remove (TreePosition pos)
 
361
                {
 
362
                        NodePosition np = GetPosition (pos);
 
363
                        np.ParentList.RemoveAt (np.NodeIndex);
 
364
                        var parent = np.ParentList.Parent;
 
365
                        var index = np.NodeIndex;
 
366
                        version++;
 
367
                        if (NodeDeleted != null)
 
368
                                NodeDeleted (this, new TreeNodeChildEventArgs (parent, index));
 
369
                }
 
370
                
 
371
                public TreePosition GetParent (TreePosition pos)
 
372
                {
 
373
                        NodePosition np = GetPosition (pos);
 
374
                        if (np.ParentList == rootNodes)
 
375
                                return null;
 
376
                        var parent = np.ParentList.Parent;
 
377
                        return new NodePosition () { ParentList = parent.ParentList, NodeId = parent.NodeId, NodeIndex = parent.NodeIndex, StoreVersion = version };
 
378
                }
 
379
                
 
380
                public Type[] ColumnTypes {
 
381
                        get {
 
382
                                return columnTypes;
 
383
                        }
 
384
                }
 
385
                
 
386
                public void EnableEvent (object eventId)
 
387
                {
 
388
                }
 
389
                
 
390
                public void DisableEvent (object eventId)
 
391
                {
 
392
                }
 
393
        }
 
394
}