Click here to Skip to main content
15,886,799 members
Articles / Desktop Programming / Windows Forms

Making SVG Charts with Common Objects

Rate me:
Please Sign up or sign in to vote.
4.79/5 (15 votes)
22 Jun 2010CPOL4 min read 86.1K   3.4K   70  
This article explains how to create some interesting charts in SVG documents
//AUTHOR	: GERARD CASTELLÓ
//DATE		: 28/OCT/2009

using System;
using System.Text;
using System.Collections;
using System.Data;
using System.Drawing;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;
using SVGObjects;

namespace Charts
{
    public abstract class Chart
    {
        #region Attributes

        protected readonly int width;
        protected readonly int height;
        protected readonly int legendItems;
        protected Color[] colors;
        private System.Drawing.Rectangle legendArea;
        private System.Drawing.Rectangle chartArea;        
        public Document doc;

        #endregion

        #region Constants

        const short leftMargin = 10;
        const short rightMargin = 10;
        const short topMargin = 10;
        const short bottomMargin = 25;
        const short rectLegendWidth = 10;
        const short rectLegendHeight = 10;
        const short rectLegendSpace = 5;
        const short maxLengthLegendText = 15;
        protected const short weightChar = 8;

        #endregion

        #region Properties

        #region Legend Area

        public System.Drawing.Rectangle LegendArea
        {
            get
            {
                return this.legendArea;
            }
        }

        #endregion

        #region Chart Area

        public System.Drawing.Rectangle ChartArea
        {
            get
            {
                return this.chartArea;
            }
        }

        #endregion

        public Color[] Colors
        {
            get
            {
                return this.colors;
            }
        }

        public Document Doc
        {
            get
            {
                return this.doc;
            }
        }

        #endregion

        #region Constructor

        public Chart(int _width, int _height, int _legendItems)
        {
            this.width = _width;
            this.height = _height;
            this.legendItems = _legendItems;
            this.doc = new Document(this.width, this.height);
            this.CalcLegendArea();
            Random rnd;
            this.colors = new System.Drawing.Drawing2D.ColorBlend(this.legendItems).Colors;
            if (this.GetType() != typeof(LinealChart))
            {                
                for (int i = 0; i < this.colors.Length; i++)
                {
                    rnd = new Random(i);
                    this.colors[i] = System.Drawing.Color.FromArgb(rnd.Next(0, 255), rnd.Next(0, 255), rnd.Next(0, 255));
                }
            }
            this.CalcChartArea();
        }

        #endregion

        #region Methods

        #region Private Methods

        /// <summary>
        /// Calculate the Legend Area
        /// </summary>
        private void CalcLegendArea()
        {
            short rows = 0;
            int yStartPos = this.height - 20;
            if (this.GetType() != typeof(LinealChart))
            {
                rows = 1;
                if (((rectLegendHeight + rectLegendSpace) * this.legendItems) > (this.height - 40))
                    rows++;
            }

            this.legendArea = new System.Drawing.Rectangle(leftMargin, topMargin, ((maxLengthLegendText * weightChar / 2) + rectLegendWidth + rectLegendSpace) * rows, this.height - topMargin - bottomMargin);
        }

        /// <summary>
        /// Calculate the Chart Area
        /// </summary>
        private void CalcChartArea()
        {
            int xStartPos = (this.legendArea.X + this.legendArea.Width) + 10;
            int yStartPos = this.legendArea.Y;
            this.chartArea = new System.Drawing.Rectangle(xStartPos, yStartPos, (this.width - rightMargin - xStartPos), (this.height - topMargin - bottomMargin));
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Get a XmlDocument with the svg's transformed document.
        /// </summary>
        /// <param name="_data">DataTable</param>
        /// <param name="_colNames">string</param>
        /// <param name="_colValues">string</param>
        /// <returns>XmlDocument</returns>
        public virtual XmlDocument GenerateChart(DataTable _data, string _colNames, string _colValues)
        {            
            return (XmlDocument) this.doc.ToXml();
        }

        #endregion

        #region Protected Methods

        /// <summary>
        /// Creates the legend item for a value.
        /// </summary>
        /// <param name="text">string</param>
        /// <param name="indexColumn">int</param>
        /// <param name="indexRow">int</param>
        /// <param name="indexColor">int</param>
        protected virtual void GenerateLegendItem(string text, ref int indexColumn, ref int indexRow, int indexColor)
        {
            int x = 0;
            int y = 0;

            Text txt;
            if (this.LegendArea.Y + ((rectLegendSpace + rectLegendHeight) * indexRow) > (this.legendArea.Y + this.legendArea.Height))
            {
                indexColumn++;
                indexRow = 0;
            }

            x = this.legendArea.X + (indexColumn * ((maxLengthLegendText * (weightChar / 2)) + rectLegendSpace * 4));
            y = this.LegendArea.Y + ((rectLegendSpace + rectLegendHeight) * indexRow);

            SVGObjects.Rectangle rect = new SVGObjects.Rectangle(rectLegendWidth, rectLegendHeight);
            rect.X = x;
            rect.Y = y;
            rect.Color = this.colors[indexColor];
            this.doc.SvgObjects.Add(rect);

            text = text.ToLower();
            if (text.Length > 15)
                text = text.Substring(0, maxLengthLegendText);
            txt = new Text(text);
            txt.X = x + rectLegendWidth + rectLegendSpace;
            txt.Y = y + rectLegendHeight;
            txt.Font_Size = weightChar;
            this.doc.SvgObjects.Add(txt);                        
        }

        /// <summary>
        /// Parse de XmlDocument with the svg objects to a well formated SVG Document.
        /// </summary>
        /// <returns>XmlDocument</returns>
        protected XmlDocument Transform()
        {
            XmlDocument xmlResult = new XmlDocument();
            XslCompiledTransform xslt = new XslCompiledTransform();
            xslt.Load(AppDomain.CurrentDomain.BaseDirectory + @"\Charts.xslt");
            XPathNavigator nav = this.Doc.ToXml().CreateNavigator();
            StringBuilder sw = new StringBuilder();
            XmlWriter xr = XmlWriter.Create(sw, null);
            xslt.Transform(nav, xr);
            xmlResult.LoadXml(sw.ToString());
            return xmlResult;
        }

        #endregion

        #endregion

    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Software Developer (Senior)
Spain Spain
http://www.linkedin.com/in/gerard-castello-viader
https://github.com/gcastellov

Comments and Discussions