📄 bargraph.cs
字号:
// Disclaimer and Copyright Information
// BarGraph.cs :
//
// All rights reserved.
//
// Written by Pardesi Services, LLC
// Version 1.01
//
// Distribute freely, except: don't remove our name from the source or
// documentation (don't take credit for my work), mark your changes (don't
// get me blamed for your possible bugs), don't alter or remove this
// notice.
// No warrantee of any kind, express or implied, is included with this
// software; use at your own risk, responsibility for damages (if any) to
// anyone resulting from the use of this software rests entirely with the
// user.
//
// Send bug reports, bug fixes, enhancements, requests, flames, etc. to
// softomatix@CommonComponent.com
///////////////////////////////////////////////////////////////////////////////
//
using System;
using System.Diagnostics;
using System.Xml;
using System.Collections;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
namespace CommonComponent.CommonChart
{
/// <summary>
///
/// </summary>
public abstract class BarGraph : CommonChart.AxialGraph
{
protected Alignment m_GraphAlignment;
protected double m_dEqualBarWidth;
protected double m_dDrawBarWidth;
protected double m_dBarHeightScale;
protected double m_dIslandWidth;
protected float m_fReductionFactor;
protected float m_fIslandDrawWidth;
protected float m_fIslandWidth;
public BarGraph()
{
m_dDrawBarWidth = 0.0;
m_dEqualBarWidth = 0.0;
m_dIslandWidth = 0.0;
m_fReductionFactor = 0.90F;
m_fLeftSpacing = 5F;
m_fRightSpacing = 5F;
m_fIslandSpacing = 10F;
m_GraphAlignment = Alignment.Horizontal;
m_LegendLocation = LegendLocationType.OutsideChart;
m_LegendPosition = PositionType.Right;
m_LegendAlignment = LegendAlignmentType.Vertical;
}
/// <summary>
///
/// </summary>
public Alignment GraphAlignment
{
get{return this.m_GraphAlignment;}
set{this.m_GraphAlignment = value;}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
protected bool CalculateIslandDrawData()
{
// Calculate Island width
if (Alignment.Vertical == this.GraphAlignment)
{
m_fIslandWidth = (this.m_ChartRectangle.Height - m_fIslandSpacing - (((m_iNumberOfDataIslands - 1)*m_fIslandSpacing)))/m_iNumberOfDataIslands;
}
else
{
m_fIslandWidth = (this.m_ChartRectangle.Width - m_fIslandSpacing - (((m_iNumberOfDataIslands - 1)*m_fIslandSpacing)))/m_iNumberOfDataIslands;
}
m_fIslandDrawWidth = m_fIslandWidth * m_fReductionFactor;
return true;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
override protected bool CalculateAxisLocation()
{
// Calculate the origin of axis.
CalculateAxis();
return true;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
override protected bool CalculateAxis()
{
return base.CalculateAxis();
}
/// <summary>
///
/// </summary>
/// <returns></returns>
override protected bool DrawAxisLines(bool bDrawGrid)
{
bool bRet = false;
if (Alignment.Vertical == this.GraphAlignment)
{
bRet = this.DrawAxisForVerticalAlignment(bDrawGrid);
}
else
{
bRet = this.DrawAxisForHorizontalAlignment(bDrawGrid);
}
return bRet;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
override protected bool DrawGraphAxis(bool bDrawGrid)
{
// Calculate the width of x-axis and y-axis lines
CalculateAxisSpan();
// Calculate the axis location.
CalculateAxisLocation();
CalculateAxisLabelLocations();
DrawAxisLines(bDrawGrid);
DrawAxisLabels();
return true;
}
/// <summary>
///
/// </summary>
/// <param name="barCount"></param>
/// <returns></returns>
virtual protected bool CalculateBarWidth(int barCount)
{
int nDataPoints = 0;
// First we will get the number of data points in each island.
ArrayList dataList = (ArrayList)this.m_obIslandList[0];
nDataPoints = dataList.Count;
// Now we need to calculate data about islands.
if (false == CalculateIslandDrawData())
{
Trace.WriteLine("Failed to caluclate island draw data.");
return false;
}
if (Alignment.Vertical == this.GraphAlignment)
{
//m_dDrawBarWidth = m_dEqualBarWidth = this.m_iYAxisSpan/barCount;
m_dDrawBarWidth = m_dEqualBarWidth = this.m_fIslandDrawWidth/nDataPoints;
}
else
{
//m_dDrawBarWidth = m_dEqualBarWidth = this.m_iXAxisSpan/barCount;
m_dDrawBarWidth = m_dEqualBarWidth = this.m_fIslandDrawWidth/nDataPoints;
}
// TODO: Provide attribuye to set the spacing between bars.
// For now its fixed to about 85% of the width.
m_dDrawBarWidth *= 0.85;
return true;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
virtual protected bool CalculateBarHeightScale()
{
if (Alignment.Vertical == this.GraphAlignment)
{
m_dBarHeightScale = this.m_iXAxisSpan/((double)(this.MaxYValue - this.MinYValue));
}
else
{
m_dBarHeightScale = this.m_iYAxisSpan/((double)(this.MaxYValue - this.MinYValue));
}
return true;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
override protected bool CalculateQudarantToShow()
{
base.CalculateQudarantToShow();
// If the graph alignment is vertical, then we need to modify
// the quadarant information.
if (Alignment.Vertical == this.GraphAlignment)
{
switch (this.m_QuadrantToShow)
{
case QuadrantType.Quad14:
this.m_QuadrantToShow = QuadrantType.Quad12;
break;
}
}
return true;
}
virtual protected bool DrawAxisForHorizontalAlignment(bool bDrawGrid)
{
Pen obPen = null;
Pen obGridPen = null;
try
{
// Draw the grid lines now.
if (this.YTickSpacing > 0)
{
SizeF rectText;
string strVal = "";
PointF pt1 = new PointF();
PointF pt2 = new PointF();
obGridPen = new Pen(GridColor);
int iTickCount = (int)((this.MaxYValue - this.MinYValue)/this.YTickSpacing);
float dYScale = (this.m_iYAxisSpan)/(float)(this.MaxYValue - this.MinYValue);
for (int i = 0; i <= iTickCount; i++)
{
pt1.X = this.m_ChartAxis.X1.X;
pt2.X = pt1.X + this.m_iXAxisSpan;
pt1.Y = this.m_ChartAxis.Y2.Y - (i * this.YTickSpacing) * dYScale;
pt2.Y = pt1.Y;
if (HasGridLines && bDrawGrid)
{
this.m_obGraphics.DrawLine(obGridPen, pt1, pt2);
}
strVal = (MinYValue + (i * YTickSpacing)).ToString();
rectText = this.m_obGraphics.MeasureString(strVal, this.m_YTickFont);
pt1.X = pt1.X - (rectText.Width + 2);
this.m_obGraphics.DrawString(strVal, this.m_YTickFont, new SolidBrush(this.m_TitleColor), pt1);
}
}
obPen = new Pen(new SolidBrush(Color.Black));
this.m_obGraphics.DrawLine(obPen, this.m_ChartAxis.X1, this.m_ChartAxis.X2);
this.m_obGraphics.DrawLine(obPen, this.m_ChartAxis.Y2, this.m_ChartAxis.Y1);
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message);
throw ex;
}
finally
{
if (obPen != null)
{
obPen.Dispose();
}
}
return true;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
virtual protected bool DrawAxisForVerticalAlignment(bool bDrawGrid)
{
return true;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
virtual protected bool DrawDataForVerticalAlignment()
{
return false;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
virtual protected bool DrawDataForHorizontalAlignment()
{
return false;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
override protected bool DrawLegends()
{
//this.CalculateLegendsRectangle(this.m_sLegendCount);
switch (this.LegendAlignment)
{
case LegendAlignmentType.Horizontal:
return this.DrawHorizontalLegends();
case LegendAlignmentType.Vertical:
return this.DrawVerticalLegends();
}
return false;
}
/// <summary>
///
/// </summary>
override protected void CalculateTickerTextDirection()
{
// If the total length of legend text is more than the span of axis
// that means we can't draw the ticker text in horizontal direction.
// It has to be vertical or diagonal.
switch (this.GraphAlignment)
{
case Alignment.Horizontal:
if (this.m_fAvgLegendTextWidth * this.DataPointCount >= this.m_fIslandWidth)
{
this.m_TickerTextDirection = TextDirectionType.Diagonal;
}
break;
case Alignment.Vertical:
if (this.m_fMaxLegendTextWidth > this.LeftSpacing)
{
this.m_TickerTextDirection = TextDirectionType.Diagonal;
}
break;
}
}
/// <summary>
///
/// </summary>
override protected void CalculateIslandLegendTextDirection()
{
// If the total length of legend text is more than the span of axis
// that means we can't draw the ticker text in horizontal direction.
// It has to be vertical or diagonal.
switch (this.GraphAlignment)
{
case Alignment.Horizontal:
if (this.m_fAvgIslandLegendTextWidth >= (this.m_fIslandWidth + this.m_fIslandSpacing/2.0F))
{
this.m_IslandLegendTextDirection = TextDirectionType.Diagonal;
}
break;
case Alignment.Vertical:
if (this.m_fAvgIslandLegendTextWidth >= (this.m_fIslandWidth + this.m_fIslandSpacing/2.0F))
{
this.m_IslandLegendTextDirection = TextDirectionType.Diagonal;
}
else
{
this.m_IslandLegendTextDirection = TextDirectionType.Vertical;
}
break;
}
}
protected bool DrawDataValue(Graphics obGraphics, Font textFont, double ptX, double ptY, double dWidth, double dHeight,
string strVal, TextDirectionType direction, Alignment align, Color color, Color barColor)
{
Pen obPen = null;
SolidBrush obTextBrush = null;
SolidBrush obMarkerBrush = null;
RectangleF markerRect = new RectangleF();
PointF pt = new PointF();
SizeF textSize;
try
{
obTextBrush = new SolidBrush(color);
obMarkerBrush = new SolidBrush(barColor);
obPen = new Pen(obTextBrush);
markerRect.Width = markerRect.Height = 6.0F;
// Calculate the size of text string.
textSize = obGraphics.MeasureString(strVal, textFont);
switch (align)
{
case Alignment.Horizontal:
pt.X = (float)(ptX + dWidth/2.0F);
pt.Y = (float)(ptY);
markerRect.X = pt.X - 3.0F;
markerRect.Y = (float)(pt.Y - 6.0F - dHeight);
obGraphics.FillEllipse(obMarkerBrush, markerRect);
//obGraphics.DrawEllipse(obPen, markerRect);
pt.X -= textSize.Width/2.0F;
pt.Y = markerRect.Y - textSize.Height;
obGraphics.DrawString(strVal, textFont, obTextBrush, pt);
break;
case Alignment.Vertical:
pt.X = (float)(ptX + dWidth);
pt.Y = (float)(ptY + dHeight/2.0F);
markerRect.X = pt.X;
markerRect.Y = (float)(pt.Y - 3.0F);
obGraphics.FillEllipse(obMarkerBrush, markerRect);
//obGraphics.DrawEllipse(obPen, markerRect);
pt.X += 6.0F;
pt.Y = (float)(pt.Y - textSize.Height/2.0F);
obGraphics.DrawString(strVal, textFont, obTextBrush, pt);
break;
}
/*
// Time to draw ticker text.
switch (direction)
{
case TextDirectionType.Horizontal:
this.DrawHorizontalTickerText(obGraphics, strLegend, ptTicker2, this.m_XTickFont, this.m_TickColor, align);
break;
case TextDirectionType.Diagonal:
this.DrawDiagonalTickerText(obGraphics, strLegend, ptTicker2, this.m_XTickFont, this.m_TickColor, align);
break;
}
*/
}
finally
{
if (null != obPen)
{
obPen.Dispose();
}
if (null != obTextBrush)
{
obTextBrush.Dispose();
}
if (null != obMarkerBrush)
{
obMarkerBrush.Dispose();
}
}
return true;
}
/// <summary>
///
/// </summary>
/// <param name="obGraphics"></param>
/// <param name="ptX"></param>
/// <param name="ptY"></param>
/// <param name="dWidth"></param>
/// <param name="dHeight"></param>
/// <param name="sLength"></param>
/// <param name="strLegend"></param>
/// <param name="direction"></param>
/// <param name="align"></param>
/// <param name="color"></param>
/// <returns></returns>
protected bool DrawChartTicker(Graphics obGraphics, double ptX, double ptY, double dWidth, double dHeight,
short sLength, string strLegend, TextDirectionType direction, Alignment align, Color color)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -