// 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;
}
}
}