252 lines
No EOL
7.7 KiB
C#
252 lines
No EOL
7.7 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Drawing;
|
|
using System.Drawing.Imaging;
|
|
using System.Drawing.Drawing2D;
|
|
|
|
namespace Server.Engines.Reports
|
|
{
|
|
// Modified from MS sample
|
|
|
|
//*********************************************************************
|
|
//
|
|
// PieChart Class
|
|
//
|
|
// This class uses GDI+ to render Pie Chart.
|
|
//
|
|
//*********************************************************************
|
|
|
|
public class PieChartRenderer : ChartRenderer
|
|
{
|
|
private const int _bufferSpace = 125;
|
|
private ArrayList _chartItems;
|
|
private int _perimeter;
|
|
private Color _backgroundColor;
|
|
private Color _borderColor;
|
|
private float _total;
|
|
private int _legendWidth;
|
|
private int _legendHeight;
|
|
private int _legendFontHeight;
|
|
private string _legendFontStyle;
|
|
private float _legendFontSize;
|
|
private bool _showPercents;
|
|
|
|
public bool ShowPercents{ get{ return _showPercents; } set{ _showPercents = value; } }
|
|
|
|
public PieChartRenderer()
|
|
{
|
|
_chartItems = new ArrayList();
|
|
_perimeter = 250;
|
|
_backgroundColor = Color.White;
|
|
_borderColor = Color.FromArgb(63,63,63);
|
|
_legendFontSize = 8;
|
|
_legendFontStyle = "Verdana";
|
|
}
|
|
|
|
public PieChartRenderer(Color bgColor)
|
|
{
|
|
_chartItems = new ArrayList();
|
|
_perimeter = 250;
|
|
_backgroundColor = bgColor;
|
|
_borderColor = Color.FromArgb(63,63,63);
|
|
_legendFontSize = 8;
|
|
_legendFontStyle = "Verdana";
|
|
}
|
|
|
|
//*********************************************************************
|
|
//
|
|
// This method collects all data points and calculate all the necessary dimensions
|
|
// to draw the chart. It is the first method called before invoking the Draw() method.
|
|
//
|
|
//*********************************************************************
|
|
|
|
public void CollectDataPoints(string[] xValues, string[] yValues)
|
|
{
|
|
_total = 0.0f;
|
|
|
|
for (int i = 0;i < xValues.Length;i++)
|
|
{
|
|
float ftemp = Convert.ToSingle(yValues[i]);
|
|
_chartItems.Add(new DataItem(xValues[i], xValues.ToString(), ftemp, 0, 0, Color.AliceBlue));
|
|
_total += ftemp;
|
|
}
|
|
|
|
float nextStartPos = 0.0f;
|
|
int counter = 0;
|
|
foreach (DataItem item in _chartItems)
|
|
{
|
|
item.StartPos = nextStartPos;
|
|
item.SweepSize = item.Value / _total * 360;
|
|
nextStartPos = item.StartPos + item.SweepSize;
|
|
item.ItemColor = GetColor(counter++);
|
|
}
|
|
|
|
CalculateLegendWidthHeight();
|
|
}
|
|
|
|
//*********************************************************************
|
|
//
|
|
// This method returns a bitmap to the calling function. This is the method
|
|
// that actually draws the pie chart and the legend with it.
|
|
//
|
|
//*********************************************************************
|
|
|
|
public override Bitmap Draw()
|
|
{
|
|
int perimeter = _perimeter;
|
|
Rectangle pieRect = new Rectangle(0, 0, perimeter, perimeter-1);
|
|
Bitmap bmp = new Bitmap(perimeter + _legendWidth, perimeter);
|
|
Font fnt = null;
|
|
Pen pen = null;
|
|
Graphics grp = null;
|
|
StringFormat sf = null, sfp = null;
|
|
|
|
try
|
|
{
|
|
grp = Graphics.FromImage(bmp);
|
|
grp.CompositingQuality = CompositingQuality.HighQuality;
|
|
grp.SmoothingMode = SmoothingMode.AntiAlias;
|
|
sf = new StringFormat();
|
|
|
|
//Paint Back ground
|
|
using ( SolidBrush brsh = new SolidBrush( _backgroundColor ) )
|
|
grp.FillRectangle(brsh, -1, -1, perimeter + _legendWidth+1, perimeter+1);
|
|
|
|
//Align text to the right
|
|
sf.Alignment = StringAlignment.Far;
|
|
|
|
//Draw all wedges and legends
|
|
for(int i=0; i<_chartItems.Count; i++)
|
|
{
|
|
DataItem item = (DataItem) _chartItems[i];
|
|
SolidBrush brs = null;
|
|
try
|
|
{
|
|
brs = new SolidBrush(item.ItemColor);
|
|
grp.FillPie(brs, pieRect, item.StartPos, item.SweepSize);
|
|
|
|
//grp.DrawPie(new Pen(_borderColor,1.2f),pieRect,item.StartPos,item.SweepSize);
|
|
|
|
if ( fnt == null )
|
|
fnt = new Font( _legendFontStyle, _legendFontSize );
|
|
|
|
if ( _showPercents && item.SweepSize > 10 )
|
|
{
|
|
if ( sfp == null )
|
|
{
|
|
sfp = new StringFormat();
|
|
sfp.Alignment = StringAlignment.Center;
|
|
sfp.LineAlignment = StringAlignment.Center;
|
|
}
|
|
|
|
float perc = (item.SweepSize * 100.0f) / 360.0f;
|
|
string percString = String.Format( "{0:F0}%", perc );
|
|
|
|
float px = pieRect.X+(pieRect.Width/2);
|
|
float py = pieRect.Y+(pieRect.Height/2);
|
|
|
|
double angle = item.StartPos + (item.SweepSize/2);
|
|
double rads = (angle/180.0)*Math.PI;
|
|
|
|
px += (float)(Math.Cos( rads ) * perimeter / 3);
|
|
py += (float)(Math.Sin( rads ) * perimeter / 3);
|
|
|
|
grp.DrawString( percString, fnt, Brushes.Gray,
|
|
new RectangleF( px - 30 - 1, py - 20, 60, 40 ), sfp );
|
|
|
|
grp.DrawString( percString, fnt, Brushes.Gray,
|
|
new RectangleF( px - 30 + 1, py - 20, 60, 40 ), sfp );
|
|
|
|
grp.DrawString( percString, fnt, Brushes.Gray,
|
|
new RectangleF( px - 30, py - 20 - 1, 60, 40 ), sfp );
|
|
|
|
grp.DrawString( percString, fnt, Brushes.Gray,
|
|
new RectangleF( px - 30, py - 20 + 1, 60, 40 ), sfp );
|
|
|
|
|
|
grp.DrawString( percString, fnt, Brushes.White,
|
|
new RectangleF( px - 30, py - 20, 60, 40 ), sfp );
|
|
}
|
|
|
|
if ( pen == null )
|
|
pen = new Pen( _borderColor, 0.5f );
|
|
|
|
grp.FillRectangle(brs, perimeter + _bufferSpace, i * _legendFontHeight + 15, 10, 10);
|
|
grp.DrawRectangle(pen, perimeter + _bufferSpace, i * _legendFontHeight + 15, 10, 10);
|
|
|
|
grp.DrawString(item.Label, fnt,
|
|
Brushes.Black, perimeter + _bufferSpace + 20, i * _legendFontHeight + 13);
|
|
|
|
grp.DrawString(item.Value.ToString("#,###.##"), fnt,
|
|
Brushes.Black, perimeter + _bufferSpace + 200, i * _legendFontHeight + 13,sf);
|
|
}
|
|
finally
|
|
{
|
|
if (brs !=null)
|
|
brs.Dispose();
|
|
}
|
|
}
|
|
|
|
for(int i=0; i<_chartItems.Count; i++)
|
|
{
|
|
DataItem item = (DataItem) _chartItems[i];
|
|
SolidBrush brs = null;
|
|
try
|
|
{
|
|
grp.DrawPie(new Pen(_borderColor,0.5f),pieRect,item.StartPos,item.SweepSize);
|
|
}
|
|
finally
|
|
{
|
|
if (brs !=null)
|
|
brs.Dispose();
|
|
}
|
|
}
|
|
|
|
//draws the border around Pie
|
|
using ( Pen pen2 = new Pen( _borderColor, 2 ) )
|
|
grp.DrawEllipse(pen2, pieRect);
|
|
|
|
//draw border around legend
|
|
using ( Pen pen1 = new Pen( _borderColor, 1 ) )
|
|
grp.DrawRectangle(pen1, perimeter + _bufferSpace - 10, 10, 220, _chartItems.Count * _legendFontHeight + 25);
|
|
|
|
//Draw Total under legend
|
|
using ( Font fntb = new Font( _legendFontStyle, _legendFontSize, FontStyle.Bold ) )
|
|
{
|
|
grp.DrawString("Total", fntb,
|
|
Brushes.Black, perimeter + _bufferSpace + 30, (_chartItems.Count+1) * _legendFontHeight,sf);
|
|
grp.DrawString(_total.ToString("#,###.##"), fntb,
|
|
Brushes.Black, perimeter + _bufferSpace + 200, (_chartItems.Count+1) * _legendFontHeight,sf);
|
|
}
|
|
|
|
grp.SmoothingMode = SmoothingMode.AntiAlias;
|
|
}
|
|
finally
|
|
{
|
|
if (sf != null) sf.Dispose();
|
|
if (grp != null) grp.Dispose();
|
|
if (sfp != null) sfp.Dispose();
|
|
if (fnt != null) fnt.Dispose();
|
|
if (pen != null) pen.Dispose();
|
|
}
|
|
return bmp;
|
|
}
|
|
|
|
//*********************************************************************
|
|
//
|
|
// This method calculates the space required to draw the chart legend.
|
|
//
|
|
//*********************************************************************
|
|
|
|
private void CalculateLegendWidthHeight()
|
|
{
|
|
Font fontLegend = new Font(_legendFontStyle, _legendFontSize);
|
|
_legendFontHeight = fontLegend.Height+3;
|
|
_legendHeight = fontLegend.Height * (_chartItems.Count + 1);
|
|
if (_legendHeight > _perimeter) _perimeter = _legendHeight;
|
|
|
|
_legendWidth = _perimeter + _bufferSpace;
|
|
fontLegend.Dispose();
|
|
}
|
|
}
|
|
} |