XmlTreeView.cs
上传用户:hbhltzc
上传日期:2022-06-04
资源大小:1925k
文件大小:73k
源码类别:

xml/soap/webservice

开发平台:

Visual C++

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Windows.Forms;
  6. using System.Xml;
  7. using System.Xml.XPath;
  8. using System.Xml.Schema;
  9. using System.Diagnostics;
  10. using System.Drawing.Drawing2D;
  11. using System.Text;
  12. namespace XmlNotepad {
  13.     public class XmlTreeView : System.Windows.Forms.UserControl {
  14.         XmlCache model;
  15.         Settings settings;
  16.         bool disposed;
  17.         const int HScrollIncrement = 5;
  18.         public event EventHandler<NodeChangeEventArgs> NodeChanged;
  19.         public event EventHandler<NodeChangeEventArgs> NodeInserted;
  20.         public event EventHandler SelectionChanged;
  21.         public event EventHandler ClipboardChanged;
  22.         XmlTreeNode dragged;
  23.         XmlTreeViewDropFeedback feedback;
  24.         IntelliTip tip;
  25.         private NodeTextView nodeTextView;
  26.         private TreeView myTreeView;
  27.         private System.Windows.Forms.ImageList imageList1;
  28.         private System.ComponentModel.IContainer components;
  29.         private PaneResizer resizer;
  30.         private System.Windows.Forms.VScrollBar vScrollBar1;
  31.         private System.Windows.Forms.HScrollBar hScrollBar1;
  32.         public XmlTreeView() {
  33.             this.SetStyle(ControlStyles.ContainerControl, true);
  34.             this.SetStyle(ControlStyles.ResizeRedraw, true);
  35.             this.SetStyle(ControlStyles.UserPaint, true);
  36.             this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
  37.             this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
  38.             // This call is required by the Windows.Forms Form Designer.
  39.             InitializeComponent();
  40.             myTreeView.AfterLabelEdit += new EventHandler<NodeLabelEditEventArgs>(myTreeView_AfterLabelEdit);            
  41.             myTreeView.AfterCollapse += new EventHandler<TreeViewEventArgs>(myTreeView_AfterCollapse);
  42.             myTreeView.AfterExpand += new EventHandler<TreeViewEventArgs>(myTreeView_AfterExpand);
  43.             myTreeView.AfterSelect += new EventHandler<TreeViewEventArgs>(myTreeView_AfterSelect);
  44.             myTreeView.MouseWheel += new MouseEventHandler(HandleMouseWheel);
  45.             myTreeView.KeyDown += new KeyEventHandler(myTreeView_KeyDown);
  46.             this.myTreeView.DragDrop += new DragEventHandler(treeViewFeedback_DragDrop);
  47.             this.myTreeView.DragEnter += new DragEventHandler(treeViewFeedback_DragEnter);
  48.             this.myTreeView.DragLeave += new EventHandler(treeViewFeedback_DragLeave);
  49.             this.myTreeView.DragOver += new DragEventHandler(treeViewFeedback_DragOver);
  50.             this.myTreeView.AllowDrop = true;
  51.             this.myTreeView.GiveFeedback += new GiveFeedbackEventHandler(myTreeView_GiveFeedback);
  52.             this.myTreeView.ItemDrag += new ItemDragEventHandler(myTreeView_ItemDrag);
  53.             this.myTreeView.AfterBatchUpdate += new EventHandler(myTreeView_AfterBatchUpdate);
  54.             this.nodeTextView.KeyDown += new KeyEventHandler(nodeTextView_KeyDown);
  55.             this.nodeTextView.MouseWheel += new MouseEventHandler(HandleMouseWheel);
  56.             this.nodeTextView.AfterSelect += new EventHandler<TreeViewEventArgs>(nodeTextView_AfterSelect);
  57.             this.nodeTextView.AccessibleRole=System.Windows.Forms.AccessibleRole.List;            
  58.             this.Disposed += new EventHandler(OnDisposed);
  59.             tip = new IntelliTip(this);
  60.             tip.AddWatch(this.nodeTextView);
  61.             tip.AddWatch(this.myTreeView);
  62.             tip.ShowToolTip += new IntelliTipEventHandler(OnShowToolTip);
  63.         }
  64.         void OnDisposed(object sender, EventArgs e) {
  65.             this.disposed = true;
  66.         }
  67.         public void Close() {
  68.             this.myTreeView.Close();
  69.             this.nodeTextView.Close();
  70.         }
  71.         [Browsable(false)]
  72.         public XmlTreeNode SelectedNode {
  73.             get {
  74.                 return this.myTreeView.SelectedNode as XmlTreeNode;
  75.             }
  76.             set {
  77.                 this.myTreeView.SelectedNode = value;
  78.             }
  79.         }
  80.         void OnShowToolTip(object sender, IntelliTipEventArgs args) {
  81.             Point pt = this.myTreeView.ApplyScrollOffset(args.Location);            
  82.             XmlTreeNode tn = this.TreeView.FindNodeAt(20, pt.Y) as XmlTreeNode;
  83.             if (tn != null) {
  84.                 args.ToolTip = tn.GetToolTip();
  85.             }
  86.         }
  87.         public void ExpandAll() {
  88.             this.SuspendLayout();
  89.             this.myTreeView.ExpandAll();
  90.             this.ResumeLayout();
  91.         }
  92.         public void CollapseAll() {
  93.             this.SuspendLayout();
  94.             this.myTreeView.CollapseAll();
  95.             this.ResumeLayout();
  96.         }
  97.         public void SetSite(ISite site) {
  98.             base.Site = site;
  99.             this.nodeTextView.SetSite(site);
  100.             this.myTreeView.SetSite(site);
  101.             this.model = (XmlCache)this.Site.GetService(typeof(XmlCache));
  102.             if (this.model != null) {
  103.                 this.model.FileChanged += new EventHandler(OnFileChanged);
  104.                 this.model.ModelChanged += new EventHandler<ModelChangedEventArgs>(OnModelChanged);
  105.             }
  106.             this.settings = (Settings)this.Site.GetService(typeof(Settings));
  107.             if (this.settings != null) {
  108.                 this.settings.Changed += new SettingsEventHandler(settings_Changed);
  109.             }            
  110.             if (this.model != null) BindTree();
  111.         }
  112.         [Browsable(false)]
  113.         public XmlCache Model {
  114.             get {
  115.                 if (this.Site == null) {
  116.                     throw new ApplicationException("ISite has not been provided, so model cannot be found");
  117.                 }
  118.                 return this.model; 
  119.             }
  120.         }
  121.         [Browsable(false)]
  122.         public Settings Settings {
  123.             get {
  124.                 if (this.Site == null) {
  125.                     throw new ApplicationException("ISite has not been provided, so settings cannot be found");
  126.                 }
  127.                 return this.settings; 
  128.             }
  129.         }
  130.         public NodeTextView NodeTextView {
  131.             get { return nodeTextView; }
  132.             set { nodeTextView = value; }
  133.         }
  134.         public void CancelEdit() {
  135.             TreeNode n = myTreeView.SelectedNode;
  136.             if (n != null && n.IsEditing) {
  137.                 n.EndEdit(true);
  138.             }
  139.             this.nodeTextView.EndEdit(true);
  140.         }
  141.         public virtual XmlTreeNode CreateTreeNode() {
  142.             return new XmlTreeNode(this);
  143.         }
  144.         public virtual XmlTreeNode CreateTreeNode(XmlNode node) {
  145.             return new XmlTreeNode(this, node);
  146.         }
  147.         public virtual XmlTreeNode CreateTreeNode(XmlTreeNode parent, XmlNode node) {
  148.             return new XmlTreeNode(this, parent, node);
  149.         }
  150.         public XmlTreeNode FindNode(XmlNode node) {
  151.             return FindNode(this.myTreeView.Nodes, node);
  152.         }
  153.         XmlTreeNode FindNode(TreeNodeCollection nodes, XmlNode node) {
  154.             foreach (XmlTreeNode xn in nodes) {
  155.                 if (xn.Node == node) return xn;
  156.                 if (xn.Nodes != null) {
  157.                     XmlTreeNode child = FindNode(xn.Nodes, node);
  158.                     if (child != null) return child;
  159.                 }
  160.             }
  161.             return null;
  162.         }
  163.         
  164.         public bool Commit() {
  165.             this.nodeTextView.EndEdit(false);
  166.             TreeNode n = myTreeView.SelectedNode;
  167.             if (n != null && n.IsEditing) {
  168.                 return n.EndEdit(false);
  169.             }
  170.             return true;
  171.         }
  172.         [Browsable(false)]
  173.         public UndoManager UndoManager {
  174.             get { return (UndoManager)this.Site.GetService(typeof(UndoManager)); }
  175.         }
  176.         [System.ComponentModel.Browsable(false)]
  177.         public IIntellisenseProvider IntellisenseProvider {
  178.             get { return (IIntellisenseProvider)this.Site.GetService(typeof(IIntellisenseProvider)); }
  179.         }
  180.         [Browsable(false)]
  181.         public TreeView TreeView {
  182.             get { return this.myTreeView; }
  183.         }
  184.         private void myTreeView_AfterLabelEdit(object sender, NodeLabelEditEventArgs e) {
  185.             try {
  186.                 XmlTreeNode xn = (XmlTreeNode)e.Node;
  187.                 XmlNode n = xn.Node;
  188.                 if (e.CancelEdit) return; // it's being cancelled.
  189.                 if (e.Label == null || StringHelper.IsNullOrEmpty(e.Label.Trim())) {
  190.                     
  191.                     string arg = null;
  192.                     if (xn.NodeImage == NodeImage.Attribute) 
  193.                         arg = "attributes";
  194.                     else if (xn.NodeImage == NodeImage.Element || xn.NodeImage == NodeImage.OpenElement || xn.NodeImage == NodeImage.Leaf) 
  195.                         arg = "elements";
  196.                     if (arg != null && n == null && MessageBox.Show(this,
  197.                         SR.XmlNameEmptyPrompt, SR.XmlNameErrorCaption,
  198.                         MessageBoxButtons.YesNo, MessageBoxIcon.Error) == DialogResult.No) {
  199.                         e.Node.BeginEdit();
  200.                         e.CancelEdit = true;
  201.                     }                     
  202.                     return; 
  203.                 }
  204.                 Command cmd = null;
  205.                 if (n == null) {
  206.                     TreeNode parent = e.Node.Parent;
  207.                     XmlNode context = (parent == null) ? this.model.Document : ((XmlTreeNode)parent).Node;
  208.                     cmd = this.UndoManager.Peek();
  209.                     try {
  210.                         InsertNode inode = cmd as InsertNode;
  211.                         if (inode != null) {
  212.                             if (inode.RequiresName) {
  213.                                 inode.XmlNode = inode.CreateNode(context, e.Label); 
  214.                                 // Cause selection event to be triggered so that menu state
  215.                                 // is recalculated.
  216.                                 this.myTreeView.SelectedNode = null;
  217.                                 this.OnNodeInserted(inode.NewNode);
  218.                             }
  219.                         }
  220.                     } 
  221.                     catch (Exception ex) {
  222.                         MessageBox.Show(this, ex.Message,
  223.                             SR.XmlNameErrorCaption, MessageBoxButtons.OK, MessageBoxIcon.Error);
  224.                         this.myTreeView.SelectedNode = e.Node;
  225.                         e.CancelEdit = true;
  226.                         xn.Label = e.Label.Trim();
  227.                         e.Node.BeginEdit();
  228.                         return;
  229.                     }
  230.                     e.Node.Label = e.Label;
  231.                     this.myTreeView.SelectedNode = e.Node;
  232.                     this.nodeTextView.Invalidate(e.Node);
  233.                     this.nodeTextView.FocusBeginEdit(null);
  234.                     return; // one undoable unit.
  235.                 }
  236.                 switch (n != null ? n.NodeType : XmlNodeType.None) {
  237.                     case XmlNodeType.Comment:
  238.                     case XmlNodeType.Text:
  239.                     case XmlNodeType.CDATA:
  240.                         e.CancelEdit = true;
  241.                         // actually it would be cool to change the node type at this point.
  242.                         break;
  243.                     case XmlNodeType.Attribute:
  244.                         cmd = new EditAttributeName(n as XmlAttribute, e);
  245.                         break;
  246.                     case XmlNodeType.Element:
  247.                         cmd =  new EditElementName(n as XmlElement, e);
  248.                         break;
  249.                     case XmlNodeType.ProcessingInstruction:
  250.                         cmd = new EditProcessingInstructionName(n as XmlProcessingInstruction, e);
  251.                         break;
  252.                 }
  253.                 if (cmd != null) {
  254.                     this.UndoManager.Push(cmd);
  255.                 }
  256.             } 
  257.             catch (Exception ex) {
  258.                 e.CancelEdit = true;
  259.                 MessageBox.Show(this, ex.Message, SR.EditErrorCaption, MessageBoxButtons.OK, MessageBoxIcon.Error);
  260.             }
  261.         }        
  262.         private void myTreeView_AfterCollapse(object sender, TreeViewEventArgs e) {
  263.             if (!this.myTreeView.InBatchUpdate) {
  264.                 PerformLayout();
  265.                 Invalidate();
  266.             }
  267.         }
  268.         private void myTreeView_AfterExpand(object sender, TreeViewEventArgs e) {
  269.             if (!this.myTreeView.InBatchUpdate) {
  270.                 PerformLayout();
  271.                 Invalidate();
  272.             }
  273.         }
  274.         private void myTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
  275.             TreeNode n = e.Node;
  276.             if (this.TreeView.InBatchUpdate) {
  277.                 this.nodeTextView.InternalSelect(n);
  278.             } else {
  279.                 this.nodeTextView.SelectedNode = n;
  280.                 if (n != null) {
  281.                     ScrollIntoView(n);
  282.                 }
  283.                 if (SelectionChanged != null) SelectionChanged(this, EventArgs.Empty); 
  284.             }
  285.         }
  286.         void myTreeView_AfterBatchUpdate(object sender, EventArgs e) {
  287.             if (this.SelectedNode != null) {
  288.                 ScrollIntoView(this.SelectedNode);
  289.             }
  290.         }
  291.         void nodeTextView_AfterSelect(object sender, TreeViewEventArgs e) {
  292.             if (this.myTreeView != null) {
  293.                 this.myTreeView.SelectedNode = e.Node;
  294.             }
  295.         }
  296.         public Point ScrollPosition {
  297.             get { return myTreeView.ScrollPosition; }
  298.         }
  299.         public virtual void ScrollIntoView(TreeNode n) {
  300.             // Scroll the newly selected node into view vertically.
  301.             Rectangle r = n.LabelBounds;
  302.             int delta = myTreeView.TreeIndent + imageList1.ImageSize.Width + TreeNode.GetGap(myTreeView.TreeIndent);
  303.             r = new Rectangle(r.Left - delta, r.Top, r.Width + delta, r.Height);
  304.             int y = r.Top + myTreeView.ScrollPosition.Y;
  305.             if (y > myTreeView.Height - myTreeView.ItemHeight) {
  306.                 y = y - myTreeView.Height + myTreeView.ItemHeight;
  307.             } 
  308.             else if (y > 0) {
  309.                 y = 0;
  310.             }
  311.             if (y != 0) {
  312.                 int newy = myTreeView.ScrollPosition.Y - y;
  313.                 myTreeView.ScrollPosition = new Point(myTreeView.ScrollPosition.X, newy);
  314.                 nodeTextView.ScrollPosition = new Point(0, newy);
  315.                 this.nodeTextView.Invalidate();
  316.                 this.vScrollBar1.Value = Math.Max(0,Math.Min(this.vScrollBar1.Maximum, this.vScrollBar1.Value + (y / myTreeView.ItemHeight)));
  317.             }
  318.             // Tweak horizontal to make the newly selected label visible.
  319.             int x = this.myTreeView.ScrollPosition.X;
  320.             if (r.Left + this.myTreeView.ScrollPosition.X < 0) {
  321.                 // Label is off the left hand side.
  322.                 x = -r.Left;
  323.             } else if (r.Right + this.myTreeView.ScrollPosition.X > this.resizer.Left) {
  324.                 // Label is off the right hand side
  325.                 x = this.resizer.Left - r.Right - 10;
  326.                 if (r.Left + x < 0) {
  327.                     // Label is too long to fit, now it hangs off the left side, so
  328.                     // let's just leave it where it was
  329.                     x = this.myTreeView.ScrollPosition.X;
  330.                 }
  331.             }
  332.             if (x != this.myTreeView.ScrollPosition.X) {
  333.                 int pos = Math.Max(0, Math.Min(this.hScrollBar1.Maximum * HScrollIncrement, -x));
  334.                 myTreeView.ScrollPosition = new Point(-pos, myTreeView.ScrollPosition.Y);
  335.                 this.hScrollBar1.Value = pos / HScrollIncrement;
  336.             }            
  337.         }
  338.         internal void OnNodeChanged(XmlTreeNode node) {
  339.             if (NodeChanged != null) NodeChanged(this, new NodeChangeEventArgs(node));
  340.         }
  341.         public virtual void OnNodeInserted(XmlTreeNode node) {
  342.             if (NodeInserted != null) NodeInserted(this, new NodeChangeEventArgs(node));
  343.             // Populate default value.
  344.             if (node.Node != null && !node.Node.HasChildNodes &&
  345.                 (node.NodeType == XmlNodeType.Attribute || node.NodeType == XmlNodeType.Element)) {
  346.                 SetDefaultValue(node);
  347.             }
  348.         }
  349.         protected virtual void SetDefaultValue(XmlTreeNode node) {
  350.             IIntellisenseProvider provider = this.IntellisenseProvider;
  351.             if (provider != null) {
  352.                 provider.SetContextNode(node);
  353.                 string defaultValue = provider.GetDefaultValue();
  354.                 if (!string.IsNullOrEmpty(defaultValue)) {
  355.                     EditNodeValue cmd = new EditNodeValue(this, node, defaultValue);
  356.                     this.UndoManager.Push(cmd);                    
  357.                 }
  358.             }
  359.         }
  360.         private void OnModelChanged(object sender, ModelChangedEventArgs e) {
  361.             if (disposed) return;
  362.             ModelChangeType t = e.ModelChangeType;            
  363.             switch (t) {
  364.                 case ModelChangeType.Reloaded:
  365.                     BindTree();
  366.                     break;
  367.                 case ModelChangeType.NamespaceChanged:
  368.                     RecalculateNamespaces(e.Node);
  369.                     break;
  370.             }
  371.             nodeTextView.Invalidate();
  372.         }
  373.         
  374.         public bool IsEditing {
  375.             get { return this.myTreeView.IsEditing || this.nodeTextView.IsEditing;  }
  376.         }
  377.         private void OnFileChanged(object sender, EventArgs e) {
  378.             BindTree();
  379.         }
  380.         void BindTree() {
  381.             this.myTreeView.ScrollPosition = new Point(0,0);
  382.             this.vScrollBar1.Maximum = 0;
  383.             this.vScrollBar1.Value = 0;
  384.             this.hScrollBar1.Maximum = 0;
  385.             this.hScrollBar1.Value = 0;
  386.             this.nodeTextView.Top = 0;
  387.             this.nodeTextView.ScrollPosition = new Point(0, 0);
  388.             this.SuspendLayout();
  389.             this.myTreeView.BeginUpdate();
  390.             try {
  391.                 XmlTreeNodeCollection nodes = new XmlTreeNodeCollection(this, this.model.Document);
  392.                 this.myTreeView.Nodes = this.nodeTextView.Nodes = nodes;
  393.                 foreach (XmlTreeNode tn in this.myTreeView.Nodes) {
  394.                     tn.Expand();
  395.                 }
  396.                 this.nodeTextView.Reset();
  397.             } 
  398.             finally {
  399.                 this.myTreeView.EndUpdate();
  400.             }
  401.             this.ResumeLayout();
  402.             this.myTreeView.Invalidate();
  403.             this.myTreeView.Focus();
  404.             if (this.myTreeView.Nodes.Count > 0) {
  405.                 this.SelectedNode = (XmlTreeNode)this.myTreeView.Nodes[0];
  406.             }
  407.         }
  408.         int CountVisibleNodes(TreeNodeCollection tc) {
  409.             if (tc == null) return 0;
  410.             int count = 0;
  411.             foreach (TreeNode tn in tc) {
  412.                 count++;
  413.                 if (tn.IsExpanded) {
  414.                     count += CountVisibleNodes(tn.Nodes);
  415.                 }
  416.             }
  417.             return count;
  418.         }
  419.         internal void SyncScrollbars() {
  420.             if (this.hScrollBar1.Visible) {
  421.                 int x = this.resizer.Left;
  422.                 int w = this.myTreeView.VirtualWidth + 10;
  423.                 this.myTreeView.Height = this.Height - this.hScrollBar1.Height;
  424.                 int hScrollMax = 10 + ((w - x) / HScrollIncrement);
  425.                 this.hScrollBar1.Minimum = 0;
  426.                 this.hScrollBar1.Maximum = hScrollMax;
  427.                 this.hScrollBar1.Value = Math.Min(this.hScrollBar1.Value, hScrollMax);
  428.             } else {
  429.                 this.hScrollBar1.Visible = false;
  430.                 this.hScrollBar1.Value = 0;
  431.             }
  432.             int itemHeight = this.myTreeView.ItemHeight;
  433.             int visibleNodes = this.myTreeView.VirtualHeight / itemHeight;
  434.             int vScrollMax = Math.Max(0, visibleNodes - 1);
  435.             this.vScrollBar1.Maximum = vScrollMax;
  436.             this.vScrollBar1.SmallChange = 1;
  437.             this.vScrollBar1.LargeChange = this.myTreeView.VisibleRows;
  438.             this.vScrollBar1.Minimum = 0;
  439.             if (this.myTreeView.VirtualHeight < this.Height) {
  440.                 this.vScrollBar1.Value = 0;
  441.             } else {
  442.                 this.vScrollBar1.Value = Math.Min(this.vScrollBar1.Value, vScrollMax);
  443.             }
  444.         }
  445.         public int ResizerPosition {
  446.             get { return this.resizer.Left; }
  447.             set { this.resizer.Left = value; this.PerformLayout();  }
  448.         }
  449.         
  450.         protected override void OnLayout(LayoutEventArgs levent) {
  451.             
  452.             int x = this.resizer.Left;
  453.             this.myTreeView.Width = x;
  454.             int count = CountVisibleNodes(this.myTreeView.Nodes);
  455.             int h = Math.Max(this.Height, this.myTreeView.ItemHeight * count);
  456.             this.vScrollBar1.Left = this.Right - this.vScrollBar1.Width;
  457.             this.vScrollBar1.Height = this.Height;
  458.             this.hScrollBar1.Top = this.Height - this.hScrollBar1.Height;
  459.             this.hScrollBar1.Width = x;
  460.             this.myTreeView.Size = new Size(x, this.Height);
  461.             this.nodeTextView.Size = new Size(this.vScrollBar1.Left - this.resizer.Right, this.Height);
  462.             this.nodeTextView.Left = this.resizer.Right;
  463.             int w = this.myTreeView.VirtualWidth + 10;            
  464.             this.myTreeView.Width = Math.Max(w, x);
  465.             if (w > x) {
  466.                 this.myTreeView.Height = this.Height - this.hScrollBar1.Height;
  467.                 this.hScrollBar1.Visible = true;
  468.             } else {
  469.                 this.hScrollBar1.Visible = false;
  470.             }
  471.             SyncScrollbars();
  472.             int y = -this.vScrollBar1.Value * this.myTreeView.ItemHeight;
  473.             this.myTreeView.ScrollPosition = new Point(-this.hScrollBar1.Value * HScrollIncrement, y);
  474.             this.resizer.Height = this.Height;            
  475.             Invalidate();
  476.             this.nodeTextView.Invalidate();
  477.         }
  478.         public void Cut() {
  479.             this.Commit();
  480.             XmlTreeNode selection = (XmlTreeNode)this.myTreeView.SelectedNode;
  481.             if (selection != null) {
  482.                 this.UndoManager.Push(new CutCommand(this, selection));
  483.                 if (ClipboardChanged != null) ClipboardChanged(this, EventArgs.Empty);
  484.             }
  485.         }
  486.         public void Copy() {
  487.             this.Commit();
  488.             XmlTreeNode selection = (XmlTreeNode)this.myTreeView.SelectedNode;
  489.             if (selection != null) {
  490.                 TreeData.SetData(selection);
  491.                 if (ClipboardChanged != null) ClipboardChanged(this, EventArgs.Empty);
  492.             }
  493.         }
  494.         public void Paste(InsertPosition position) {
  495.             this.Commit();
  496.             try {
  497.                 this.UndoManager.Push(new PasteCommand(this.model.Document, this, position, TreeData.GetData()));
  498.             } 
  499.             catch (Exception ex) {
  500.                 MessageBox.Show(this, ex.Message, SR.PasteErrorCaption, MessageBoxButtons.OK, MessageBoxIcon.Error);
  501.             }
  502.         }
  503.         public void PasteXml(InsertPosition position, string xml ) {
  504.             this.Commit();
  505.             try {
  506.                 this.UndoManager.Push(new PasteCommand(this.model.Document, this, position, new TreeData(xml)));
  507.             } catch (Exception ex) {
  508.                 MessageBox.Show(this, ex.Message, SR.PasteErrorCaption, MessageBoxButtons.OK, MessageBoxIcon.Error);
  509.             }
  510.         }
  511.         public virtual bool CanInsertNode(InsertPosition position, XmlNodeType type) {
  512.             XmlTreeNode n = (XmlTreeNode)this.myTreeView.SelectedNode;
  513.             if (n!= null && n.Node == null) {
  514.                 // We are still editing this tree node and haven't created XmlNode
  515.                 // for it yet - so bail!
  516.                 return false;
  517.             }
  518.             InsertNode inode = new InsertNode(this);
  519.             return inode.Initialize(n, position, type);
  520.         }
  521.         public void ChangeTo(XmlNodeType nt) {
  522.             try {
  523.                 if (this.Commit()) {
  524.                     XmlTreeNode n = (XmlTreeNode)this.myTreeView.SelectedNode;
  525.                     if (n == null) return;
  526.                     ChangeNode cmd = new ChangeNode(this, n, nt);
  527.                     this.UndoManager.Push(cmd);
  528.                     this.nodeTextView.Invalidate();
  529.                     this.myTreeView.SelectedNode = cmd.NewNode;                    
  530.                 }
  531.             } catch (Exception ex) {
  532.                 MessageBox.Show(this, ex.Message, SR.ChangeErrorCaption, MessageBoxButtons.OK, MessageBoxIcon.Error);
  533.             }
  534.         }
  535.         public void InsertNode(InsertPosition position, XmlNodeType type) {
  536.             try {
  537.                 XmlTreeNode n = (XmlTreeNode)this.myTreeView.SelectedNode;
  538.                 InsertNode inode = new InsertNode(this);
  539.                 inode.Initialize(n, position, type);
  540.                 this.UndoManager.Push(inode);
  541.                 this.nodeTextView.Invalidate();
  542.                 this.myTreeView.SelectedNode = inode.NewNode;
  543.                 if (inode.RequiresName) {
  544.                     this.myTreeView.Focus();
  545.                     inode.NewNode.BeginEdit();
  546.                 } else {
  547.                     this.nodeTextView.FocusBeginEdit(null);
  548.                 }
  549.             } catch (Exception ex) {
  550.                 MessageBox.Show(this, ex.Message, SR.InsertErrorCaption, MessageBoxButtons.OK, MessageBoxIcon.Error);
  551.             }
  552.         }
  553.         
  554.         public bool Delete() {
  555.             if (this.myTreeView.SelectedNode != null) {
  556.                 XmlTreeNode t = (XmlTreeNode)this.myTreeView.SelectedNode;                 
  557.                 this.UndoManager.Push(new DeleteNode(this.model.Document, t));
  558.                 this.nodeTextView.Invalidate();
  559.                 return true;
  560.             }
  561.             return false;
  562.         }
  563.         public bool Insert() {
  564.             // Insert empty node of same type as current node right after current node.
  565.             if (this.myTreeView.SelectedNode != null) {
  566.                 XmlTreeNode n = (XmlTreeNode)this.myTreeView.SelectedNode;
  567.                 InsertNode(InsertPosition.After, n.Node.NodeType);
  568.                 return true;
  569.             }
  570.             return false;
  571.         }
  572.         public bool Duplicate() {
  573.             if (this.myTreeView.SelectedNode != null) {
  574.                 XmlTreeNode t = (XmlTreeNode)this.myTreeView.SelectedNode;
  575.                 this.UndoManager.Push(new MoveNode(this, t, t, InsertPosition.After, true));
  576.                 this.nodeTextView.Invalidate();
  577.                 return true;
  578.             }
  579.             return false;
  580.         }
  581.         private void HandleMouseWheel(object sender, MouseEventArgs e) {            
  582.             int y = SystemInformation.MouseWheelScrollLines * (e.Delta/120);
  583.             int v = Math.Max(0, Math.Min(this.vScrollBar1.Value - y, this.vScrollBar1.Maximum + 1 - this.vScrollBar1.LargeChange));
  584.             this.vScrollBar1.Value = v;
  585.             vScrollBar1_Scroll(this, new ScrollEventArgs(ScrollEventType.ThumbTrack, v));
  586.         }
  587.         private void hScrollBar1_Scroll(object sender, System.Windows.Forms.ScrollEventArgs e) {
  588.             if (this.TreeView.IsEditing) {
  589.                 this.TreeView.EndEdit(true);
  590.             }
  591.             if (this.nodeTextView.IsEditing) {
  592.                 this.nodeTextView.EndEdit(true);
  593.             }
  594.             this.myTreeView.ScrollPosition = new Point(-e.NewValue * HScrollIncrement, this.myTreeView.ScrollPosition.Y);            
  595.         }
  596.         
  597.         private void vScrollBar1_Scroll(object sender, System.Windows.Forms.ScrollEventArgs e) {
  598.             if (this.TreeView.IsEditing) {
  599.                 this.TreeView.EndEdit(true);
  600.             }
  601.             if (this.nodeTextView.IsEditing) {
  602.                 this.nodeTextView.EndEdit(true);
  603.             }
  604.             int y = -e.NewValue * this.myTreeView.ItemHeight;
  605.             this.myTreeView.ScrollPosition = new Point(this.myTreeView.ScrollPosition.X, y);
  606.             this.nodeTextView.ScrollPosition = new Point(0, y);
  607.             this.nodeTextView.Invalidate();
  608.         }        
  609.         
  610.         protected override bool ProcessDialogKey(Keys keyData) {
  611.             CurrentEvent.Event = new KeyEventArgs(keyData);
  612.             Keys modifiers = (keyData & Keys.Modifiers);
  613.             Keys key = keyData & ~modifiers;
  614.             switch (key) {
  615.                 case Keys.Tab:
  616.                     if (modifiers == Keys.Shift) {
  617.                         bool editing = this.nodeTextView.IsEditing;
  618.                         if (this.nodeTextView.Focused || editing) {
  619.                             if (this.nodeTextView.EndEdit(false)) {
  620.                                 this.myTreeView.Focus();
  621.                             }
  622.                         } else {
  623.                             if (this.myTreeView.SelectedNode != null) {
  624.                                 TreeNode previous = this.myTreeView.SelectedNode.PrevVisibleNode;
  625.                                 if (previous != null) this.myTreeView.SelectedNode = previous;
  626.                             }
  627.                             this.nodeTextView.Focus();
  628.                         }
  629.                     } else {
  630.                         bool editing = this.myTreeView.IsEditing;
  631.                         if (this.myTreeView.Focused || editing) {
  632.                             if (this.myTreeView.EndEdit(false)) {
  633.                                 this.nodeTextView.Focus();
  634.                                 if (editing) {
  635.                                     this.nodeTextView.FocusBeginEdit(null);
  636.                                 }
  637.                             }
  638.                         } else {
  639.                             if (this.myTreeView.SelectedNode != null) {
  640.                                 TreeNode next = this.myTreeView.SelectedNode.NextVisibleNode;
  641.                                 if (next != null) this.myTreeView.SelectedNode = next;
  642.                             }
  643.                             this.myTreeView.Focus();
  644.                         }
  645.                     }
  646.                     return true;
  647.             }
  648.             return false;
  649.         }
  650.         public void StartIncrementalSearch() {
  651.             if (this.TreeView.ContainsFocus) {
  652.                 this.TreeView.StartIncrementalSearch();
  653.             } else if (this.nodeTextView.ContainsFocus) {
  654.                 this.nodeTextView.StartIncrementalSearch();
  655.             }
  656.         }
  657.         private void myTreeView_KeyDown(object sender, KeyEventArgs e) {
  658.             CurrentEvent.Event = e;
  659.             if (!this.IsEditing) {
  660.                 bool ctrlMods = e.Modifiers == Keys.Control || e.Modifiers == (Keys.Control | Keys.Shift);
  661.                 bool nudgeMods = e.Modifiers == (Keys.Control | Keys.Shift);
  662.                 XmlTreeNode xn = this.SelectedNode;
  663.                 TreeNode n = this.myTreeView.SelectedNode;
  664.                 switch (e.KeyCode) {
  665.                     case Keys.Escape:
  666.                         this.Commit();
  667.                         if (!e.Handled) {
  668.                             this.myTreeView.SelectedNode = null;
  669.                             if (this.SelectionChanged != null)
  670.                                 SelectionChanged(this, EventArgs.Empty);
  671.                         }
  672.                         break;
  673.                     case Keys.X:
  674.                         if (ctrlMods) {
  675.                             this.Cut();
  676.                             e.Handled = true;
  677.                         }
  678.                         break;
  679.                     case Keys.C:
  680.                         if (ctrlMods) {
  681.                             this.Copy();
  682.                             e.Handled = true;
  683.                         }
  684.                         break;
  685.                     case Keys.V:
  686.                         if (ctrlMods) {
  687.                             this.Paste(InsertPosition.Child);
  688.                             e.Handled = true;
  689.                         }
  690.                         break;
  691.                     case Keys.Right:
  692.                         if (nudgeMods && CanNudgeNode(xn, NudgeDirection.Right)) {
  693.                             this.NudgeNode(xn, NudgeDirection.Right);
  694.                             e.Handled = true;
  695.                         } else if (!this.IsEditing && n != null && n.Nodes.Count == 0) {
  696.                             this.nodeTextView.Focus();
  697.                             e.Handled = true;
  698.                         }
  699.                         break;
  700.                     case Keys.Delete:
  701.                         this.Delete();
  702.                         break;
  703.                     case Keys.F2:
  704.                     case Keys.Enter:
  705.                         BeginEditNodeName();
  706.                         e.Handled = true;
  707.                         break;
  708.                     case Keys.Up:
  709.                         if (nudgeMods && CanNudgeNode(xn, NudgeDirection.Up)) {
  710.                             this.NudgeNode(xn, NudgeDirection.Up);
  711.                             e.Handled = true;
  712.                         }
  713.                         break;
  714.                     case Keys.Down:
  715.                         if (nudgeMods && CanNudgeNode(xn, NudgeDirection.Down)) {
  716.                             this.NudgeNode(xn, NudgeDirection.Down);
  717.                             e.Handled = true;
  718.                         }
  719.                         break;
  720.                     case Keys.Left:
  721.                         if (nudgeMods && CanNudgeNode(xn, NudgeDirection.Left)) {
  722.                             this.NudgeNode(xn, NudgeDirection.Left);
  723.                             e.Handled = true;
  724.                         }
  725.                         break;
  726.                     default:
  727.                         if (!e.Handled) {
  728.                             nodeTextView_KeyDown(sender, e);
  729.                         }
  730.                         break;
  731.                 }
  732.             } else if (!e.Handled) {
  733.                 base.OnKeyDown(e);
  734.             }
  735.         }
  736.         public void BeginEditNodeName() {
  737.             TreeNode n = this.myTreeView.SelectedNode;                
  738.             if (!this.IsEditing && n != null && n.IsLabelEditable) {
  739.                 n.BeginEdit();
  740.             }
  741.         }
  742.         private void nodeTextView_KeyDown(object sender, KeyEventArgs e) {
  743.             tip.Hide();
  744.             CurrentEvent.Event = e;
  745.             if (!this.IsEditing) {
  746.                 bool ctrlMods = e.Modifiers == Keys.Control || e.Modifiers == (Keys.Control | Keys.Shift);
  747.                 Keys key = (e.KeyData & ~Keys.Modifiers);
  748.                 switch (key) {
  749.                     case Keys.Left:
  750.                         if (nodeTextView.Focused) {
  751.                             this.myTreeView.Focus();
  752.                             e.Handled = true;
  753.                         }
  754.                         break;
  755.                     case Keys.Delete:
  756.                         this.Delete();
  757.                         e.Handled = true;
  758.                         return;
  759.                     case Keys.X:
  760.                         if (ctrlMods) {
  761.                             this.Cut();
  762.                             e.Handled = true;
  763.                         }
  764.                         break;
  765.                     case Keys.C:
  766.                         if (ctrlMods) {
  767.                             this.Copy();
  768.                             e.Handled = true;
  769.                         }
  770.                         break;
  771.                     case Keys.V:
  772.                         if (ctrlMods) {
  773.                             this.Paste(InsertPosition.Child);
  774.                             e.Handled = true;
  775.                         }
  776.                         break;
  777.                     default:
  778.                         if (!e.Handled) {
  779.                             this.myTreeView.HandleKeyDown(e);
  780.                         }
  781.                         break;
  782.                 }
  783.             }
  784.             if (!e.Handled) {
  785.                 base.OnKeyDown(e);
  786.             }
  787.         }
  788.         private void settings_Changed(object sender, string name) {
  789.             ISynchronizeInvoke si = (ISynchronizeInvoke)this;
  790.             if (si.InvokeRequired){
  791.                 this.Invoke(new SettingsEventHandler(OnSettingsChanged), new object[] { sender, name });
  792.             } else {
  793.                 OnSettingsChanged(sender, name);
  794.             }
  795.         }
  796.         private void OnSettingsChanged(object sender, string name) {
  797.             // change the node colors.
  798.             System.Collections.Hashtable colors = (System.Collections.Hashtable)this.settings["Colors"];
  799.             Color backColor = (Color)colors["Background"];
  800.             this.BackColor = backColor;
  801.             this.myTreeView.BackColor = backColor;
  802.             this.nodeTextView.BackColor = backColor;
  803.             this.Font = (Font)this.settings["Font"];
  804.             this.myTreeView.BeginUpdate();
  805.             InvalidateNodes(this.myTreeView.Nodes); // force nodes to pick up new colors.
  806.             this.myTreeView.EndUpdate();
  807.         }
  808.         void InvalidateNodes(TreeNodeCollection nodes) {
  809.             if (nodes == null) return;
  810.             foreach (XmlTreeNode xn in nodes) {
  811.                 if (xn.IsVisible) {
  812.                     xn.Invalidate();
  813.                     if (xn.IsExpanded) {
  814.                         InvalidateNodes(xn.Nodes);
  815.                     }
  816.                 }
  817.             }
  818.         }
  819.         enum DragKeyState {
  820.             LeftButton = 1,
  821.             RightButton = 2,
  822.             Shift = 4,
  823.             Control = 8,
  824.             MiddleButton = 16,
  825.             Alt = 32
  826.         }
  827.         static TreeData CheckDragEvent(DragEventArgs e) {
  828.             TreeData data = null;
  829.             string name = DataFormats.GetFormat(typeof(TreeData).FullName).Name;
  830.             try {
  831.                 if (e.Data.GetDataPresent(name, false)) {
  832.                     data = (TreeData)e.Data.GetData(name);
  833.                 }
  834.             } 
  835.             catch (Exception ex) {
  836.                 Trace.WriteLine("Exception:" + ex.ToString());
  837.             }
  838.             if (data == null && e.Data.GetDataPresent(DataFormats.Text)) {
  839.                 string xml = (string)e.Data.GetData(DataFormats.Text);
  840.                 data = new TreeData(xml);
  841.             }
  842.             if (data != null) {
  843.                 DragKeyState ks = (DragKeyState)e.KeyState;
  844.                 // Copy when the control key is down.
  845.                 e.Effect = ((ks & DragKeyState.Control) != DragKeyState.Control) ?
  846.                     DragDropEffects.Move : DragDropEffects.Copy;
  847.             } 
  848.             else {
  849.                 e.Effect = DragDropEffects.None;
  850.             }
  851.             return data;
  852.         }
  853.         private void treeViewFeedback_DragDrop(object sender, DragEventArgs e) {
  854.             TreeData data = CheckDragEvent(e);
  855.             FinishDragDrop(data, e.Effect);
  856.         }
  857.         private void treeViewFeedback_DragEnter(object sender, DragEventArgs e) {
  858.             TreeData data = CheckDragEvent(e);
  859.             if (data != null && this.feedback == null) {
  860.                 this.feedback = new XmlTreeViewDropFeedback();
  861.                 if (this.dragged == null) {
  862.                     // dragging from another app, so we have to import the node at this point.
  863.                     XmlTreeNode target = (XmlTreeNode)this.myTreeView.FindNodeAt(e.X, e.Y);
  864.                     this.dragged = data.GetTreeNode(this.Model.Document, target, this);
  865.                 }
  866.                 this.feedback.Item = this.dragged;
  867.                 this.feedback.TreeView = this.myTreeView;
  868.             }            
  869.             if (this.feedback != null) {
  870.                 this.feedback.Position = new Point(e.X, e.Y);
  871.             }
  872.         }
  873.         private void treeViewFeedback_DragLeave(object sender, EventArgs e) {
  874.             RemoveFeedback();
  875.         }
  876.         private void treeViewFeedback_DragOver(object sender, DragEventArgs e) {
  877.             // find the node under the X,Y position and draw feedback as to where the new node will
  878.             // be dropped. 
  879.             if (this.feedback != null) {
  880.                 CheckDragEvent(e);                
  881.                 this.feedback.Position = new Point(e.X, e.Y);
  882.             }
  883.         }
  884.         private void myTreeView_GiveFeedback(object sender, GiveFeedbackEventArgs e) {
  885.             e.UseDefaultCursors = true;
  886.         }
  887.         private void myTreeView_ItemDrag(object sender, ItemDragEventArgs e) {
  888.             if (e.Button == MouseButtons.Left) {
  889.                 this.dragged = (XmlTreeNode)e.Item;
  890.                 this.myTreeView.SelectedNode = this.dragged;
  891.                 TreeData data = new TreeData(this.dragged);
  892.                 DragDropEffects effect = this.DoDragDrop(data, DragDropEffects.All);
  893.                 if (this.dragged != null && effect != DragDropEffects.None) {
  894.                     FinishDragDrop(data, effect);
  895.                 }
  896.                 RemoveFeedback();
  897.             }
  898.         }
  899.         void RemoveFeedback() {
  900.             if (this.feedback != null) {
  901.                 this.feedback.Finish(this.dragged != null);
  902.                 this.feedback.Dispose();
  903.                 this.feedback = null;
  904.             }
  905.         }
  906.         protected void FinishDragDrop(TreeData data, DragDropEffects effect) {
  907.             if (data != null && effect != DragDropEffects.None && this.dragged != null) {
  908.                 bool copy = (effect == DragDropEffects.Copy);
  909.                 if (this.feedback != null) {
  910.                     // Then we are also the drop site
  911.                     MoveNode cmd = null;
  912.                     if (this.feedback.Before != null) {
  913.                         cmd = MoveNode(this.dragged, (XmlTreeNode)this.feedback.Before, InsertPosition.Before, copy);
  914.                     } 
  915.                     else if (this.feedback.After != null) {
  916.                         cmd = MoveNode(this.dragged, (XmlTreeNode)this.feedback.After, InsertPosition.After, copy);
  917.                     }
  918.                     // Now we can expand it because it is now in the tree
  919.                     if (cmd != null && cmd.Source.Nodes.Count > 1) {
  920.                         cmd.Source.Expand();
  921.                     }
  922.                 } 
  923.                 else if (!copy) {
  924.                     // Then this was a move to another process, so now we have to remove it
  925.                     // from this process.
  926.                     Debug.Assert(this.myTreeView.SelectedNode == this.dragged);
  927.                     this.Delete();
  928.                 }
  929.             }
  930.             this.dragged = null;
  931.             RemoveFeedback();
  932.         }
  933.         private MoveNode MoveNode(XmlTreeNode source, XmlTreeNode dest, InsertPosition where, bool copy) {
  934.             try {
  935.                 MoveNode cmd = new MoveNode(this, source, dest, where, copy);
  936.                 this.UndoManager.Push(cmd);
  937.                 return cmd;
  938.             } 
  939.             catch (Exception ex) {
  940.                 MessageBox.Show(this, ex.Message, SR.MoveErrorCaption, MessageBoxButtons.OK, MessageBoxIcon.Error);
  941.             }
  942.             return null;
  943.         }
  944.         public bool CanNudgeNode(XmlTreeNode node, NudgeDirection dir) {
  945.             if (node == null) return false;
  946.             NudgeNode n = new NudgeNode(this, node, dir);
  947.             return n.IsEnabled;
  948.         }
  949.         public void NudgeNode(XmlTreeNode node, NudgeDirection dir) {
  950.             try {
  951.                 NudgeNode cmd = new NudgeNode(this, node, dir);
  952.                 this.UndoManager.Push(cmd);
  953.             } 
  954.             catch (Exception ex) {
  955.                 MessageBox.Show(this, ex.Message, SR.NudgeErrorCaption, MessageBoxButtons.OK, MessageBoxIcon.Error);
  956.             }
  957.         }
  958.         bool reentrantLock = false;
  959.         public void RecalculateNamespaces(XmlNode node) {
  960.             if (node is XmlText) node = node.ParentNode;
  961.             if (node.NodeType != XmlNodeType.Element && node.NodeType != XmlNodeType.Attribute) {
  962.                 return;
  963.             }
  964.             if (reentrantLock) return;
  965.             Command exec = this.UndoManager.Executing;
  966.             if (exec != null && exec.Name == "Edit Namespace")
  967.                 return; // don't "redo" this during Commnad.Redo()! 
  968.             this.SuspendLayout();
  969.             this.myTreeView.BeginUpdate();
  970.             this.model.BeginUpdate();
  971.             
  972.             Cursor.Current = Cursors.WaitCursor;
  973.             
  974.             // Do not re-enter this when we are processing the recalcNamespaces compound command!
  975.             reentrantLock = true;
  976.             try {
  977.                 // This xmlns attribute has changed, so we need to recalculate the NamespaceURI
  978.                 // property on the scoped element and it's children so that validation works
  979.                 // as expected.  
  980.                 XmlElement scope;
  981.                 if (node is XmlAttribute) {
  982.                     scope = ((XmlAttribute)node).OwnerElement;
  983.                 } else {
  984.                     scope = (XmlElement)node;
  985.                 }
  986.                 if (scope == null) return;
  987.                 XmlTreeNode tnode = FindNode(scope);
  988.                 if (tnode == null) return;
  989.                 if (tnode.Node == null) return;
  990.                 XmlNamespaceManager nsmgr = XmlHelpers.GetNamespaceScope(scope);
  991.                 CompoundCommand cmd = new CompoundCommand("Edit Namespace");
  992.                 tnode.RecalculateNamespaces(nsmgr, cmd);
  993.                 if (cmd.Count > 0) {
  994.                     this.UndoManager.Merge(cmd);
  995.                 }
  996.             } finally {
  997.                 reentrantLock = false;
  998.                 this.myTreeView.EndUpdate();
  999.                 this.ResumeLayout();
  1000.                 this.myTreeView.Invalidate();
  1001.                 this.model.EndUpdate();
  1002.                 Cursor.Current = Cursors.Arrow;
  1003.             }
  1004.         }
  1005.         //=======================================================================================
  1006.         // DO NOT EDIT BELOW THIS LINE
  1007.         //=======================================================================================
  1008.         /// <summary> 
  1009.         /// Clean up any resources being used.
  1010.         /// </summary>
  1011.         protected override void Dispose(bool disposing) {
  1012.             if (disposing) {
  1013.                 if (components != null) {
  1014.                     components.Dispose();
  1015.                 }
  1016.             }
  1017.             base.Dispose(disposing);
  1018.         }
  1019.         #region Component Designer generated code
  1020.         /// <summary> 
  1021.         /// Required method for Designer support - do not modify 
  1022.         /// the contents of this method with the code editor.
  1023.         /// </summary>
  1024.         private void InitializeComponent() {
  1025.             this.components = new System.ComponentModel.Container();
  1026.             System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(XmlTreeView));
  1027.             this.myTreeView = new TreeView();
  1028.             this.imageList1 = new System.Windows.Forms.ImageList(this.components);
  1029.             this.nodeTextView = new XmlNotepad.NodeTextView();
  1030.             this.resizer = new XmlNotepad.PaneResizer();
  1031.             this.vScrollBar1 = new System.Windows.Forms.VScrollBar();
  1032.             this.hScrollBar1 = new HScrollBar();
  1033.             this.SuspendLayout();
  1034.             // 
  1035.             // myTreeView
  1036.             // 
  1037.             this.myTreeView.BorderStyle = System.Windows.Forms.BorderStyle.None;
  1038.             this.myTreeView.ImageList = this.imageList1;
  1039.             this.myTreeView.LabelEdit = true;
  1040.             this.myTreeView.Location = new System.Drawing.Point(0, 0);
  1041.             this.myTreeView.Name = "TreeView";
  1042.             this.myTreeView.AccessibleName = "TreeView";
  1043.             //this.myTreeView.Scrollable = false;
  1044.             this.myTreeView.Size = new System.Drawing.Size(216, 224);
  1045.             this.myTreeView.TabIndex = 1;
  1046.             // 
  1047.             // imageList1
  1048.             // 
  1049.             this.imageList1.ColorDepth = System.Windows.Forms.ColorDepth.Depth24Bit;
  1050.             this.imageList1.ImageSize = new System.Drawing.Size(16, 16);
  1051.             object imgStream = resources.GetObject("imageList1.ImageStream");
  1052.             this.imageList1.ImageStream = (System.Windows.Forms.ImageListStreamer)imgStream;
  1053.             this.imageList1.TransparentColor = System.Drawing.Color.Transparent;
  1054.             // 
  1055.             // nodeTextView
  1056.             // 
  1057.             this.nodeTextView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
  1058.                 | System.Windows.Forms.AnchorStyles.Left)
  1059.                 | System.Windows.Forms.AnchorStyles.Right)));
  1060.             this.nodeTextView.BackColor = System.Drawing.Color.White;
  1061.             this.nodeTextView.Location = new System.Drawing.Point(301, 0);
  1062.             this.nodeTextView.Name = "nodeTextView";
  1063.             this.nodeTextView.SelectedNode = null;
  1064.             this.nodeTextView.Size = new System.Drawing.Size(179, 224);
  1065.             this.nodeTextView.TabIndex = 4;
  1066.             // 
  1067.             // resizer
  1068.             // 
  1069.             this.resizer.Border3DStyle = System.Windows.Forms.Border3DStyle.Raised;
  1070.             this.resizer.Location = new System.Drawing.Point(200, 0);
  1071.             this.resizer.Name = "XmlTreeResizer";
  1072.             this.resizer.AccessibleName = "XmlTreeResizer";
  1073.             this.resizer.Pane1 = this.myTreeView;
  1074.             this.resizer.Pane2 = this.nodeTextView;
  1075.             this.resizer.PaneWidth = 5;
  1076.             this.resizer.Size = new System.Drawing.Size(5, 408);
  1077.             this.resizer.TabIndex = 3;
  1078.             this.resizer.Vertical = true;
  1079.             //
  1080.             // hScrollBar1
  1081.             //
  1082.             this.hScrollBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
  1083.                 | System.Windows.Forms.AnchorStyles.Right)));
  1084.             this.hScrollBar1.Location = new System.Drawing.Point(0, 207);
  1085.             this.hScrollBar1.Name = "HScrollBar";
  1086.             this.hScrollBar1.AccessibleName = "HScrollBar";
  1087.             this.hScrollBar1.Size = new System.Drawing.Size(179, 17);
  1088.             this.hScrollBar1.TabIndex = 2;
  1089.             this.hScrollBar1.Scroll += new System.Windows.Forms.ScrollEventHandler(this.hScrollBar1_Scroll);
  1090.             
  1091.             // 
  1092.             // vScrollBar1
  1093.             // 
  1094.             this.vScrollBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
  1095.                 | System.Windows.Forms.AnchorStyles.Right)));
  1096.             this.vScrollBar1.Location = new System.Drawing.Point(480, 0);
  1097.             this.vScrollBar1.Name = "VScrollBar";
  1098.             this.vScrollBar1.AccessibleName = "VScrollBar";
  1099.             this.vScrollBar1.Size = new System.Drawing.Size(17, 224);
  1100.             this.vScrollBar1.TabIndex = 0;
  1101.             this.vScrollBar1.Scroll += new System.Windows.Forms.ScrollEventHandler(this.vScrollBar1_Scroll);
  1102.             // 
  1103.             // XmlTreeView
  1104.             // 
  1105.             this.BackColor = System.Drawing.SystemColors.Window;
  1106.             this.Controls.Add(this.vScrollBar1);
  1107.             this.Controls.Add(this.hScrollBar1);
  1108.             this.Controls.Add(this.resizer);
  1109.             this.Controls.Add(this.nodeTextView);
  1110.             this.Controls.Add(this.myTreeView);
  1111.             this.Size = new System.Drawing.Size(496, 224);
  1112.             this.ResumeLayout(false);
  1113.         }
  1114.         #endregion
  1115.     }
  1116.     public enum NodeImage {
  1117.         None,
  1118.         Element,
  1119.         Attribute,
  1120.         Leaf,
  1121.         Text,
  1122.         Comment,
  1123.         PI,
  1124.         OpenElement,
  1125.         CData,
  1126.     }
  1127.     public class XmlTreeNode : TreeNode {
  1128.         Settings settings;
  1129.         NodeImage img;
  1130.         Color foreColor;
  1131.         internal List<XmlTreeNode> children;
  1132.         XmlTreeView view;
  1133.         XmlNode node;
  1134.         XmlSchemaType type;
  1135.         XmlNodeType nodeType;
  1136.         string editLabel;
  1137.         public XmlTreeNode(XmlTreeView view) {
  1138.             this.view = view;
  1139.         }
  1140.         public XmlTreeNode(XmlTreeView view, XmlNode node) {
  1141.             this.view = view;
  1142.             this.node = node;
  1143.             Init();
  1144.         }
  1145.         public XmlTreeNode(XmlTreeView view, XmlTreeNode parent, XmlNode node)
  1146.             : base(parent) {
  1147.             this.view = view;
  1148.             this.node = node;
  1149.             Init();
  1150.         }
  1151.         [Browsable(false)]
  1152.         public XmlNodeType NodeType {
  1153.             get { return (this.node != null) ? this.node.NodeType : this.nodeType; }
  1154.             set { this.nodeType = value; }
  1155.         }
  1156.         [Browsable(false)]
  1157.         public XmlTreeView XmlTreeView {
  1158.             get { return this.view; }
  1159.             set {
  1160.                 this.view = value;
  1161.                 this.TreeView = value == null ? null : value.TreeView;
  1162.                 PropagateView(value, children);
  1163.                 Init();
  1164.             }
  1165.         }
  1166.         public override void Remove() {
  1167.             base.Remove();
  1168.             XmlTreeNode xp = this.Parent as XmlTreeNode;
  1169.             if (xp != null) {
  1170.                 xp.OnChildRemoved();
  1171.             }
  1172.         }
  1173.         void OnChildRemoved() {
  1174.             if (this.img == NodeImage.Element && this.Nodes.Count == 0) {
  1175.                 MakeLeaf();
  1176.             }
  1177.         }
  1178.         void MakeLeaf() {
  1179.             this.Collapse();
  1180.             this.img = NodeImage.Leaf;
  1181.             this.Invalidate();
  1182.         }
  1183.         [Browsable(false)]
  1184.         public XmlSchemaType SchemaType {
  1185.             get { return this.type; }
  1186.             set { this.type = value; }
  1187.         }
  1188.         void PropagateView(XmlTreeView view, List<XmlTreeNode> children) {
  1189.             if (children != null) {
  1190.                 foreach (XmlTreeNode child in children) {
  1191.                     child.XmlTreeView = view;
  1192.                     PropagateView(view, child.children);
  1193.                 }
  1194.             }
  1195.         }
  1196.         void Init() {
  1197.             if (this.view != null) {
  1198.                 this.settings = view.Settings;
  1199.                 this.img = CalculateNodeImage(this.Node);
  1200.                 this.foreColor = this.GetForeColor(this.img);
  1201.             }
  1202.         }
  1203.         public override void Invalidate() {
  1204.             base.Invalidate();
  1205.             Init();
  1206.             this.XmlTreeView.SyncScrollbars();
  1207.         }
  1208.         public Settings Settings { get { return this.settings; } }
  1209.         public XmlNode Node {
  1210.             get { return this.node; }
  1211.             set {
  1212.                 this.node = value;
  1213.                 int count = this.Nodes.Count;
  1214.                 Init();
  1215.                 this.Invalidate();
  1216.                 if (this.TreeView != null) {
  1217.                     this.TreeView.InvalidateLayout(); // LabelBounds needs recalculating.                
  1218.                     this.TreeView.InvalidateNode(this);
  1219.                 }
  1220.             }
  1221.         }
  1222.         public override string Label {
  1223.             get {
  1224.                 return this.Node == null ? editLabel : this.Node.Name;
  1225.             }
  1226.             set {
  1227.                 editLabel = value;
  1228.                 this.Invalidate();
  1229.             }
  1230.         }
  1231.         public override bool IsLabelEditable {
  1232.             get {
  1233.                 return (this.node == null || this.node is XmlProcessingInstruction ||
  1234.                     ((this.node is XmlAttribute || this.node is XmlElement)));
  1235.             }
  1236.         }
  1237.         public override string Text {
  1238.             get {
  1239.                 XmlNode n = this.Node;
  1240.                 string text = null;
  1241.                 if (n is XmlElement) {
  1242.                     NodeImage i = this.NodeImage;
  1243.                     if (NodeImage.Element != i && NodeImage.OpenElement != i) {
  1244.                         text = n.InnerText;
  1245.                     }
  1246.                 } else if (n is XmlProcessingInstruction) {
  1247.                     text = ((XmlProcessingInstruction)n).Data;
  1248.                 } else if (n != null) {
  1249.                     text = n.Value;
  1250.                 }
  1251.                 return text;
  1252.             }
  1253.             set {
  1254.                 EditNodeValue ev = new EditNodeValue(this.XmlTreeView, this, value);
  1255.                 UndoManager undo = this.XmlTreeView.UndoManager;
  1256.                 undo.Push(ev);
  1257.             }
  1258.         }
  1259.         public override Color ForeColor {
  1260.             get {
  1261.                 return this.foreColor;
  1262.             }
  1263.         }
  1264.         public override TreeNodeCollection Nodes {
  1265.             get {
  1266.                 return new XmlTreeNodeCollection(this);
  1267.             }
  1268.         }
  1269.         public NodeImage NodeImage {
  1270.             get {
  1271.                 if (this.IsExpanded) {
  1272.                     return NodeImage.OpenElement;
  1273.                 }
  1274.                 return this.img;
  1275.             }
  1276.         }
  1277.         public override int ImageIndex {
  1278.             get {
  1279.                 return (int)this.NodeImage - 1;
  1280.             }
  1281.         }
  1282.         public Color GetForeColor(NodeImage img) {
  1283.             System.Collections.Hashtable colors = (System.Collections.Hashtable)this.settings["Colors"];
  1284.             switch (img) {
  1285.                 case NodeImage.Element:
  1286.                 case NodeImage.OpenElement:
  1287.                 case NodeImage.Leaf:
  1288.                     return (Color)colors["Element"];
  1289.                 case NodeImage.Attribute:
  1290.                     return (Color)colors["Attribute"];
  1291.                 case NodeImage.PI:
  1292.                     return (Color)colors["PI"];
  1293.                 case NodeImage.CData:
  1294.                     return (Color)colors["CDATA"];
  1295.                 case NodeImage.Comment:
  1296.                     return (Color)colors["Comment"];
  1297.                 default:
  1298.                     return (Color)colors["Text"];
  1299.             }
  1300.         }
  1301.         NodeImage CalculateNodeImage(XmlNode n) {
  1302.             XmlNodeType nt = (n == null) ? this.nodeType : n.NodeType;
  1303.             switch (nt) {
  1304.                 case XmlNodeType.Attribute:
  1305.                     return NodeImage.Attribute;
  1306.                 case XmlNodeType.Comment:
  1307.                     return NodeImage.Comment;
  1308.                 case XmlNodeType.ProcessingInstruction:
  1309.                 case XmlNodeType.XmlDeclaration:
  1310.                     return NodeImage.PI;
  1311.                 case XmlNodeType.Text:
  1312.                 case XmlNodeType.Whitespace:
  1313.                 case XmlNodeType.SignificantWhitespace:
  1314.                     return NodeImage.Text;
  1315.                 case XmlNodeType.CDATA:
  1316.                     return NodeImage.CData;
  1317.                 case XmlNodeType.Element:
  1318.                     XmlElement e = (XmlElement)n;
  1319.                     if (e != null && IsContainer(e)) {
  1320.                         return NodeImage.Element;
  1321.                     }
  1322.                     return NodeImage.Leaf;
  1323.                 default:
  1324.                     return NodeImage.PI;
  1325.             }
  1326.         }
  1327.         static bool IsContainer(XmlElement e) {
  1328.             if (e.HasChildNodes) {
  1329.                 int count = 0;
  1330.                 foreach (XmlNode c in e.ChildNodes) {
  1331.                     if (c is XmlComment || c is XmlProcessingInstruction || c is XmlElement)
  1332.                         return true;
  1333.                     if (c is XmlText || c is XmlCDataSection) {
  1334.                         count++;
  1335.                         if (count > 1) return true;
  1336.                     }
  1337.                 }
  1338.             }
  1339.             return HasSpecifiedAttributes(e);
  1340.         }
  1341.         static bool HasSpecifiedAttributes(XmlElement e) {
  1342.             if (e.HasAttributes) {
  1343.                 foreach (XmlAttribute a in e.Attributes) {
  1344.                     if (a.Specified) return true;
  1345.                 }
  1346.             }
  1347.             return false;
  1348.         }
  1349.         public void RecalculateNamespaces(XmlNamespaceManager nsmgr, CompoundCommand cmd) {
  1350.             Debug.Assert(this.NodeType == XmlNodeType.Element || this.NodeType == XmlNodeType.Attribute);
  1351.             XmlNode e = this.Node;
  1352.             if (e == null) return; // user is still editing this tree node!
  1353.             bool hasXmlNs = false;
  1354.             if (e.Attributes != null) {
  1355.                 XmlAttributeCollection acol = e.Attributes;
  1356.                 for (int i = 0, n = acol.Count; i < n; i++) {
  1357.                     XmlAttribute a = acol[i];
  1358.                     string value = a.Value;
  1359.                     if (a.NamespaceURI == XmlHelpers.XmlnsUri) {
  1360.                         if (!hasXmlNs) {
  1361.                             nsmgr.PushScope();
  1362.                             hasXmlNs = true;
  1363.                         }
  1364.                         XmlNameTable nt = nsmgr.NameTable;
  1365.                         string prefix = nt.Add(a.LocalName);
  1366.                         if (prefix == "xmlns") prefix = "";
  1367.                         if (!nsmgr.HasNamespace(prefix)) {
  1368.                             try {
  1369.                                 nsmgr.AddNamespace(prefix, nt.Add(value));
  1370.                             } catch (Exception ex) {
  1371.                                 // illegal namespace declaration, perhaps user has not finished editing it yet.
  1372.                                 Trace.WriteLine(ex.Message);
  1373.                             }
  1374.                         }
  1375.                     }
  1376.                 }
  1377.             }
  1378.             XmlName name = XmlHelpers.ParseName(nsmgr, e.Name, this.NodeType);
  1379.             if (name.NamespaceUri != e.NamespaceURI &&
  1380.                 (string.IsNullOrEmpty(name.Prefix) || !string.IsNullOrEmpty(name.NamespaceUri))) {
  1381.                 // Node has bound to a different namespace!
  1382.                 // Note that XmlNode doesn't let you change the NamespaceURI property
  1383.                 // so we have to recreate the XmlNode objects, and so we have to create
  1384.                 // a command for this since it is editing the tree!
  1385.                 EditNodeName rename = new EditNodeName(this, name, false);
  1386.                 cmd.Add(rename);
  1387.             }
  1388.             foreach (XmlTreeNode child in this.Nodes) {
  1389.                 switch (child.NodeType) {
  1390.                     case XmlNodeType.Attribute:
  1391.                     case XmlNodeType.Element:
  1392.                         child.RecalculateNamespaces(nsmgr, cmd);
  1393.                         break;
  1394.                     default:
  1395.                         // no change required on text nodes.
  1396.                         break;
  1397.                 }
  1398.             }
  1399.             if (hasXmlNs) {
  1400.                 nsmgr.PopScope();
  1401.             }
  1402.         }
  1403.         public override bool CanExpandAll {
  1404.             get {
  1405.                 return (this.NodeImage != NodeImage.Leaf); // don't expand the leaves
  1406.             }
  1407.         }
  1408.         public virtual string GetDefinition() {
  1409.             string ipath = this.GetIncludePath();
  1410.             if (string.IsNullOrEmpty(ipath)) {
  1411.                 ipath = this.GetSchemaLocation();
  1412.             }
  1413.             if (string.IsNullOrEmpty(ipath)) {
  1414.                 ipath = this.GetTypeInfo();
  1415.             }
  1416.             // todo: other forms of goto...
  1417.             return ipath;
  1418.         }
  1419.         public virtual string GetIncludePath() {
  1420.             if (this.NodeType == XmlNodeType.Attribute){
  1421.                 XmlTreeNode e = this.Parent as XmlTreeNode;
  1422.                 return e.GetIncludePath();
  1423.             }
  1424.             XmlNode n = this.Node;
  1425.             if (n != null && n.NamespaceURI == XmlIncludeReader.XIncludeNamespaceUri) {
  1426.                 string href = n.Attributes["href"].Value;
  1427.                 Uri resolved = ResolveUri(href);
  1428.                 return resolved.LocalPath;
  1429.             }
  1430.             return null;
  1431.         }
  1432.         public virtual string GetSchemaLocation() {
  1433.             XmlNode n = this.Node;
  1434.             if (this.NodeType == XmlNodeType.Attribute) {
  1435.                 if (n.NamespaceURI == "http://www.w3.org/2001/XMLSchema-instance") {
  1436.                     if (n.LocalName == "noNamespaceSchemaLocation") {
  1437.                         string href = n.Value;
  1438.                         Uri resolved = ResolveUri(href);
  1439.                         return resolved.LocalPath;
  1440.                     }
  1441.                 }
  1442.             }
  1443.             return null;
  1444.         }
  1445.         public virtual XmlSchemaAnnotated GetSchemaObject() {
  1446.             XmlSchemaInfo si = this.XmlTreeView.Model.GetTypeInfo(this.Node);
  1447.             if (si != null) {
  1448.                 XmlSchemaElement e = si.SchemaElement;
  1449.                 if (e != null) return e;
  1450.                 XmlSchemaAttribute a = si.SchemaAttribute;
  1451.                 if (a != null) return a;
  1452.                 XmlSchemaSimpleType st = si.MemberType;
  1453.                 if (st != null) return st;
  1454.                 return si.SchemaType;
  1455.             }
  1456.             return null;
  1457.         }
  1458.         public virtual string GetTypeInfo() {
  1459.             XmlSchemaObject o = GetSchemaObject();
  1460.             if (o != null) return GetSourceUri(o);
  1461.             return null;
  1462.         }
  1463.         public virtual string GetToolTip() {
  1464.             if (this.node == null) return null;
  1465.             XmlSchemaInfo si = this.XmlTreeView.Model.GetTypeInfo(this.Node);
  1466.             if (si != null) {
  1467.                 foreach (XmlSchemaAnnotated a in new XmlSchemaAnnotated[] {
  1468.                                                      si.SchemaElement, si.SchemaAttribute, 
  1469.                                                      si.MemberType, si.SchemaType}) {
  1470.                     if (a != null) {
  1471.                         string s = SchemaCache.GetAnnotation(a, SchemaCache.AnnotationNode.Tooltip);
  1472.                         if (!string.IsNullOrEmpty(s)) return s;
  1473.                     }
  1474.                 }
  1475.             }
  1476.             return null;
  1477.         }
  1478.         public virtual XmlDocument GetDocumentation() {
  1479.             if (this.node == null) return null;
  1480.             XmlDocument xmlDoc = new XmlDocument();
  1481.             XmlElement root = xmlDoc.CreateElement("documentation");
  1482.             xmlDoc.AppendChild(root);
  1483.             XmlSchemaInfo si = this.XmlTreeView.Model.GetTypeInfo(this.Node);
  1484.             if (si != null) {
  1485.                 foreach (XmlSchemaAnnotated a in new XmlSchemaAnnotated[] {
  1486.                                                      si.SchemaElement, si.SchemaAttribute, 
  1487.                                                      si.MemberType, si.SchemaType}) {
  1488.                     if (a != null) {
  1489.                         XmlSchemaDocumentation d = SchemaCache.GetDocumentation(a);
  1490.                         if (null != d && d.Markup != null && d.Markup.Length > 0) {
  1491.                             foreach (XmlNode n in d.Markup) {
  1492.                                 XmlNode node = xmlDoc.ImportNode(n, true);
  1493.                                 root.AppendChild(node);
  1494.                             }
  1495.                             return xmlDoc;
  1496.                         }
  1497.                     }
  1498.                 }
  1499.             }
  1500.             return null;
  1501.         }
  1502.         string GetSourceUri(XmlSchemaObject o) {
  1503.             while (o != null) {
  1504.                 string s = o.SourceUri;
  1505.                 if (!string.IsNullOrEmpty(s)) return s;
  1506.                 o = o.Parent;
  1507.             }
  1508.             return null;
  1509.         }
  1510.         public Uri ResolveUri(string href) {
  1511.             XmlNode n = this.Node;
  1512.             Uri baseUri = new Uri(this.XmlTreeView.Model.FileName);
  1513.             if (n != null) {
  1514.                 string uri = n.BaseURI;
  1515.                 if (!string.IsNullOrEmpty(uri))
  1516.                     baseUri = new Uri(uri);
  1517.             }
  1518.             Uri resolved = new Uri(baseUri, href);
  1519.             return resolved;
  1520.         }
  1521.     }
  1522.     public class XmlTreeNodeCollection : TreeNodeCollection, IEnumerable<XmlTreeNode> {
  1523.         XmlTreeNode parent;
  1524.         XmlNode node;
  1525.         XmlTreeView treeView;
  1526.         List<XmlTreeNode> children;
  1527.         public XmlTreeNodeCollection(XmlTreeView treeView, XmlNode parent) {
  1528.             this.node = parent;
  1529.             this.treeView = treeView;
  1530.         }
  1531.         public XmlTreeNodeCollection(XmlTreeNode parent) {
  1532.             this.treeView = parent.XmlTreeView;
  1533.             this.parent = parent;
  1534.             if (parent != null) this.children = parent.children;
  1535.             this.node = parent.Node;
  1536.         }
  1537.         
  1538.         IEnumerator<XmlTreeNode> IEnumerable<XmlTreeNode>.GetEnumerator() {
  1539.             Populate();
  1540.             return this.children.GetEnumerator();
  1541.         }
  1542.         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
  1543.             IEnumerable<XmlTreeNode> ie = (IEnumerable<XmlTreeNode>)this;
  1544.             return ie.GetEnumerator();
  1545.         }
  1546.         public override IEnumerator<TreeNode> GetEnumerator() {
  1547.             System.Collections.IEnumerable e = (System.Collections.IEnumerable)this;
  1548.             foreach (XmlTreeNode xn in e) {
  1549.                 yield return xn;
  1550.             }           
  1551.         }
  1552.         public override int Count {
  1553.             get {
  1554.                 Populate();
  1555.                 return this.children == null ? 0 : this.children.Count;
  1556.             }
  1557.         }
  1558.         public override int GetIndex(TreeNode node) {
  1559.             Populate();
  1560.             XmlTreeNode xn = ((XmlTreeNode)node);
  1561.             return this.children.IndexOf(xn);
  1562.         }
  1563.         public override void Add(TreeNode node) {
  1564.             node.Parent = this.parent;
  1565.             XmlTreeNode xn = ((XmlTreeNode)node);
  1566.             xn.XmlTreeView = this.treeView;
  1567.             Populate();
  1568.             this.children.Add(xn);
  1569.         }
  1570.         public override void Insert(int i, TreeNode node) {
  1571.             node.Parent = this.parent;
  1572.             XmlTreeNode xn = ((XmlTreeNode)node);
  1573.             xn.XmlTreeView = this.treeView;
  1574.             Populate();            
  1575.             if (i > this.children.Count) i = this.children.Count;
  1576.             this.children.Insert(i, xn);            
  1577.         }
  1578.         public override void Remove(TreeNode child) {
  1579.             if (this.children != null) {
  1580.                 XmlTreeNode xn = ((XmlTreeNode)child);            
  1581.                 if (this.children.Contains(xn)) {
  1582.                     this.children.Remove(xn);
  1583.                     return;
  1584.                 }
  1585.             }
  1586.             throw new InvalidOperationException(SR.NotAChild);
  1587.         }
  1588.         public override TreeNode this[int i] {
  1589.             get {
  1590.                 Populate();
  1591.                 return this.children[i] as TreeNode;
  1592.             }
  1593.         }
  1594.         void Populate() {
  1595.             if (this.children == null ) {
  1596.                 List<XmlTreeNode> children = new List<XmlTreeNode>();
  1597.                 if (node != null && !(node is XmlAttribute)) {
  1598.                     if (node.Attributes != null) {
  1599.                         foreach (XmlAttribute a in node.Attributes) {
  1600.                             if (a.Specified) {
  1601.                                 XmlTreeNode c = treeView.CreateTreeNode(parent, a);
  1602.                                 c.XmlTreeView = this.treeView;
  1603.                                 children.Add(c);
  1604.                             }
  1605.                         }
  1606.                     }
  1607.                     if (node.HasChildNodes) {
  1608.                         foreach (XmlNode n in node.ChildNodes) {
  1609.                             XmlTreeNode c = treeView.CreateTreeNode(parent, n);
  1610.                             c.XmlTreeView = this.treeView;
  1611.                             children.Add(c);
  1612.                         }
  1613.                     }
  1614.                 }
  1615.                 this.children = children;
  1616.                 if (parent != null) parent.children = children;
  1617.                 if (this.treeView != null) this.treeView.PerformLayout();
  1618.             }
  1619.         }
  1620.     }
  1621.     public sealed class StringHelper {
  1622.         StringHelper() { }
  1623.         public static bool IsNullOrEmpty(string s) {
  1624.             return (s == null || s.Length == 0);
  1625.         }
  1626.     }
  1627.     public class NodeChangeEventArgs : EventArgs {
  1628.         XmlTreeNode node;
  1629.         public XmlTreeNode Node {
  1630.             get { return node; }
  1631.             set { node = value; }
  1632.         }
  1633.         public NodeChangeEventArgs(XmlTreeNode node) {
  1634.             this.node = node;
  1635.         }
  1636.     }
  1637.     public class XmlTreeViewDropFeedback : TreeViewDropFeedback {
  1638.         int autoScrollCount;
  1639.         public override Point Position {
  1640.             get { return base.Position; }
  1641.             set {
  1642.                 base.Position = value;
  1643.                 CheckAutoScroll(value);
  1644.             }
  1645.         }
  1646.         void CheckAutoScroll(Point pt) {
  1647.             TreeView tv = this.TreeView;
  1648.             Point local = tv.PointToClient(pt);
  1649.             Point pos = tv.ApplyScrollOffset(local);
  1650.             XmlTreeView parent = (XmlTreeView)tv.Parent;
  1651.             int height = tv.ItemHeight;
  1652.             int halfheight = height / 2;
  1653.             TreeNode node = null;
  1654.             bool nearEnd = false;
  1655.             if (local.Y - height < tv.Top) {
  1656.                 node = tv.FindNodeAt(pos.X, pos.Y - height);
  1657.                 nearEnd = (local.Y - halfheight < tv.Top);
  1658.             } else if (local.Y + height > tv.Bottom) {
  1659.                 node = tv.FindNodeAt(pos.X, pos.Y + height);
  1660.                 nearEnd = (local.Y + halfheight > tv.Bottom);
  1661.             }
  1662.             if (node != null) {
  1663.                 if (nearEnd || autoScrollCount > 1) {
  1664.                     parent.ScrollIntoView(node);
  1665.                     autoScrollCount = 0;
  1666.                 } else {
  1667.                     autoScrollCount++;
  1668.                 }
  1669.                 ResetToggleCount();
  1670.             }
  1671.         }
  1672.     }
  1673. }