351 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			351 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System;
 | 
						|
using System.Xml;
 | 
						|
using System.IO;
 | 
						|
 | 
						|
namespace DevComponents.Tree
 | 
						|
{
 | 
						|
	/// <summary>
 | 
						|
	/// Provides means for TreeGX serialization.
 | 
						|
	/// </summary>
 | 
						|
	public class TreeSerializer
 | 
						|
	{
 | 
						|
		#region Private Variables
 | 
						|
		private static string XmlNodeName="Node";
 | 
						|
		private static string XmlCellsName="Cells";
 | 
						|
		private static string XmlCellName="Cell";
 | 
						|
		private static string XmlCellImagesName="Images";
 | 
						|
		private static string XmlTreeGXName="TreeGX";
 | 
						|
		private static string XmlCustomName = "Custom";
 | 
						|
		#endregion
 | 
						|
		
 | 
						|
		#region Saving
 | 
						|
		/// <summary>
 | 
						|
		/// Saves Nodes to specified file.
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="tree">TreeGX to save</param>
 | 
						|
		/// <param name="fileName">Target file name</param>
 | 
						|
		public static void Save(TreeGX tree, string fileName)
 | 
						|
		{
 | 
						|
			XmlDocument document=Save(tree);
 | 
						|
			document.Save(fileName);
 | 
						|
		}
 | 
						|
		
 | 
						|
		/// <summary>
 | 
						|
		/// Saves Nodes to stream.
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="tree">TreeGX to save</param>
 | 
						|
		/// <param name="outStream">Stream to save nodes to.</param>
 | 
						|
		public static void Save(TreeGX tree, Stream outStream)
 | 
						|
		{
 | 
						|
			XmlDocument document=Save(tree);
 | 
						|
			document.Save(outStream);
 | 
						|
		}
 | 
						|
		
 | 
						|
		/// <summary>
 | 
						|
		/// Saves Nodes to TextWriter
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="tree">TreeGX to save</param>
 | 
						|
		/// <param name="writer">TextWriter to write nodes to.</param>
 | 
						|
		public static void Save(TreeGX tree, TextWriter writer)
 | 
						|
		{
 | 
						|
			XmlDocument document=Save(tree);
 | 
						|
			document.Save(writer);
 | 
						|
		}
 | 
						|
		
 | 
						|
		/// <summary>
 | 
						|
		/// Saves nodes to XmlWriter.
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="tree">TreeGX to save</param>
 | 
						|
		/// <param name="writer">XmlWriter to write nodes to</param>
 | 
						|
		public static void Save(TreeGX tree, XmlWriter writer)
 | 
						|
		{
 | 
						|
			XmlDocument document=Save(tree);
 | 
						|
			document.Save(writer);
 | 
						|
		}
 | 
						|
		
 | 
						|
		/// <summary>
 | 
						|
		/// Creates new XmlDocument and serializes TreeGX into it.
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="tree">TreeGX to serialize</param>
 | 
						|
		/// <returns>New instance of XmlDocument/returns>
 | 
						|
		public static XmlDocument Save(TreeGX tree)
 | 
						|
		{
 | 
						|
			XmlDocument document=new XmlDocument();
 | 
						|
			Save(tree, document);
 | 
						|
			return document;
 | 
						|
		}
 | 
						|
		
 | 
						|
		/// <summary>
 | 
						|
		/// Saves TreeGX to an existing XmlDocument. New node TreeGX is created in document and Nodes are serialized into it.
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="tree">TreeGX to serialize</param>
 | 
						|
		/// <param name="document">XmlDocument instance.</param>
 | 
						|
		public static void Save(TreeGX tree, XmlDocument document)
 | 
						|
		{
 | 
						|
			XmlElement parent = document.CreateElement(XmlTreeGXName);
 | 
						|
			document.AppendChild(parent);
 | 
						|
			TreeSerializer.Save(tree, parent);
 | 
						|
		}
 | 
						|
		
 | 
						|
		/// <summary>
 | 
						|
		/// Serializes TreeGX object to XmlElement object.
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="tree">Instance of TreeGX to serialize.</param>
 | 
						|
		/// <param name="parent">XmlElement to serialize to.</param>
 | 
						|
		public static void Save(TreeGX tree, XmlElement parent)
 | 
						|
		{
 | 
						|
			NodeSerializationContext context = new NodeSerializationContext();
 | 
						|
			context.RefXmlElement = parent;
 | 
						|
			context.TreeGX = tree;
 | 
						|
			context.HasSerializeNodeHandlers = tree.HasSerializeNodeHandlers;
 | 
						|
			context.HasDeserializeNodeHandlers = tree.HasDeserializeNodeHandlers;
 | 
						|
			
 | 
						|
			foreach(Node node in tree.Nodes)
 | 
						|
			{
 | 
						|
				Save(node, context);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		
 | 
						|
		/// <summary>
 | 
						|
		/// Serializes Node and all child nodes to XmlElement object.
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="node">Node to serialize.</param>
 | 
						|
		/// <param name="context">Provides serialization context.</param>
 | 
						|
		public static void Save(Node node, NodeSerializationContext context)
 | 
						|
		{
 | 
						|
			XmlElement parent = context.RefXmlElement;
 | 
						|
			
 | 
						|
			XmlElement xmlNode=parent.OwnerDocument.CreateElement(XmlNodeName);
 | 
						|
			parent.AppendChild(xmlNode);
 | 
						|
			
 | 
						|
			ElementSerializer.Serialize(node, xmlNode);
 | 
						|
			
 | 
						|
			if(node.Cells.Count>1)
 | 
						|
			{
 | 
						|
				XmlElement xmlCells = parent.OwnerDocument.CreateElement(XmlCellsName);
 | 
						|
				xmlNode.AppendChild(xmlCells);
 | 
						|
				
 | 
						|
				for(int i=1; i<node.Cells.Count;i++)
 | 
						|
				{
 | 
						|
					Cell cell=node.Cells[i];
 | 
						|
					XmlElement xmlCell= parent.OwnerDocument.CreateElement(XmlCellName);
 | 
						|
					xmlCells.AppendChild(xmlCell);
 | 
						|
					ElementSerializer.Serialize(cell, xmlCell);
 | 
						|
					if(cell.ShouldSerializeImages())
 | 
						|
					{
 | 
						|
						XmlElement xmlCellImages = parent.OwnerDocument.CreateElement(XmlCellImagesName);
 | 
						|
						xmlCell.AppendChild(xmlCellImages);
 | 
						|
						ElementSerializer.Serialize(cell.Images, xmlCellImages);
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
            if (context.HasSerializeNodeHandlers)
 | 
						|
            {
 | 
						|
                XmlElement customXml = parent.OwnerDocument.CreateElement(XmlCustomName);
 | 
						|
                SerializeNodeEventArgs e = new SerializeNodeEventArgs(node, xmlNode, customXml);
 | 
						|
                context.TreeGX.InvokeSerializeNode(e);
 | 
						|
                if (customXml.Attributes.Count > 0 || customXml.ChildNodes.Count > 0)
 | 
						|
                    xmlNode.AppendChild(customXml);
 | 
						|
            }
 | 
						|
			
 | 
						|
			context.RefXmlElement = xmlNode;
 | 
						|
			foreach(Node childNode in node.Nodes)
 | 
						|
			{
 | 
						|
				Save(childNode, context);
 | 
						|
			}
 | 
						|
			context.RefXmlElement = parent;
 | 
						|
		}
 | 
						|
		#endregion
 | 
						|
		
 | 
						|
		#region Loading
 | 
						|
		/// <summary>
 | 
						|
		/// Load TreeGX Nodes from file.
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="tree">Reference to TreeGX to populate</param>
 | 
						|
		/// <param name="fileName">File name.</param>
 | 
						|
		public static void Load(TreeGX tree, string fileName)
 | 
						|
		{
 | 
						|
			XmlDocument document=new XmlDocument();
 | 
						|
			document.Load(fileName);
 | 
						|
			Load(tree, document);
 | 
						|
		}
 | 
						|
		
 | 
						|
		/// <summary>
 | 
						|
		/// Load TreeGX Nodes from stream.
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="tree">Reference to TreeGX to populate</param>
 | 
						|
		/// <param name="inStream">Reference to stream</param>
 | 
						|
		public static void Load(TreeGX tree, Stream inStream)
 | 
						|
		{
 | 
						|
			XmlDocument document=new XmlDocument();
 | 
						|
			document.Load(inStream);
 | 
						|
			Load(tree, document);
 | 
						|
		}
 | 
						|
		
 | 
						|
		/// <summary>
 | 
						|
		/// Load TreeGX Nodes from reader.
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="tree">Reference to TreeGX to populate</param>
 | 
						|
		/// <param name="reader">Reference to reader.</param>
 | 
						|
		public static void Load(TreeGX tree, TextReader reader)
 | 
						|
		{
 | 
						|
			XmlDocument document=new XmlDocument();
 | 
						|
			document.Load(reader);
 | 
						|
			Load(tree, document);
 | 
						|
		}
 | 
						|
		
 | 
						|
		/// <summary>
 | 
						|
		/// Load TreeGX Nodes from reader.
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="tree">Reference to TreeGX to populate</param>
 | 
						|
		/// <param name="reader">Reference to reader.</param>
 | 
						|
		public static void Load(TreeGX tree, XmlReader reader)
 | 
						|
		{
 | 
						|
			XmlDocument document=new XmlDocument();
 | 
						|
			document.Load(reader);
 | 
						|
			Load(tree, document);
 | 
						|
		}
 | 
						|
		
 | 
						|
		/// <summary>
 | 
						|
		/// Load TreeGX from XmlDocument that was created by Save method.
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="tree">Tree Control to load</param>
 | 
						|
		/// <param name="document">XmlDocument to load control from</param>
 | 
						|
		public static void Load(TreeGX tree, XmlDocument document)
 | 
						|
		{
 | 
						|
			foreach(XmlNode xmlNode in document.ChildNodes)
 | 
						|
			{
 | 
						|
				if(xmlNode.Name==XmlTreeGXName && xmlNode is XmlElement)
 | 
						|
				{
 | 
						|
					Load(tree, xmlNode as XmlElement);
 | 
						|
					break;
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		
 | 
						|
		/// <summary>
 | 
						|
		/// Load nodes from XmlElement.
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="tree">Reference to TreeGX to be populated.</param>
 | 
						|
		/// <param name="parent">XmlElement that tree was serialized to.</param>
 | 
						|
		public static void Load(TreeGX tree, XmlElement parent)
 | 
						|
		{
 | 
						|
			tree.BeginUpdate();
 | 
						|
			tree.DisplayRootNode = null;
 | 
						|
			tree.Nodes.Clear();
 | 
						|
			
 | 
						|
			NodeSerializationContext context = new NodeSerializationContext();
 | 
						|
			context.TreeGX = tree;
 | 
						|
			context.HasDeserializeNodeHandlers  = tree.HasDeserializeNodeHandlers;
 | 
						|
			context.HasSerializeNodeHandlers = tree.HasSerializeNodeHandlers;
 | 
						|
			
 | 
						|
			try
 | 
						|
			{
 | 
						|
				foreach(XmlNode xmlNode in parent.ChildNodes)
 | 
						|
				{
 | 
						|
					if(xmlNode.Name==XmlNodeName && xmlNode is XmlElement)
 | 
						|
					{
 | 
						|
						Node node=new Node();
 | 
						|
						tree.Nodes.Add(node);
 | 
						|
						context.RefXmlElement = xmlNode as XmlElement;
 | 
						|
						LoadNode(node, context);
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
			finally
 | 
						|
			{
 | 
						|
				tree.EndUpdate();
 | 
						|
			}
 | 
						|
		}
 | 
						|
		
 | 
						|
		/// <summary>
 | 
						|
		/// Load single node and it's child nodes if any.
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="nodeToLoad">New instance of node that is populated with loaded data.</param>
 | 
						|
		/// <param name="context">Provides deserialization context.</param>
 | 
						|
		public static void LoadNode(Node nodeToLoad, NodeSerializationContext context)
 | 
						|
		{
 | 
						|
			XmlElement xmlNode = context.RefXmlElement;
 | 
						|
			
 | 
						|
			ElementSerializer.Deserialize(nodeToLoad, xmlNode);
 | 
						|
 | 
						|
			foreach(XmlNode xmlChild in xmlNode.ChildNodes)
 | 
						|
			{
 | 
						|
				XmlElement xmlElem = xmlChild as XmlElement;
 | 
						|
				if(xmlElem == null)
 | 
						|
					continue;
 | 
						|
				if(xmlElem.Name==XmlNodeName)
 | 
						|
				{
 | 
						|
					Node node=new Node();
 | 
						|
					nodeToLoad.Nodes.Add(node);
 | 
						|
					context.RefXmlElement = xmlElem;
 | 
						|
					LoadNode(node, context);
 | 
						|
				}
 | 
						|
				else if(xmlElem.Name == XmlCellsName)
 | 
						|
				{
 | 
						|
					LoadCells(nodeToLoad, xmlElem);
 | 
						|
				}
 | 
						|
				else if(xmlElem.Name == XmlCustomName)
 | 
						|
				{
 | 
						|
					if(context.HasDeserializeNodeHandlers)
 | 
						|
					{
 | 
						|
						SerializeNodeEventArgs e = new SerializeNodeEventArgs(nodeToLoad, xmlNode, xmlElem);
 | 
						|
						context.TreeGX.InvokeDeserializeNode(e);
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
			context.RefXmlElement = xmlNode;
 | 
						|
		}
 | 
						|
		
 | 
						|
		private static void LoadCells(Node parentNode, XmlElement xmlCells)
 | 
						|
		{
 | 
						|
			foreach(XmlNode xmlChild in xmlCells.ChildNodes)
 | 
						|
			{
 | 
						|
				if(xmlChild.Name==XmlCellName && xmlChild is XmlElement)
 | 
						|
				{
 | 
						|
					Cell cell=new Cell();
 | 
						|
					parentNode.Cells.Add(cell);
 | 
						|
					ElementSerializer.Deserialize(cell, xmlChild as XmlElement);
 | 
						|
					// Load images if any
 | 
						|
					foreach(XmlElement xmlImage in xmlChild.ChildNodes)
 | 
						|
					{
 | 
						|
						if(xmlImage.Name==XmlCellImagesName)
 | 
						|
						{
 | 
						|
							ElementSerializer.Deserialize(cell.Images, xmlImage);
 | 
						|
							break;
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		#endregion
 | 
						|
	}
 | 
						|
	
 | 
						|
	/// <summary>
 | 
						|
	/// Provides context information for serialization.
 | 
						|
	/// </summary>
 | 
						|
	public class NodeSerializationContext
 | 
						|
	{
 | 
						|
		/// <summary>
 | 
						|
		/// Gets or sets reference to context parent XmlElement when serializing or actual Node element when deserializing.
 | 
						|
		/// </summary>
 | 
						|
		public System.Xml.XmlElement RefXmlElement = null;
 | 
						|
 | 
						|
		/// <summary>
 | 
						|
		/// Gets or sets whether SerializeNode event handler has been defined and whether event should be fired.
 | 
						|
		/// </summary>
 | 
						|
		public bool HasSerializeNodeHandlers = false;
 | 
						|
 | 
						|
		/// <summary>
 | 
						|
		/// Gets or sets whether DeserializeNode event handler has been defined and whether event should be fired.
 | 
						|
		/// </summary>
 | 
						|
		public bool HasDeserializeNodeHandlers = false;
 | 
						|
 | 
						|
		/// <summary>
 | 
						|
		/// Provides access to serializer.
 | 
						|
		/// </summary>
 | 
						|
		public TreeGX TreeGX = null;
 | 
						|
	}
 | 
						|
}
 |