Csharp/C Sharp/Components/Chart

Материал из .Net Framework эксперт
Перейти к: навигация, поиск

Pie Chart Demo

/*
Code revised from chapter 13

GDI+ Custom Controls with Visual C# 2005
By Iulian Serban, Dragos Brezoi, Tiberiu Radu, Adam Ward 
Language English
Paperback 272 pages [191mm x 235mm]
Release date July 2006
ISBN 1904811604
Sample chapter
http://www.packtpub.ru/files/1604_CustomControls_SampleChapter.pdf

For More info on GDI+ Custom Control with Microsoft Visual C# book 
visit website www.packtpub.ru 

*/ 
using System;
using System.Collections.Generic;
using System.ruponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Collections;
using System.Drawing.Printing;
namespace PieChartApp
{
    public partial class Form1 : Form
    {
        Color tempSliceColor;
        string tempSliceName;
        int tempSliceSize;
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            pieChart1.AddSlice(new Slice("Mozzarella", 55, Color.FromArgb(255, 128, 128)));
            pieChart1.AddSlice(new Slice("Gorgonzola", 15, Color.FromArgb(128, 255, 128)));
            pieChart1.AddSlice(new Slice("Parmigiano", 25, Color.FromArgb(128, 128, 255)));
            pieChart1.AddSlice(new Slice("Ricotta", 25, Color.FromArgb(255, 128, 255)));
            // the first unnamed slice will be automatically named "Slice 0"
            pieChart1.AddSlice(new Slice("", 25, Color.FromArgb(255, 255, 128)));
            // the seconf unnamed slice will be automatically named "Slice 1"
            pieChart1.AddSlice(new Slice("", 25, Color.FromArgb(128, 255, 255)));
            // get the "Ricotta" slice
            Slice tempSlice = pieChart1.GetSlice("Ricotta");
            // if the slice exists i.e. has the name different form ""
            if (tempSlice.GetSliceName() != "")
                // and name it Ricotta cheese"
                tempSlice.SetSliceName("Ricotta cheese");
        }
        private void button1_Click(object sender, EventArgs e)
        {
            pieChart1.Print(false);
        }
        private void pieChart1_Load(object sender, EventArgs e)
        {
        }
        private void addSliceColorButton_Click(object sender, EventArgs e)
        {
            colorDialog1.ShowDialog();
            tempSliceColor = colorDialog1.Color;
            addSliceColorButton.BackColor = tempSliceColor;
        }
        private void addSliceButton_Click(object sender, EventArgs e)
        {
            if (addSliceNameTextBox.Text.ToString().Length <= 20)
            {
                tempSliceName = addSliceNameTextBox.Text;
            }
            else
            {
                MessageBox.Show("The entered name is not un up to 20 char string");
                return;
            }
            if (ParseNumber(addSliceSizeTextBox.Text))
            {
                if (addSliceSizeTextBox.Text != "")
                    tempSliceSize = Int32.Parse(addSliceSizeTextBox.Text.ToString());
                if (tempSliceSize == 0)
                    return;
            }
            else
            {
                MessageBox.Show("The entered size is not an up to 8 digit number!");
                return;
            }
            if (tempSliceColor.A == 0)
                tempSliceColor = Color.FromArgb(255, 255, 255, 255);
            pieChart1.AddSlice(new Slice(tempSliceName, tempSliceSize, tempSliceColor));
            pieChart1.Invalidate();
            // clean name, size and color
            addSliceNameTextBox.Text = "";
            addSliceSizeTextBox.Text = "";
            tempSliceName = "";
            tempSliceColor = Color.FromArgb(255, 255, 255);
            tempSliceSize = 0;
            colorDialog1.Color = Color.FromArgb(255, 255, 255, 255);
            addSliceColorButton.BackColor = Color.FromArgb(236, 233, 216);
        }
        private void removeSliceButton_Click(object sender, EventArgs e)
        {
            tempSliceName = removeSliceNameTextBox.Text;
            pieChart1.RemoveSlice(tempSliceName);
        }
        private bool ParseNumber(string userNumber)
        {
            //create our parser that will do all our work for us
            Regex parser = new Regex(@"^\d{0,8}$");
            //return the bool result of parser"s findings
            return parser.IsMatch(userNumber);
        }

        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ruponentModel.IContainer components = null;
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.addSliceButton = new System.Windows.Forms.Button();
            this.addSliceColorButton = new System.Windows.Forms.Button();
            this.label3 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.addSliceSizeTextBox = new System.Windows.Forms.TextBox();
            this.addSliceNameTextBox = new System.Windows.Forms.TextBox();
            this.label1 = new System.Windows.Forms.Label();
            this.groupBox2 = new System.Windows.Forms.GroupBox();
            this.removeSliceButton = new System.Windows.Forms.Button();
            this.removeSliceNameTextBox = new System.Windows.Forms.TextBox();
            this.label4 = new System.Windows.Forms.Label();
            this.colorDialog1 = new System.Windows.Forms.ColorDialog();
            this.pieChart1 = new PieChartApp.PieChart();
            this.groupBox1.SuspendLayout();
            this.groupBox2.SuspendLayout();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(294, 383);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 1;
            this.button1.Text = "Print";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // groupBox1
            // 
            this.groupBox1.Controls.Add(this.addSliceButton);
            this.groupBox1.Controls.Add(this.addSliceColorButton);
            this.groupBox1.Controls.Add(this.label3);
            this.groupBox1.Controls.Add(this.label2);
            this.groupBox1.Controls.Add(this.addSliceSizeTextBox);
            this.groupBox1.Controls.Add(this.addSliceNameTextBox);
            this.groupBox1.Controls.Add(this.label1);
            this.groupBox1.Location = new System.Drawing.Point(51, 398);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(200, 139);
            this.groupBox1.TabIndex = 2;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "Add Slice";
            // 
            // addSliceButton
            // 
            this.addSliceButton.Location = new System.Drawing.Point(52, 110);
            this.addSliceButton.Name = "addSliceButton";
            this.addSliceButton.Size = new System.Drawing.Size(75, 23);
            this.addSliceButton.TabIndex = 6;
            this.addSliceButton.Text = "Add Slice";
            this.addSliceButton.UseVisualStyleBackColor = true;
            this.addSliceButton.Click += new System.EventHandler(this.addSliceButton_Click);
            // 
            // addSliceColorButton
            // 
            this.addSliceColorButton.Location = new System.Drawing.Point(52, 73);
            this.addSliceColorButton.Name = "addSliceColorButton";
            this.addSliceColorButton.Size = new System.Drawing.Size(75, 23);
            this.addSliceColorButton.TabIndex = 5;
            this.addSliceColorButton.Text = "Set Color";
            this.addSliceColorButton.UseVisualStyleBackColor = true;
            this.addSliceColorButton.Click += new System.EventHandler(this.addSliceColorButton_Click);
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(7, 73);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(34, 13);
            this.label3.TabIndex = 4;
            this.label3.Text = "Color:";
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(7, 50);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(30, 13);
            this.label2.TabIndex = 3;
            this.label2.Text = "Size:";
            // 
            // addSliceSizeTextBox
            // 
            this.addSliceSizeTextBox.Location = new System.Drawing.Point(52, 47);
            this.addSliceSizeTextBox.Name = "addSliceSizeTextBox";
            this.addSliceSizeTextBox.Size = new System.Drawing.Size(100, 20);
            this.addSliceSizeTextBox.TabIndex = 2;
            // 
            // addSliceNameTextBox
            // 
            this.addSliceNameTextBox.Location = new System.Drawing.Point(52, 20);
            this.addSliceNameTextBox.Name = "addSliceNameTextBox";
            this.addSliceNameTextBox.Size = new System.Drawing.Size(100, 20);
            this.addSliceNameTextBox.TabIndex = 1;
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(7, 20);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(38, 13);
            this.label1.TabIndex = 0;
            this.label1.Text = "Name:";
            // 
            // groupBox2
            // 
            this.groupBox2.Controls.Add(this.removeSliceButton);
            this.groupBox2.Controls.Add(this.removeSliceNameTextBox);
            this.groupBox2.Controls.Add(this.label4);
            this.groupBox2.Location = new System.Drawing.Point(423, 398);
            this.groupBox2.Name = "groupBox2";
            this.groupBox2.Size = new System.Drawing.Size(200, 130);
            this.groupBox2.TabIndex = 3;
            this.groupBox2.TabStop = false;
            this.groupBox2.Text = "Remove Slice";
            // 
            // removeSliceButton
            // 
            this.removeSliceButton.Location = new System.Drawing.Point(32, 80);
            this.removeSliceButton.Name = "removeSliceButton";
            this.removeSliceButton.Size = new System.Drawing.Size(124, 23);
            this.removeSliceButton.TabIndex = 2;
            this.removeSliceButton.Text = "Remove Slice";
            this.removeSliceButton.UseVisualStyleBackColor = true;
            this.removeSliceButton.Click += new System.EventHandler(this.removeSliceButton_Click);
            // 
            // removeSliceNameTextBox
            // 
            this.removeSliceNameTextBox.Location = new System.Drawing.Point(50, 25);
            this.removeSliceNameTextBox.Name = "removeSliceNameTextBox";
            this.removeSliceNameTextBox.Size = new System.Drawing.Size(100, 20);
            this.removeSliceNameTextBox.TabIndex = 1;
            // 
            // label4
            // 
            this.label4.AutoSize = true;
            this.label4.Location = new System.Drawing.Point(6, 28);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(38, 13);
            this.label4.TabIndex = 0;
            this.label4.Text = "Name:";
            // 
            // pieChart1
            // 
            this.pieChart1.Location = new System.Drawing.Point(37, 25);
            this.pieChart1.Name = "pieChart1";
            this.pieChart1.SetArray = null;
            this.pieChart1.Size = new System.Drawing.Size(538, 352);
            this.pieChart1.TabIndex = 0;
            this.pieChart1.Load += new System.EventHandler(this.pieChart1_Load);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(673, 581);
            this.Controls.Add(this.groupBox2);
            this.Controls.Add(this.groupBox1);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.pieChart1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.groupBox1.ResumeLayout(false);
            this.groupBox1.PerformLayout();
            this.groupBox2.ResumeLayout(false);
            this.groupBox2.PerformLayout();
            this.ResumeLayout(false);
        }
        #endregion
        private PieChart pieChart1;
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.GroupBox groupBox1;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Button addSliceButton;
        private System.Windows.Forms.Button addSliceColorButton;
        private System.Windows.Forms.Label label3;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.TextBox addSliceSizeTextBox;
        private System.Windows.Forms.TextBox addSliceNameTextBox;
        private System.Windows.Forms.GroupBox groupBox2;
        private System.Windows.Forms.Button removeSliceButton;
        private System.Windows.Forms.TextBox removeSliceNameTextBox;
        private System.Windows.Forms.Label label4;
        private System.Windows.Forms.ColorDialog colorDialog1;

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
    
   public partial class PieChart : UserControl
    {
        int totalCount;
        ArrayList mySlices;
        PrintDocument pieChartPrintDoc = null;
        public PieChart()
        {
            InitializeComponent();
            pieChartPrintDoc = new PrintDocument();
            pieChartPrintDoc.PrintPage += new PrintPageEventHandler(_pieChartPrintDoc_PrintPage);
        }
        public ArrayList SetArray
        {
            get
            {
                return mySlices;
            }
            set
            {
                if (mySlices != value)
                    mySlices = value;
                Invalidate();
            }
        }
        private void SetValues()
        {
            totalCount = 0;
            if (mySlices != null)
            {
                foreach (Slice slice in mySlices)
                    totalCount += slice.GetSliceRange();
            }
            //mySlicesPercent.Clear();
        }
        public bool AddSlice(Slice slice)
        {
            bool isThisSlice = false;
            if (mySlices == null)
            {
                mySlices = new ArrayList();
                mySlices.Add(slice);
                return true;
            }
            foreach (Slice sliceTemp in mySlices)
            {
                if (sliceTemp.GetSliceName() == slice.GetSliceName())
                    isThisSlice = true;
            }
            if (isThisSlice == false)
            {
                mySlices.Add(slice);
                Invalidate();
                return true;
            }
            return false;
        }
        public bool RemoveSlice(string sliceName)
        {
            bool isThisSliceName = false;
            foreach (Slice sliceTemp in mySlices)
            {
                if (sliceName == sliceTemp.GetSliceName())
                {
                    mySlices.Remove(sliceTemp);
                    isThisSliceName = true;
                    break;
                }
            }
            if (isThisSliceName)
                Invalidate();
            return isThisSliceName;
        }
        private void PieChart_Paint(object sender, PaintEventArgs e)
        {
            {
                Pen penCircle = Pens.Black;
                Pen penLine = Pens.BlanchedAlmond;
                SetValues();
                e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                e.Graphics.DrawEllipse(penCircle, new Rectangle(1, 1, this.Width / 2 - 5, this.Width / 2 - 5));
                if (mySlices != null)
                {
                    int actualCount = 0;
                    // draw each slice
                    foreach (Slice slice in mySlices)
                    {
                        Pen penSlice = new Pen(slice.GetSliceColor());
                        int actualRangeSlice = slice.GetSliceRange();
                        int startAngle = (int)((actualCount / (double)totalCount) * 360);
                        int widthAngle = (int)(((actualRangeSlice) / (double)totalCount) * 360) + 1;
                        Brush br = new SolidBrush(slice.GetSliceColor());
                        e.Graphics.FillPie(br, new Rectangle(1, 1, this.Width / 2 - 5, this.Width / 2 - 5), startAngle, widthAngle);
                        e.Graphics.DrawPie(penCircle, new Rectangle(1, 1, this.Width / 2 - 5, this.Width / 2 - 5), startAngle, widthAngle);
                        actualCount += slice.GetSliceRange();
                    }
                    // draw the text within the legend
                    string itemName;
                    int itemFontSize = 64;
                    Font itemFont = new Font("SansSerif", itemFontSize);
                    StringFormat itemFormatName = new StringFormat(StringFormatFlags.NoClip);
                    itemFormatName.Alignment = StringAlignment.Near;
                    itemFormatName.LineAlignment = StringAlignment.Near;
                    int verticalPosition = 50;
                    // check if the text fits the legend
                    // if not -> modify the font
                    foreach (Slice slice in mySlices)
                    {
                        itemName = "  ";
                        itemName += slice.GetSliceName();
                        itemName += " - " + string.Format("{0:f}", (double)(slice.GetSliceRange() / (double)totalCount * 100)) + "%";
                        SizeF itemSize = e.Graphics.MeasureString(itemName, itemFont);
                        Point position = new Point(this.Width / 2 + 40, verticalPosition);
                        while ((e.Graphics.MeasureString(itemName, itemFont).Width > (this.Width / 2 - 40)))
                        {
                            if (itemFontSize > 4)
                                itemFont = new Font("SansSerif", itemFontSize--);
                            else
                                return;
                        }
                        while ((50 + mySlices.Count * (e.Graphics.MeasureString(itemName, itemFont).Height + 5)) > (this.Height))
                        {
                            if (itemFontSize > 4)
                                itemFont = new Font("SansSerif", itemFontSize--);
                            else
                                return;
                        }
                    }
                    verticalPosition = 50;
                    // draw the legend outline
                    Font legendTitleFont = new Font("SansSerif", itemFontSize + 5);
                    e.Graphics.DrawString("Legend", legendTitleFont, Brushes.Black, new Point(this.Width / 2 + 20, 10));
                    int legendHeight = (int)(e.Graphics.MeasureString("Legend", legendTitleFont).Height) * 2;
                    // draw items text and colored rectangle
                    foreach (Slice slice in mySlices)
                    {
                        itemName = "  ";
                        itemName += slice.GetSliceName();
                        itemName += " - " + string.Format("{0:f}", (double)(slice.GetSliceRange() / (double)totalCount * 100)) + "%";
                        SizeF itemSize = e.Graphics.MeasureString(itemName, itemFont);
                        Point position = new Point(this.Width / 2 + 40, verticalPosition);
                        e.Graphics.DrawRectangle(Pens.Black, new Rectangle(this.Width / 2 + 20, verticalPosition, 15, (int)itemSize.Height));
                        e.Graphics.FillRectangle(new SolidBrush(slice.GetSliceColor()), new Rectangle(this.Width / 2 + 20, verticalPosition, 15, (int)itemSize.Height));
                        e.Graphics.DrawString(itemName, itemFont, Brushes.Black, position, itemFormatName);
                        verticalPosition += (int)itemSize.Height + 5;
                    }
                    // draw the reactangle to include the legend
                    e.Graphics.DrawRectangle(Pens.Black, new Rectangle(this.Width / 2 + 5, 5, this.Width / 2 - 10, verticalPosition));
                    string stringName = "";
                    Font fontName = new Font("SansSerif", 8);
                    StringFormat formatName = new StringFormat(StringFormatFlags.NoClip);
                    formatName.Alignment = StringAlignment.Center;
                    formatName.LineAlignment = StringAlignment.Center;
                    Point pointName = new Point(this.Width / 8, 0);
                    double actualAngle = 0;
                    e.Graphics.TranslateTransform((float)(this.Width / 4.0), (float)(this.Width / 4.0));
                    // draw the text and percent for each slice
                    foreach (Slice slice in mySlices)
                    {
                        Pen penSlice = new Pen(slice.GetSliceColor());
                        double actualRangeSlice = slice.GetSliceRange();
                        double rotateAngle = ((((actualRangeSlice) / (double)totalCount) * 360)) / 2.0;
                        Brush br = new SolidBrush(Color.FromArgb(0, 0, 0));
                        e.Graphics.RotateTransform((float)(rotateAngle + actualAngle));
                        stringName = "";
                        stringName = string.Format("{0:f}", (double)(slice.GetSliceRange() / (double)totalCount * 100));
                        stringName += "% " + slice.GetSliceName();
                        if (e.Graphics.MeasureString(stringName, fontName).Width < (Width / 4))
                            e.Graphics.DrawString(stringName, fontName, br, pointName, formatName);
                        actualAngle = rotateAngle;
                    }
                }
                e.Graphics.Dispose();
            }
        }

        public Slice GetSlice(string sliceName)
        {
            foreach (Slice sliceTemp in mySlices)
            {
                if (sliceName == sliceTemp.GetSliceName())
                {
                    return sliceTemp;
                }
            }
            // if there is no slice by a given name this function
            // will return a null text, zero range, white slice
            return new Slice("", 0, Color.FromArgb(255, 255, 255));
        }
        public void Print(bool hardcopy)
        {
            //create a PrintDialog based on the PrintDocument
            PrintDialog pdlg = new PrintDialog();
            pdlg.Document = pieChartPrintDoc;
            //show the PrintDialog
            if (pdlg.ShowDialog() == DialogResult.OK)
            {
                //create a PageSetupDialog based on the PrintDocument and PrintDialog
                PageSetupDialog psd = new PageSetupDialog();
                psd.EnableMetric = true; //Ensure all dialog measurements are in metric
                psd.Document = pdlg.Document;
                psd.PageSettings.Landscape = true; //Ensure landscape view
                //show the PageSetupDialog
                if (psd.ShowDialog() == DialogResult.OK)
                {
                    //apply the settings of both dialogs
                    pieChartPrintDoc.DefaultPageSettings = psd.PageSettings;
                    //decide what action to take
                    if (hardcopy)
                    {
                        //actually print hardcopy
                        pieChartPrintDoc.Print();
                    }
                    else
                    {
                        //preview onscreen instead
                        PrintPreviewDialog prvw = new PrintPreviewDialog();
                        prvw.Document = pieChartPrintDoc;
                        prvw.ShowDialog();
                    }
                }
            }
        }
        private void _pieChartPrintDoc_PrintPage(object sender, PrintPageEventArgs e)
        {
            Pen penCircle = Pens.Black;
            Pen penLine = Pens.BlanchedAlmond;
            e.Graphics.Clip = new Region(e.MarginBounds);
            Single x = e.MarginBounds.Left;
            Single y = e.MarginBounds.Top;
            int leftMargin = (int)x;
            int topMargin = (int)y;
            RectangleF mainTextArea = RectangleF.FromLTRB(x, y, e.MarginBounds.Right, e.MarginBounds.Bottom);
            e.HasMorePages = false;
            if ((this.Height > mainTextArea.Height) || (this.Width > mainTextArea.Width))
            {
                MessageBox.Show("The control doesn"t fit in the page. Resize the control then try again printing");
                return;
            }
            Pen contourPen = new Pen(Color.FromArgb(0, 0, 0), 2);
            e.Graphics.DrawRectangle(contourPen, leftMargin, topMargin, this.Width, this.Height);
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            e.Graphics.DrawEllipse(penCircle, new Rectangle(leftMargin + 1, topMargin + 1, this.Width / 2 - 5, this.Width / 2 - 5));
            if (mySlices != null)
            {
                int actualCount = 0;
                // draw each slice
                foreach (Slice slice in mySlices)
                {
                    Pen penSlice = new Pen(slice.GetSliceColor());
                    int actualRangeSlice = slice.GetSliceRange();
                    int startAngle = (int)((actualCount / (double)totalCount) * 360);
                    int widthAngle = (int)(((actualRangeSlice) / (double)totalCount) * 360) + 1;
                    Brush br = new SolidBrush(slice.GetSliceColor());
                    e.Graphics.FillPie(br, new Rectangle(leftMargin + 1, topMargin + 1, this.Width / 2 - 5, this.Width / 2 - 5), startAngle, widthAngle);
                    e.Graphics.DrawPie(penCircle, new Rectangle(leftMargin + 1, topMargin + 1, this.Width / 2 - 5, this.Width / 2 - 5), startAngle, widthAngle);
                    actualCount += slice.GetSliceRange();
                }
                // draw the text within the legend
                string itemName;
                int itemFontSize = 64;
                Font itemFont = new Font("SansSerif", itemFontSize);
                StringFormat itemFormatName = new StringFormat(StringFormatFlags.NoClip);
                itemFormatName.Alignment = StringAlignment.Near;
                itemFormatName.LineAlignment = StringAlignment.Near;
                int verticalPosition = 50;
                // check if the text fits the legend
                // if not -> modify the font
                foreach (Slice slice in mySlices)
                {
                    itemName = "  ";
                    itemName += slice.GetSliceName();
                    itemName += " - " + string.Format("{0:f}", (double)(slice.GetSliceRange() / (double)totalCount * 100)) + "%";
                    SizeF itemSize = e.Graphics.MeasureString(itemName, itemFont);
                    Point position = new Point(this.Width / 2 + 40 + leftMargin, verticalPosition + topMargin);
                    while ((e.Graphics.MeasureString(itemName, itemFont).Width > (this.Width / 2 - 40)))
                    {
                        if (itemFontSize > 4)
                            itemFont = new Font("SansSerif", itemFontSize--);
                        else
                            return;
                    }
                    while ((50 + mySlices.Count * (e.Graphics.MeasureString(itemName, itemFont).Height + 5)) > (this.Height))
                    {
                        if (itemFontSize > 4)
                            itemFont = new Font("SansSerif", itemFontSize--);
                        else
                            return;
                    }
                }
                verticalPosition = 50;
                // draw the legend title
                Font legendTitleFont = new Font("SansSerif", itemFontSize + 5);
                e.Graphics.DrawString("Legend", legendTitleFont, Brushes.Black, new Point(leftMargin + this.Width / 2 + 20, topMargin + 10));
                int legendHeight = (int)(e.Graphics.MeasureString("Legend", legendTitleFont).Height) * 2 + topMargin;
                // draw items text and colored rectangle
                foreach (Slice slice in mySlices)
                {
                    itemName = "  ";
                    itemName += slice.GetSliceName();
                    itemName += " - " + string.Format("{0:f}", (double)(slice.GetSliceRange() / (double)totalCount * 100)) + "%";
                    SizeF itemSize = e.Graphics.MeasureString(itemName, itemFont);
                    Point position = new Point(leftMargin + this.Width / 2 + 40, topMargin + verticalPosition);
                    e.Graphics.DrawRectangle(Pens.Black, new Rectangle(leftMargin + this.Width / 2 + 20, topMargin + verticalPosition, 15, (int)itemSize.Height));
                    e.Graphics.FillRectangle(new SolidBrush(slice.GetSliceColor()), new Rectangle(leftMargin + this.Width / 2 + 20, topMargin + verticalPosition, 15, (int)itemSize.Height));
                    e.Graphics.DrawString(itemName, itemFont, Brushes.Black, position, itemFormatName);
                    verticalPosition += (int)itemSize.Height + 5;
                }
                // draw the legend outline
                e.Graphics.DrawRectangle(Pens.Black, new Rectangle(leftMargin + this.Width / 2 + 5, topMargin + 5, this.Width / 2 - 10, verticalPosition));
                string stringName = "";
                Font fontName = new Font("SansSerif", 8);
                StringFormat formatName = new StringFormat(StringFormatFlags.NoClip);
                formatName.Alignment = StringAlignment.Center;
                formatName.LineAlignment = StringAlignment.Center;
                Point pointName = new Point(this.Width / 8, 0);
                double actualAngle = 0;
                e.Graphics.TranslateTransform((float)(this.Width / 4.0 + leftMargin), (float)(this.Width / 4.0 + topMargin));
                // draw the text and percent for each slice
                foreach (Slice slice in mySlices)
                {
                    Pen penSlice = new Pen(slice.GetSliceColor());
                    double actualRangeSlice = slice.GetSliceRange();
                    double rotateAngle = ((((actualRangeSlice) / (double)totalCount) * 360)) / 2.0;
                    Brush br = new SolidBrush(Color.FromArgb(0, 0, 0));
                    e.Graphics.RotateTransform((float)(rotateAngle + actualAngle));
                    stringName = "";
                    stringName = string.Format("{0:f}", (double)(slice.GetSliceRange() / (double)totalCount * 100));
                    stringName += "% " + slice.GetSliceName();
                    if (e.Graphics.MeasureString(stringName, fontName).Width < (Width / 4))
                        e.Graphics.DrawString(stringName, fontName, br, pointName, formatName);
                    actualAngle = rotateAngle;
                }
            }
        }
        /// <summary> 
        /// Required designer variable.
        /// </summary>
        private System.ruponentModel.IContainer components = null;
        /// <summary> 
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
        #region Component Designer generated code
        /// <summary> 
        /// Required method for Designer support - do not modify 
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // PieChart
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.Name = "PieChart";
            this.Paint += new System.Windows.Forms.PaintEventHandler(this.PieChart_Paint);
            this.ResumeLayout(false);
        }
        #endregion

    }
public class Slice
    {
        private string sliceName;
        private int sliceRange;
        private Color sliceColor;
        // countNoName is static to know in all instances of the 
        // slice class what is this count
        private static int countNoName = 0;
        private Slice()
        {
        }
        public Slice(string name, int range, Color color)
        {
            if (name == "")
            {
                sliceName = "Slice " + countNoName.ToString();
                countNoName++;
            }
            else
                sliceName = name;
            if (range < 0)
                range = 0;
            else
                sliceRange = range;
            sliceColor = color;
        }
        public string GetSliceName()
        {
            return sliceName;
        }
        public int GetSliceRange()
        {
            return sliceRange;
        }
        public Color GetSliceColor()
        {
            return sliceColor;
        }
        public void SetSliceName(string name)
        {
            if (name == "")
            {
                sliceName = "Slice " + countNoName.ToString();
                countNoName++;
            }
            else
                sliceName = name;
        }
        public void SetSliceRange(int range)
        {
            if (range < 0)
                range = 0;
            else
                sliceRange = range;
        }
        public void SetSliceColor(Color color)
        {
            sliceColor = color;
        }

    }        
}