// 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 { /// /// Provides a collection to a directory type structure /// public sealed class DirectoryCollection : IEnumerable, IEnumerator { // -------------------------------- // PUBLIC // -------------------------------- /// /// Construct a DirectoryCollection /// public DirectoryCollection() { m_dirsep='/'; m_table=new Hashtable(); m_iter_list=null; } /// /// Sets the path seperator (default '/'). /// public char Seperator { get {return m_dirsep;} set {m_dirsep=value;} } /// /// Adds an item /// /// The path to the item /// The item to add 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); } } /// /// Gets an item. /// /// The path to the item /// The item public object Get(string path) { CheckPath(path,true); DirNode n=(DirNode)m_table[path]; return n.Tag; } /// /// Gets the parent item. /// /// The path whose parent you want /// The parent item 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; } /// /// Recursively remove a section of the directory structure /// /// The path to remove 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); } } /// /// Returns true if the supplied path is the directory root. /// /// The path to check /// True is path is root public bool IsRoot(string path) { return (path.Length==1 && path[0]==m_dirsep); } /// /// Gets an enumerator /// /// The enumerator public IEnumerator GetEnumerator() { Reset(); return this; } /// /// Get the current object from the enumerator /// public object Current { get { if (m_iter_list==null) { throw new InvalidOperationException(); } DirNode t=(DirNode)m_iter_list[m_iter_index]; return t.Tag; } } /// /// Reset the enumerator to the start of the collection. /// public void Reset() { m_iter_index=-1; FlattenTree(); } /// /// Move the enumerator to the next item. /// /// True if there are more objects to enumerate over 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; } } }