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 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);
        }
Exemple #4
0
        private void CheckNodeDoubleClick(DarkTreeNode node, Point location)
        {
            var rect = GetNodeFullRowArea(node);

            if (node.ExpandArea.Contains(location))
            {
                return;
            }

            if (rect.Contains(location))
            {
                if (node.Nodes.Count > 0)
                {
                    node.Expanded = !node.Expanded;
                }
                else
                {
                    node.OnDoubleClicked();
                }
            }

            if (node.Expanded)
            {
                foreach (var childNode in node.Nodes ?? Enumerable.Empty <DarkTreeNode>())
                {
                    CheckNodeDoubleClick(childNode, location);
                }
            }
        }
Exemple #5
0
        /// <summary>
        /// Recursively paints only the nodes and child nodes within the viewport.
        /// </summary>
        private void DrawChildNodes(DarkTreeNode node, Graphics g)
        {
            if (node.Expanded)
            {
                foreach (var childNode in node.Nodes)
                {
                    if (childNode.Expanded)
                    {
                        DrawChildNodes(childNode, g);
                    }

                    bool isInTopView      = Viewport.Top <= childNode.FullArea.Y;
                    bool isWithin         = childNode.FullArea.Y < Viewport.Top + Viewport.Height;
                    bool isPastBottomView = childNode.FullArea.Y > Viewport.Top + Viewport.Height;

                    if (isInTopView && isWithin)
                    {
                        DrawNode(childNode, g);
                    }

                    if (isPastBottomView)
                    {
                        break;
                    }
                }
            }
        }
        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())
            {
                var 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 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 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);
            }
        }
        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 ExpandNodes(DarkTreeNode parent)
 {
     parent.EnsureVisible();
     foreach (var node in parent.Nodes)
     {
         ExpandNodes(node);
     }
 }
        private void SortChildNodes(DarkTreeNode node)
        {
            node.Nodes.Sort(TreeViewNodeSorter);

            foreach (var childNode in node.Nodes)
            {
                SortChildNodes(childNode);
            }
        }
Exemple #12
0
        void ResumeNodeEvents(DarkTreeNode child)
        {
            HookNodeEvents(child);

            foreach (var darkTreeNode in child.Nodes)
            {
                HookNodeEvents(darkTreeNode);
            }
        }
        public void SelectNode(DarkTreeNode node)
        {
            _selectedNodes.Clear();
            _selectedNodes.Add(node);

            _anchoredNodeStart = node;
            _anchoredNodeEnd   = node;

            Invalidate();
        }
        private void NodeMouseLeave(DarkTreeNode node)
        {
            node.ExpandAreaHot = false;

            foreach (var childNode in node.Nodes)
            {
                NodeMouseLeave(childNode);
            }

            Invalidate();
        }
        protected override void StopDrag()
        {
            _dragNodes = null;
            _dropNode  = null;

            Cursor = Cursors.Default;

            Invalidate();

            base.StopDrag();
        }
Exemple #16
0
        private void NodeMouseLeave(DarkTreeNode node)
        {
            node.ExpandAreaHot = false;

            foreach (var childNode in node.Nodes ?? Enumerable.Empty <DarkTreeNode>())
            {
                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);
            }
        }
Exemple #19
0
        public void HookNodeEvents(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)
            {
                HookNodeEvents(childNode);
            }
        }
        private bool CanMoveNodes(IEnumerable <DarkTreeNode> dragNodes, DarkTreeNode dropNode, bool isMoving = false)
        {
            if (dropNode == null)
            {
                return(false);
            }

            foreach (var node in dragNodes)
            {
                if (node == dropNode)
                {
                    if (isMoving)
                    {
                        DarkMessageBox.Show(this, $"Cannot move {node.Text}. The destination folder is the same as the source folder.,", Application.ProductName, MessageBoxIcon.Error);
                    }

                    return(false);
                }

                if (node.ParentNode != null && node.ParentNode == dropNode)
                {
                    if (isMoving)
                    {
                        DarkMessageBox.Show(this, $"Cannot move {node.Text}. The destination folder is the same as the source folder.", Application.ProductName, MessageBoxIcon.Error);
                    }

                    return(false);
                }

                var parentNode = dropNode.ParentNode;
                while (parentNode != null)
                {
                    if (node == parentNode)
                    {
                        if (isMoving)
                        {
                            DarkMessageBox.Show(this, $"Cannot move {node.Text}. The destination folder is a subfolder of the source folder.", Application.ProductName, MessageBoxIcon.Error);
                        }

                        return(false);
                    }

                    parentNode = parentNode.ParentNode;
                }
            }

            return(true);
        }
        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);
        }
Exemple #22
0
        public bool IsNodeAncestor(DarkTreeNode node)
        {
            var parent = ParentNode;

            while (parent != null)
            {
                if (parent == node)
                {
                    return(true);
                }

                parent = parent.ParentNode;
            }

            return(false);
        }
