Beispiel #1
0
 public RectangleF GetNodeBounds(TreeNodeEx node)
 {
     if (node.parent != null)
     {
         int nodeFromTop = -1;
         NodeEnumeratorEx nodes = new NodeEnumeratorEx(this.nodes);
         while (nodes.MoveNext())
         {
             if (nodes.currentNode == topNode)
             {
                 // We are at the top of the control.
                 nodeFromTop = 0;
             }
             if (nodes.currentNode == node)
             {
                 using (Graphics g = CreateGraphics())
                 {
                     return GetTextBounds(g, node, nodeFromTop, nodes.level);
                 }
             }
             if (nodeFromTop >= 0)
             {
                 nodeFromTop++;
             }
         }
     }
     return Rectangle.Empty;
 }
Beispiel #2
0
        // Render the treeview starting from startingLine
        internal void Draw(Graphics g, TreeNodeEx startNode)
        {
            if (updating > 0)
            {
                return;
            }

            Rectangle clientRectangle = ClientRectangle;
            int drawableHeight = clientRectangle.Height;
            int drawableWidth = clientRectangle.Width - xOffset;

            // We count the visible rows to see if we need the v scrollbar but we wait before deciding if we need the h scroll bar.
            bool needsHScrollBar = false;
            bool needsVScrollBar = GetNeedVScrollBar() && scrollable;
            bool createNewVScrollBar = false;
            bool createNewHScrollBar = false;

            if (needsVScrollBar)
            {
                // Don't allow drawing on the area that is going to be the scroll bar.
                // Create the scroll bar so we can get its width.
                if (vScrollBar == null)
                {
                    vScrollBar = new Forms.VScrollBar();
                    createNewVScrollBar = true;
                }
                drawableWidth -= vScrollBar.Width;
                Rectangle rect = new Rectangle(drawableWidth + xOffset, 0, vScrollBar.Width, clientRectangle.Height);
                g.ExcludeClip(rect);
            }
            else
            {
                // Check to see if the top node is not the first node and we have room for the whole tree.
                // If so, abandon the draw and redraw the whole tree from the top.
                if (topNode != null && topNode != this.nodes[0])
                {
                    topNode = null;
                    Invalidate();
                    return;
                }
                if (vScrollBar != null)
                {
                    // We don't need the scroll bar anymore.
                    Controls.Remove(vScrollBar);
                    vScrollBar.Dispose();
                    vScrollBar = null;
                }
            }
            // Is the node being processed on the screen.
            bool drawing = false;
            // Start counting from the top.
            int nodeFromTop = -1;
            // Number of nodes.
            int nodeCount = 0;
            int topNodePosition = 0;
            // The maximum width of a displayed node.
            float maxWidth = 0;
            //StringFormat format = new StringFormat(StringFormatFlags.NoWrap);
            if (topNode == null && this.nodes.Count > 0)
            {
                topNode = this.nodes[0];
            }
            RectangleF textBounds = Rectangle.Empty;

            NodeEnumeratorEx nodes = new NodeEnumeratorEx(this.nodes);
            using (Pen markerPen = new Pen(SystemColors.ControlDarkDark))
            {
                markerPen.DashStyle = DashStyle.Dot;
                while (nodes.MoveNext())
                {
                    // If we havnt started drawing yet, then see if we need to and if so clear the background.
                    if (!drawing)
                    {
                        if (nodes.currentNode  == topNode)
                        {
                            // We are at the top node.
                            nodeFromTop = 0;
                            topNodePosition = nodeCount;
                        }

                        // Check to see if we must start drawing. Clear the background.
                        if (nodeFromTop >= 0 && (nodes.currentNode == startNode || startNode == root))
                        {
                            // Clear background.
                            int y = ItemHeight * nodeFromTop;
                            using (SolidBrush b = new SolidBrush(BackColor))
                            {
                                g.FillRectangle(b, 0, y, ClientSize.Width, ClientSize.Height - y);
                            }
                            drawing = true;
                        }
                    }

                    // Even if we arnt drawing nodes yet, we need to measure if the nodes are visible, for hscrollbar purposes.
                    if (nodeFromTop >= 0 && drawableHeight > 0)
                    {
                        textBounds = GetTextBounds(g, nodes.currentNode, nodeFromTop, nodes.level);
                        // Is the text too wide to fit in - if so we need an h scroll bar.
                        if (textBounds.Right > drawableWidth && !needsHScrollBar && scrollable)
                        {
                            needsHScrollBar = true;
                            if (hScrollBar == null)
                            {
                                hScrollBar = new Forms.HScrollBar();
                                createNewHScrollBar = true;
                            }
                            drawableHeight -= hScrollBar.Height;
                            // Don't allow drawing on the area that is going to be the scroll bar.
                            Rectangle rect = new Rectangle(0, clientRectangle.Height - hScrollBar.Height, clientRectangle.Width, hScrollBar.Height);
                            g.ExcludeClip(rect);
                        }
                        if (textBounds.Right > maxWidth)
                        {
                            maxWidth = textBounds.Right;
                        }

                    }

                    // Draw the node if we still have space.
                    if (drawing && drawableHeight > 0)
                    {
                        RectangleF bounds;
                        // Draw the lines and the expander.
                        DrawExpanderMarker(g, markerPen, nodes.currentNode, nodeFromTop, nodes.level);

                        // Draw checkboxes.
                        if (checkBoxes)
                        {
                            bounds = GetCheckBounds(nodeFromTop, nodes.level);
                            Forms.ButtonState state;
                            if (nodes.currentNode.isChecked)
                            {
                                state = Forms.ButtonState.Checked;
                            }
                            else
                            {
                                state = Forms.ButtonState.Normal;
                            }
                            Forms.ControlPaint.DrawCheckBox(g, RectIFromRectF(bounds), state);
                        }

                        // Draw the node image.
                        if (imageList != null)
                        {
                            bounds = GetImageBounds(nodeFromTop, nodes.level);
                            int index = GetDisplayIndex(nodes.currentNode);

                            if (index < imageList.Images.Count && index >= 0)
                            {
                                Image image = imageList.Images[index];
                                g.DrawImage(image, bounds.X, bounds.Y);
                            }
                        }

                        bounds = textBounds;
                        // The height may be too small now.
                        // If we are currently editing a node then dont draw it.
                        if (drawableHeight > 0 && nodes.currentNode != editNode)
                        {
                            // Draw the node text.
                            var bnds = RectIFromRectF(bounds);

                            if (selectedDropNode == nodes.currentNode)
                            {
                                if (dragMoveDirection == DragMoveDirection.Above)
                                    g.DrawLine(Pens.Black, new PointF(bnds.X, bnds.Y), new PointF(bnds.X + bnds.Width, bnds.Y));
                                else if (dragMoveDirection == DragMoveDirection.Below)
                                    g.DrawLine(Pens.Black, new PointF(bnds.X, bnds.Y + bnds.Height), new PointF(bnds.X + bnds.Width, bnds.Y + bnds.Height));
                                else
                                    g.FillRectangle(SystemBrushes.Highlight, bnds);
                            }

                            if ((selectedDropNode == nodes.currentNode && dragMoveDirection == DragMoveDirection.On) ||
                                (((nodeToBeDropped == null && nodes.currentNode == selectedNode)
                                || (nodes.currentNode == nodeToBeDropped))
                                && (Focused || !hideSelection)))
                            {
                                // TODO: FullRowSelect
                                g.FillRectangle(SystemBrushes.Highlight, bnds);
                                Forms.TextRenderer.DrawText(g, nodes.currentNode.Text, Font, bnds, SystemColors.HighlightText, Forms.TextFormatFlags.NoClipping);
                                // Draw the focus rectangle.
                                Rectangle r = new Rectangle((int)(bounds.X), (int)(bounds.Y), (int)(bounds.Width), (int)(bounds.Height));
                                Forms.ControlPaint.DrawFocusRectangle(g, r);
                            }
                            else
                            {
                                Forms.TextRenderer.DrawText(g, nodes.currentNode.Text, Font, bnds, SystemColors.ControlText, Forms.TextFormatFlags.NoClipping);
                            }
                        }
                        drawableHeight -= ItemHeight;
                    }

                    if (nodeFromTop >= 0)
                    {
                        nodeFromTop++;
                    }
                    nodeCount++;
                }
            }
            // If we need a v scroll bar, then set it up.
            if (needsVScrollBar)
            {
                SetupVScrollBar(nodeCount, needsHScrollBar, createNewVScrollBar, topNodePosition);
            }
            if (needsHScrollBar)
            {
                SetupHScrollBar(needsVScrollBar, (int)maxWidth, createNewHScrollBar, g);
            }
            else if (hScrollBar != null)
            {
                // We dont need the scroll bar.
                // If we have scrolled then we need to reset the position.
                if (xOffset != 0)
                {
                    xOffset = 0;
                    Invalidate();
                }
                Controls.Remove(hScrollBar);
                hScrollBar.Dispose();
                hScrollBar = null;
            }
        }
