using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text; // -- used by drag & drop stuff.
using System.Windows.Forms;
using System.Xml;
using Clifton.Tools.Xml;
using Clifton.Windows.Forms.XmlTree;
namespace Clifton.Windows.Forms
{
public class GTreeEventArgs : EventArgs
{
protected bool handled;
public bool Handled
{
get { return handled; }
set { handled = value; }
}
public GTreeEventArgs()
{
}
}
public class XTree : TreeView, ISupportInitialize
{
public event EventHandler DisplayContextMenu;
protected RootNode rootNode;
protected Point mousePos;
protected TreeNode selNode;
protected string treeDefFileName;
protected IXtreeNode selectedNodeInstance;
protected Dictionary<string, NodeDef> nodeList;
protected Dictionary<Type, NodeDef> controllerToNodeDefMap;
protected Dictionary<string, NodeDef> nameToNodeDefMap;
public Point MousePos
{
get { return mousePos; }
set { mousePos = value; }
}
public string TreeDefinitionFileName
{
get { return treeDefFileName; }
set { treeDefFileName = value; }
}
public XTree()
{
}
public virtual void BeginInit()
{
}
public virtual void EndInit()
{
if (treeDefFileName != null)
{
XmlDocument xdoc = new XmlDocument();
xdoc.Load(treeDefFileName);
Initialize(xdoc);
}
AllowDrop = true;
DragOver += new DragEventHandler(OnXTreeDragOver);
DragEnter += new DragEventHandler(OnXTreeDragEnter);
ItemDrag += new ItemDragEventHandler(OnXTreeItemDrag);
DragDrop += new DragEventHandler(OnXTreeDragDrop);
}
public virtual void Clear()
{
Nodes.Clear();
}
public void Initialize(XmlDocument xdoc)
{
nodeList = new Dictionary<string, NodeDef>();
controllerToNodeDefMap = new Dictionary<Type, NodeDef>();
nameToNodeDefMap = new Dictionary<string, NodeDef>();
// LabelEdit = true;
ImageList = new ImageList();
MycroParser mp = new MycroParser();
mp.Load(xdoc, null, null);
mp.NamespaceMap[""] = "Clifton.Windows.Forms.XmlTree, Clifton.Windows.Forms";
rootNode=(RootNode)mp.Process();
nodeList[rootNode.Name] = rootNode;
BuildFlatNodeList(rootNode);
// TreeNode tn=CreateNodeAndRequiredChildren(rootNode);
// Nodes.Add(tn);
}
public TreeNode AddNode(IXtreeNode inst, TreeNode parent)
{
NodeDef nodeDef = null;
if (!controllerToNodeDefMap.ContainsKey(inst.GetType()))
{
throw new ApplicationException("The controller instance "+inst.GetType().Name+" is expected but not defined in a TypeName attribute of the tree schema.");
}
nodeDef = controllerToNodeDefMap[inst.GetType()];
TreeNode tn = CreateNodeAndRequiredChildren(nodeDef, inst);
if (parent != null)
{
parent.Nodes.Add(tn);
}
else
{
Nodes.Add(tn);
}
return tn;
}
public TreeNode CreateNode(NodeDef node, IXtreeNode inst)
{
TreeNode tn = new TreeNode();
tn.Text = node.Text;
// If no controller is specified, use the text in the NodeDef.
if (!(inst is PlaceholderInstance))
{
tn.Text = inst.Name;
}
tn.Tag = new NodeInstance(tn, node, inst);
if (node.ImageList != null)
{
// Have images been loaded into the TreeView's image list?
if (node.ImageOffset == -1)
{
// No. Load them and save the offset.
node.ImageOffset = ImageList.Images.Count;
foreach (Image img in node.ImageList.Images)
{
ImageList.Images.Add(img);
}
}
// Yes, just update the indices.
tn.ImageIndex = node.ImageOffset + inst.IconIndex;
tn.SelectedImageIndex = node.ImageOffset + inst.SelectedIconIndex;
}
return tn;
}
public TreeNode CreateNodeAndRequiredChildren(NodeDef node, IXtreeNode parentInst)
{
TreeNode tn = CreateNode(node, parentInst);
foreach (NodeDef child in node.Nodes)
{
if (child.IsRequired)
{
IXtreeNode inst = child.CreateImplementingType(parentInst);
TreeNode tnChild = CreateNodeAndRequiredChildren(child, inst);
tn.Nodes.Add(tnChild);
tn.Expand();
}
}
return tn;
}
public ContextMenu BuildContextMenu(TreeNode tn, NodeDef n)
{
ContextMenu cm = new ContextMenu();
bool first = true;
// Populate from this node's popup collection.
if (n.PopupItems.Count != 0)
{
foreach (Popup popup in n.PopupItems)
{
NodeMenuItem nmi = new NodeMenuItem(popup.Text, tn, n, null, popup);
nmi.Click += new EventHandler(OnContextItem);
nmi.Enabled = ((NodeInstance)tn.Tag).Instance.IsEnabled(popup.Tag, popup.Enabled);
cm.MenuItems.Add(nmi);
}
first = false;
}
// For each child node, populate from the child's ParentPopupItems collection.
foreach (NodeDef child in n.Nodes)
{
NodeDef refNode = child;
// Resolve any referenced node.
if (child.IsRef)
{
if (!nodeList.ContainsKey(child.RefName))
{
throw new ApplicationException("referenced node does not exist.");
}
refNode = nodeList[child.RefName];
}
if (refNode.ParentPopupItems.Count != 0)
{
if (!first)
{
cm.MenuItems.Add("-");
}
first = false;
// Populate the items.
foreach (Popup popup in refNode.ParentPopupItems)
{
NodeMenuItem nmi = new NodeMenuItem(popup.Text, tn, n, refNode, popup);
nmi.Click += new EventHandler(OnContextItem);
nmi.Enabled = ((NodeInstance)tn.Tag).Instance.IsEnabled(popup.Tag, popup.Enabled);
cm.MenuItems.Add(nmi);
}
}
}
return cm;
}
public void Serialize(string fn)
{
XmlDocument xdoc = new XmlDocument();
XmlDeclaration xmlDeclaration = xdoc.CreateXmlDeclaration("1.0", "utf-8", null);
xdoc.InsertBefore(xmlDeclaration, xdoc.DocumentElement);
XmlNode xnode = xdoc.CreateElement("XTree");
xdoc.AppendChild(xnode);
foreach (TreeNode tn in Nodes)
{
WriteNode(xdoc, xnode, tn);
}
xdoc.Save("tree.xml");
}
public void Deserialize(string fn)
{
Nodes.Clear();
XmlDocument xdoc = new XmlDocument();
xdoc.Load("tree.xml");
XmlNode node = xdoc.DocumentElement;
ReadNode(xdoc, node, Nodes, null);
}
protected void ReadNode(XmlDocument xdoc, XmlNode node, TreeNodeCollection nodes, IXtreeNode parent)
{
foreach (XmlNode xn in node.ChildNodes)
{
IXtreeNode inst = nodeList[xn.Name].CreateImplementingType(parent);
TreeNode tn = CreateNode(nodeList[xn.Name], inst);
nodes.Add(tn);
ReadNode(xdoc, xn, tn.Nodes, inst);
if (Convert.ToBoolean(xn.Attributes["IsExpanded"].Value))
{
tn.Expand();
}
}
}
protected void WriteNode(XmlDocument xdoc, XmlNode xnode, TreeNode tn)
{
XmlNode xn = xdoc.CreateElement(((NodeInstance)tn.Tag).NodeDef.Name);
xn.Attributes.Append(xdoc.CreateAttribute("Text"));
xn.Attributes.Append(xdoc.CreateAttribute("IsExpanded"));
xn.Attributes["Text"].Value = tn.Text;
xn.Attributes["IsExpanded"].Value = tn.IsExpanded.ToString();
xnode.AppendChild(xn);
foreach (TreeNode child in tn.Nodes)
{
WriteNode(xdoc, xn, child);
}
}
protected void BuildFlatNodeList(NodeDef node)
{
foreach (NodeDef child in node.Nodes)
{
if (child.Name == null)
{
throw new ApplicationException("NodeDef Name cannot be null.");
}
nodeList[child.Name] = child;
controllerToNodeDefMap[child.ImplementingType] = child;
nameToNodeDefMap[child.Name] = child;
if (!child.Recurse)
{
BuildFlatNodeList(child);
}
}
}
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (e.KeyCode == Keys.F2)
{
if (!((NodeInstance)SelectedNode.Tag).NodeDef.IsReadOnly)
{
if (!SelectedNode.IsEditing)
{
LabelEdit = true;
SelectedNode.BeginEdit();
}
}
}
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
selNode = GetNodeAt(e.Location);
if (selNode != null)
{
if (e.Button == MouseButtons.Left)
{
// clicked twice on the same node?
if (selNode == SelectedNode)
{
if (!((NodeInstance)selNode.Tag).NodeDef.IsReadOnly)
{
SelectedNode = selNode;
if (!selNode.IsEditing)
{
LabelEdit = true;
selNode.BeginEdit();
}
}
}
else
{
((NodeInstance)selNode.Tag).Instance.Select(selNode);
}
}
else
{
SelectedNode = selNode;
((NodeInstance)selNode.Tag).Instance.Select(selNode);
}
selectedNodeInstance = ((NodeInstance)SelectedNode.Tag).Instance;
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
if (e.Button == MouseButtons.Right)
{
mousePos = new Point(e.X, e.Y);
OnDisplayContextMenu();
}
}
protected override void OnAfterLabelEdit(NodeLabelEditEventArgs e)
{
if (e.Label != null)
{
base.OnAfterLabelEdit(e);
LabelEdit = false;
}
}
protected virtual void OnDisplayContextMenu()
{
GTreeEventArgs ea = new GTreeEventArgs();
if (DisplayContextMenu != null)
{
DisplayContextMenu(this, ea);
}
if (!ea.Handled)
{
TreeNode tn = GetNodeAt(mousePos);
NodeDef nodeDef;
if (tn == null)
{
nodeDef = rootNode;
}
else
{
nodeDef = ((NodeInstance)tn.Tag).NodeDef;
}
ContextMenu cm=BuildContextMenu(tn, nodeDef);
cm.Show(this, mousePos);
}
}
private void OnContextItem(object sender, EventArgs e)
{
NodeMenuItem nmi = (NodeMenuItem)sender;
if (nmi.PopupInfo.IsAdd)
{
IXtreeNode parentInst = null;
if (nmi.TreeNode != null)
{
parentInst = ((NodeInstance)nmi.TreeNode.Tag).Instance;
}
IXtreeNode inst = nmi.ChildNode.CreateImplementingType(parentInst);
bool success=inst.AddNode(parentInst, nmi.PopupInfo.Tag);
if (success)
{
TreeNode tn = CreateNodeAndRequiredChildren(nmi.ChildNode, inst);
// This wouldn't be necessary if there was something like an ITreeNode interface
// which both TreeView and TreeNode implemented to give you access to the Nodes collection!
if (nmi.TreeNode == null)
{
Nodes.Add(tn);
}
else
{
nmi.TreeNode.Nodes.Add(tn);
tn.Parent.Expand();
}
tn.TreeView.SelectedNode = tn;
inst.Select(tn);
}
}
else if (nmi.PopupInfo.IsRemove)
{
NodeInstance ni = (NodeInstance)nmi.TreeNode.Tag;
IXtreeNode inst = ni.Instance;
IXtreeNode parentInst = null;
TreeNode parentNode = nmi.TreeNode.Parent;
if (parentNode != null)
{
parentInst = ((NodeInstance)parentNode.Tag).Instance;
}
bool success = inst.DeleteNode(parentInst);
if (success)
{
nmi.TreeNode.Remove();
}
}
}
// ------------ Drag & Drop Events --------------
// Modified from Gabe Anguiano's work here: http://www.codeproject.com/cs/miscctrl/TreeViewReArr.asp
private string NodeMap;
private const int MAPSIZE = 128;
private StringBuilder NewNodeMap = new StringBuilder(MAPSIZE);
private void OnXTreeItemDrag(object sender, System.Windows.Forms.ItemDragEventArgs e)
{
DoDragDrop(e.Item, DragDropEffects.Move);
}
private void OnXTreeDragEnter(object sender, System.Windows.Forms.DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
private void OnXTreeDragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false) && this.NodeMap != "")
{
TreeNode MovingNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");
string[] NodeIndexes = this.NodeMap.Split('|');
TreeNodeCollection InsertCollection = Nodes;
TreeNode newParent=null;
for (int i = 0; i < NodeIndexes.Length - 1; i++)
{
newParent=InsertCollection[Int32.Parse(NodeIndexes[i])];
InsertCollection = newParent.Nodes;
}
if (InsertCollection != null)
{
try
{
int idx = Int32.Parse(NodeIndexes[NodeIndexes.Length - 1]);
// Get the node controller for the moving node.
NodeInstance ni = (NodeInstance)MovingNode.Tag;
IXtreeNode inst = ni.Instance;
// Get the node controller for the new parent.
NodeInstance parent = (NodeInstance)newParent.Tag;
IXtreeNode parentInst = parent.Instance;
IXtreeNode movingNodeParentInst = ((NodeInstance)MovingNode.Parent.Tag).Instance;
// Can only move to another parent of the same type.
if (parentInst.GetType() == movingNodeParentInst.GetType())
{
inst.MoveTo(parentInst, movingNodeParentInst, idx);
InsertCollection.Insert(idx, (TreeNode)MovingNode.Clone());
SelectedNode = InsertCollection[idx];
MovingNode.Remove();
}
else
{
// Remove markers.
Refresh();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
private void OnXTreeDragOver(object sender, System.Windows.Forms.DragEventArgs e)
{
TreeNode NodeOver = GetNodeAt(PointToClient(Cursor.Position));
TreeNode NodeMoving = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");
// A bit long, but to summarize, process the following code only if the nodeover is null
// and either the nodeover is not the same thing as nodemoving UNLESSS nodeover happens
// to be the last node in the branch (so we can allow drag & drop below a parent branch)
if (NodeOver != null && (NodeOver != NodeMoving || (NodeOver.Parent != null && NodeOver.Index == (NodeOver.Parent.Nodes.Count - 1))))
{
int OffsetY = PointToClient(Cursor.Position).Y - NodeOver.Bounds.Top;
// int NodeOverImageWidth = ImageList.Images[NodeOver.ImageIndex].Size.Width + 8;
Graphics g = CreateGraphics();
// Image index of 1 is the non-folder icon
// if (NodeOver.ImageIndex == 1)
// MTC
// If there are subnodes already, or we're at the last node, then draw the "before/after" markers.
// What this prevents happening is the ability to add subnodes to a last node that has no children.
// So we need to add an AND expression, that if we're at the last node AND the mouse Y is at the top third or bottom third of the node,
// THEN we want to treat this as a "before/after" selection. Otherwise, treat it as adding a child node.
if ( (NodeOver.Nodes.Count > 0) ||
( (NodeOver.Index == (NodeOver.Parent.Nodes.Count - 1)) &&
( (OffsetY < NodeOver.Bounds.Height / 3) || (OffsetY > 2*NodeOver.Bounds.Height/3) ) )
)
{
#region Standard Node
if (OffsetY < (NodeOver.Bounds.Height / 2))
{
//this.lblDebug.Text = "top";
#region If NodeOver is a child then cancel
TreeNode tnParadox = NodeOver;
while (tnParadox.Parent != null)
{
if (tnParadox.Parent == NodeMoving)
{
this.NodeMap = "";
return;
}
tnParadox = tnParadox.Parent;
}
#endregion
#region Store the placeholder info into a pipe delimited string
SetNewNodeMap(NodeOver, false);
if (SetMapsEqual() == true)
return;
#endregion
#region Clear placeholders above and below
this.Refresh();
#endregion
#region Draw the placeholders
this.DrawLeafTopPlaceholders(NodeOver);
#endregion
}
else
{
//this.lblDebug.Text = "bottom";
#region If NodeOver is a child then cancel
TreeNode tnParadox = NodeOver;
while (tnParadox.Parent != null)
{
if (tnParadox.Parent == NodeMoving)
{
this.NodeMap = "";
return;
}
tnParadox = tnParadox.Parent;
}
#endregion
#region Allow drag drop to parent branches
TreeNode ParentDragDrop = null;
// If the node the mouse is over is the last node of the branch we should allow
// the ability to drop the "nodemoving" node BELOW the parent node
if (NodeOver.Parent != null && NodeOver.Index == (NodeOver.Parent.Nodes.Count - 1))
{
int XPos = PointToClient(Cursor.Position).X;
if (XPos < NodeOver.Bounds.Left)
{
ParentDragDrop = NodeOver.Parent;
// MTC - commented out--maybe there isn't an image list!!!
//if (XPos < (ParentDragDrop.Bounds.Left - ImageList.Images[ParentDragDrop.ImageIndex].Size.Width))
//{
// if (ParentDragDrop.Parent != null)
// ParentDragDrop = ParentDragDrop.Parent;
//}
}
}
#endregion
#region Store the placeholder info into a pipe delimited string
// Since we are in a special case here, use the ParentDragDrop node as the current "nodeover"
SetNewNodeMap(ParentDragDrop != null ? ParentDragDrop : NodeOver, true);
if (SetMapsEqual() == true)
return;
#endregion
#region Clear placeholders above and below
this.Refresh();
#endregion
#region Draw the placeholders
DrawLeafBottomPlaceholders(NodeOver, ParentDragDrop);
#endregion
}
#endregion
}
else
{
#region Folder Node
if (OffsetY < (NodeOver.Bounds.Height / 3))
{
//this.lblDebug.Text = "folder top";
#region If NodeOver is a child then cancel
TreeNode tnParadox = NodeOver;
while (tnParadox.Parent != null)
{
if (tnParadox.Parent == NodeMoving)
{
this.NodeMap = "";
return;
}
tnParadox = tnParadox.Parent;
}
#endregion
#region Store the placeholder info into a pipe delimited string
SetNewNodeMap(NodeOver, false);
if (SetMapsEqual() == true)
return;
#endregion
#region Clear placeholders above and below
this.Refresh();
#endregion
#region Draw the placeholders
this.DrawFolderTopPlaceholders(NodeOver);
#endregion
}
else if ((NodeOver.Parent != null && NodeOver.Index == 0) && (OffsetY > (NodeOver.Bounds.Height - (NodeOver.Bounds.Height / 3))))
{
//this.lblDebug.Text = "folder bottom";
#region If NodeOver is a child then cancel
TreeNode tnParadox = NodeOver;
while (tnParadox.Parent != null)
{
if (tnParadox.Parent == NodeMoving)
{
this.NodeMap = "";
return;
}
tnParadox = tnParadox.Parent;
}
#endregion
#region Store the placeholder info into a pipe delimited string
SetNewNodeMap(NodeOver, true);
if (SetMapsEqual() == true)
return;
#endregion
#region Clear placeholders above and below
this.Refresh();
#endregion
#region Draw the placeholders
DrawFolderTopPlaceholders(NodeOver);
#endregion
}
else
{
//this.lblDebug.Text = "folder over";
if (NodeOver.Nodes.Count > 0)
{
NodeOver.Expand();
//this.Refresh();
}
else
{
#region Prevent the node from being dragged onto itself
if (NodeMoving == NodeOver)
return;
#endregion
#region If NodeOver is a child then cancel
TreeNode tnParadox = NodeOver;
while (tnParadox.Parent != null)
{
if (tnParadox.Parent == NodeMoving)
{
this.NodeMap = "";
return;
}
tnParadox = tnParadox.Parent;
}
#endregion
#region Store the placeholder info into a pipe delimited string
SetNewNodeMap(NodeOver, false);
NewNodeMap = NewNodeMap.Insert(NewNodeMap.Length, "|0");
if (SetMapsEqual() == true)
return;
#endregion
#region Clear placeholders above and below
this.Refresh();
#endregion
#region Draw the "add to folder" placeholder
DrawAddToFolderPlaceholder(NodeOver);
#endregion
}
}
#endregion
}
}
}
private void SetNewNodeMap(TreeNode tnNode, bool boolBelowNode)
{
NewNodeMap.Length = 0;
if (boolBelowNode)
NewNodeMap.Insert(0, (int)tnNode.Index + 1);
else
NewNodeMap.Insert(0, (int)tnNode.Index);
TreeNode tnCurNode = tnNode;
while (tnCurNode.Parent != null)
{
tnCurNode = tnCurNode.Parent;
if (NewNodeMap.Length == 0 && boolBelowNode == true)
{
NewNodeMap.Insert(0, (tnCurNode.Index + 1) + "|");
}
else
{
NewNodeMap.Insert(0, tnCurNode.Index + "|");
}
}
}//oem
private bool SetMapsEqual()
{
if (this.NewNodeMap.ToString() == this.NodeMap)
return true;
else
{
this.NodeMap = this.NewNodeMap.ToString();
return false;
}
}//oem
private void DrawLeafTopPlaceholders(TreeNode NodeOver)
{
Graphics g = CreateGraphics();
// MTC
// int NodeOverImageWidth = ImageList.Images[NodeOver.ImageIndex].Size.Width + 8;
int LeftPos = NodeOver.Bounds.Left; // MTC -NodeOverImageWidth;
int RightPos = Width - 4;
Point[] LeftTriangle = new Point[5]{
new Point(LeftPos, NodeOver.Bounds.Top - 4),
new Point(LeftPos, NodeOver.Bounds.Top + 4),
new Point(LeftPos + 4, NodeOver.Bounds.Y),
new Point(LeftPos + 4, NodeOver.Bounds.Top - 1),
new Point(LeftPos, NodeOver.Bounds.Top - 5)};
Point[] RightTriangle = new Point[5]{
new Point(RightPos, NodeOver.Bounds.Top - 4),
new Point(RightPos, NodeOver.Bounds.Top + 4),
new Point(RightPos - 4, NodeOver.Bounds.Y),
new Point(RightPos - 4, NodeOver.Bounds.Top - 1),
new Point(RightPos, NodeOver.Bounds.Top - 5)};
g.FillPolygon(System.Drawing.Brushes.Black, LeftTriangle);
g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle);
g.DrawLine(new System.Drawing.Pen(Color.Black, 2), new Point(LeftPos, NodeOver.Bounds.Top), new Point(RightPos, NodeOver.Bounds.Top));
}//eom
private void DrawLeafBottomPlaceholders(TreeNode NodeOver, TreeNode ParentDragDrop)
{
Graphics g = CreateGraphics();
// MTC
// int NodeOverImageWidth = ImageList.Images[NodeOver.ImageIndex].Size.Width + 8;
// Once again, we are not dragging to node over, draw the placeholder using the ParentDragDrop bounds
int LeftPos, RightPos;
// MTC
//if (ParentDragDrop != null)
// LeftPos = ParentDragDrop.Bounds.Left - (ImageList.Images[ParentDragDrop.ImageIndex].Size.Width + 8);
//else
LeftPos = NodeOver.Bounds.Left; // MTC -NodeOverImageWidth;
RightPos = Width - 4;
Point[] LeftTriangle = new Point[5]{
new Point(LeftPos, NodeOver.Bounds.Bottom - 4),
new Point(LeftPos, NodeOver.Bounds.Bottom + 4),
new Point(LeftPos + 4, NodeOver.Bounds.Bottom),
new Point(LeftPos + 4, NodeOver.Bounds.Bottom - 1),
new Point(LeftPos, NodeOver.Bounds.Bottom - 5)};
Point[] RightTriangle = new Point[5]{
new Point(RightPos, NodeOver.Bounds.Bottom - 4),
new Point(RightPos, NodeOver.Bounds.Bottom + 4),
new Point(RightPos - 4, NodeOver.Bounds.Bottom),
new Point(RightPos - 4, NodeOver.Bounds.Bottom - 1),
new Point(RightPos, NodeOver.Bounds.Bottom - 5)};
g.FillPolygon(System.Drawing.Brushes.Black, LeftTriangle);
g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle);
g.DrawLine(new System.Drawing.Pen(Color.Black, 2), new Point(LeftPos, NodeOver.Bounds.Bottom), new Point(RightPos, NodeOver.Bounds.Bottom));
}//eom
private void DrawFolderTopPlaceholders(TreeNode NodeOver)
{
Graphics g = CreateGraphics();
// MTC
// int NodeOverImageWidth = ImageList.Images[NodeOver.ImageIndex].Size.Width + 8;
int LeftPos, RightPos;
LeftPos = NodeOver.Bounds.Left; // MTC -NodeOverImageWidth;
RightPos = Width - 4;
Point[] LeftTriangle = new Point[5]{
new Point(LeftPos, NodeOver.Bounds.Top - 4),
new Point(LeftPos, NodeOver.Bounds.Top + 4),
new Point(LeftPos + 4, NodeOver.Bounds.Y),
new Point(LeftPos + 4, NodeOver.Bounds.Top - 1),
new Point(LeftPos, NodeOver.Bounds.Top - 5)};
Point[] RightTriangle = new Point[5]{
new Point(RightPos, NodeOver.Bounds.Top - 4),
new Point(RightPos, NodeOver.Bounds.Top + 4),
new Point(RightPos - 4, NodeOver.Bounds.Y),
new Point(RightPos - 4, NodeOver.Bounds.Top - 1),
new Point(RightPos, NodeOver.Bounds.Top - 5)};
g.FillPolygon(System.Drawing.Brushes.Black, LeftTriangle);
g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle);
g.DrawLine(new System.Drawing.Pen(Color.Black, 2), new Point(LeftPos, NodeOver.Bounds.Top), new Point(RightPos, NodeOver.Bounds.Top));
}//eom
private void DrawAddToFolderPlaceholder(TreeNode NodeOver)
{
Graphics g = CreateGraphics();
int RightPos = NodeOver.Bounds.Right + 6;
Point[] RightTriangle = new Point[5]{
new Point(RightPos, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2) + 4),
new Point(RightPos, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2) + 4),
new Point(RightPos - 4, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2)),
new Point(RightPos - 4, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2) - 1),
new Point(RightPos, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2) - 5)};
this.Refresh();
g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle);
}//eom
}
}