using bzit.bomg; using bzit.bomg.Data; using bzit.bomg.Models; using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.IO; using System.Text; using System.Windows.Forms; using Resources = bzit.bomg.Properties.Resources; namespace RyzStudio.Windows.Forms { public class BookmarkTreeView : System.Windows.Forms.TreeView { public enum IconSet { Root = 0, Folder1, Folder2, Default } public enum NodeType { None = 0, Root, Folder, Page } public BookmarkTreeViewSNode SNode { get; set; } protected IconDatabase iconDatabase = null; protected TreeNode draggingNode = null; protected bool allowBeginEdit = false; protected bool hasChanged = false; public BookmarkTreeView() : base() { this.SNode = new BookmarkTreeViewSNode(this); if (this.ImageList == null) { this.ImageList = new ImageList(); } this.ImageList.ColorDepth = ColorDepth.Depth16Bit; this.ImageList.ImageSize = new Size(16, 16); this.ImageList.TransparentColor = Color.Transparent; this.ImageList.Images.Clear(); this.ImageList.Images.Add(Resources.hexagon); this.ImageList.Images.Add(Resources.folder); this.ImageList.Images.Add(Resources.folder_explore); this.ImageList.Images.Add(Resources.file_text); this.PathSeparator = "\n"; } [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public new ImageList ImageList { get => base.ImageList; set => base.ImageList = value; } [Browsable(false)] public bool HasChanged { get { return hasChanged; } set { hasChanged = value; //OnChanged?.Invoke(null, null); } } #region public methods 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(TreeNode node) { //return this.AddFolder("New Folder " + (new Random()).Next(10001, 99999).ToString()); return this.AddFolder(node, "New Folder (" + DateTime.Now.ToString("yyyy-MM-dd-HHmmss") + ")"); } public TreeNode AddFolder(TreeNode node, string name) { if (node == null) { return null; } if (node.Tag != null) { return null; } return node.Nodes.Add(encodePath(name), name, (int)IconSet.Folder1, (int)IconSet.Folder2); } public void AddItem(List viewModelList) { this.Clear(); if (viewModelList == null) { return; } foreach (BookmarkItemViewModel item in viewModelList) { AddItem(item); } } public void AddItem(BookmarkItemViewModel viewModel) { int iconIndex = addIcon(viewModel); TreeNode tn = new TreeNode(viewModel.SiteName, iconIndex, iconIndex); tn.Tag = viewModel; tn.ToolTipText = viewModel.ToString(); TreeNode tn2 = addFolderPath(viewModel.TreeviewPath); tn2.Nodes.Add(tn); this.HasChanged = true; } public void AddOrUpdateItem_OnSelectedNode(BookmarkItemViewModel viewModel) { switch (this.SNode.GetNodeType()) { case NodeType.Root: case NodeType.Folder: addItem_OnSelectedNode(viewModel); this.HasChanged = true; break; case NodeType.Page: updateItem_OnSelectedNode(viewModel); this.HasChanged = true; break; default: break; } } public void Clear() { this.Nodes.Clear(); this.HasChanged = true; } public void Clear(string name) { this.Nodes.Clear(); this.Nodes.Add("", name?.Trim(), (int)IconSet.Root, (int)IconSet.Root); this.HasChanged = true; } public void CloseIconDatabase() { iconDatabase.Close(); } public NodeType GetNodeType(TreeNode node) { if (node.Tag == null) { if (node.Equals(this.Nodes[0])) { return NodeType.Root; } else { return NodeType.Folder; } } else { if (node.Tag is BookmarkItemViewModel) { return NodeType.Page; } else { return NodeType.None; } } } public 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 BookmarkItemViewModel GetViewModel(TreeNode node) => (BookmarkItemViewModel)node.Tag; public List GetBookmarkList() { List rs = new List(); 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; } #endregion #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 en = this.GetNodeAt(this.PointToClient(new Point(e.X, e.Y))); if (en == null) { return; } if (isNodeChild(draggingNode, en)) { return; } TreeNode dn = draggingNode; if (en.Tag == null) { dn.Parent.Nodes.Remove(dn); en.Nodes.Insert(0, dn); } else { en.Parent.Nodes.Remove(dn); en.Parent.Nodes.Insert(en.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 OnPreviewKeyDown(PreviewKeyDownEventArgs e) { TreeNode tn = this.SelectedNode; if (tn == null) { return; } NodeType nodeType = this.SNode.GetNodeType(); switch (e.KeyCode) { case Keys.Insert: if (e.Modifiers == Keys.Shift) { if ((nodeType == NodeType.Root) || (nodeType == NodeType.Folder)) { this.SelectedNode = this.SNode.AddFolder(); } else if (nodeType == NodeType.Page) { this.SelectedNode = tn.Parent; this.SelectedNode = this.SNode.AddFolder(); } } break; case Keys.Delete: if (!tn.IsEditing) { this.SNode.Delete(); } break; case Keys.F2: allowBeginEdit = true; this.SNode.Edit(); break; case Keys.F3: switch (nodeType) { case NodeType.Root: case NodeType.Folder: try { Clipboard.SetText(tn.Text ?? string.Empty); } catch { } break; case NodeType.Page: BookmarkItemViewModel viewModel = this.SNode.GetViewModel(); if (viewModel != null) { try { Clipboard.SetText(viewModel.SiteAddress ?? string.Empty); } catch { } } break; default: break; } break; case Keys.Up: if (e.Modifiers == Keys.Control) { this.SNode.MoveUp(); } break; case Keys.Down: if (e.Modifiers == Keys.Control) { this.SNode.MoveDown(); } break; default: break; } base.OnPreviewKeyDown(e); } #endregion protected int addIcon(BookmarkItemViewModel viewModel) => addIcon(viewModel.ToModel()); protected int addIcon(BookmarkItemModel model) { if (this.ImageList.Images.ContainsKey(model.SiteAddress)) { return this.ImageList.Images.IndexOfKey(model.SiteAddress); } if (iconDatabase.HasIcon(model.SiteAddress)) { Image rs = iconDatabase.GetIcon(model.SiteAddress); if (rs == null) { return (int)IconSet.Default; } else { this.ImageList.Images.Add(model.SiteAddress, rs); return this.ImageList.Images.IndexOfKey(model.SiteAddress); } } Bitmap bmp = model.RetrieveFavicon(); if (bmp == null) { return (int)IconSet.Default; } this.ImageList.Images.Add(model.SiteAddress, bmp); return this.ImageList.Images.IndexOfKey(model.SiteAddress); } 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 System.Web.HttpUtility.UrlDecode(value); protected string encodePath(string value) => System.Web.HttpUtility.UrlEncode(value); protected void traverseBookmarkList(List rs, TreeNode node) { foreach (TreeNode tn in node.Nodes) { NodeType nodeType = this.GetNodeType(tn); if (nodeType == NodeType.Folder) { traverseBookmarkList(rs, tn); } else if (nodeType == NodeType.Page) { BookmarkItemViewModel nodeTag = this.GetViewModel(tn); nodeTag.TreeviewPath = this.GetNodePath(tn); if (nodeTag != null) { rs.Add(nodeTag); } } } } protected void updateItem_OnSelectedNode(BookmarkItemViewModel viewModel) { if (this.SelectedNode == null) { return; } int iconIndex = addIcon(viewModel); this.SelectedNode.Text = viewModel.SiteName; this.SelectedNode.ImageIndex = iconIndex; this.SelectedNode.SelectedImageIndex = iconIndex; this.SelectedNode.Tag = viewModel; this.SelectedNode.ToolTipText = viewModel.ToString(); } protected bool isNodeChild(TreeNode drag_node, TreeNode drop_node) { TreeNode tn = drop_node; while (true) { if (tn.Parent == null) { break; } if (tn.Equals(drag_node)) { return true; } tn = tn.Parent; } return false; } } }