Beispiel #3
0
 private void vScrollBar_ValueChanged(object sender, EventArgs e)
 {
     int nodeFromTop = 0;
     NodeEnumeratorEx nodes = new NodeEnumeratorEx(this.nodes);
     while (nodes.MoveNext())
     {
         if (nodeFromTop == vScrollBar.Value)
         {
             topNode = nodes.currentNode;
             Invalidate();
             return;
         }
         nodeFromTop++;
     }
 }
Beispiel #4
0
 public TreeNodeEx GetNodeAt(int x, int y)
 {
     int height = ItemHeight;
     int nodeFromTop = -1;
     NodeEnumeratorEx nodes = new NodeEnumeratorEx(this.nodes);
     while (nodes.MoveNext())
     {
         if (nodes.currentNode == topNode)
         {
             // We are now at the top of the control.
             nodeFromTop = 1;
         }
         if (nodeFromTop > -1)
         {
             if (y < height * nodeFromTop)
             {
                 return nodes.currentNode;
             }
             nodeFromTop++;
         }
     }
     return null;
 }
Beispiel #5
0
        void ProcessClick(int x, int y, bool rightMouse)
        {
            int nodeFromTop = -1;
            int height = ItemHeight;
            using (Graphics g = CreateGraphics())
            {
                // Iterate through all the nodes, looking for the bounds that match.
                NodeEnumeratorEx nodes = new NodeEnumeratorEx(this.nodes);
                while (nodes.MoveNext())
                {
                    if (nodes.currentNode == topNode)
                    {
                        // We are now at the top of the control.
                        nodeFromTop = 0;
                    }
                    if (nodeFromTop > -1)
                    {
                        // Check if the y matches this node.
                        if (y < height * (nodeFromTop + 1))
                        {
                            bool allowEdit = false;
                            bool allowSelect = true;
                            // Clicking the image can be used to select.
                            if (imageList == null || !GetImageBounds(nodeFromTop, nodes.level).Contains(x, y))
                            {
                                // Clicking the text can be used to edit and select.
                                // if false then the hierarchy marker must have been clicked.
                                if (GetTextBounds(g, nodes.currentNode, nodeFromTop, nodes.level).Contains(x, y))
                                {
                                    allowEdit = true;
                                }
                                else
                                {
                                    allowSelect = false;
                                }
                            }
                            if (SelectedNode == nodes.Current && mouseClickTimer != null && mouseClickTimer.Enabled && (allowEdit || allowSelect))
                            {
                                mouseClickTimer.Stop();
                                nodeToEdit = null;
                                nodes.currentNode.Toggle();
                                return;
                            }
                            if (allowSelect || rightMouse)
                            {
                                if (selectedNode == nodes.Current)
                                {
                                    if (labelEdit && allowEdit && !rightMouse)
                                    {
                                        if (selectedNode.CanRename())
                                            nodeToEdit = nodes.currentNode;
                                    }
                                    Focus();
                                }
                                else
                                {
                                    nodeToEdit = null;
                                    // Do the events.
                                    TreeViewExCancelEventArgs eventArgs = new TreeViewExCancelEventArgs(nodes.currentNode, false, TreeViewExAction.ByMouse);
                                    OnBeforeSelect(eventArgs);
                                    if (!eventArgs.Cancel)
                                    {
                                        SelectedNode = nodes.currentNode;
                                        Focus();
                                    }
                                }
                                if (rightMouse)
                                {
                                    return;
                                }
                                if (mouseClickTimer == null)
                                {
                                    mouseClickTimer = new Forms.Timer();
                                    mouseClickTimer.Tick +=new EventHandler(mouseClickTimer_Tick);
                                    mouseClickTimer.Interval = mouseEditTimeout;
                                }

                                mouseClickTimer.Start();
                                break;
                            }
                        }
                        nodeFromTop++;
                    }
                }
            }
        }
