using System;
using System.Collections.Generic;
using System.Xml;
using System.Text;
using System.Windows.Forms;

namespace Mesnac.Basic
{
    /// <summary>
    /// TreeView扩展方法类   基于.NetFramework3.5及以上版本
    /// </summary>
    public static class TreeViewHelper
    {
        #region TreeView扩展方法

        /// <summary>
        /// TreeView的扩展方法:把工程树节点的内容保存到工程文件中
        /// </summary>
        /// <param name="tv">TreeView对象</param>
        /// <param name="filePath">要保存的工程文件完整路径</param>
        public static void SaveToXml(this TreeView tv, string filePath)
        {
            XmlDocument doc = new XmlDocument();
            XmlElement eroot = doc.CreateElement("MesnacPrj");
            foreach (TreeNode n in tv.Nodes)
            {
                XmlElement en = doc.CreateElement("Node");
                //XmlAttribute aId = doc.CreateAttribute("Id");
                XmlAttribute aName = doc.CreateAttribute("Name");
                XmlAttribute aText = doc.CreateAttribute("Text");
                XmlAttribute aToolTipText = doc.CreateAttribute("ToolTipText");
                XmlAttribute aTag = doc.CreateAttribute("Tag");
                XmlAttribute aImageIndex = doc.CreateAttribute("ImageIndex");
                XmlAttribute aSelectedImageIndex = doc.CreateAttribute("SelectedImageIndex");

                //aId.Value = n.Index.ToString();
                aName.Value = n.Name;
                aText.Value = n.Text;
                aToolTipText.Value = n.ToolTipText;
                aTag.Value = n.Tag.ToString();
                aImageIndex.Value = n.ImageIndex.ToString();
                aSelectedImageIndex.Value = n.SelectedImageIndex.ToString();

                //en.Attributes.Append(aId);
                en.Attributes.Append(aName);
                en.Attributes.Append(aText);
                en.Attributes.Append(aToolTipText);
                en.Attributes.Append(aTag);
                en.Attributes.Append(aImageIndex);
                en.Attributes.Append(aSelectedImageIndex);

                ToXmlElement(doc, en, n);

                eroot.AppendChild(en);                
            }
            doc.AppendChild(eroot);
            doc.Save(filePath);
        }
        /// <summary>
        /// 递归解析工程数据节点
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="e"></param>
        /// <param name="tn"></param>
        private static void ToXmlElement(XmlDocument doc, XmlElement e, TreeNode tn)
        {
            foreach (TreeNode n in tn.Nodes)
            {
                XmlElement en = doc.CreateElement("Node");
                //XmlAttribute aId = doc.CreateAttribute("Id");
                XmlAttribute aName = doc.CreateAttribute("Name");
                XmlAttribute aText = doc.CreateAttribute("Text");
                XmlAttribute aToolTipText = doc.CreateAttribute("ToolTipText");
                XmlAttribute aTag = doc.CreateAttribute("Tag");
                XmlAttribute aImageIndex = doc.CreateAttribute("ImageIndex");
                XmlAttribute aSelectedImageIndex = doc.CreateAttribute("SelectedImageIndex");

                //aId.Value = n.Index.ToString();
                aName.Value = n.Name;
                aText.Value = n.Text;
                aToolTipText.Value = n.ToolTipText;
                aTag.Value = n.Tag == null ? String.Empty : n.Tag.ToString();
                aImageIndex.Value = n.ImageIndex.ToString();
                aSelectedImageIndex.Value = n.SelectedImageIndex.ToString();

                //en.Attributes.Append(aId);
                en.Attributes.Append(aName);
                en.Attributes.Append(aText);
                en.Attributes.Append(aToolTipText);
                en.Attributes.Append(aTag);
                en.Attributes.Append(aImageIndex);
                en.Attributes.Append(aSelectedImageIndex);
                e.AppendChild(en);

                ToXmlElement(doc, en, n);
            }
        }
        /// <summary>
        /// 通过载入工程文件,构建工程树
        /// </summary>
        /// <param name="tv"></param>
        /// <param name="filePath">工程文件的完整路径</param>
        public static void LoadFromXml(this TreeView tv, string filePath)
        {
            tv.Nodes.Clear();
            XmlDocument doc = new XmlDocument();
            doc.Load(filePath);
            XmlElement eroot = doc.DocumentElement;
            List<TreeNode> nodes = new List<TreeNode>();
            if (eroot.HasChildNodes)
            {
                foreach (XmlNode xn in eroot.ChildNodes)
                {
                    TreeNode tn = new TreeNode();
                    tn.Name = xn.Attributes["Name"].Value;
                    tn.Text = xn.Attributes["Text"].Value;
                    tn.ToolTipText = xn.Attributes["ToolTipText"].Value;
                    tn.Tag = xn.Attributes["Tag"].Value;
                    tn.ImageIndex = Convert.ToInt32(xn.Attributes["ImageIndex"].Value);
                    tn.SelectedImageIndex = Convert.ToInt32(xn.Attributes["SelectedImageIndex"].Value);
                    ToTreeNode(xn, tn);
                    nodes.Add(tn);
                }
            }
            tv.Nodes.AddRange(nodes.ToArray());
            tv.ExpandAll();
        }
        /// <summary>
        /// 递归解析工程文件节点
        /// </summary>
        /// <param name="xn"></param>
        /// <param name="tn"></param>
        private static void ToTreeNode(XmlNode xn, TreeNode tn)
        {
            if (xn.HasChildNodes)
            {
                foreach (XmlNode xxn in xn.ChildNodes)
                {
                    TreeNode ttn = new TreeNode();
                    ttn.Name = xxn.Attributes["Name"].Value;
                    ttn.Text = xxn.Attributes["Text"].Value;
                    ttn.ToolTipText = xxn.Attributes["ToolTipText"].Value;
                    ttn.Tag = xxn.Attributes["Tag"].Value;
                    ttn.ImageIndex = Convert.ToInt32(xxn.Attributes["ImageIndex"].Value);
                    ttn.SelectedImageIndex = Convert.ToInt32(xxn.Attributes["SelectedImageIndex"].Value);
                    ToTreeNode(xxn, ttn);
                    tn.Nodes.Add(ttn);
                }
            }
        }

