5,696,576 members and growing! (18,692 online)
Email Password   helpLost your password?
Desktop Development » Tree Controls » Custom Tree Controls License: The Code Project Open License (CPOL)

Tree circle draw control

By eng. Plamen Kovandjiev

This control draws circles include text and link them with a line
C# (C# 1.0, C# 2.0, C# 3.0, C#)

Posted: 3 Sep 2008
Updated: 3 Sep 2008
Views: 6,439
Bookmarked: 14 times
Announcements
Loading...



Search    
Advanced Search
Sitemap
9 votes for this Article.
Popularity: 3.40 Rating: 3.56 out of 5
1 vote, 11.1%
1
1 vote, 11.1%
2
2 votes, 22.2%
3
2 votes, 22.2%
4
3 votes, 33.3%
5
Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article
CircleTree

Introduction

This is a custom control which gives ability to easy draw circles and edges between them.
This control is very useful for drawing binary trees.

Using the code

The control is based on Panel class, which is derived and extended with methods for manipulation of circles and edges.
Every circle is placed in invisible grid. The step of the grid can be specified by property GridSize. The size of circles can be changed with property CircleSize. The origin of coordinate system can be changed by using property InvertGridYPosition, for an example the origin can be changed from upper left corner to lower right corner.
The other properties of the class can manipulate background color, border color, font of the text, color of the text in circles, color and with of the binding lines.

The methods are divided as follows:
Circle manipulation: Add - add new circle, caption Edit - ChangeText, delete circle - Remove, delete of all edges for current circle - RemoveAllLink, and delete of circle by its position - RemovePos. Check for existence of circle - Exist, searching by index - FindIndex.
Edge manipulation: add new edge - AddLink, change text of the link - ChangeTextLink, check for existing edge - ExistLink, searching of edge - FindLink and delete edge - RemoveLink.

Common methods:
BeginUpdate, EndUpdate - when is needed to be added many circles and edges at the same time without redraw all elements after every addition, the methods BeginUpdate which stops redraw and EndUpdate which restores redraw mode can be used. Clear - removes all circles and edges between them. Refresh - will redraw all elements.

Description of each circle is stored in structure CircleEntity, where are stored: coordinates, caption and List of all vertices which are direct linked to a given circle. All circles are stored in Generic List of type CircleEntity.

The most interesting method is a derived and rewritten method OnPaint:
        /// <summary>
        /// Override OnPaint and implement custom draw functionality
        /// First draw linked lines. Next add text in link lines.
        /// Second draw Circles.
        /// </summary>
        /// <param name="e">Paint arguments</param>
        protected override void OnPaint(PaintEventArgs e)
        {
            int x;
            int y;
            string s;
            float textX;
            float textY;
            SizeF sizeText;
            Graphics g = e.Graphics;
            Point pStart;
            Point pEnd;

            // First draw linked lines and draw text if exist
            for (int i = 0; i < _circles.Count; i++)
            {
                List<CircleLinkEntity> cl = _circles[i].Links;
                for (int j = 0; j < cl.Count; j++)
                {
                    // Calculate center grid coordinates position
                    pStart = CalculateGrigPosCenter(_circles[i].PosX, _circles[i].PosY);
                    pEnd = CalculateGrigPosCenter(cl[j].Link.PosX, cl[j].Link.PosY);
                    g.DrawLine(_linkedLinePen, pStart, pEnd);

                    s = cl[j].Text;
                    // if text empty not draw
                    if (String.IsNullOrEmpty(s))
                        continue;

                    // Calculate text position
                    sizeText = g.MeasureString(s, _circleFont);
                    textX = Math.Min(pStart.X, pEnd.X) + (Math.Abs(pStart.X - pEnd.X) / 2) - (sizeText.Width / 2);
                    textY = Math.Min(pStart.Y, pEnd.Y) + (Math.Abs(pStart.Y - pEnd.Y) / 2) - (sizeText.Height / 2);

                    // Draw background rectangle
                    g.FillRectangle(_circleFillSolidBrush, textX, textY, sizeText.Width, sizeText.Height);
                    // Draw outside rectangle
                    g.DrawRectangle(new Pen(_circleOutlineColor, 1), textX, textY, sizeText.Width, sizeText.Height);
                    // Draw text
                    e.Graphics.DrawString(s, _circleFont, _circleFontColorSolidBrush, textX, textY);
                }
            }

            Point p;

            // Draw Circles and add inside text
            for (int i = 0; i < _circles.Count; i++)
            {
                p = CalculateGrigPos(_circles[i].PosX, _circles[i].PosY);

                // Centred to grid coordinates
                x = p.X + _gridCoordinateCorrection;
                y = p.Y + _gridCoordinateCorrection;

                // Draw first fill circle for background
                g.FillEllipse(_circleFillSolidBrush, x, y, _circleSize, _circleSize);
                // Draw outside circle
                g.DrawEllipse(_circlePen, x, y, _circleSize, _circleSize);

                s = _circles[i].Text;

                // Calculate text Height and Width
                sizeText = g.MeasureString(s, _circleFont);

                // Calculate text position. Justify
                textX = p.X + _cellHalfSize - (sizeText.Width / 2);
                textY = p.Y + _cellHalfSize - (sizeText.Height / 2);

                g.DrawString(s, _circleFont, _circleFontColorSolidBrush, textX, textY);
                // Rectangle over text
                //g.DrawRectangle(new Pen(Color.Red, 1.0F), textX, textY, sizeText.Width, sizeText.Height);
            }

            base.OnPaint(e);
        }       

In first step are drawn all linking edges and their captions, and meanwhile all coordinates of grid are translated to real view coordinates.
On second step all circles and their captions are drawn.

When new vertices are added out of the viewable area, the control automatically will be resized and if needed will add scroll bars.

Points of Interest

This control can be used in studding of binary and other types of trees. We used it to display results of Huffman algorithm.

History

In first version we have made the base functionality, which contains only adding of circles and linking edges, and later we added editing, searching and deleting of elements. Also we have made ability to show captions on edges.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

eng. Plamen Kovandjiev



Occupation: Software Developer (Senior)
Company: Osceola EOOD
Location: Bulgaria Bulgaria

Other popular Tree Controls articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
  (Refresh) 
-- There are no messages in this forum --

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 3 Sep 2008
Editor:
Copyright 2008 by eng. Plamen Kovandjiev
Everything else Copyright © CodeProject, 1999-2008
Web11 | Advertise on the Code Project