/// <summary> /// Draws the data labels of the pie chart. /// </summary> internal override void Draw() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; if (cri.seriesRendererInfos.Length == 0) { return; } SeriesRendererInfo sri = cri.seriesRendererInfos[0]; if (sri.dataLabelRendererInfo == null) { return; } if (sri != null) { XGraphics gfx = this.rendererParms.Graphics; XFont font = sri.dataLabelRendererInfo.Font; XBrush fontColor = sri.dataLabelRendererInfo.FontColor; XStringFormat format = XStringFormats.Center; format.LineAlignment = XLineAlignment.Center; foreach (DataLabelEntryRendererInfo dataLabel in sri.dataLabelRendererInfo.Entries) { if (dataLabel.Text != null) { gfx.DrawString(dataLabel.Text, font, fontColor, dataLabel.Rect, format); } } } }
/// <summary> /// Draws all markers given in rendererInfo at the positions specified by points. /// </summary> private void DrawMarker(XGraphics graphics, XPoint[] points, SeriesRendererInfo rendererInfo) { foreach (XPoint pos in points) { MarkerRenderer.Draw(graphics, pos, rendererInfo.markerRendererInfo); } }
/// <summary> /// Calculate angles for each sector. /// </summary> protected override void CalcSectors() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; if (cri.seriesRendererInfos.Length == 0) { return; } SeriesRendererInfo sri = cri.seriesRendererInfos[0]; double sumValues = sri.SumOfPoints; if (sumValues == 0) { return; } double textMeasure = 0; if (sri.dataLabelRendererInfo != null && sri.dataLabelRendererInfo.Position == DataLabelPosition.OutsideEnd) { foreach (DataLabelEntryRendererInfo dleri in sri.dataLabelRendererInfo.Entries) { textMeasure = Math.Max(textMeasure, dleri.Width); textMeasure = Math.Max(textMeasure, dleri.Height); } } XRect pieRect = cri.plotAreaRendererInfo.Rect; if (textMeasure != 0) { pieRect.X += textMeasure; pieRect.Y += textMeasure; pieRect.Width -= 2 * textMeasure; pieRect.Height -= 2 * textMeasure; } double startAngle = 270, sweepAngle = 0; foreach (SectorRendererInfo sector in sri.pointRendererInfos) { if (!double.IsNaN(sector.point.value) && sector.point.value != 0) { sweepAngle = 360 / (sumValues / Math.Abs(sector.point.value)); sector.Rect = pieRect; sector.StartAngle = startAngle; sector.SweepAngle = sweepAngle; startAngle += sweepAngle; } else { sector.StartAngle = double.NaN; sector.SweepAngle = double.NaN; } } }
/// <summary> /// Initializes the legend's renderer info. Each data point will be represented through /// a legend entry renderer info. /// </summary> internal override RendererInfo Init() { LegendRendererInfo lri = null; ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; if (cri.chart.legend != null) { lri = new LegendRendererInfo(); lri.legend = cri.chart.legend; lri.Font = Converter.ToXFont(lri.legend.font, cri.DefaultFont); lri.FontColor = new XSolidBrush(XColors.Black); if (lri.legend.lineFormat != null) { lri.BorderPen = Converter.ToXPen(lri.legend.lineFormat, XColors.Black, DefaultLineWidth, XDashStyle.Solid); } XSeries xseries = null; if (cri.chart.xValues != null) { xseries = cri.chart.xValues[0]; } int index = 0; SeriesRendererInfo sri = cri.seriesRendererInfos[0]; lri.Entries = new LegendEntryRendererInfo[sri.pointRendererInfos.Length]; foreach (PointRendererInfo pri in sri.pointRendererInfos) { LegendEntryRendererInfo leri = new LegendEntryRendererInfo(); leri.seriesRendererInfo = sri; leri.legendRendererInfo = lri; leri.EntryText = string.Empty; if (xseries != null) { if (xseries.Count > index) { leri.EntryText = xseries[index].Value; } } else { leri.EntryText = (index + 1).ToString(CultureInfo.InvariantCulture); // create default/dummy entry } leri.MarkerPen = pri.LineFormat; leri.MarkerBrush = pri.FillFormat; lri.Entries[index++] = leri; } } return(lri); }
/// <summary> /// Initializes all necessary data to draw series for a combination chart. /// </summary> private void InitSeriesRendererInfo() { CombinationRendererInfo cri = (CombinationRendererInfo)this.rendererParms.RendererInfo; SeriesCollection seriesColl = cri.chart.SeriesCollection; cri.seriesRendererInfos = new SeriesRendererInfo[seriesColl.Count]; for (int idx = 0; idx < seriesColl.Count; ++idx) { SeriesRendererInfo sri = new SeriesRendererInfo(); sri.series = seriesColl[idx]; cri.seriesRendererInfos[idx] = sri; } }
/// <summary> /// Initializes all necessary data to draw all series for a column chart. /// </summary> private void InitSeriesRendererInfo() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; SeriesCollection seriesColl = cri.chart.SeriesCollection; cri.seriesRendererInfos = new SeriesRendererInfo[seriesColl.Count]; // Lowest series is the first, like in Excel for (int idx = 0; idx < seriesColl.Count; ++idx) { SeriesRendererInfo sri = new SeriesRendererInfo(); sri.series = seriesColl[idx]; cri.seriesRendererInfos[idx] = sri; } InitSeries(); }
/// <summary> /// Calculates the space used by the data labels. /// </summary> internal override void Format() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; if (cri.seriesRendererInfos.Length == 0) { return; } SeriesRendererInfo sri = cri.seriesRendererInfos[0]; if (sri.dataLabelRendererInfo == null) { return; } double sumValues = sri.SumOfPoints; XGraphics gfx = this.rendererParms.Graphics; sri.dataLabelRendererInfo.Entries = new DataLabelEntryRendererInfo[sri.pointRendererInfos.Length]; int index = 0; foreach (SectorRendererInfo sector in sri.pointRendererInfos) { DataLabelEntryRendererInfo dleri = new DataLabelEntryRendererInfo(); if (sri.dataLabelRendererInfo.Type != DataLabelType.None) { if (sri.dataLabelRendererInfo.Type == DataLabelType.Percent) { double percent = 100 / (sumValues / Math.Abs(sector.point.value)); dleri.Text = percent.ToString(sri.dataLabelRendererInfo.Format) + "%"; } else if (sri.dataLabelRendererInfo.Type == DataLabelType.Value) { dleri.Text = sector.point.value.ToString(sri.dataLabelRendererInfo.Format); } if (dleri.Text.Length > 0) { dleri.Size = gfx.MeasureString(dleri.Text, sri.dataLabelRendererInfo.Font); } } sri.dataLabelRendererInfo.Entries[index++] = dleri; } }
/// <summary> /// Initializes all necessary data to draw a series for a pie chart. /// </summary> protected void InitSeries(ChartRendererInfo rendererInfo) { SeriesCollection seriesColl = rendererInfo.chart.SeriesCollection; rendererInfo.seriesRendererInfos = new SeriesRendererInfo[seriesColl.Count]; for (int idx = 0; idx < seriesColl.Count; ++idx) { SeriesRendererInfo sri = new SeriesRendererInfo(); rendererInfo.seriesRendererInfos[idx] = sri; sri.series = seriesColl[idx]; sri.LineFormat = Converter.ToXPen(sri.series.lineFormat, XColors.Black, ChartRenderer.DefaultSeriesLineWidth); sri.FillFormat = Converter.ToXBrush(sri.series.fillFormat, ColumnColors.Item(idx)); sri.pointRendererInfos = new SectorRendererInfo[sri.series.seriesElements.Count]; for (int pointIdx = 0; pointIdx < sri.pointRendererInfos.Length; ++pointIdx) { PointRendererInfo pri = new SectorRendererInfo(); Point point = sri.series.seriesElements[pointIdx]; pri.point = point; if (point != null) { pri.LineFormat = sri.LineFormat; if (point.lineFormat != null && !point.lineFormat.color.IsEmpty) { pri.LineFormat = new XPen(point.lineFormat.color); } if (point.fillFormat != null && !point.fillFormat.color.IsEmpty) { pri.FillFormat = new XSolidBrush(point.fillFormat.color); } else { pri.FillFormat = new XSolidBrush(PieColors.Item(pointIdx)); } pri.LineFormat.LineJoin = XLineJoin.Round; } sri.pointRendererInfos[pointIdx] = pri; } } }
/// <summary> /// Draws the content of the pie plot area. /// </summary> internal override void Draw() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; XRect plotAreaRect = cri.plotAreaRendererInfo.Rect; if (plotAreaRect.IsEmpty) { return; } if (cri.seriesRendererInfos.Length == 0) { return; } XGraphics gfx = this.rendererParms.Graphics; XGraphicsState state = gfx.Save(); // Draw sectors. SeriesRendererInfo sri = cri.seriesRendererInfos[0]; foreach (SectorRendererInfo sector in sri.pointRendererInfos) { if (!double.IsNaN(sector.StartAngle) && !double.IsNaN(sector.SweepAngle)) { gfx.DrawPie(sector.FillFormat, sector.Rect, sector.StartAngle, sector.SweepAngle); } } // Draw border of the sectors. foreach (SectorRendererInfo sector in sri.pointRendererInfos) { if (!double.IsNaN(sector.StartAngle) && !double.IsNaN(sector.SweepAngle)) { gfx.DrawPie(sector.LineFormat, sector.Rect, sector.StartAngle, sector.SweepAngle); } } gfx.Restore(state); }
/// <summary> /// Calculate angles for each sector. /// </summary> protected override void CalcSectors() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; if (cri.seriesRendererInfos.Length == 0) { return; } SeriesRendererInfo sri = cri.seriesRendererInfos[0]; double sumValues = sri.SumOfPoints; if (sumValues == 0) { return; } double textMeasure = 0; if (sri.dataLabelRendererInfo != null && sri.dataLabelRendererInfo.Position == DataLabelPosition.OutsideEnd) { foreach (DataLabelEntryRendererInfo dleri in sri.dataLabelRendererInfo.Entries) { textMeasure = Math.Max(textMeasure, dleri.Width); textMeasure = Math.Max(textMeasure, dleri.Height); } } XRect pieRect = cri.plotAreaRendererInfo.Rect; if (textMeasure != 0) { pieRect.X += textMeasure; pieRect.Y += textMeasure; pieRect.Width -= 2 * textMeasure; pieRect.Height -= 2 * textMeasure; } XPoint origin = new XPoint(pieRect.X + pieRect.Width / 2, pieRect.Y + pieRect.Height / 2); XRect innerRect = new XRect(); XPoint p1 = new XPoint(); double midAngle = 0, sectorStartAngle = 0, sectorSweepAngle = 0, deltaAngle = 2, startAngle = 270, sweepAngle = 0, rInnerCircle = pieRect.Width / 15, rOuterCircle = pieRect.Width / 2; foreach (SectorRendererInfo sector in sri.pointRendererInfos) { if (!double.IsNaN(sector.point.value) && sector.point.value != 0) { sweepAngle = 360 / (sumValues / Math.Abs(sector.point.value)); midAngle = startAngle + sweepAngle / 2; sectorStartAngle = Math.Max(0, startAngle + deltaAngle); sectorSweepAngle = Math.Max(sweepAngle, sweepAngle - deltaAngle); p1.X = origin.X + rInnerCircle * Math.Cos(midAngle / 180 * Math.PI); p1.Y = origin.Y + rInnerCircle * Math.Sin(midAngle / 180 * Math.PI); innerRect.X = p1.X - rOuterCircle + rInnerCircle; innerRect.Y = p1.Y - rOuterCircle + rInnerCircle; innerRect.Width = (rOuterCircle - rInnerCircle) * 2; innerRect.Height = innerRect.Width; sector.Rect = innerRect; sector.StartAngle = sectorStartAngle; sector.SweepAngle = sectorSweepAngle; startAngle += sweepAngle; } else { sector.StartAngle = double.NaN; sector.SweepAngle = double.NaN; } } }
/// <summary> /// Calculates the data label positions specific for pie charts. /// </summary> internal override void CalcPositions() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; XGraphics gfx = this.rendererParms.Graphics; if (cri.seriesRendererInfos.Length > 0) { SeriesRendererInfo sri = cri.seriesRendererInfos[0]; if (sri != null && sri.dataLabelRendererInfo != null) { int sectorIndex = 0; foreach (SectorRendererInfo sector in sri.pointRendererInfos) { // Determine output rectangle double midAngle = sector.StartAngle + sector.SweepAngle / 2; double radMidAngle = midAngle / 180 * Math.PI; XPoint origin = new XPoint(sector.Rect.X + sector.Rect.Width / 2, sector.Rect.Y + sector.Rect.Height / 2); double radius = sector.Rect.Width / 2; double halfradius = radius / 2; DataLabelEntryRendererInfo dleri = sri.dataLabelRendererInfo.Entries[sectorIndex++]; switch (sri.dataLabelRendererInfo.Position) { case DataLabelPosition.OutsideEnd: // Outer border of the circle. dleri.X = origin.X + (radius * Math.Cos(radMidAngle)); dleri.Y = origin.Y + (radius * Math.Sin(radMidAngle)); if (dleri.X < origin.X) { dleri.X -= dleri.Width; } if (dleri.Y < origin.Y) { dleri.Y -= dleri.Height; } break; case DataLabelPosition.InsideEnd: // Inner border of the circle. dleri.X = origin.X + (radius * Math.Cos(radMidAngle)); dleri.Y = origin.Y + (radius * Math.Sin(radMidAngle)); if (dleri.X > origin.X) { dleri.X -= dleri.Width; } if (dleri.Y > origin.Y) { dleri.Y -= dleri.Height; } break; case DataLabelPosition.Center: // Centered dleri.X = origin.X + (halfradius * Math.Cos(radMidAngle)); dleri.Y = origin.Y + (halfradius * Math.Sin(radMidAngle)); dleri.X -= dleri.Width / 2; dleri.Y -= dleri.Height / 2; break; case DataLabelPosition.InsideBase: // Aligned at the base/center of the circle dleri.X = origin.X; dleri.Y = origin.Y; if (dleri.X < origin.X) { dleri.X -= dleri.Width; } if (dleri.Y < origin.Y) { dleri.Y -= dleri.Height; } break; } } } } }