-//
-// System.Windows.Forms.TreeNode.cs
-//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-// Autors:
-// Marek Safar marek.safar@seznam.cz
-//
-//
-//
+// Copyright (c) 2004 Novell, Inc.
//
+// Authors:
+// Jackson Harper (jackson@ximian.com)
-// NOT COMPLETE
+// TODO: Sorting
using System;
using System.Collections;
+using System.Globalization;
+
+namespace System.Windows.Forms {
-namespace System.Windows.Forms
-{
- public class TreeNodeCollection: ICollection, IEnumerable, IList
- {
- TreeNode owner;
+ public class TreeNodeCollection : IList, ICollection, IEnumerable {
- ArrayList collection = new ArrayList ();
+ private static readonly int OrigSize = 50;
+
+ private TreeNode owner;
+ private int count;
+ private TreeNode [] nodes;
+
+ private TreeNodeCollection ()
+ {
+ }
internal TreeNodeCollection (TreeNode owner)
{
this.owner = owner;
+ nodes = new TreeNode [OrigSize];
}
- [MonoTODO ("Check implementation")]
- public virtual int Add (TreeNode node)
- {
- if (node == null)
- throw new ArgumentNullException("value");
+ public virtual int Count {
+ get { return count; }
+ }
- if (node.Parent != null)
- throw new ArgumentException("Object already has a parent", "node");
+ public virtual bool IsReadOnly {
+ get { return false; }
+ }
- node.SetParent (owner);
- int index = collection.Add (node);
- node.SetIndex (index);
- return index;
+ bool ICollection.IsSynchronized {
+ get { return false; }
}
- public virtual void AddRange (TreeNode[] nodes)
- {
- if (nodes == null)
- throw new ArgumentNullException("nodes");
+ object ICollection.SyncRoot {
+ get { return this; }
+ }
- foreach (TreeNode node in nodes) {
- Add (node);
- }
+ bool IList.IsFixedSize {
+ get { return false; }
}
- public int Count {
+ object IList.this [int index] {
get {
- return collection.Count;
+ if (index < 0 || index > Count)
+ throw new ArgumentOutOfRangeException ("index");
+ return nodes [index];
+ }
+ set {
+ if (index < 0 || index > Count)
+ throw new ArgumentOutOfRangeException ("index");
+ TreeNode node = (TreeNode) value;
+ SetData (node);
+ nodes [index] = node;
}
}
- [MonoTODO ("set")]
public virtual TreeNode this [int index] {
get {
- return (TreeNode)collection [index];
+ if (index < 0 || index > Count)
+ throw new ArgumentOutOfRangeException ("index");
+ return nodes [index];
}
set {
- throw new NotImplementedException ();
+ if (index < 0 || index > Count)
+ throw new ArgumentOutOfRangeException ("index");
+ SetData (value);
+ nodes [index] = value;
}
}
-
- #region IEnumerable Members
- public IEnumerator GetEnumerator ()
+ public virtual TreeNode Add (string text)
{
- return collection.GetEnumerator ();
+ TreeNode res = new TreeNode (text);
+ Add (res);
+ return res;
}
- #endregion
-
- #region ICollection Members
+ public virtual int Add (TreeNode node)
+ {
+ if (node == null)
+ throw new ArgumentNullException("node");
- bool ICollection.IsSynchronized {
- get {
- return false;
- }
+ if (owner != null && owner.TreeView != null && owner.TreeView.Sorted)
+ return AddSorted (node);
+ SetData (node);
+ if (count >= nodes.Length)
+ Grow ();
+ nodes [count++] = node;
+
+ if (owner.TreeView != null)
+ owner.TreeView.Refresh ();
+ return count;
}
- public void CopyTo(Array array, int index)
+ public virtual void AddRange (TreeNode [] nodes)
{
- collection.CopyTo (array, index);
+ if (nodes == null)
+ throw new ArgumentNullException("node");
+
+ // We can't just use Array.Copy because the nodes also
+ // need to have some properties set when they are added.
+ for (int i = 0; i < nodes.Length; i++)
+ Add (nodes [i]);
}
- object ICollection.SyncRoot {
- get {
- return this;
- }
+ public virtual void Clear ()
+ {
+ Array.Clear (nodes, 0, count);
+ count = 0;
}
- #endregion
+ public bool Contains (TreeNode node)
+ {
+ return (Array.BinarySearch (nodes, node) > 0);
+ }
- #region IList Members
+ public virtual void CopyTo (Array dest, int index)
+ {
+ nodes.CopyTo (dest, index);
+ }
- public bool IsReadOnly {
- get {
- return false;
- }
+ public virtual IEnumerator GetEnumerator ()
+ {
+ return new TreeNodeEnumerator (this);
}
- [MonoTODO]
- object IList.this[int index] {
- get {
- return null;
- }
- set {
- }
+ public int IndexOf (TreeNode node)
+ {
+ return Array.IndexOf (nodes, node);
}
- public void RemoveAt (int index)
+ public virtual void Insert (int index, TreeNode node)
{
- collection.RemoveAt (index);
+ SetData (node);
+ IList list = (IList) nodes;
+ list.Insert (index, node);
}
- [MonoTODO]
- void IList.Insert(int index, object value)
- {
+ public virtual void Remove (TreeNode node)
+ {
+ int index = IndexOf (node);
+ if (index > 0)
+ RemoveAt (index);
}
- [MonoTODO]
- void IList.Remove(object value)
+ public virtual void RemoveAt (int index)
{
+ Array.Copy (nodes, index, nodes, index - 1, count - index);
+ count--;
+ if (nodes.Length > OrigSize && nodes.Length > (count * 2))
+ Shrink ();
+ if (owner.TreeView != null)
+ owner.TreeView.TotalNodeCount--;
}
-
- [MonoTODO]
- bool IList.Contains(object value)
+
+ int IList.Add (object node)
{
- return false;
+ return Add ((TreeNode) node);
}
- public void Clear()
+ bool IList.Contains (object node)
{
- collection.Clear ();
+ return Contains ((TreeNode) node);
+ }
+
+ int IList.IndexOf (object node)
+ {
+ return IndexOf ((TreeNode) node);
}
- [MonoTODO]
- int IList.IndexOf(object value)
+ void IList.Insert (int index, object node)
{
- return 0;
+ Insert (index, (TreeNode) node);
}
- [MonoTODO]
- int IList.Add(object value)
+ void IList.Remove (object node)
{
- return 0;
+ Remove ((TreeNode) node);
}
- public bool IsFixedSize {
- get {
- return false;
+ private int AddSorted (TreeNode node)
+ {
+
+ if (count >= nodes.Length)
+ Grow ();
+
+ CompareInfo compare = Application.CurrentCulture.CompareInfo;
+ int pos = 0;
+ bool found = false;
+ for (int i = 0; i < count; i++) {
+ pos = i;
+ int comp = compare.Compare (node.Text, nodes [i].Text);
+ if (comp < 0) {
+ found = true;
+ break;
+ }
+ }
+
+ // Stick it at the end
+ if (!found)
+ pos = count;
+
+ // Move the nodes up and adjust their indices
+ for (int i = count - 1; i >= pos; i--) {
+ nodes [i + 1] = nodes [i];
+ nodes [i + 1].SetIndex (i + 1);
+ }
+ count++;
+ nodes [pos] = node;
+
+ SetData (node, pos);
+ return count;
+ }
+
+ // Would be nice to do this without running through the collection twice
+ internal void Sort () {
+
+ Array.Sort (nodes, 0, count, new TreeNodeComparer (Application.CurrentCulture.CompareInfo));
+
+ for (int i = 0; i < count; i++) {
+ nodes [i].SetIndex (i);
+ nodes [i].Nodes.Sort ();
+ }
+ }
+
+ private void SetData (TreeNode node)
+ {
+ SetData (node, count);
+ }
+
+ private void SetData (TreeNode node, int pos)
+ {
+ node.SetAddedData ((owner != null ? owner.TreeView : null), owner, pos);
+ }
+
+ private void Grow ()
+ {
+ TreeNode [] nn = new TreeNode [nodes.Length + 50];
+ Array.Copy (nodes, nn, nodes.Length);
+ nodes = nn;
+ }
+
+ private void Shrink ()
+ {
+ int len = (count > OrigSize ? count : OrigSize);
+ TreeNode [] nn = new TreeNode [len];
+ Array.Copy (nodes, nn, count);
+ nodes = nn;
+ }
+
+
+ internal class TreeNodeEnumerator : IEnumerator {
+
+ private TreeNodeCollection collection;
+ private int index = -1;
+
+ public TreeNodeEnumerator (TreeNodeCollection collection)
+ {
+ this.collection = collection;
+ }
+
+ public object Current {
+ get { return collection [index]; }
+ }
+
+ public bool MoveNext ()
+ {
+ if (index + 1 >= collection.Count)
+ return false;
+ index++;
+ return true;
+ }
+
+ public void Reset ()
+ {
+ index = 0;
}
}
- #endregion
+ private class TreeNodeComparer : IComparer {
+
+ private CompareInfo compare;
+
+ public TreeNodeComparer (CompareInfo compare)
+ {
+ this.compare = compare;
+ }
+
+ public int Compare (object x, object y)
+ {
+ TreeNode l = (TreeNode) x;
+ TreeNode r = (TreeNode) y;
+ int res = compare.Compare (l.Text, r.Text);
+
+ return (res == 0 ? l.Index - r.Index : res);
+ }
+ }
}
}
+