Example #1
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);
            }
        }
Example #2
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);
                }
            }
        }
Example #3
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);
            }
        }
Example #4
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);
        }
Example #5
0
        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();
        }
Example #6
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);
        }
Example #7
0
        private static 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)
                {
                    continue;
                }

                var compNode = FindNode(node, path);
                if (compNode != null)
                {
                    return(compNode);
                }
            }

            return(null);
        }
Example #8
0
        private void SortChildNodes(DarkTreeNode node)
        {
            node.Nodes.Sort(TreeViewNodeSorter);

            foreach (var childNode in node.Nodes)
            {
                SortChildNodes(childNode);
            }
        }
Example #9
0
        public void SelectNode(DarkTreeNode node)
        {
            SelectedNodes.Clear();
            SelectedNodes.Add(node);

            _anchoredNodeStart = node;
            _anchoredNodeEnd   = node;

            Invalidate();
        }
Example #10
0
        private void NodeMouseLeave(DarkTreeNode node)
        {
            node.ExpandAreaHot = false;

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

            Invalidate();
        }
Example #11
0
        protected override void StopDrag()
        {
            _dragNodes = null;
            _dropNode  = null;

            Cursor = Cursors.Default;

            Invalidate();

            base.StopDrag();
        }
Example #12
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);
        }
Example #13
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);
            }
        }
Example #14
0
        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);
        }
Example #15
0
        public bool IsNodeAncestor(DarkTreeNode node)
        {
            var parent = ParentNode;

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

                parent = parent.ParentNode;
            }

            return(false);
        }
Example #16
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();
        }
Example #17
0
        private void CheckHover()
        {
            if (!ClientRectangle.Contains(PointToClient(MousePosition)))
            {
                if (IsDragging && _dropNode != null)
                {
                    _dropNode = null;
                    Invalidate();
                }

                return;
            }

            foreach (var node in Nodes)
            {
                CheckNodeHover(node, OffsetMousePosition);
            }
        }
Example #18
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);
                }
            }
        }
Example #19
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)
                {
                    Debug.Assert(_anchoredNodeEnd != null, nameof(_anchoredNodeEnd) + " != null");
                    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)
                {
                    Debug.Assert(_anchoredNodeStart != null, nameof(_anchoredNodeStart) + " != null");
                    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();
        }
Example #20
0
 private void SelectAnchoredRange(DarkTreeNode node)
 {
     _anchoredNodeEnd = node;
     SelectNodes(_anchoredNodeStart, _anchoredNodeEnd);
 }
Example #21
0
        private void DrawNode(DarkTreeNode node, Graphics g)
        {
            var rect = GetNodeFullRowArea(node);

            // 1. Draw background
            var bgColor = node.Odd ? Colours.HeaderBackground : Colours.GreyBackground;

            if (SelectedNodes.Count > 0 && SelectedNodes.Contains(node))
            {
                bgColor = Focused ? Colours.BlueSelection : Colours.GreySelection;
            }

            if (IsDragging && _dropNode == node)
            {
                bgColor = Focused ? Colours.BlueSelection : Colours.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.DrawImage(icon, pos);
            }

            // 3. Draw icon
            if (ShowIcons && node.Icon != null)
            {
                if (node.Expanded && node.ExpandedIcon != null)
                {
                    g.DrawImage(node.ExpandedIcon, node.IconArea.Location);
                }
                else
                {
                    g.DrawImage(node.Icon, node.IconArea.Location);
                }
            }

            // 4. Draw text
            using (var b = new SolidBrush(Colours.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);
                }
            }
        }
Example #22
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
                {
                    switch (button)
                    {
                    case 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;

                    case 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);
                }
            }
        }