bookmark-manager-r4/Windows/Forms/BookmarkTreeView.cs

920 lines
26 KiB
C#

using BookmarkManager;
using bzit.bomg.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Resources = BookmarkManager.AppResource;
namespace RyzStudio.Windows.Forms
{
public partial class BookmarkTreeView : TreeView
{
public static string DecodePath(string value) => System.Web.HttpUtility.UrlDecode(value);
public static void DeleteNode(TreeNode node)
{
if (node == null)
{
return;
}
if (node.TreeView.Nodes.Count <= 0)
{
return;
}
if (node.Equals(node.TreeView.Nodes[0]))
{
return;
}
node.Remove();
}
public static string EncodePath(string value)
{
return System.Web.HttpUtility.UrlEncode(value);
}
public static BookmarkItem GetNodeModel(TreeNode node)
{
if (node == null)
{
return null;
}
return (BookmarkItem)node.Tag;
}
public static string GetNodePath(TreeNode node)
{
string[] folderList = node.FullPath.Split('\n');
if (folderList.Length < 2)
{
return null;
}
//if (folderList.Length < 2)
//{
// return "/";
//}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < (folderList.Length - 1); i++)
{
sb.Append("\\");
sb.Append(EncodePath(folderList[i] ?? string.Empty));
}
sb.Append("\\");
return sb.ToString();
}
public static NodeType GetNodeType(TreeNode node)
{
if (node.Tag == null)
{
if (node.Equals(node.TreeView.Nodes[0]))
{
return NodeType.Root;
}
else
{
return NodeType.Folder;
}
}
else
{
if (node.Tag is BookmarkItem)
{
return NodeType.Page;
}
else
{
return NodeType.None;
}
}
}
public static void MoveDown(TreeNode node)
{
if (node == null)
{
return;
}
TreeNode tn = node;
if (tn.Parent == null)
{
return;
}
TreeNode tn1 = tn.Parent;
if (tn.Index >= (tn1.Nodes.Count - 1))
{
return;
}
int n = tn.Index + 1;
tn1.Nodes.Remove(tn);
tn1.Nodes.Insert(n, tn);
node.TreeView.SelectedNode = tn;
}
public static void MoveUp(TreeNode node)
{
if (node == null)
{
return;
}
TreeNode tn = node;
if (tn.Parent == null)
{
return;
}
if (tn.Index <= 0)
{
return;
}
int n = tn.Index - 1;
TreeNode tn1 = tn.Parent;
tn1.Nodes.Remove(tn);
tn1.Nodes.Insert(n, tn);
node.TreeView.SelectedNode = tn;
}
public static void Sort(TreeNode node)
{
if (node == null)
{
return;
}
string[] tnv = new string[0];
TreeNode[] tna = new TreeNode[0];
foreach (TreeNode tn2 in node.Nodes)
{
Array.Resize(ref tna, (tna.Length + 1));
tna[(tna.Length - 1)] = tn2;
Array.Resize(ref tnv, (tnv.Length + 1));
tnv[(tnv.Length - 1)] = tn2.Text;
}
Array.Sort(tnv, tna);
node.Nodes.Clear();
foreach (TreeNode tn2 in tna)
{
node.Nodes.Add(tn2);
}
}
public enum IconSet
{
Root = 0,
Folder1,
Folder2,
Default
}
public enum NodeType
{
None = 0,
Root,
Folder,
Page
}
protected const string DEFAULT_NEW_FOLDER_NAME = "New Folder";
protected const string PATH_SEPARATOR = "\n";
public event EventHandler OnNodeChanged = null;
protected TreeNode draggingNode = null;
protected bool hasChanged = false;
public BookmarkTreeView()
{
if (this.ImageList == null) this.ImageList = new ImageList();
this.PathSeparator = PATH_SEPARATOR;
this.AllowDrop = true;
this.HideSelection = false;
this.HotTracking = true;
this.ImageIndex = 0;
this.LabelEdit = true;
this.PathSeparator = "\n";
this.SelectedImageIndex = 0;
this.ShowNodeToolTips = true;
this.ImageList.ColorDepth = ColorDepth.Depth32Bit;
this.ImageList.ImageSize = new Size(16, 16);
this.ImageList.TransparentColor = Color.Transparent;
ResetImageList();
}
#region integrated behaviour
protected override void OnItemDrag(ItemDragEventArgs e)
{
base.OnItemDrag(e);
draggingNode = (TreeNode)e.Item;
DoDragDrop(e.Item, DragDropEffects.Move);
}
protected override void OnDragDrop(DragEventArgs e)
{
base.OnDragDrop(e);
if (draggingNode.Level <= 0)
{
return;
}
TreeNode node = this.GetNodeAt(this.PointToClient(new Point(e.X, e.Y)));
if (node == null)
{
return;
}
if (UIControl.IsChild(draggingNode, node))
{
return;
}
TreeNode dn = draggingNode;
if (node.Tag == null)
{
dn.Parent.Nodes.Remove(dn);
node.Nodes.Insert(0, dn);
}
else
{
node.Parent.Nodes.Remove(dn);
node.Parent.Nodes.Insert(node.Index + 1, dn);
}
this.HasChanged = true;
}
protected override void OnDragEnter(DragEventArgs e)
{
base.OnDragEnter(e);
e.Effect = DragDropEffects.Move;
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
this.SelectedNode = this.GetNodeAt(e.Location);
}
protected override void OnDragOver(DragEventArgs e)
{
base.OnDragOver(e);
this.SelectedNode = this.GetNodeAt(this.PointToClient(new Point(e.X, e.Y)));
}
protected override void OnBeforeLabelEdit(NodeLabelEditEventArgs e)
{
if (!AllowBeginEdit)
{
AllowBeginEdit = false;
e.CancelEdit = true;
return;
}
this.HasChanged = true;
base.OnBeforeLabelEdit(e);
}
protected override void OnAfterLabelEdit(NodeLabelEditEventArgs e)
{
base.OnAfterLabelEdit(e);
//if (e.Node.Tag == null)
//{
// if (e.Label == null)
// {
// e.CancelEdit = true;
// }
// else
// {
// if (e.Label.Trim().Length <= 0)
// {
// e.CancelEdit = true;
// }
// }
//}
//else
//{
// e.CancelEdit = true;
//}
AllowBeginEdit = false;
}
protected override void OnNodeMouseClick(TreeNodeMouseClickEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
switch (this.GetNodeType())
{
case BookmarkTreeView.NodeType.Root:
if (this.RootContextMenu != null) this.RootContextMenu.Show(e.Node.TreeView, e.X, e.Y);
break;
case BookmarkTreeView.NodeType.Folder:
if (this.FolderContextMenu != null) this.FolderContextMenu.Show(e.Node.TreeView, e.X, e.Y);
break;
case BookmarkTreeView.NodeType.Page:
if (this.PageContextMenu != null) this.PageContextMenu.Show(e.Node.TreeView, e.X, e.Y);
break;
default:
break;
}
}
base.OnNodeMouseClick(e);
}
protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
{
TreeNode tn = this.SelectedNode;
if (tn == null)
{
return;
}
NodeType nodeType = this.GetNodeType();
switch (e.KeyCode)
{
case Keys.Insert:
if (e.Modifiers == Keys.Shift)
{
if ((nodeType == NodeType.Root) || (nodeType == NodeType.Folder))
{
this.SelectedNode = this.AddFolder();
}
else if (nodeType == NodeType.Page)
{
this.SelectedNode = tn.Parent;
this.SelectedNode = this.AddFolder();
}
}
break;
case Keys.Delete:
if (!tn.IsEditing)
{
this.DeleteNode();
}
break;
case Keys.F2:
if ((nodeType == NodeType.Root) || (nodeType == NodeType.Folder))
{
this.AllowBeginEdit = true;
this.EditNode();
}
break;
case Keys.F3:
switch (nodeType)
{
case NodeType.Root:
case NodeType.Folder:
try
{
Clipboard.SetText(tn.Text ?? string.Empty);
}
catch
{
}
break;
case NodeType.Page:
BookmarkItem viewModel = this.GetNodeModel();
if (viewModel != null)
{
try
{
Clipboard.SetText(viewModel.SiteAddress ?? string.Empty);
}
catch
{
}
}
break;
default:
break;
}
break;
case Keys.Up:
if (e.Modifiers == Keys.Control)
{
this.MoveUp();
this.HasChanged = true;
}
break;
case Keys.Down:
if (e.Modifiers == Keys.Control)
{
this.MoveDown();
this.HasChanged = true;
}
break;
case Keys.Apps:
this.OnNodeMouseClick(new TreeNodeMouseClickEventArgs(tn, MouseButtons.Right, 1, tn.Bounds.X, tn.Bounds.Y));
break;
default: break;
}
base.OnPreviewKeyDown(e);
}
#endregion
#region encapsulation
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new ImageList ImageList { get => base.ImageList; set => base.ImageList = value; }
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new bool AllowDrop { get => base.AllowDrop; set => base.AllowDrop = value; }
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new bool HideSelection { get => base.HideSelection; set => base.HideSelection = value; }
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new bool HotTracking { get => base.HotTracking; set => base.HotTracking = value; }
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new int ImageIndex { get => base.ImageIndex; set => base.ImageIndex = value; }
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new bool LabelEdit { get => base.LabelEdit; set => base.LabelEdit = value; }
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new string PathSeparator { get => base.PathSeparator; set => base.PathSeparator = value; }
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new int SelectedImageIndex { get => base.SelectedImageIndex; set => base.SelectedImageIndex = value; }
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new bool ShowNodeToolTips { get => base.ShowNodeToolTips; set => base.ShowNodeToolTips = value; }
#endregion
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool AllowBeginEdit { get; set; } = false;
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool HasChanged
{
get => hasChanged;
protected set
{
hasChanged = value;
OnNodeChanged?.Invoke(null, null);
}
}
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public IconDatabase IconDatabase { get; set; } = null;
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ContextMenuStrip RootContextMenu { get; set; } = null;
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ContextMenuStrip FolderContextMenu { get; set; } = null;
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ContextMenuStrip PageContextMenu { get; set; } = null;
public bool InitialiseIconDatabase(out string message, string filename)
{
message = string.Empty;
//if (string.IsNullOrWhiteSpace(filename))
//{
// return false;
//}
//if (iconDatabase == null)
//{
// iconDatabase = new IconDatabase();
//}
//bool rv = false;
//if (File.Exists(filename))
//{
// rv = iconDatabase.LoadFile(filename);
// if (!rv)
// {
// rv = iconDatabase.Create(filename, true, null, true);
// if (!rv)
// {
// message = iconDatabase.LastError;
// return false;
// }
// }
//}
//else
//{
// rv = iconDatabase.Create(filename, true, null, true);
// if (!rv)
// {
// message = iconDatabase.LastError;
// return false;
// }
//}
return true;
}
public TreeNode AddFolder(string name = "")
{
return this.AddFolder(this.SelectedNode, name);
}
public TreeNode AddFolder(TreeNode node, string name = "")
{
if (node == null)
{
return null;
}
if (node.Tag != null)
{
return null;
}
if (string.IsNullOrWhiteSpace(name))
{
name = DEFAULT_NEW_FOLDER_NAME;
}
return node.Nodes.Add(EncodePath(name), name, (int)IconSet.Folder1, (int)IconSet.Folder2);
}
public TreeNode AddItem(BookmarkItem item)
{
int iconIndex = FindIcon(item);
TreeNode tn = new TreeNode(item.SiteName, iconIndex, iconIndex);
tn.Tag = item;
tn.ToolTipText = item.ToString();
TreeNode tn2 = AddFolderPath(item.TreeviewPath);
UIControl.Add(tn2, tn);
this.HasChanged = true;
return tn;
}
public TreeNode AddItem(TreeNode treeNode, BookmarkItem item)
{
if (treeNode == null) return null;
if (item == null) return null;
int iconIndex = FindIcon(item);
TreeNode tn = new TreeNode(item.SiteName, iconIndex, iconIndex);
tn.Tag = item;
tn.ToolTipText = item.ToString();
//treeNode.Nodes.Add(tn);
UIControl.Add(treeNode, tn);
this.HasChanged = true;
return tn;
}
public void Clear()
{
ResetImageList();
UIControl.Clear(this);
this.HasChanged = false;
}
public void Clear(string name)
{
ResetImageList();
var tt1 = this.ImageList;
UIControl.Clear(this);
UIControl.Add(this, this.Nodes, "", name?.Trim(), (int)IconSet.Root, (int)IconSet.Root);
this.HasChanged = true;
}
public void CloseIconDatabase()
{
//iconDatabase.Close();
}
public void DeleteNode() => DeleteNode(this.SelectedNode);
public void EditNode()
{
this.EditNode(this.SelectedNode);
}
public void EditNode(TreeNode node)
{
if (node == null)
{
return;
}
if (node.IsEditing)
{
return;
}
switch (GetNodeType(node))
{
case BookmarkTreeView.NodeType.Root:
case BookmarkTreeView.NodeType.Folder:
this.AllowBeginEdit = true;
node.BeginEdit();
break;
case BookmarkTreeView.NodeType.Page:
this.AllowBeginEdit = true;
node.BeginEdit();
break;
default: break;
}
}
public NodeType GetNodeType() => GetNodeType(this.SelectedNode);
public string GetNodePath() => GetNodePath(this.SelectedNode);
public BookmarkItem GetNodeModel() => GetNodeModel(this.SelectedNode);
public List<BookmarkItem> GetBookmarkList()
{
List<BookmarkItem> rs = new List<BookmarkItem>();
if (this.Nodes.Count <= 0)
{
return rs;
}
foreach (TreeNode item in this.Nodes)
{
TraverseBookmarkList(rs, item);
}
return rs;
}
public bool FindTextNode(TreeNode node, string term)
{
if (node == null)
{
return false;
}
if (this.Nodes.Count <= 0)
{
return false;
}
bool rt = false;
bool inclusive = false;
TreeNode tn = node;
while (true)
{
if (tn == null)
{
break;
}
if (inclusive)
{
if (tn.Text.ToLower().Contains(term.ToLower()))
{
this.SelectedNode = tn;
this.SelectedNode.EnsureVisible();
rt = true;
break;
}
}
if (tn.Nodes.Count > 0)
{
tn = tn.Nodes[0];
inclusive = true;
}
else
{
if (tn.NextNode != null)
{
tn = tn.NextNode;
inclusive = true;
}
else
{
while (true)
{
tn = tn.Parent;
if (tn == null)
{
break;
}
if (tn.NextNode != null)
{
tn = tn.NextNode;
break;
}
}
inclusive = true;
}
}
}
return rt;
}
public void MoveDown() => MoveDown(this.SelectedNode);
public void MoveUp() => MoveUp(this.SelectedNode);
public void SetNoChanges()
{
this.HasChanged = false;
}
public new void Sort() => Sort(this.SelectedNode);
public void UpdateItem(TreeNode treeNode, BookmarkItem item)
{
if (treeNode == null) return;
if (item == null) return;
int iconIndex = FindIcon(item);
treeNode.Text = item.SiteName;
treeNode.ImageIndex = iconIndex;
treeNode.SelectedImageIndex = iconIndex;
treeNode.Tag = item;
treeNode.ToolTipText = item.ToString();
this.HasChanged = true;
}
protected int FindIcon(BookmarkItem item)
{
if (this.IconDatabase == null) return (int)IconSet.Default;
if (item == null) return (int)IconSet.Default;
if (string.IsNullOrWhiteSpace(item.SiteAddress)) return (int)IconSet.Default;
string iconID = item?.ToHash();
if (this.ImageList.Images.ContainsKey(iconID))
{
return this.ImageList.Images.IndexOfKey(iconID);
}
Image image = this.IconDatabase.FindIcon(iconID);
if (image == null)
{
return (int)IconSet.Default;
}
UIControl.Add(this, this.ImageList, iconID, image);
return this.ImageList.Images.IndexOfKey(iconID);
}
protected TreeNode AddFolderPath(string path)
{
TreeNode tn = null;
//TreeNode tn = this.Nodes[0];
//if (tn == null)
//{
// return tn;
//}
if (string.IsNullOrWhiteSpace(path))
{
return tn;
}
if (string.IsNullOrWhiteSpace(path.Trim('\\')))
{
return tn;
}
string[] folderList = path.Trim('\\').Split('\\');
if (folderList.Length <= 0)
{
return tn;
}
for (int i=0; i<folderList.Length; i++)
{
string item = folderList[i];
if (i <= 0)
{
if (!this.Nodes.ContainsKey(item))
{
UIControl.Add(this, item, DecodePath(item), (int)IconSet.Root, (int)IconSet.Root);
}
tn = this.Nodes[item];
}
else
{
if (!tn.Nodes.ContainsKey(item))
{
UIControl.Add(tn, item, DecodePath(item), (int)IconSet.Folder1, (int)IconSet.Folder2);
}
tn = tn.Nodes[item];
}
}
return tn;
}
protected void ResetImageList()
{
UIControl.Clear(this, this.ImageList);
UIControl.Add(this, this.ImageList, Resources.hexagon);
UIControl.Add(this, this.ImageList, Resources.folder);
UIControl.Add(this, this.ImageList, Resources.folder_explore);
UIControl.Add(this, this.ImageList, Resources.file_text);
}
protected void TraverseBookmarkList(List<BookmarkItem> rs, TreeNode node)
{
foreach (TreeNode tn in node.Nodes)
{
NodeType nodeType = GetNodeType(tn);
if (nodeType == NodeType.Folder)
{
TraverseBookmarkList(rs, tn);
}
else if (nodeType == NodeType.Page)
{
BookmarkItem nodeTag = GetNodeModel(tn);
nodeTag.TreeviewPath = GetNodePath(tn);
if (nodeTag != null)
{
rs.Add(nodeTag);
}
}
}
}
}
}