using System; using System.Collections.Generic; using System.Text; using System.Drawing; using System.Drawing.Drawing2D; using System.ComponentModel; namespace DevComponents.DotNetBar.MicroCharts { internal class LineMicroChart : MicroChartBase { public override void CreateChart(MicroChartRenderInfo info) { Graphics graphics = info.Graphics; int pointRadius = Dpi.Width(PointRadius); int chartHeight = info.ChartHeight - pointRadius * 2; int chartWidth = info.ChartWidth - pointRadius * 2; int drawStep = (int)Math.Max(1, chartWidth / (Math.Max(1, info.DataPoints.Count - 1))); int dataStep = Math.Max(1, ((info.DataPoints.Count * drawStep) / chartWidth)); if (info.DataPoints.Count <= 2) dataStep = 1; int x = pointRadius; double dataPointMinValue = info.DataPointMinValue; double dataPointMaxValue = info.DataPointMaxValue; if (_MicroChartStyle.DrawZeroLine && dataPointMinValue > _MicroChartStyle.ZeroLineValue) dataPointMinValue = _MicroChartStyle.ZeroLineValue; if (_MicroChartStyle.DrawControlLine1) { if (dataPointMinValue > _MicroChartStyle.ControlLine1StartValue) dataPointMinValue = _MicroChartStyle.ControlLine1StartValue; if (dataPointMinValue > _MicroChartStyle.ControlLine1EndValue) dataPointMinValue = _MicroChartStyle.ControlLine1EndValue; if (dataPointMaxValue < _MicroChartStyle.ControlLine1StartValue) dataPointMaxValue = _MicroChartStyle.ControlLine1StartValue; if (dataPointMaxValue < _MicroChartStyle.ControlLine1EndValue) dataPointMaxValue = _MicroChartStyle.ControlLine1EndValue; } if (_MicroChartStyle.DrawControlLine2) { if (dataPointMinValue > _MicroChartStyle.ControlLine2StartValue) dataPointMinValue = _MicroChartStyle.ControlLine2StartValue; if (dataPointMinValue > _MicroChartStyle.ControlLine2EndValue) dataPointMinValue = _MicroChartStyle.ControlLine2EndValue; if (dataPointMaxValue < _MicroChartStyle.ControlLine2StartValue) dataPointMaxValue = _MicroChartStyle.ControlLine2StartValue; if (dataPointMaxValue < _MicroChartStyle.ControlLine2EndValue) dataPointMaxValue = _MicroChartStyle.ControlLine2EndValue; } double range = dataPointMaxValue - dataPointMinValue; if (range == 0) range = 1; int totalPoints = (int)Math.Ceiling((double)info.DataPoints.Count / dataStep); Point[] chartPoints = new Point[totalPoints]; MicroChartHotPoint[] microHotPoints = new MicroChartHotPoint[totalPoints]; Point lowPoint = Point.Empty, highPoint = Point.Empty; int index = 0; for (int i = 0; i < info.DataPoints.Count; i += dataStep) { double value = info.DataPoints[i]; Point p = new Point(x, (int)Math.Min((int)(chartHeight * (1 - (value - dataPointMinValue) / range)), chartHeight - 1) + pointRadius); if (lowPoint.IsEmpty && value == info.DataPointMinValue) lowPoint = p; else if (/*highPoint.IsEmpty &&*/ value == dataPointMaxValue) highPoint = p; chartPoints[index] = p; microHotPoints[index] = new MicroChartHotPoint(GetHotPointBounds(p, info), new Rectangle(p.X - drawStep / 2, 0, drawStep, chartHeight), _MicroChartStyle.LineColor, value, index); index++; x += drawStep; if (x > chartWidth || i >= info.DataPoints.Count - dataStep * 2) x = chartWidth; } if (_MicroChartStyle.DrawAverageLine && !_MicroChartStyle.AverageLineColor.IsEmpty) { using (Pen pen = new Pen(_MicroChartStyle.AverageLineColor, Dpi.Width1)) graphics.DrawLine(pen, 0, chartHeight / 2, chartWidth, chartHeight / 2); } //if (_MicroChartStyle.DrawTrendLine && !_MicroChartStyle.TrendLineColor.IsEmpty) //{ // using (Pen pen = new Pen(_MicroChartStyle.TrendLineColor)) // graphics.DrawLine(pen, 0, (int)(chartHeight * (1 - (info.TrendInfo.Start - dataPointMinValue) / range)), // chartWidth, (int)(chartHeight * (1 - (info.TrendInfo.End - dataPointMinValue) / range))); //} if (_MicroChartStyle.DrawZeroLine && !_MicroChartStyle.ZeroLineColor.IsEmpty) { using (Pen pen = new Pen(_MicroChartStyle.ZeroLineColor, Dpi.Width1)) { int y = Math.Min((int)(chartHeight * (1 - (_MicroChartStyle.ZeroLineValue - dataPointMinValue) / range)) + pointRadius, (chartHeight + pointRadius) - 1); if (y < 0) y = 0; graphics.DrawLine(pen, 0, y, chartWidth, y); } } if (_MicroChartStyle.DrawControlLine1 && !_MicroChartStyle.ControlLine1Color.IsEmpty) { using (Pen pen = new Pen(_MicroChartStyle.ControlLine1Color, Dpi.Width1)) { int y1 = Math.Min((int)(chartHeight * (1 - (_MicroChartStyle.ControlLine1StartValue - dataPointMinValue) / range)) + pointRadius, (chartHeight + pointRadius) - 1); if (y1 < 0) y1 = 0; int y2 = Math.Min((int)(chartHeight * (1 - (_MicroChartStyle.ControlLine1EndValue - dataPointMinValue) / range)) + pointRadius, (chartHeight + pointRadius) - 1); if (y2 < 0) y2 = 0; graphics.DrawLine(pen, 0, y1, chartWidth, y2); } } if (_MicroChartStyle.DrawControlLine2 && !_MicroChartStyle.ControlLine2Color.IsEmpty) { using (Pen pen = new Pen(_MicroChartStyle.ControlLine2Color, Dpi.Width1)) { int y1 = Math.Min((int)(chartHeight * (1 - (_MicroChartStyle.ControlLine2StartValue - dataPointMinValue) / range)) + pointRadius, (chartHeight + pointRadius) - 1); if (y1 < 0) y1 = 0; int y2 = Math.Min((int)(chartHeight * (1 - (_MicroChartStyle.ControlLine2EndValue - dataPointMinValue) / range)) + pointRadius, (chartHeight + pointRadius) - 1); if (y2 < 0) y2 = 0; graphics.DrawLine(pen, 0, y1, chartWidth, y2); } } if (chartPoints.Length > 1) { using (Pen pen = new Pen(_MicroChartStyle.LineColor, Dpi.Width1)) graphics.DrawLines(pen, chartPoints); } if (!lowPoint.IsEmpty && !_MicroChartStyle.LowPointColor.IsEmpty && chartPoints.Length > 0) { using (SolidBrush brush = new SolidBrush(_MicroChartStyle.LowPointColor)) graphics.FillPolygon(brush, GetChartPointBounds(lowPoint)); } if (!highPoint.IsEmpty && !_MicroChartStyle.HighPointColor.IsEmpty && chartPoints.Length > 0) { using (SolidBrush brush = new SolidBrush(_MicroChartStyle.HighPointColor)) graphics.FillPolygon(brush, GetChartPointBounds(highPoint)); } if (!_MicroChartStyle.FirstPointColor.IsEmpty && chartPoints.Length > 0) { using (SolidBrush brush = new SolidBrush(_MicroChartStyle.FirstPointColor)) graphics.FillPolygon(brush, GetChartPointBounds(chartPoints[0])); } if (!_MicroChartStyle.LastPointColor.IsEmpty && chartPoints.Length > 1) { using (SolidBrush brush = new SolidBrush(_MicroChartStyle.LastPointColor)) graphics.FillPolygon(brush, GetChartPointBounds(chartPoints[chartPoints.Length - 1])); } info.MicroChartHotPoints = microHotPoints; } private static int HotPointOffset { get { return Dpi.Width4; } } private Rectangle GetHotPointBounds(Point hotPoint, MicroChartRenderInfo info) { //Rectangle bounds = new Rectangle(Math.Min(info.ChartWidth - HotPointOffset * 2, Math.Max(-1, hotPoint.X - HotPointOffset)), // Math.Min(info.ChartHeight - HotPointOffset * 2, Math.Max(-1, hotPoint.Y - HotPointOffset)), // HotPointOffset * 2, // HotPointOffset * 2); Rectangle bounds = new Rectangle(hotPoint.X - HotPointOffset, hotPoint.Y - HotPointOffset, HotPointOffset * 2, HotPointOffset * 2); return bounds; } private LineMicroChartStyle _MicroChartStyle; public LineMicroChartStyle Style { get { return _MicroChartStyle; } set { _MicroChartStyle = value; } } } /// /// Defines the style for the line micro chart. /// [System.ComponentModel.ToolboxItem(false), System.ComponentModel.DesignTimeVisible(false), TypeConverter(typeof(System.ComponentModel.ExpandableObjectConverter))] public class LineMicroChartStyle { private Color _LineColor = Color.Black; /// /// Gets or sets the color of the chart line. /// [Category("Appearance"), Description("Indicates color of chart line .")] public Color LineColor { get { return _LineColor; } set { _LineColor = value; OnStyleChanged(); } } /// /// Gets whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeLineColor() { return _LineColor != Color.Black; } /// /// Resets property to its default value. /// [EditorBrowsable(EditorBrowsableState.Never)] public void ResetLineColor() { this.LineColor = Color.Black; } private bool _DrawAverageLine = false; /// /// Gets or sets whether average line is drawn. /// [DefaultValue(false), Category("Appearance")] public bool DrawAverageLine { get { return _DrawAverageLine; } set { _DrawAverageLine = value; OnStyleChanged(); } } private Color _AverageLineColor = ColorScheme.GetColor(0xFAC08F); /// /// Gets or sets the color of the /// [Category("Columns"), Description("Indicates color of.")] public Color AverageLineColor { get { return _AverageLineColor; } set { _AverageLineColor = value; OnStyleChanged(); } } /// /// Gets whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeAverageLineColor() { return _AverageLineColor != ColorScheme.GetColor(0xFAC08F); } /// /// Resets property to its default value. /// [EditorBrowsable(EditorBrowsableState.Never)] public void ResetAverageLineColor() { this.AverageLineColor = ColorScheme.GetColor(0xFAC08F); } //private bool _DrawTrendLine = false; //[DefaultValue(false), Category("Appearance")] //public bool DrawTrendLine //{ // get { return _DrawTrendLine; } // set // { // _DrawTrendLine = value; // } //} //private Color _TrendLineColor = ColorScheme.GetColor(0xBFBFBF); ///// ///// Gets or sets the color of the trend line. ///// //[Category("Columns"), Description("Indicates color of trend line.")] //public Color TrendLineColor //{ // get { return _TrendLineColor; } // set { _TrendLineColor = value; } //} ///// ///// Gets whether property should be serialized. ///// //[EditorBrowsable(EditorBrowsableState.Never)] //public bool ShouldSerializeTrendLineColor() //{ // return !_TrendLineColor.IsEmpty; //} ///// ///// Resets property to its default value. ///// //[EditorBrowsable(EditorBrowsableState.Never)] //public void ResetTrendLineColor() //{ // this.TrendLineColor = Color.Empty; //} private bool _DrawZeroLine = true; /// /// Gets or sets whether zero-line is drawn on chart. /// [DefaultValue(true), Category("Appearance"), Description("Gets or sets whether zero-line is drawn on chart.")] public bool DrawZeroLine { get { return _DrawZeroLine; } set { _DrawZeroLine = value; OnStyleChanged(); } } private double _ZeroLineValue = 0d; /// /// Gets or sets the value of the zero line, i.e. where zero line is drawn. Default value is 0. /// [DefaultValue(0d), Category("Appearance"), Description("Indicates value of the zero line, i.e. where zero line is drawn.")] public double ZeroLineValue { get { return _ZeroLineValue; } set { _ZeroLineValue = value; OnStyleChanged(); } } private Color _ZeroLineColor = Color.Red; /// /// Gets or sets the color of the /// [Category("Columns"), Description("Indicates color of.")] public Color ZeroLineColor { get { return _ZeroLineColor; } set { _ZeroLineColor = value; OnStyleChanged(); } } /// /// Gets whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeZeroLineColor() { return _ZeroLineColor != Color.Red; } /// /// Resets property to its default value. /// [EditorBrowsable(EditorBrowsableState.Never)] public void ResetZeroLineColor() { this.ZeroLineColor = Color.Red; } /// /// Occurs when style appearance changes. /// public event EventHandler StyleChanged; /// /// Raises StyleChanged event. /// /// Provides event arguments. protected virtual void OnStyleChanged(EventArgs e) { EventHandler handler = StyleChanged; if (handler != null) handler(this, e); } private void OnStyleChanged() { OnStyleChanged(EventArgs.Empty); } private Color _HighPointColor = Color.Empty; /// /// Gets or sets the color of the high point dot on chart. /// [Category("Columns"), Description("Indicates color of high point dot on chart..")] public Color HighPointColor { get { return _HighPointColor; } set { _HighPointColor = value; OnStyleChanged(); } } /// /// Gets whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeHighPointColor() { return !_HighPointColor.IsEmpty; } /// /// Resets property to its default value. /// [EditorBrowsable(EditorBrowsableState.Never)] public void ResetHighPointColor() { this.HighPointColor = Color.Empty; } private Color _LowPointColor = Color.Empty; /// /// Gets or sets the color of the low point dot on chart. /// [Category("Columns"), Description("Indicates color of low point dot on chart.")] public Color LowPointColor { get { return _LowPointColor; } set { _LowPointColor = value; OnStyleChanged(); } } /// /// Gets whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeLowPointColor() { return !_LowPointColor.IsEmpty; } /// /// Resets property to its default value. /// [EditorBrowsable(EditorBrowsableState.Never)] public void ResetLowPointColor() { this.LowPointColor = Color.Empty; } private Color _FirstPointColor = Color.Empty; /// /// Gets or sets the color of the first point dot on chart. /// [Category("Columns"), Description("Indicates color of first point dot on chart..")] public Color FirstPointColor { get { return _FirstPointColor; } set { _FirstPointColor = value; OnStyleChanged(); } } /// /// Gets whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeFirstPointColor() { return !_FirstPointColor.IsEmpty; } /// /// Resets property to its default value. /// [EditorBrowsable(EditorBrowsableState.Never)] public void ResetFirstPointColor() { this.FirstPointColor = Color.Empty; } private Color _LastPointColor = Color.Empty; /// /// Gets or sets the color of the last point dot on chart. /// [Category("Columns"), Description("Indicates color of last point dot on chart.")] public Color LastPointColor { get { return _LastPointColor; } set { _LastPointColor = value; OnStyleChanged(); } } /// /// Gets whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeLastPointColor() { return !_LastPointColor.IsEmpty; } /// /// Resets property to its default value. /// [EditorBrowsable(EditorBrowsableState.Never)] public void ResetLastPointColor() { this.LastPointColor = Color.Empty; } private bool _DrawControlLine1 = false; /// /// Gets or sets whether control line is drawn. Default value is false. Control lines can be used to display for example low and high control bounds for the chart. /// [DefaultValue(false), Description("Indicates whether control line is drawn. Control lines can be used to display for example low and high control bounds for the chart")] public bool DrawControlLine1 { get { return _DrawControlLine1; } set { _DrawControlLine1 = value; OnStyleChanged(); } } private Color _ControlLine1Color = Color.Empty; /// /// Gets or sets the color of the first control line. /// [Category("Columns"), Description("Indicates color of.")] public Color ControlLine1Color { get { return _ControlLine1Color; } set { _ControlLine1Color = value; OnStyleChanged(); } } /// /// Gets whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeControlLine1Color() { return !_ControlLine1Color.IsEmpty; } /// /// Resets property to its default value. /// [EditorBrowsable(EditorBrowsableState.Never)] public void ResetControlLine1Color() { this.ControlLine1Color = Color.Empty; } private double _ControlLine1StartValue = 0d; /// /// Gets or sets starting value that is used to draw first control line. /// [DefaultValue(0d), Description("Indicates the starting value that is used to draw first control line.")] public double ControlLine1StartValue { get { return _ControlLine1StartValue; } set { _ControlLine1StartValue = value; OnStyleChanged(); } } private double _ControlLine1EndValue = 0d; /// /// Gets or sets end value that is used to draw first control line. /// [DefaultValue(0d), Description("Indicates the end value that is used to draw first control line.")] public double ControlLine1EndValue { get { return _ControlLine1EndValue; } set { _ControlLine1EndValue = value; OnStyleChanged(); } } private bool _DrawControlLine2 = false; /// /// Gets or sets whether control line is drawn. Default value is false. Control lines can be used to display for example low and high control bounds for the chart. /// [DefaultValue(false), Description("Indicates whether control line is drawn. Control lines can be used to display for example low and high control bounds for the chart")] public bool DrawControlLine2 { get { return _DrawControlLine2; } set { _DrawControlLine2 = value; OnStyleChanged(); } } private Color _ControlLine2Color = Color.Empty; /// /// Gets or sets the color of the second control line. /// [Category("Columns"), Description("Indicates color of second control line.")] public Color ControlLine2Color { get { return _ControlLine2Color; } set { _ControlLine2Color = value; OnStyleChanged(); } } /// /// Gets whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeControlLine2Color() { return !_ControlLine2Color.IsEmpty; } /// /// Resets property to its default value. /// [EditorBrowsable(EditorBrowsableState.Never)] public void ResetControlLine2Color() { this.ControlLine2Color = Color.Empty; } private double _ControlLine2StartValue = 0d; /// /// Gets or sets starting value that is used to draw second control line. /// [DefaultValue(0d), Description("Indicates the starting value that is used to draw first second line.")] public double ControlLine2StartValue { get { return _ControlLine2StartValue; } set { _ControlLine2StartValue = value; OnStyleChanged(); } } private double _ControlLine2EndValue = 0d; /// /// Gets or sets end value that is used to draw second control line. /// [DefaultValue(0d), Description("Indicates the end value that is used to draw second control line.")] public double ControlLine2EndValue { get { return _ControlLine2EndValue; } set { _ControlLine2EndValue = value; OnStyleChanged(); } } } }