using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace SteamWare { /// /// tipo di chart (2D/3D) /// public enum ChartType { /// /// 2D /// due_D = 0, /// /// 3D /// tre_D = 1 } /// /// web control che disegna un grafico a torta /// [DefaultProperty("Tipo")] [ToolboxData("<{0}:pieChart runat=server>")] public class pieChart : WebControl { // Chart layout fields private ChartType tipoPie = ChartType.due_D; /// /// tipo di grafico (2D/3D) /// [DefaultValue(ChartType.due_D)] [Category("Pie Common")] [Description("Tipo di grafico a torta da creare (2d/3d)")] public ChartType Tipo { get { return tipoPie; } set { tipoPie = value; } } /// /// altezza di default /// protected int _height = 250; /// /// larghezza di default /// protected int _width = 250; /// /// padding di default /// protected int _padding = 3; /// /// legenda visibile di default /// protected bool _showLegend = true; /// /// soglia minima 5% per mostrare il dato /// protected float _minPercent = (float)0.05; /// /// ampiezza del grafico /// public int width { get { return _width; } set { _width = value; } } /// /// altezza del grafico /// public int height { get { return _height; } set { _height = value; } } /// /// padding grafico/container /// public int padding { get { return _padding; } set { _padding = value; } } /// /// boolean se si debba mostrale la legenda /// public bool showLegend { get { return _showLegend; } set { _showLegend = value; } } /// /// percentuale minima da mostrare /// public float minPercent { get { return _minPercent; } set { _minPercent = value; } } /// /// serie di dati (tipizzata) ma mostrare /// public DataLayer_generic.serieDatiDataTable serie { get { return (DataLayer_generic.serieDatiDataTable)HttpContext.Current.Session["serie"]; } set { HttpContext.Current.Session["serie"] = value; } } /// /// testo associato al controllo /// [Bindable(true)] [Category("Appearance")] [DefaultValue("")] [Localizable(true)] public string Text { get { String s = (String)ViewState["Text"]; return ((s == null) ? String.Empty : s); } set { ViewState["Text"] = value; } } /// /// renderizza il contenuto /// /// protected override void RenderContents(HtmlTextWriter output) { Bitmap objBitmap = new Bitmap(width, height); Graphics objGraphics = Graphics.FromImage(objBitmap); // Crea un background.. objGraphics.FillRectangle(new SolidBrush(Color.White), 0, 0, width, height); // disegna pieChart if (tipoPie == ChartType.tre_D) { Draw3DPieChart(ref objGraphics); } else { Draw2DPieChart(ref objGraphics); } // disegna legenda... // Salva image su file Random rand = new Random(); string _nomeFile = string.Format("./WebCharts/{0}_{1}.png", DateTime.Now.Ticks, rand.Next(99)); //objBitmap.Save(Page.Response.OutputStream, ImageFormat.Jpeg); objBitmap.Save(HttpContext.Current.Server.MapPath(_nomeFile), ImageFormat.Png); // clean up... objGraphics.Dispose(); objBitmap.Dispose(); // preparo div... output.Write("
"); // scrivo file da inglobare... output.Write(string.Format("", _nomeFile)); // scrivo una tabella di legenda se richiesto... if (_showLegend) { output.Write(""); output.Write(drawLegend()); } output.Write("
"); // pulisco cache files di ieri... fileMover fm = new fileMover("./WebCharts/", "./logs/"); foreach (DataLayer_generic.filesRow riga in fm.elencoFiles("png")) { if (riga.dataCreaz <= DateTime.Now.AddHours(-1)) { fm.eliminaFile(riga.Nome); } } } /// /// disegna la leggenda html laterale... /// /// protected string drawLegend() { string _answ = ""; int i = 1; double totale = 1; if (serie != null) { try { totale = Convert.ToDouble(serie.Compute(" SUM(valore)", "")); double parziale = 0; foreach (DataLayer_generic.serieDatiRow riga in serie) { if ((riga.valore / totale) > _minPercent) { _answ += string.Format("{2}) {0:#%} {1}
", riga.valore / totale, riga.label, i); i++; parziale = parziale + riga.valore; } } if (parziale < totale) { _answ += string.Format("{2}) {0:#%} {1}
", (totale - parziale) / totale, "altro", i); } } catch { } } return _answ; } /// /// disegna piechart 2-dim /// /// protected void Draw2DPieChart(ref Graphics objGraphics) { // calcolo il totale... double totale = 1; if (serie != null) { try { totale = Convert.ToDouble(serie.Compute(" SUM(valore)", "")); double parziale = 0; double angolo; float xt, yt, xl, yl, xc, yc; float radius; int i = 1; // oggetto plotting... SolidBrush objBrush = new SolidBrush(Color.Black); objGraphics.SmoothingMode = SmoothingMode.AntiAlias; SolidBrush _brush = new SolidBrush(Color.Black); Font _font = new Font("Verdana,Arial", 10); xc = (float)(width / 2) - _padding; yc = (float)(height / 2) - _padding; radius = (float)((width / 2) - _padding); Pen _penna = new Pen(Color.Black); foreach (DataLayer_generic.serieDatiRow riga in serie) { if ((riga.valore / totale) > _minPercent) { angolo = (riga.valore / totale) * 360; objBrush.Color = colorFromString(riga.colore); objGraphics.FillPie(objBrush, 0, 0, width - 2 * _padding, height - 2 * _padding, (float)parziale, (float)angolo); xl = (float)(xc + (Math.Cos((parziale) / 180 * (Math.PI)) * radius)); yl = (float)(yc + (Math.Sin((parziale) / 180 * (Math.PI)) * radius)); objGraphics.DrawLine(_penna, xc, yc, xl, yl); xt = (float)((float)(width / 2) - 2 * _padding + (Math.Cos((parziale + angolo / 2) / 180 * (Math.PI)) * (width / 3))); yt = (float)((float)(height / 2) - 2 * _padding + (Math.Sin((parziale + angolo / 2) / 180 * (Math.PI)) * (height / 3))); objGraphics.DrawString(i.ToString(), _font, _brush, xt, yt); i++; parziale = parziale + angolo; } if (parziale < 360) // indico "altro" { angolo = 360 - parziale; objBrush.Color = Color.White; objGraphics.FillPie(objBrush, 0, 0, width - 2 * _padding, height - 2 * _padding, (float)parziale, (float)angolo); xl = (float)(xc + (Math.Cos((parziale) / 180 * (Math.PI)) * radius)); yl = (float)(yc + (Math.Sin((parziale) / 180 * (Math.PI)) * radius)); objGraphics.DrawLine(_penna, xc, yc, xl, yl); xt = (float)((float)(width / 2) - 2 * _padding + (Math.Cos((parziale + angolo / 2) / 180 * (Math.PI)) * (width / 3))); yt = (float)((float)(height / 2) - 2 * _padding + (Math.Sin((parziale + angolo / 2) / 180 * (Math.PI)) * (height / 3))); objGraphics.DrawString(i.ToString(), _font, _brush, xt, yt); } objGraphics.DrawLine(_penna, xc, yc, xc + radius, yc); objGraphics.DrawEllipse(_penna, 0, 0, width - 2 * _padding, height - 2 * _padding); } } catch { } } } /// /// disegna piechart 3d ellittica /// /// protected void Draw3DPieChart(ref Graphics objGraphics) { int iLoop, iLoop2; // Create location and size of ellipse. int x = 50; int y = 20; //int width = 200; //int height = 100; // Create start and sweep angles. int startAngle = 0; int sweepAngle = 45; SolidBrush objBrush = new SolidBrush(Color.Aqua); Random rand = new Random(); objGraphics.SmoothingMode = SmoothingMode.HighQuality; //Loop through 180 back around to 135 degress so it gets drawn // correctly. for (iLoop = 0; iLoop <= 315; iLoop += 45) { startAngle = (iLoop + 180) % 360; objBrush.Color = Color.FromArgb(rand.Next(255), rand.Next(255), rand.Next(255)); // On degrees from 0 to 180 draw 10 Hatched brush slices to show // depth if ((startAngle < 135) || (startAngle == 180)) { for (iLoop2 = 0; iLoop2 < 10; iLoop2++) objGraphics.FillPie(new HatchBrush(HatchStyle.Percent50, objBrush.Color), x, y + iLoop2, width, height, startAngle, sweepAngle); } // Displace this pie slice from pie. if (startAngle == 135) { // Show Depth for (iLoop2 = 0; iLoop2 < 10; iLoop2++) objGraphics.FillPie(new HatchBrush(HatchStyle.Percent50, objBrush.Color), x - 30, y + iLoop2 + 15, width, height, startAngle, sweepAngle); objGraphics.FillPie(objBrush, x - 30, y + 15, width, height, startAngle, sweepAngle); } else // Draw normally objGraphics.FillPie(objBrush, x, y, width, height, startAngle, sweepAngle); } } /// /// traduce la stringa colore in oggetto colore /// /// /// protected Color colorFromString(string colore) { int r, g, b; r = 0; g = 0; b = 0; if ((colore.StartsWith("#")) && (colore.Length == 7)) { r = HexToInt(colore.Substring(1, 2)); g = HexToInt(colore.Substring(3, 2)); b = HexToInt(colore.Substring(5, 2)); } return Color.FromArgb(r, g, b); } /// /// converte intero a stringa esadecimale /// /// /// protected string IntToHex(int number) { return String.Format("{0:x}", number); } /// /// converte stringa esadecimale a intero /// /// /// protected int HexToInt(string hexString) { return int.Parse(hexString, System.Globalization.NumberStyles.HexNumber, null); } } }