Beispiel #6
0
 // Returns true if we dont have vertical space to draw all the items.
 private bool GetNeedVScrollBar()
 {
     int fullNodes = VisibleCount;
     NodeEnumeratorEx nodes = new NodeEnumeratorEx(Nodes);
     while (nodes.MoveNext())
     {
         if (--fullNodes == 0)
         {
             return true;
         }
     }
     return false;
 }
Beispiel #7
0
        protected override bool ProcessDialogKey(Forms.Keys keyData)
        {
            if ((keyData & Forms.Keys.Alt) == 0)
            {
                Forms.Keys key = keyData & Forms.Keys.KeyCode;
                bool shiftKey = (keyData & Forms.Keys.Shift) != 0;
                bool controlKey = (keyData & Forms.Keys.Control) != 0;
                TreeNodeEx selectedNode = SelectedNode;

                switch (key)
                {
                case Forms.Keys.Left:
                    if (selectedNode != null)
                    {
                        if (selectedNode.IsExpanded)
                        {
                            selectedNode.Collapse();
                        }
                        else if (selectedNode.Parent != null)
                        {
                            SelectedNode = selectedNode.Parent;
                        }
                    }
                    return true;
                case Forms.Keys.Right:
                    if (selectedNode != null && selectedNode.Nodes.Count != 0)
                    {
                        if (selectedNode.IsExpanded)
                        {
                            SelectedNode = selectedNode.NextVisibleNode;
                        }
                        else
                        {
                            selectedNode.Expand();
                        }
                    }
                    return true;
                case Forms.Keys.Up:
                    if (selectedNode != null)
                    {
                        selectedNode = selectedNode.PrevVisibleNode;
                        if (selectedNode != null)
                        {
                            SelectedNode = selectedNode;
                        }
                    }
                    return true;
                case Forms.Keys.Down:
                    if (selectedNode != null)
                    {
                        selectedNode = selectedNode.NextVisibleNode;
                        if (selectedNode != null)
                        {
                            SelectedNode = selectedNode;
                        }
                    }
                    return true;
                case Forms.Keys.Home:
                    if (Nodes[0] != null)
                    {
                        SelectedNode = Nodes[0];
                    }
                    return true;
                case Forms.Keys.End:
                    {
                        NodeEnumeratorEx nodes = new NodeEnumeratorEx(this.nodes);
                        while (nodes.MoveNext())
                        {
                        }
                        SelectedNode = nodes.currentNode;
                        return true;
                    }
                case Forms.Keys.Prior:
                    {
                        int nodePosition = 0;
                        // Get the position of the current selected node.
                        NodeEnumeratorEx nodes = new NodeEnumeratorEx(this.nodes);
                        while (nodes.MoveNext())
                        {
                            if (nodes.currentNode == selectedNode)
                            {
                                break;
                            }
                            nodePosition++;
                        }

                        nodePosition -= VisibleCountActual - 1;
                        if (nodePosition < 0)
                        {
                            nodePosition = 0;
                        }

                        // Get the node that corresponds to the position.
                        nodes.Reset();
                        while (nodes.MoveNext())
                        {
                            if (nodePosition-- == 0)
                            {
                                break;
                            }
                        }

                        // Set the selectedNode.
                        SelectedNode = nodes.currentNode;

                    }
                    return true;
                case Forms.Keys.Next:
                    {
                        int rows = 0;
                        int rowsPerPage = VisibleCountActual;
                        NodeEnumeratorEx nodes = new NodeEnumeratorEx(this.nodes);
                        while (nodes.MoveNext())
                        {
                            if (nodes.currentNode == selectedNode || rows > 0)
                            {
                                rows++;
                                if (rows >= rowsPerPage)
                                {
                                    break;
                                }
                            }
                        }
                        SelectedNode = nodes.currentNode;

                        return true;
                    }
                }

            }
            return base.ProcessDialogKey(keyData);
        }
