summaryrefslogtreecommitdiff
path: root/DirectoryCollection.cs
diff options
context:
space:
mode:
Diffstat (limited to 'DirectoryCollection.cs')
-rw-r--r--DirectoryCollection.cs340
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;
+ }
+ }
+}