diff options
Diffstat (limited to 'DirectoryCollection.cs')
-rw-r--r-- | DirectoryCollection.cs | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/DirectoryCollection.cs b/DirectoryCollection.cs new file mode 100644 index 0000000..fa29506 --- /dev/null +++ b/DirectoryCollection.cs @@ -0,0 +1,340 @@ +// Noddybox.GUI - various GUI support routines +// Copyright (C) 2004 Ian Cowburn +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// 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 General Public License for more details. +// +// You should have received a copy of the GNU 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. +// +// $Id$ +// +using System; +using System.Collections; + +namespace Noddybox.GUI +{ + /// <summary> + /// Provides a collection to a directory type structure + /// </summary> + public sealed class DirectoryCollection : IEnumerable, IEnumerator + { + // -------------------------------- + // PUBLIC + // -------------------------------- + + /// <summary> + /// Construct a DirectoryCollection + /// </summary> + public DirectoryCollection() + { + m_dirsep='/'; + m_table=new Hashtable(); + m_iter_list=null; + } + + /// <summary> + /// Sets the path seperator (default '/'). + /// </summary> + public char Seperator + { + get {return m_dirsep;} + set {m_dirsep=value;} + } + + /// <summary> + /// Adds an item + /// </summary> + /// <param name="path">The path to the item</param> + /// <param name="tag">The item to add</param> + public void Add(string path, object tag) + { + CheckPath(path,false); + + if (IsRoot(path)) + { + m_root=new DirNode(); + m_root.Tag=tag; + m_table[path]=m_root; + } + else + { + string parent=Parent(path); + + CheckPath(parent,true); + + m_table[path]=new DirNode(Locate(parent),path,tag); + } + } + + /// <summary> + /// Gets an item. + /// </summary> + /// <param name="path">The path to the item</param> + /// <returns>The item</returns> + public object Get(string path) + { + CheckPath(path,true); + + DirNode n=(DirNode)m_table[path]; + + return n.Tag; + } + + /// <summary> + /// Gets the parent item. + /// </summary> + /// <param name="path">The path whose parent you want</param> + /// <returns>The parent item</returns> + public object GetParent(string path) + { + if (IsRoot(path)) + { + throw new ArgumentException("Root has no parent"); + } + + CheckPath(path,true); + + DirNode n=(DirNode)m_table[path]; + + return n.Parent.Tag; + } + + /// <summary> + /// Recursively remove a section of the directory structure + /// </summary> + /// <param name="path">The path to remove</param> + public void Remove(string path) + { + CheckPath(path,true); + + if (IsRoot(path)) + { + m_table.Clear(); + m_root=null; + } + else + { + DirNode n=Locate(path); + + n.Parent.Children.Remove(n); + n.Parent=null; + + m_table.Remove(path); + } + } + + /// <summary> + /// Returns true if the supplied path is the directory root. + /// </summary> + /// <param name="path">The path to check</param> + /// <returns>True is path is root</returns> + public bool IsRoot(string path) + { + return (path.Length==1 && path[0]==m_dirsep); + } + + /// <summary> + /// Gets an enumerator + /// </summary> + /// <returns>The enumerator</returns> + public IEnumerator GetEnumerator() + { + Reset(); + return this; + } + + /// <summary> + /// Get the current object from the enumerator + /// </summary> + public object Current + { + get + { + if (m_iter_list==null) + { + throw new InvalidOperationException(); + } + + DirNode t=(DirNode)m_iter_list[m_iter_index]; + return t.Tag; + } + } + + /// <summary> + /// Reset the enumerator to the start of the collection. + /// </summary> + public void Reset() + { + m_iter_index=-1; + FlattenTree(); + } + + /// <summary> + /// Move the enumerator to the next item. + /// </summary> + /// <returns>True if there are more objects to enumerate over</returns> + public bool MoveNext() + { + m_iter_index++; + + if (m_iter_index>=m_iter_list.Count) + { + m_iter_list=null; + } + + return m_iter_list!=null; + } + + + // -------------------------------- + // PRIVATE + // -------------------------------- + + private DirNode m_root; + private Hashtable m_table; + + private char m_dirsep; + + private ArrayList m_iter_list; + private int m_iter_index; + + private void FlattenTree() + { + m_iter_list=new ArrayList(); + FlattenTree(m_root); + } + + private void FlattenTree(DirNode n) + { + m_iter_list.Add(n); + + foreach (DirNode dn in n.Children) + { + FlattenTree(dn); + } + } + + private void CheckPath(string path, bool must_exist) + { + if (path.Length==0 || path[0]!=m_dirsep) + { + throw new ArgumentException("Invalid path format: "+path); + } + + if (path.Length>1 && path.EndsWith(m_dirsep+"")) + { + throw new ArgumentException("Invalid path format: "+path); + } + + if (must_exist) + { + if (!m_table.ContainsKey(path)) + { + throw new ArgumentException(path+" does not exist"); + } + } + else + { + if (m_table.ContainsKey(path)) + { + throw new ArgumentException(path+" already exists"); + } + } + } + + private string Parent(string path) + { + int i=path.LastIndexOf(m_dirsep); + + if (i==0) + { + return "/"; + } + else + { + return path.Substring(0,i); + } + } + + + private string Name(string path) + { + int i=path.LastIndexOf(m_dirsep); + + return path.Substring(i+1); + } + + private DirNode Locate(string path) + { + return (DirNode)m_table[path]; + } + + private class DirNode + { + public DirNode() + { + m_children=new ArrayList(); + m_parent=null; + } + + public DirNode(DirNode parent, string path, object tag) + { + m_children=new ArrayList(); + m_path=path; + m_tag=tag; + m_parent=parent; + + m_parent.m_children.Add(this); + } + + public string Path + { + get {return m_path;} + set {m_path=value;} + } + + public object Tag + { + get {return m_tag;} + set {m_tag=value;} + } + + public ArrayList Children + { + get {return m_children;} + } + + public DirNode Parent + { + get {return m_parent;} + set {m_parent=value;} + } + + override public bool Equals(object o) + { + DirNode n=(DirNode)o; + + return n.m_path==m_path; + } + + override public int GetHashCode() + { + return m_path.GetHashCode(); + } + + private DirNode m_parent; + private string m_path; + private object m_tag; + private ArrayList m_children; + } + } +} |