Beispiel #8
0
        // Non Microsoft member.
        protected override void OnMouseDown(Forms.MouseEventArgs e)
        {
            nodeToEdit = null;
            if (e.Button == Forms.MouseButtons.Left)
            {
                int nodeFromTop = -1;
                // Iterate through all the nodes, looking for the bounds that match.
                NodeEnumeratorEx nodes = new NodeEnumeratorEx(this.nodes);
                bool _clicked = false;

                while (nodes.MoveNext())
                {
                    if (nodes.currentNode == topNode)
                    {
                        // We are now at the top of the control.
                        nodeFromTop = 0;
                    }
                    if (nodeFromTop > -1)
                    {
                        if (GetExpanderBounds(nodeFromTop, nodes.level).Contains(e.X, e.Y))
                        {
                            nodes.currentNode.Toggle();
                            _clicked = true;
                            break;
                        }
                        else if (GetCheckBounds(nodeFromTop, nodes.level).Contains(e.X, e.Y))
                        {
                            TreeViewExCancelEventArgs args = new TreeViewExCancelEventArgs(nodes.currentNode, false, TreeViewExAction.ByMouse);
                            OnBeforeCheck(args);
                            if (!args.Cancel)
                            {
                                nodes.currentNode.isChecked = !nodes.currentNode.isChecked;
                                OnAfterCheck(new TreeViewExEventArgs(nodes.currentNode, TreeViewExAction.ByMouse));
                            }

                            Invalidate(GetCheckBounds(nodeFromTop, nodes.level));
                            _clicked = true;
                            break;

                        }
                        nodeFromTop++;
                    }
                }

                if (!_clicked)
                {
                    var pt = new Point(e.X, e.Y);
                    var node = GetNodeAt(e.X, e.Y);

                    if (node != null && node.Bounds.Contains(pt))
                    {
                        Focus();
                        nodeToBeDropped = node;

                        if (selectedNode != null)
                            selectedNode.Invalidate();
                        nodeToBeDropped.Invalidate();
                    }
                }
            }
            else
            {
                ProcessClick(e.X, e.Y, true);
            }
            base.OnMouseDown(e);
        }
Beispiel #9
0
        // Invalidate from startNode down.
        internal void InvalidateDown(TreeNodeEx startNode)
        {
            if (updating > 0 || this.nodes == null)
            {
                return;
            }

            // Find the position of startNode relative to the top node.
            int nodeFromTop = -1;
            NodeEnumeratorEx nodes = new NodeEnumeratorEx(this.nodes);
            while (nodes.MoveNext())
            {
                if (nodes.currentNode == topNode)
                {
                    // We are at the top of the control.
                    nodeFromTop = 0;
                }
                if (nodes.currentNode == startNode)
                {
                    break;
                }
                if (nodeFromTop >= 0)
                {
                    nodeFromTop++;
                }
            }
            // Calculate the y position of startNode.
            int y = nodeFromTop * ItemHeight;
            // Invalidate from this position down.
            // Start one pixel higher to cover the focus rectangle.
            Invalidate(new Rectangle(0, y - 1, ClientRectangle.Width, ClientRectangle.Height - y + 1));
        }