Exemple #23
0
        private void UnhookNodeEvents(DarkTreeNode node)
        {
            if (node.Nodes != null)
            {
                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 ?? Enumerable.Empty <DarkTreeNode>())
            {
                UnhookNodeEvents(childNode);
            }
        }
        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 && _dropNode != null)
                {
                    _dropNode = null;
                    Invalidate();
                }

                return;
            }

            foreach (var node in Nodes)
            {
                CheckNodeHover(node, OffsetMousePosition);
            }
        }
Exemple #26
0
        public DialogControls()
        {
            InitializeComponent();

            // Build dummy list data
            for (var i = 0; i < 100; i++)
            {
                var item = new DarkListItem($"List item #{i}");
                lstTest.Items.Add(item);
            }

            // Build dummy nodes
            var childCount = 0;
            for (var i = 0; i < 20; i++)
            {
                var node = new DarkTreeNode($"Root node #{i}");
                node.ExpandedIcon = Icons.folder_open;
                node.Icon = Icons.folder_closed;

                for (var x = 0; x < 10; x++)
                {
                    var childNode = new DarkTreeNode($"Child node #{childCount}");
                    childNode.Icon = Icons.files;
                    childCount++;
                    node.Nodes.Add(childNode);
                }

                treeTest.Nodes.Add(node);
            }

            // Hook dialog button events
            btnDialog.Click += delegate
            {
                DarkMessageBox.ShowError("This is an error", "Dark UI - Example");
            };

            btnMessageBox.Click += delegate
            {
                DarkMessageBox.ShowInformation("This is some information, except it is much bigger, so there we go. I wonder how this is going to go. I hope it resizes properly. It probably will.", "Dark UI - Example");
            };
        }
        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);
                }
            }
        }
Exemple #28
0
        public DockProject()
        {
            InitializeComponent();

            // Build dummy nodes
            var childCount = 0;
            for (var i = 0; i < 20; i++)
            {
                var node = new DarkTreeNode($"Root node #{i}");
                node.ExpandedIcon = Icons.folder_open;
                node.Icon = Icons.folder_closed;

                for (var x = 0; x < 10; x++)
                {
                    var childNode = new DarkTreeNode($"Child node #{childCount}");
                    childNode.Icon = Icons.files;
                    childCount++;
                    node.Nodes.Add(childNode);
                }

                treeProject.Nodes.Add(node);
            }
        }
        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);
                }
            }
        }
Exemple #30
0
        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;
        }
Exemple #31
0
 protected virtual void MoveNodes(List<DarkTreeNode> dragNodes, DarkTreeNode dropNode)
 { }
Exemple #32
0
 protected virtual bool ForceDropToParent(DarkTreeNode node)
 {
     return false;
 }
Exemple #33
0
        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);
            }
        }
Exemple #34
0
        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);
        }
Exemple #35
0
        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);
        }
Exemple #36
0
        public void SelectNode(DarkTreeNode node)
        {
            _selectedNodes.Clear();
            _selectedNodes.Add(node);

            _anchoredNodeStart = node;
            _anchoredNodeEnd = node;

            Invalidate();
        }
Exemple #37
0
        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();
        }
Exemple #38
0
 private void SelectAnchoredRange(DarkTreeNode node)
 {
     _anchoredNodeEnd = node;
     SelectNodes(_anchoredNodeStart, _anchoredNodeEnd);
 }
Exemple #39
0
        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();
        }
Exemple #40
0
        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);
            }
        }
Exemple #41
0
        public bool IsNodeAncestor(DarkTreeNode node)
        {
            var parent = ParentNode;
            while (parent != null)
            {
                if (parent == node)
                    return true;

                parent = parent.ParentNode;
            }

            return false;
        }
Exemple #42
0
        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);
        }
Exemple #43
0
        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);
            }
        }
Exemple #44
0
        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);
            }
        }
Exemple #45
0
        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);
        }
Exemple #46
0
        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;
        }
Exemple #47
0
        private void NodeMouseLeave(DarkTreeNode node)
        {
            node.ExpandAreaHot = false;

            foreach (var childNode in node.Nodes)
                NodeMouseLeave(childNode);

            Invalidate();
        }
        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);
                }
            }
        }
Exemple #49
0
        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);
        }
Exemple #50
0
        protected override void StopDrag()
        {
            _dragNodes = null;
            _dropNode = null;

            Cursor = Cursors.Default;

            Invalidate();

            base.StopDrag();
        }
Exemple #51
0
        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())
            {
                var 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);
        }
Exemple #52
0
        private void SortChildNodes(DarkTreeNode node)
        {
            node.Nodes.Sort(TreeViewNodeSorter);

            foreach (var childNode in node.Nodes)
                SortChildNodes(childNode);
        }
 private void SelectAnchoredRange(DarkTreeNode node)
 {
     _anchoredNodeEnd = node;
     SelectNodes(_anchoredNodeStart, _anchoredNodeEnd);
 }
        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();
        }
Exemple #55
0
        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;
        }