public void SelectNodes(DarkTreeNode startNode, DarkTreeNode endNode) { var nodes = new List <DarkTreeNode>(); if (startNode == endNode) { nodes.Add(startNode); } if (startNode.VisibleIndex < endNode.VisibleIndex) { var node = startNode; nodes.Add(node); while (node != endNode && node != null) { node = node.NextVisibleNode; nodes.Add(node); } } else if (startNode.VisibleIndex > endNode.VisibleIndex) { var node = startNode; nodes.Add(node); while (node != endNode && node != null) { node = node.PrevVisibleNode; nodes.Add(node); } } SelectNodes(nodes, false); }
private void UpdateNodes() { if (IsDragging) { return; } if (Nodes.Count == 0) { return; } var yOffset = 0; var isOdd = false; var index = 0; DarkTreeNode prevNode = null; ContentSize = new Size(0, 0); for (var i = 0; i <= Nodes.Count - 1; i++) { var node = Nodes[i]; UpdateNode(node, ref prevNode, 0, ref yOffset, ref isOdd, ref index); } ContentSize = new Size(ContentSize.Width, yOffset); VisibleNodeCount = index; Invalidate(); }
protected override void OnMouseMove(MouseEventArgs e) { if (_provisionalDragging) { if (OffsetMousePosition != _dragPos) { StartDrag(); HandleDrag(); return; } } if (IsDragging) { if (_dropNode != null) { var rect = GetNodeFullRowArea(_dropNode); if (!rect.Contains(OffsetMousePosition)) { _dropNode = null; Invalidate(); } } } CheckHover(); if (IsDragging) { HandleDrag(); } base.OnMouseMove(e); }
private void CheckNodeHover(DarkTreeNode node, Point location) { if (IsDragging) { var rect = GetNodeFullRowArea(node); if (rect.Contains(OffsetMousePosition)) { var newDropNode = _dragNodes.Contains(node) ? null : node; if (_dropNode != newDropNode) { _dropNode = newDropNode; Invalidate(); } } } else { var hot = node.ExpandArea.Contains(location); if (node.ExpandAreaHot != hot) { node.ExpandAreaHot = hot; Invalidate(); } } foreach (var childNode in node.Nodes) { CheckNodeHover(childNode, location); } }
private DarkTreeNode FindNode(DarkTreeNode parentNode, string path, bool recursive = true) { if (parentNode.FullPath == path) { return(parentNode); } foreach (var node in parentNode.Nodes) { if (node.FullPath == path) { return(node); } if (recursive) { var compNode = FindNode(node, path); if (compNode != null) { return(compNode); } } } return(null); }
private void UpdateNode(DarkTreeNode node, ref DarkTreeNode prevNode, int indent, ref int yOffset, ref bool isOdd, ref int index) { UpdateNodeBounds(node, yOffset, indent); yOffset += ItemHeight; node.Odd = isOdd; isOdd = !isOdd; node.VisibleIndex = index; index++; node.PrevVisibleNode = prevNode; if (prevNode != null) { prevNode.NextVisibleNode = node; } prevNode = node; if (node.Expanded) { foreach (var childNode in node.Nodes) { UpdateNode(childNode, ref prevNode, indent + Indent, ref yOffset, ref isOdd, ref index); } } }
private void UpdateNodeBounds(DarkTreeNode node, int yOffset, int indent) { var expandTop = yOffset + (ItemHeight / 2) - (_expandAreaSize / 2); node.ExpandArea = new Rectangle(indent + 3, expandTop, _expandAreaSize, _expandAreaSize); var iconTop = yOffset + (ItemHeight / 2) - (_iconSize / 2); if (ShowIcons) { node.IconArea = new Rectangle(node.ExpandArea.Right + 2, iconTop, _iconSize, _iconSize); } else { node.IconArea = new Rectangle(node.ExpandArea.Right, iconTop, 0, 0); } using (var g = CreateGraphics()) { int textSize = (int)g.MeasureString(node.Text, Font).Width; node.TextArea = new Rectangle(node.IconArea.Right + 2, yOffset, textSize + 1, ItemHeight); } node.FullArea = new Rectangle(indent, yOffset, (node.TextArea.Right - indent), ItemHeight); if (ContentSize.Width < node.TextArea.Right + 2) { ContentSize = new Size(node.TextArea.Right + 2, ContentSize.Height); } }
private void SortChildNodes(DarkTreeNode node) { node.Nodes.Sort(TreeViewNodeSorter); foreach (var childNode in node.Nodes) { SortChildNodes(childNode); } }
public void SelectNode(DarkTreeNode node) { _selectedNodes.Clear(); _selectedNodes.Add(node); _anchoredNodeStart = node; _anchoredNodeEnd = node; Invalidate(); }
protected override void StopDrag() { _dragNodes = null; _dropNode = null; Cursor = Cursors.Default; Invalidate(); base.StopDrag(); }
private void NodeMouseLeave(DarkTreeNode node) { node.ExpandAreaHot = false; foreach (var childNode in node.Nodes) { NodeMouseLeave(childNode); } Invalidate(); }
public Rectangle GetNodeFullRowArea(DarkTreeNode node) { if (node.ParentNode != null && !node.ParentNode.Expanded) { return(new Rectangle(-1, -1, -1, -1)); } var width = Math.Max(ContentSize.Width, Viewport.Width); var rect = new Rectangle(0, node.FullArea.Top, width, ItemHeight); return(rect); }
private void UnhookNodeEvents(DarkTreeNode node) { node.Nodes.ItemsAdded -= ChildNodes_ItemsAdded; node.Nodes.ItemsRemoved -= ChildNodes_ItemsRemoved; node.TextChanged -= Nodes_TextChanged; node.NodeExpanded -= Nodes_NodeExpanded; node.NodeCollapsed -= Nodes_NodeCollapsed; foreach (var childNode in node.Nodes) { UnhookNodeEvents(childNode); } }
protected virtual bool CanMoveNodes(List <DarkTreeNode> dragNodes, DarkTreeNode dropNode, bool isMoving = false) { if (dropNode == null) { return(false); } foreach (var node in dragNodes) { if (node == dropNode) { if (isMoving) { DarkMessageBox.ShowError($"Cannot move {node.Text}. The destination folder is the same as the source folder.", Application.ProductName); } return(false); } if (node.ParentNode != null && node.ParentNode == dropNode) { if (isMoving) { DarkMessageBox.ShowError($"Cannot move {node.Text}. The destination folder is the same as the source folder.", Application.ProductName); } return(false); } var parentNode = dropNode.ParentNode; while (parentNode != null) { if (node == parentNode) { if (isMoving) { DarkMessageBox.ShowError($"Cannot move {node.Text}. The destination folder is a subfolder of the source folder.", Application.ProductName); } return(false); } parentNode = parentNode.ParentNode; } } return(true); }
public bool IsNodeAncestor(DarkTreeNode node) { var parent = ParentNode; while (parent != null) { if (parent == node) { return(true); } parent = parent.ParentNode; } return(false); }
public void SelectNodes(List <DarkTreeNode> nodes, bool updateAnchors = true) { _selectedNodes.Clear(); foreach (var node in nodes) { _selectedNodes.Add(node); } if (updateAnchors && _selectedNodes.Count > 0) { _anchoredNodeStart = _selectedNodes[_selectedNodes.Count - 1]; _anchoredNodeEnd = _selectedNodes[_selectedNodes.Count - 1]; } Invalidate(); }
private void CheckHover() { if (!ClientRectangle.Contains(PointToClient(MousePosition))) { if (IsDragging) { if (_dropNode != null) { _dropNode = null; Invalidate(); } } return; } foreach (var node in Nodes) { CheckNodeHover(node, OffsetMousePosition); } }
private void CheckNodeDoubleClick(DarkTreeNode node, Point location) { var rect = GetNodeFullRowArea(node); if (rect.Contains(location)) { if (!node.ExpandArea.Contains(location)) { node.Expanded = !node.Expanded; } return; } if (node.Expanded) { foreach (var childNode in node.Nodes) { CheckNodeDoubleClick(childNode, location); } } }
public void ToggleNode(DarkTreeNode node) { if (_selectedNodes.Contains(node)) { _selectedNodes.Remove(node); // If we just removed both the anchor start AND end then reset them if (_anchoredNodeStart == node && _anchoredNodeEnd == node) { if (_selectedNodes.Count > 0) { _anchoredNodeStart = _selectedNodes[0]; _anchoredNodeEnd = _selectedNodes[0]; } else { _anchoredNodeStart = null; _anchoredNodeEnd = null; } } // If we just removed the anchor start then update it accordingly if (_anchoredNodeStart == node) { if (_anchoredNodeEnd.VisibleIndex < node.VisibleIndex) { _anchoredNodeStart = node.PrevVisibleNode; } else if (_anchoredNodeEnd.VisibleIndex > node.VisibleIndex) { _anchoredNodeStart = node.NextVisibleNode; } else { _anchoredNodeStart = _anchoredNodeEnd; } } // If we just removed the anchor end then update it accordingly if (_anchoredNodeEnd == node) { if (_anchoredNodeStart.VisibleIndex < node.VisibleIndex) { _anchoredNodeEnd = node.PrevVisibleNode; } else if (_anchoredNodeStart.VisibleIndex > node.VisibleIndex) { _anchoredNodeEnd = node.NextVisibleNode; } else { _anchoredNodeEnd = _anchoredNodeStart; } } } else { _selectedNodes.Add(node); _anchoredNodeStart = node; _anchoredNodeEnd = node; } Invalidate(); }
private void SelectAnchoredRange(DarkTreeNode node) { _anchoredNodeEnd = node; SelectNodes(_anchoredNodeStart, _anchoredNodeEnd); }
protected virtual bool ForceDropToParent(DarkTreeNode node) => false;
private void CheckNodeClick(DarkTreeNode node, Point location, MouseButtons button) { var rect = GetNodeFullRowArea(node); if (rect.Contains(location)) { if (node.ExpandArea.Contains(location)) { if (button == MouseButtons.Left) { node.Expanded = !node.Expanded; } } else { if (button == MouseButtons.Left) { if (MultiSelect && ModifierKeys == Keys.Shift) { SelectAnchoredRange(node); } else if (MultiSelect && ModifierKeys == Keys.Control) { ToggleNode(node); } else { if (!SelectedNodes.Contains(node)) { SelectNode(node); } _dragPos = OffsetMousePosition; _provisionalDragging = true; _provisionalNode = node; } return; } else if (button == MouseButtons.Right) { if (MultiSelect && ModifierKeys == Keys.Shift) { return; } if (MultiSelect && ModifierKeys == Keys.Control) { return; } if (!SelectedNodes.Contains(node)) { SelectNode(node); } return; } } } if (node.Expanded) { foreach (var childNode in node.Nodes) { CheckNodeClick(childNode, location, button); } } }
protected virtual void MoveNodes(List <DarkTreeNode> dragNodes, DarkTreeNode dropNode) { }
private void DrawNode(DarkTreeNode node, Graphics g) { var rect = GetNodeFullRowArea(node); // 1. Draw background var bgColor = node.Odd ? Colors.HeaderBackground : Colors.GreyBackground; if (SelectedNodes.Count > 0 && SelectedNodes.Contains(node)) { bgColor = Focused ? Colors.BlueSelection : Colors.GreySelection; } if (IsDragging && _dropNode == node) { bgColor = Focused ? Colors.BlueSelection : Colors.GreySelection; } using (var b = new SolidBrush(bgColor)) { g.FillRectangle(b, rect); } // 2. Draw plus/minus icon if (node.Nodes.Count > 0) { var pos = new Point(node.ExpandArea.Location.X - 1, node.ExpandArea.Location.Y - 1); var icon = _nodeOpen; if (node.Expanded && !node.ExpandAreaHot) { icon = _nodeOpen; } else if (node.Expanded && node.ExpandAreaHot && !SelectedNodes.Contains(node)) { icon = _nodeOpenHover; } else if (node.Expanded && node.ExpandAreaHot && SelectedNodes.Contains(node)) { icon = _nodeOpenHoverSelected; } else if (!node.Expanded && !node.ExpandAreaHot) { icon = _nodeClosed; } else if (!node.Expanded && node.ExpandAreaHot && !SelectedNodes.Contains(node)) { icon = _nodeClosedHover; } else if (!node.Expanded && node.ExpandAreaHot && SelectedNodes.Contains(node)) { icon = _nodeClosedHoverSelected; } g.DrawImageUnscaled(icon, pos); } // 3. Draw icon if (ShowIcons && node.Icon != null) { if (node.Expanded && node.ExpandedIcon != null) { g.DrawImageUnscaled(node.ExpandedIcon, node.IconArea.Location); } else { g.DrawImageUnscaled(node.Icon, node.IconArea.Location); } } // 4. Draw text using (var b = new SolidBrush(Colors.LightText)) { var stringFormat = new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center }; g.DrawString(node.Text, Font, b, node.TextArea, stringFormat); } // 5. Draw child nodes if (node.Expanded) { foreach (var childNode in node.Nodes) { DrawNode(childNode, g); } } }