Files
SteamWare/SteamWareLib/pieChart.cs
T
2018-03-17 09:47:02 +01:00

430 lines
14 KiB
C#

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
{
/// <summary>
/// tipo di chart (2D/3D)
/// </summary>
public enum ChartType
{
/// <summary>
/// 2D
/// </summary>
due_D = 0,
/// <summary>
/// 3D
/// </summary>
tre_D = 1
}
/// <summary>
/// web control che disegna un grafico a torta
/// </summary>
[DefaultProperty("Tipo")]
[ToolboxData("<{0}:pieChart runat=server></{0}:pieChart>")]
public class pieChart : WebControl
{
// Chart layout fields
private ChartType tipoPie = ChartType.due_D;
/// <summary>
/// tipo di grafico (2D/3D)
/// </summary>
[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;
}
}
/// <summary>
/// altezza di default
/// </summary>
protected int _height = 250;
/// <summary>
/// larghezza di default
/// </summary>
protected int _width = 250;
/// <summary>
/// padding di default
/// </summary>
protected int _padding = 3;
/// <summary>
/// legenda visibile di default
/// </summary>
protected bool _showLegend = true;
/// <summary>
/// soglia minima 5% per mostrare il dato
/// </summary>
protected float _minPercent = (float)0.05;
/// <summary>
/// ampiezza del grafico
/// </summary>
public int width
{
get
{
return _width;
}
set
{
_width = value;
}
}
/// <summary>
/// altezza del grafico
/// </summary>
public int height
{
get
{
return _height;
}
set
{
_height = value;
}
}
/// <summary>
/// padding grafico/container
/// </summary>
public int padding
{
get
{
return _padding;
}
set
{
_padding = value;
}
}
/// <summary>
/// boolean se si debba mostrale la legenda
/// </summary>
public bool showLegend
{
get
{
return _showLegend;
}
set
{
_showLegend = value;
}
}
/// <summary>
/// percentuale minima da mostrare
/// </summary>
public float minPercent
{
get
{
return _minPercent;
}
set
{
_minPercent = value;
}
}
/// <summary>
/// serie di dati (tipizzata) ma mostrare
/// </summary>
public DataLayer_generic.serieDatiDataTable serie
{
get
{
return (DataLayer_generic.serieDatiDataTable)HttpContext.Current.Session["serie"];
}
set
{
HttpContext.Current.Session["serie"] = value;
}
}
/// <summary>
/// testo associato al controllo
/// </summary>
[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;
}
}
/// <summary>
/// renderizza il contenuto
/// </summary>
/// <param name="output"></param>
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("<table><tr><td>");
// scrivo file da inglobare...
output.Write(string.Format("<img src=\"{0}\" />", _nomeFile));
// scrivo una tabella di legenda se richiesto...
if (_showLegend)
{
output.Write("</td><td align=\"left\">");
output.Write(drawLegend());
}
output.Write("</td></tr></table>");
// 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);
}
}
}
/// <summary>
/// disegna la leggenda html laterale...
/// </summary>
/// <returns></returns>
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}<br />", riga.valore / totale, riga.label, i);
i++;
parziale = parziale + riga.valore;
}
}
if (parziale < totale)
{
_answ += string.Format("{2}) {0:#%} {1}<br />", (totale - parziale) / totale, "altro", i);
}
}
catch
{ }
}
return _answ;
}
/// <summary>
/// disegna piechart 2-dim
/// </summary>
/// <param name="objGraphics"></param>
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
{ }
}
}
/// <summary>
/// disegna piechart 3d ellittica
/// </summary>
/// <param name="objGraphics"></param>
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);
}
}
/// <summary>
/// traduce la stringa colore in oggetto colore
/// </summary>
/// <param name="colore"></param>
/// <returns></returns>
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);
}
/// <summary>
/// converte intero a stringa esadecimale
/// </summary>
/// <param name="number"></param>
/// <returns></returns>
protected string IntToHex(int number)
{
return String.Format("{0:x}", number);
}
/// <summary>
/// converte stringa esadecimale a intero
/// </summary>
/// <param name="hexString"></param>
/// <returns></returns>
protected int HexToInt(string hexString)
{
return int.Parse(hexString,
System.Globalization.NumberStyles.HexNumber, null);
}
}
}