430 lines
14 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|