        /// <summary>
        /// TreeView扩展方法,获取某个节点(按NodeName搜索的第一个节点)的子节点集合
        /// </summary>
        /// <param name="tv"></param>
        /// <param name="nodeName">节点名称</param>
        /// <returns>返回子节点集合</returns>
        public static TreeNodeCollection GetChildNodesByNodeName(this TreeView tv, string nodeName)
        {
            TreeNode[] nodes = tv.Nodes.Find(nodeName, true);
            if (nodes != null && nodes.Length > 0)
            {
                return nodes[0].Nodes;
            }
            return null;
        }

        /// <summary>
        /// 根据节点名称获取节点
        /// </summary>
        /// <param name="tv"></param>
        /// <param name="nodeName">节点名称</param>
        /// <returns>返回对应的节点</returns>
        public static TreeNode GetFirstNodeByNodeName(this TreeView tv, string nodeName)
        {
            if (tv != null)
            {
                TreeNode[] nodes = tv.Nodes.Find(nodeName, true);
                if (nodeName != null && nodes.Length > 0)
                {
                    return nodes[0];
                }
            }
            return null;
        }

        #endregion

        #region TreeNode扩展方法
        /// <summary>
        /// TreeNode扩展方法 获取此节点的Tag路径
        /// </summary>
        /// <param name="tn"></param>
        /// <returns></returns>
        public static string GetPathNoRoot(this TreeNode tn)
        {
            return GetPath(tn);
        }
        /// <summary>
        /// 递归获取节点Tag属性的串联
        /// </summary>
        /// <param name="tn"></param>
        /// <returns></returns>
        private static string GetPath(TreeNode tn)
        {
            if (tn != null && tn.Parent != null)
            {
                if (tn.Parent.Parent != null)
                {
                    return GetPath(tn.Parent) + @"\" + tn.Tag.ToString();
                }
                else
                {
                    return tn.Tag.ToString();
                }
            }
            else
            {
                return String.Empty;
            }
        }

        #endregion
    }
}