using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Data;
using CategoryTheory;
using MathGraph;
using DiagramUI.Labels;
using DiagramUI.Interfaces;
namespace DiagramUI
{
/// <summary>
/// Base class of desktop
/// </summary>
public class PureDesktop : IDesktop
{
#region Fields
/// <summary>
/// Objects
/// </summary>
protected ArrayList objects = new ArrayList();
/// <summary>
/// Arrows
/// </summary>
protected ArrayList arrows = new ArrayList();
/// <summary>
/// Auxiliary table for searching of componenrs
/// </summary>
protected Dictionary<string, INamedComponent> table = new Dictionary<string, INamedComponent>();
/// <summary>
/// String resources
/// </summary>
static private Hashtable resources;
/// <summary>
/// Error handler
/// </summary>
private static IErrorHandler errorHandler = null;
/// <summary>
/// Post Load
/// </summary>
private static event Action<IDesktop> desktopPostLoad;
#endregion
#region Ctor
/// <summary>
/// Default constructor
/// </summary>
public PureDesktop()
{
}
#endregion
#region IDesktop Members
/// <summary>
/// Array of all components
/// </summary>
public IList<object> Components
{
get
{
List<object> components = new List<object>();
components.AddRange(objects.ToArray());
components.AddRange(arrows.ToArray());
return components;
}
}
/// <summary>
/// All components
/// </summary>
public virtual ICollection<object> AllComponents
{
get
{
return Components;
}
}
/// <summary>
/// Array of all objects
/// </summary>
public IList<IObjectLabel> Objects
{
get
{
List<IObjectLabel> l = new List<IObjectLabel>();
foreach (IObjectLabel lab in objects)
{
l.Add(lab);
}
return l;
}
}
/// <summary>
/// Array of all arrows
/// </summary>
public IList<IArrowLabel> Arrows
{
get
{
List<IArrowLabel> l = new List<IArrowLabel>();
foreach (IArrowLabel lab in arrows)
{
l.Add(lab);
}
return l;
}
}
/// <summary>
/// Copies objects and arrows
/// </summary>
/// <param name="objects">Objects</param>
/// <param name="arrows">Arrows</param>
/// <param name="associated">Sign for setting associated objects</param>
public virtual void Copy(IList<IObjectLabel> objects, IList<IArrowLabel> arrows, bool associated)
{
foreach (IObjectLabel l in objects)
{
IObjectLabel lab = new PureObjectLabel(l.Name, l.Kind, l.Type, l.X, l.Y);
lab.Object = l.Object;
lab.Desktop = this;
this.objects.Add(lab);
// components.Add(lab);
table[l.Name] = lab;
}
foreach (IArrowLabel l in arrows)
{
IArrowLabel lab = new PureArrowLabel(l.Name, l.Kind, l.Type, l.X, l.Y);
lab.Arrow = l.Arrow;
lab.Desktop = this;
this.arrows.Add(lab);
// components.Add(lab);
table[l.Name] = lab;
int s = objects.IndexOf(l.Source);
int t = objects.IndexOf(l.Target);
IObjectLabel source = this.objects[s] as IObjectLabel;
IObjectLabel target = this.objects[t] as IObjectLabel;
lab.Source = source;
lab.Target = target;
}
if (!associated)
{
return;
}
PureObjectLabel.SetLabels(objects);
PureArrowLabel.SetLabels(arrows);
}
/// <summary>
/// Access to component
/// </summary>
/// <param name="name">Component name</param>
/// <returns>The component</returns>
public virtual INamedComponent this[string name]
{
get
{
if (!table.ContainsKey(name))
{
return null;
}
return table[name] as INamedComponent;
}
}
/// <summary>
/// Access to object
/// </summary>
/// <param name="name">Object name</param>
/// <returns>The object</returns>
public object GetObject(string name)
{
return this.GetAssociatedObject(name);
}
/// <summary>
/// Parent desktop
/// </summary>
public virtual IDesktop ParentDesktop
{
get
{
return null;
}
}
/// <summary>
/// Level of desktop
/// </summary>
public virtual int Level
{
get
{
return 0;
}
}
/// <summary>
/// Root desktop
/// </summary>
public virtual IDesktop Root
{
get
{
return this;
}
}
/// <summary>
/// Category objects
/// </summary>
public IList<ICategoryObject> CategoryObjects
{
get
{
IList<ICategoryObject> objs = new List<ICategoryObject>();
IList<ICategoryArrow> arrs = new List<ICategoryArrow>();
getAll(this, objs, arrs);
return objs;
}
}
/// <summary>
/// Category arrows
/// </summary>
public IList<ICategoryArrow> CategoryArrows
{
get
{
IList<ICategoryObject> objs = new List<ICategoryObject>();
IList<ICategoryArrow> arrs = new List<ICategoryArrow>();
getAll(this, objs, arrs);
return arrs;
}
}
#endregion
#region Specific members
#region Public Members
/// <summary>
/// Sets names of objects
/// </summary>
public void SetObjectNames()
{
foreach (IObjectLabel label in objects)
{
table[label.Name] = label;
}
}
/// <summary>
/// Clears all components
/// </summary>
public virtual void ClearAll()
{
arrows.Clear();
objects.Clear();
}
/// <summary>
/// Gets all objects of defined type
/// </summary>
/// <typeparam name="T">The type</typeparam>
/// <param name="desktop">The desktop</param>
/// <returns>Array of objects</returns>
public static T[] GetAll<T>(IDesktop desktop) where T : class
{
List<T> l = new List<T>();
foreach (ICategoryObject obj in desktop.CategoryObjects)
{
T t = CategoryOperations.GetObject<T>(obj);
if (t != null)
{
l.Add(t);
}
}
foreach (ICategoryArrow arr in desktop.CategoryArrows)
{
T t = CategoryOperations.GetObject<T>(arr);
if (t != null)
{
l.Add(t);
}
}
return l.ToArray();
}
/// <summary>
/// Gets objects from names
/// </summary>
/// <param name="names">Names</param>
/// <param name="desktop">Desktop</param>
/// <returns>Objects</returns>
public static object[] GetObjects(ICollection<string> names, IDesktop desktop)
{
List<object> l = new List<object>();
foreach (string name in names)
{
l.Add(desktop.GetObject(name));
}
return l.ToArray();
}
/// <summary>
/// Gets names of objects
/// </summary>
/// <param name="desktop">The desktop</param>
/// <returns>The names</returns>
public static string[] GetObjectNames<T>(IDesktop desktop) where T : class
{
List<string> l = new List<string>();
T[] objs = GetAll<T>(desktop);
foreach (T o in objs)
{
if (!(o is IAssociatedObject))
{
continue;
}
IAssociatedObject ao = o as IAssociatedObject;
INamedComponent nc = ao.Object as INamedComponent;
l.Add(nc.GetName(desktop));
}
return l.ToArray();
}
/// <summary>
/// Gets all objects of defined type with defined attribute
/// </summary>
/// <typeparam name="T">The type</typeparam>
/// <param name="desktop">The desktop</param>
/// <param name="attrType">Type of attribute</param>
/// <returns>Array of objects</returns>
public static T[] GetAll<T>(IDesktop desktop, Type attrType) where T : class
{
T[] objects = GetAll<T>(desktop);
List<T> l = new List<T>();
foreach (T x in objects)
{
Type tx = x.GetType();
object[] att = tx.GetCustomAttributes(attrType, true);
if (att != null)
{
if (att.Length > 0)
{
l.Add(x);
}
}
}
return l.ToArray();
}
/// <summary>
/// Performs action with object
/// Throws associated exception
/// </summary>
/// <param name="action">Action</param>
/// <param name="o">Associated object</param>
public static void PerformObjectAction(Action action, object o)
{
try
{
action();
}
catch (Exception exception)
{
exception.Log();
o.Throw(exception);
}
}
/// <summary>
/// Gets texts of elements
/// </summary>
/// <param name="element">Parent none</param>
/// <param name="tag">Tag name</param>
/// <returns>List of texts</returns>
public static List<string> GetTexts(XmlElement element, string tag)
{
List<string> l = new List<string>();
XmlNodeList list = element.GetElementsByTagName(tag);
foreach (XmlNode node in list)
{
l.Add(node.InnerText);
}
return l;
}
/// <summary>
/// Desktop copy
/// </summary>
/// <param name="src">Source</param>
/// <param name="dst">Target</param>
public static void Copy(IDesktop src, IDesktop dst)
{
dst.Copy(src.Objects, src.Arrows, true);
}
/// <summary>
/// Sets texts to childen elements
/// </summary>
/// <param name="doc">Parent document</param>
/// <param name="element">Parent element</param>
/// <param name="tag">Tag name</param>
/// <param name="list">List</param>
public static void SetTexts(XmlDocument doc, XmlElement element, string tag, List<string> list)
{
foreach (string s in list)
{
XmlElement e = doc.CreateElement(tag);
e.InnerText = s;
element.AppendChild(e);
}
}
/// <summary>
/// Creates table from Xml element
/// </summary>
/// <param name="element">The element</param>
/// <param name="tag">Tag</param>
/// <param name="attributes">Attributes</param>
/// <returns>The table</returns>
public static DataTable CreateTable(XmlElement element, string tag, string[] attributes)
{
DataTable table = new DataTable(tag);
foreach (string attr in attributes)
{
table.Columns.Add(attr, "".GetType());
}
XmlNodeList list = element.GetElementsByTagName(tag);
foreach (XmlElement e in list)
{
object[] o = new object[attributes.Length];
for (int i = 0; i < attributes.Length; i++)
{
o[i] = e.Attributes[attributes[i]].Value;
}
table.Rows.Add(o);
}
return table;
}
/// <summary>
/// Creates table from XML element
/// </summary>
/// <param name="element">The element</param>
/// <param name="tag">Tag name</param>
/// <param name="attributes">Attributes those correspond to columns</param>
/// <param name="types">Types of columns</param>
/// <returns>The table</returns>
public static DataTable CreateTable(XmlElement element, string tag, string[] attributes, Type[] types)
{
DataTable table = new DataTable(tag);
for (int i = 0; i < attributes.Length; i++)
{
table.Columns.Add(attributes[i], types[i]);
}
XmlNodeList list = element.GetElementsByTagName(tag);
foreach (XmlElement e in list)
{
object[] o = new object[attributes.Length];
for (int i = 0; i < attributes.Length; i++)
{
string s = e.Attributes[attributes[i]].Value;
o[i] = Create(s, types[i]);
}
table.Rows.Add(o);
}
return table;
}
/// <summary>
/// Sorts list of objects
/// </summary>
/// <param name="labels">Objects</param>
/// <returns>Sorted list</returns>
public static IList<IObjectLabel> Sort(IList<IObjectLabel> labels)
{
Dictionary<string, IObjectLabel> d = new Dictionary<string, IObjectLabel>();
List<string> l = new List<string>();
foreach (IObjectLabel lab in labels)
{
string n = lab.Name;
l.Add(n);
d[n] = lab;
}
l.Sort();
IList<IObjectLabel> list = new List<IObjectLabel>();
foreach (string s in l)
{
list.Add(d[s]);
}
return list;
}
/// <summary>
/// Create nodes from Xml element
/// </summary>
/// <param name="doc">Parent document</param>
/// <param name="element">Element</param>
/// <param name="tag">Tag</param>
/// <param name="table">Table</param>
public static void CreateNodes(XmlDocument doc, XmlElement element, string tag, DataTable table)
{
foreach (DataRow row in table.Rows)
{
XmlElement e = doc.CreateElement(tag);
element.AppendChild(e);
foreach (DataColumn c in table.Columns)
{
string n = c.ColumnName;
XmlAttribute attr = doc.CreateAttribute(n);
attr.Value = row[n] + "";
e.Attributes.Append(attr);
}
}
}
/// Desktop
/// </summary>
public IDesktop Desktop
{
get
{
return this;
}
}
/// <summary>
/// Table of resources
/// </summary>
static public Hashtable Resources
{
set
{
foreach (object o in value.Keys)
{
if (!(o is string))
{
throw new Exception();
}
if (!(value[o] is String))
{
throw new Exception();
}
}
resources = value;
}
}
/// <summary>
/// Creates digraph from objects and arrows
/// </summary>
/// <param name="objects">Objects</param>
/// <param name="arrows">Arrows</param>
/// <param name="checkObject">Checks objects</param>
/// <param name="checkArrow">Checks arrows</param>
/// <returns>The digraph</returns>
static public Digraph CreateDigraph(List<IObjectLabel> objects, List<IArrowLabel> arrows,
CheckObject checkObject, CheckObject checkArrow)
{
Digraph graph = new Digraph();
foreach (IArrowLabel label in arrows)
{
if (checkArrow != null)
{
if (!checkArrow(label))
{
continue;
}
}
label.SourceNumber = objects.IndexOf(label.Source);
label.TargetNumber = objects.IndexOf(label.Target);
}
ArrayList vertices = new ArrayList();
foreach (IObjectLabel label in objects)
{
if (checkObject != null)
{
if (!checkObject(label))
{
continue;
}
}
DigraphVertex v = new DigraphVertex(graph);
vertices.Add(v);
v.Object = label;
}
foreach (IArrowLabel label in arrows)
{
if (checkArrow != null)
{
if (!checkArrow(label))
{
continue;
}
}
DigraphEdge edge = new DigraphEdge();
edge.Object = label;
if (label.SourceNumber is Int32 && label.TargetNumber is Int32)
{
int sourceNum = (int)label.SourceNumber;
DigraphVertex vs = vertices[sourceNum] as DigraphVertex;
edge.Source = vs;
int targetNum = (int)label.TargetNumber;
DigraphVertex vt = vertices[targetNum] as DigraphVertex;
edge.Target = vt;
}
}
return graph;
}
/// <summary>
/// Creates digraph from objects and arrows
/// </summary>
/// <param name="objects">Objects</param>
/// <param name="arrows">Arrows</param>
/// <returns>The digraph</returns>
static public Digraph CreateDigraph(IList<IObjectLabel> objects, IList<IArrowLabel> arrows)
{
Digraph graph = new Digraph();
foreach (IArrowLabel label in arrows)
{
label.SourceNumber = objects.IndexOf(label.Source);
label.TargetNumber = objects.IndexOf(label.Target);
}
ArrayList vertices = new ArrayList();
foreach (IObjectLabel label in objects)
{
DigraphVertex v = new DigraphVertex(graph);
vertices.Add(v);
v.Object = label;
}
foreach (IArrowLabel label in arrows)
{
DigraphEdge edge = new DigraphEdge();
edge.Object = label;
if (label.SourceNumber is Int32 && label.TargetNumber is Int32)
{
int sourceNum = (int)label.SourceNumber;
DigraphVertex vs = vertices[sourceNum] as DigraphVertex;
edge.Source = vs;
int targetNum = (int)label.TargetNumber;
DigraphVertex vt = vertices[targetNum] as DigraphVertex;
edge.Target = vt;
}
}
return graph;
}
/// <summary>
/// Composition of path arrows
/// </summary>
/// <param name="category">Category of arrows</param>
/// <param name="path">The path</param>
/// <returns>The composition</returns>
static public ICategoryArrow Composition(ICategory category, DigraphPath path)
{
IArrowLabel label = path[0].Object as IArrowLabel;
ICategoryArrow arrow = label.Arrow;
for (int i = 1; i < path.Count; i++)
{
label = path[i].Object as IArrowLabel;
arrow = label.Arrow.Compose(category, arrow);
}
return arrow;
}
/// <summary>
/// Gets resources string
/// </summary>
/// <param name="str">String name</param>
/// <returns>The resources string</returns>
static public string GetResourceString(string str)
{
if (resources != null)
{
if (resources.ContainsKey(str))
{
return resources[str] as string;
}
}
return str;
}
/// <summary>
/// Disposes all objects of collection
/// </summary>
/// <param name="collection">The collection</param>
static public void DisposeCollection(ICollection collection)
{
foreach (object o in collection)
{
StaticPerformerExtension.DisposeAssociatedObject(o);
}
}
/// <summary>
/// Error handler
/// </summary>
static public IErrorHandler ErrorHandler
{
get { return errorHandler; }
set { errorHandler = value; }
}
/// <summary>
/// Post load desktop operation
/// </summary>
static public event Action<IDesktop> DesktopPostLoad
{
add { desktopPostLoad += value; }
remove { desktopPostLoad -= value; }
}
/// <summary>
/// Post load operation
/// </summary>
/// <param name="desktop">The desktop for post load</param>
public static void PostLoad(IDesktop desktop)
{
desktopPostLoad(desktop);
}
/// <summary>
/// Shows error
/// </summary>
/// <param name="errorHandler">Error handler</param>
/// <param name="e">Exception</param>
public static void ShowError(IErrorHandler errorHandler, Exception e)
{
if (errorHandler == null)
{
return;
}
errorHandler.ShowError(e);
}
/// <summary>
/// Shows error
/// </summary>
/// <param name="errorHandler">Error handler</param>
/// <param name="message">Error message</param>
public static void ShowError(IErrorHandler errorHandler, string message)
{
if (errorHandler == null)
{
return;
}
errorHandler.ShowMessage(message);
}
/// <summary>
/// Shows error
/// </summary>
/// <param name="e">Exception</param>
public static void ShowError(Exception e)
{
if (errorHandler == null)
{
return;
}
errorHandler.ShowError(e);
}
/// <summary>
/// Shows error
/// </summary>
/// <param name="message">Error message</param>
public static void ShowError(string message)
{
if (errorHandler == null)
{
return;
}
errorHandler.ShowMessage(message);
}
/// <summary>
/// Finds object from array
/// </summary>
/// <param name="source">Source labels</param>
/// <param name="target">Target labels</param>
/// <param name="label">Prototype label</param>
/// <param name="desktop">The desktop</param>
/// <returns>Found object</returns>
static public IObjectLabel Find(IList<IObjectLabel> source, IList<IObjectLabel> target, IObjectLabel label, IDesktop desktop)
{
if (source.Contains(label))
{
int n = source.IndexOf(label);
return target[n] as IObjectLabel;
}
IObjectLabel ol = label.GetRoot(desktop) as IObjectLabel;
int nt = source.IndexOf(ol);
IObjectContainer oct = ol.Object as IObjectContainer;
string tn = oct.GetName(label);
IObjectLabel ot = target[nt] as IObjectLabel;
IObjectContainer ct = ot.Object as IObjectContainer;
return ct[tn] as IObjectLabel;
}
/// <summary>
/// Gets names of typed objects
/// </summary>
/// <typeparam name="T">The type</typeparam>
/// <param name="desktop">The desktop</param>
/// <returns>Array of names</returns>
static public string[] GetNames<T>(IDesktop desktop) where T : class
{
T[] t = GetAll<T>(desktop);
List<string> l = new List<string>();
foreach (T obj in t)
{
IAssociatedObject ao = obj as IAssociatedObject;
INamedComponent nc = ao.Object as INamedComponent;
string n = nc.GetName(desktop);
if (l.Contains(n))
{
throw new Exception("Name " + n + " alerady exists");
}
l.Add(n);
}
return l.ToArray();
}
/// <summary>
/// Recursive post set arrow
/// </summary>
/// <param name="obj">Object for post set arrow</param>
public static void PostSetArrow(IAssociatedObject obj)
{
if (obj == null)
{
return;
}
if (obj is IPostSetArrow)
{
IPostSetArrow p = obj as IPostSetArrow;
p.PostSetArrow();
}
if (obj is IChildrenObject)
{
IChildrenObject cho = obj as IChildrenObject;
IAssociatedObject[] ch = cho.Children;
foreach (IAssociatedObject ao in ch)
{
PostSetArrow(ao);
}
}
}
/// <summary>
/// Gets intersection of desktop objects
/// </summary>
/// <param name="desktop">The desktop</param>
/// <param name="types">Types of objects</param>
/// <returns>The intersection</returns>
public static object[] GetIntersectObjects(IDesktop desktop, Type[] types)
{
object[] objs = GetAllRelatedObjects(desktop);
List<object> l = new List<object>();
foreach (object o in objs)
{
foreach (Type t in types)
{
Type ot = o.GetType();
if ((!ot.IsSubclassOf(t)) & (ot.GetInterface(t.FullName) == null))
{
goto fin;
}
}
l.Add(o);
fin:
continue;
}
return l.ToArray();
}
/// <summary>
/// Gets all objects related to category theory
/// </summary>
/// <param name="desktop">Desktop</param>
/// <returns>The objects</returns>
public static object[] GetAllRelatedObjects(IDesktop desktop)
{
List<object> l = new List<object>();
IList<ICategoryObject> co = desktop.CategoryObjects;
foreach (object o in co)
{
l.Add(o);
}
IList<ICategoryArrow> ca = desktop.CategoryArrows;
foreach (object a in ca)
{
l.Add(a);
}
return l.ToArray();
}
#endregion
#region Protected Members
/// <summary>
/// Gets objects and arrows of associated object
/// </summary>
/// <param name="ao">The associated object</param>
/// <param name="objects">Objects</param>
/// <param name="arrows">Arrows</param>
protected virtual void GetObjects(IAssociatedObject ao, IList<ICategoryObject> objects, IList<ICategoryArrow> arrows)
{
if (ao is ICategoryObject)
{
objects.Add(ao as ICategoryObject);
}
if (ao is ICategoryArrow)
{
arrows.Add(ao as ICategoryArrow);
}
if (ao is IChildrenObject)
{
IChildrenObject co = ao as IChildrenObject;
IAssociatedObject[] ass = co.Children;
if (ass != null)
{
foreach (IAssociatedObject asso in ass)
{
if (asso != null)
{
GetObjects(asso, objects, arrows);
}
}
}
}
}
/// <summary>
/// Creates default object from string
/// </summary>
/// <param name="s">The string</param>
/// <param name="type">Type of object</param>
/// <returns>The object</returns>
protected static object Create(string s, Type type)
{
if (type.Equals(typeof(string)))
{
return s;
}
if (type.Equals(typeof(int)))
{
return Int32.Parse(s);
}
return null;
}
#endregion
#region Private Members
/// <summary>
/// Gets all arrows and objects
/// </summary>
/// <param name="desktop">Desktop</param>
/// <param name="objects">Objects</param>
/// <param name="arrows">Arrows</param>
private void getAll(PureDesktop desktop, IList<ICategoryObject> objects, IList<ICategoryArrow> arrows)
{
IList<IObjectLabel> objs = Objects;
foreach (IObjectLabel l in objs)
{
desktop.GetObjects(l.Object as IAssociatedObject, objects, arrows);
}
IList<IArrowLabel> arrs = Arrows;
foreach (IArrowLabel l in arrs)
{
desktop.GetObjects(l.Arrow, objects, arrows);
}
}
#endregion
#endregion
}
#region Helper Delegate
/// <summary>
/// Delegate of object checking
/// </summary>
/// <param name="obj">The object</param>
/// <returns>True if object is checked and false otherwise</returns>
public delegate bool CheckObject(object obj);
#endregion
}