/// <summary> /// Calculates the space used by the data labels. /// </summary> internal override void Format() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { if (sri.dataLabelRendererInfo == null) { continue; } XGraphics gfx = this.rendererParms.Graphics; sri.dataLabelRendererInfo.Entries = new DataLabelEntryRendererInfo[sri.pointRendererInfos.Length]; int index = 0; foreach (ColumnRendererInfo column in sri.pointRendererInfos) { DataLabelEntryRendererInfo dleri = new DataLabelEntryRendererInfo(); if (sri.dataLabelRendererInfo.Type != DataLabelType.None) { if (sri.dataLabelRendererInfo.Type == DataLabelType.Value) { dleri.Text = column.point.value.ToString(sri.dataLabelRendererInfo.Format); } else if (sri.dataLabelRendererInfo.Type == DataLabelType.Percent) { throw new InvalidOperationException(PSCSR.PercentNotSupportedByColumnDataLabel); } if (dleri.Text.Length > 0) { dleri.Size = gfx.MeasureString(dleri.Text, sri.dataLabelRendererInfo.Font); } } sri.dataLabelRendererInfo.Entries[index++] = dleri; } } CalcPositions(); }
/// <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 area plot area. /// </summary> internal override void Draw() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; XRect plotAreaRect = cri.plotAreaRendererInfo.Rect; if (plotAreaRect.IsEmpty) { return; } XGraphics gfx = this.rendererParms.Graphics; XGraphicsState state = gfx.Save(); //gfx.SetClip(plotAreaRect, XCombineMode.Intersect); gfx.IntersectClip(plotAreaRect); XMatrix matrix = cri.plotAreaRendererInfo.matrix; double xMajorTick = cri.xAxisRendererInfo.MajorTick; foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { int count = sri.series.Elements.Count; XPoint[] points = new XPoint[count + 2]; points[0] = new XPoint(xMajorTick / 2, 0); for (int idx = 0; idx < count; idx++) { double pointValue = sri.series.Elements[idx].Value; if (double.IsNaN(pointValue)) { pointValue = 0; } points[idx + 1] = new XPoint(idx + xMajorTick / 2, pointValue); } points[count + 1] = new XPoint(count - 1 + xMajorTick / 2, 0); matrix.TransformPoints(points); gfx.DrawPolygon(sri.LineFormat, sri.FillFormat, points, XFillMode.Winding); } //gfx.ResetClip(); gfx.Restore(state); }
/// <summary> /// Determines the sum of the smallest and the largest stacked bar /// from all series of the chart. /// </summary> protected override void CalcYAxis(out double yMin, out double yMax) { yMin = double.MaxValue; yMax = double.MinValue; ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; int maxPoints = 0; foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { maxPoints = Math.Max(maxPoints, sri.series.seriesElements.Count); } for (int pointIdx = 0; pointIdx < maxPoints; ++pointIdx) { double valueSumPos = 0, valueSumNeg = 0; foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { if (sri.pointRendererInfos.Length <= pointIdx) { break; } ColumnRendererInfo column = (ColumnRendererInfo)sri.pointRendererInfos[pointIdx]; if (column.point != null && !double.IsNaN(column.point.value)) { if (column.point.value < 0) { valueSumNeg += column.point.value; } else { valueSumPos += column.point.value; } } } yMin = Math.Min(valueSumNeg, yMin); yMax = Math.Max(valueSumPos, yMax); } }
/// <summary> /// Draws the data labels of the column chart. /// </summary> internal override void Draw() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { if (sri.dataLabelRendererInfo == null) continue; 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> /// Calculates the space used by the legend and returns the remaining space available for the /// other parts of the chart. /// </summary> protected XRect LayoutLegend() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; XRect remainingRect = this.rendererParms.Box; if (cri.legendRendererInfo != null) { switch (cri.legendRendererInfo.legend.Docking) { case DockingType.Left: cri.legendRendererInfo.X = remainingRect.Left; cri.legendRendererInfo.Y = remainingRect.Height / 2 - cri.legendRendererInfo.Height / 2; double width = cri.legendRendererInfo.Width + ChartRenderer.LegendSpacing; remainingRect.X += width; remainingRect.Width -= width; break; case DockingType.Right: cri.legendRendererInfo.X = remainingRect.Right - cri.legendRendererInfo.Width; cri.legendRendererInfo.Y = remainingRect.Height / 2 - cri.legendRendererInfo.Height / 2; remainingRect.Width -= cri.legendRendererInfo.Width + ChartRenderer.LegendSpacing; break; case DockingType.Top: cri.legendRendererInfo.X = remainingRect.Width / 2 - cri.legendRendererInfo.Width / 2; cri.legendRendererInfo.Y = remainingRect.Top; double height = cri.legendRendererInfo.Height + ChartRenderer.LegendSpacing; remainingRect.Y += height; remainingRect.Height -= height; break; case DockingType.Bottom: cri.legendRendererInfo.X = remainingRect.Width / 2 - cri.legendRendererInfo.Width / 2; cri.legendRendererInfo.Y = remainingRect.Bottom - cri.legendRendererInfo.Height; remainingRect.Height -= cri.legendRendererInfo.Height + ChartRenderer.LegendSpacing; break; } } return(remainingRect); }
/// <summary> /// Layouts and calculates the space used by the column chart. /// </summary> internal override void Format() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; LegendRenderer lr = GetLegendRenderer(); lr.Format(); // axes AxisRenderer xar = new VerticalXAxisRenderer(this.rendererParms); xar.Format(); AxisRenderer yar = GetYAxisRenderer(); yar.Format(); // Calculate rects and positions. XRect chartRect = LayoutLegend(); cri.xAxisRendererInfo.X = chartRect.Left; cri.xAxisRendererInfo.Y = chartRect.Top; cri.xAxisRendererInfo.Height = chartRect.Height - cri.yAxisRendererInfo.Height; cri.yAxisRendererInfo.X = chartRect.Left + cri.xAxisRendererInfo.Width; cri.yAxisRendererInfo.Y = chartRect.Bottom - cri.yAxisRendererInfo.Height; cri.yAxisRendererInfo.Width = chartRect.Width - cri.xAxisRendererInfo.Width; cri.plotAreaRendererInfo.X = cri.yAxisRendererInfo.X; cri.plotAreaRendererInfo.Y = cri.xAxisRendererInfo.Y; cri.plotAreaRendererInfo.Width = cri.yAxisRendererInfo.InnerRect.Width; cri.plotAreaRendererInfo.Height = cri.xAxisRendererInfo.Height; // Calculated remaining plot area, now it's safe to format. PlotAreaRenderer renderer = GetPlotAreaRenderer(); renderer.Format(); DataLabelRenderer dlr = new BarDataLabelRenderer(this.rendererParms); dlr.Format(); }
/// <summary> /// Draws the line chart. /// </summary> internal override void Draw() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; LegendRenderer lr = new ColumnLikeLegendRenderer(this.rendererParms); lr.Draw(); // Draw wall. WallRenderer wr = new WallRenderer(this.rendererParms); wr.Draw(); // Draw gridlines. GridlinesRenderer glr = new ColumnLikeGridlinesRenderer(this.rendererParms); glr.Draw(); PlotAreaBorderRenderer pabr = new PlotAreaBorderRenderer(this.rendererParms); pabr.Draw(); // Draw line chart's plot area. LinePlotAreaRenderer lpar = new LinePlotAreaRenderer(this.rendererParms); lpar.Draw(); // Draw x- and y-axis. if (cri.xAxisRendererInfo.axis != null) { AxisRenderer xar = new HorizontalXAxisRenderer(this.rendererParms); xar.Draw(); } if (cri.yAxisRendererInfo.axis != null) { AxisRenderer yar = new VerticalYAxisRenderer(this.rendererParms); yar.Draw(); } }
/// <summary> /// Draws the column chart. /// </summary> internal override void Draw() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; LegendRenderer lr = GetLegendRenderer(); lr.Draw(); WallRenderer wr = new WallRenderer(this.rendererParms); wr.Draw(); GridlinesRenderer glr = new BarGridlinesRenderer(this.rendererParms); glr.Draw(); PlotAreaBorderRenderer pabr = new PlotAreaBorderRenderer(this.rendererParms); pabr.Draw(); PlotAreaRenderer renderer = GetPlotAreaRenderer(); renderer.Draw(); DataLabelRenderer dlr = new BarDataLabelRenderer(this.rendererParms); dlr.Draw(); if (cri.xAxisRendererInfo.axis != null) { AxisRenderer xar = new VerticalXAxisRenderer(this.rendererParms); xar.Draw(); } if (cri.yAxisRendererInfo.axis != null) { AxisRenderer yar = GetYAxisRenderer(); yar.Draw(); } }
/// <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> /// Returns an initialized and renderer specific rendererInfo. /// </summary> internal override RendererInfo Init() { ChartRendererInfo cri = new ChartRendererInfo(); cri.chart = (Chart)this.rendererParms.DrawingItem; this.rendererParms.RendererInfo = cri; InitSeries(cri); LegendRenderer lr = new PieLegendRenderer(this.rendererParms); cri.legendRendererInfo = (LegendRendererInfo)lr.Init(); PlotArea plotArea = cri.chart.PlotArea; PlotAreaRenderer renderer = GetPlotAreaRenderer(); cri.plotAreaRendererInfo = (PlotAreaRendererInfo)renderer.Init(); DataLabelRenderer dlr = new PieDataLabelRenderer(this.rendererParms); dlr.Init(); return(cri); }
/// <summary> /// Draws the horizontal X axis. /// </summary> internal override void Draw() { XGraphics gfx = this.rendererParms.Graphics; ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; AxisRendererInfo xari = cri.xAxisRendererInfo; double xMin = xari.MinimumScale; double xMax = xari.MaximumScale; double xMajorTick = xari.MajorTick; double xMinorTick = xari.MinorTick; double xMaxExtension = xari.MajorTick; // Draw tick labels. Each tick label will be aligned centered. int countTickLabels = (int)xMax; double tickLabelStep = xari.Height / countTickLabels; XPoint startPos = new XPoint(xari.X + xari.Width - xari.MajorTickMarkWidth, xari.Y + tickLabelStep / 2); foreach (XSeries xs in xari.XValues) { for (int idx = countTickLabels - 1; idx >= 0; --idx) { XValue xv = xs[idx]; string tickLabel = xv.Value; XSize size = gfx.MeasureString(tickLabel, xari.TickLabelsFont); gfx.DrawString(tickLabel, xari.TickLabelsFont, xari.TickLabelsBrush, startPos.X - size.Width, startPos.Y + size.Height / 2); startPos.Y += tickLabelStep; } } // Draw axis. // First draw tick marks, second draw axis. double majorTickMarkStart = 0, majorTickMarkEnd = 0, minorTickMarkStart = 0, minorTickMarkEnd = 0; GetTickMarkPos(xari, ref majorTickMarkStart, ref majorTickMarkEnd, ref minorTickMarkStart, ref minorTickMarkEnd); LineFormatRenderer lineFormatRenderer = new LineFormatRenderer(gfx, xari.LineFormat); XPoint[] points = new XPoint[2]; // Minor ticks. if (xari.MinorTickMark != TickMarkType.None) { int countMinorTickMarks = (int)(xMax / xMinorTick); double minorTickMarkStep = xari.Height / countMinorTickMarks; startPos.Y = xari.Y; for (int x = 0; x <= countMinorTickMarks; x++) { points[0].X = minorTickMarkStart; points[0].Y = startPos.Y + minorTickMarkStep * x; points[1].X = minorTickMarkEnd; points[1].Y = points[0].Y; lineFormatRenderer.DrawLine(points[0], points[1]); } } // Major ticks. if (xari.MajorTickMark != TickMarkType.None) { int countMajorTickMarks = (int)(xMax / xMajorTick); double majorTickMarkStep = xari.Height / countMajorTickMarks; startPos.Y = xari.Y; for (int x = 0; x <= countMajorTickMarks; x++) { points[0].X = majorTickMarkStart; points[0].Y = startPos.Y + majorTickMarkStep * x; points[1].X = majorTickMarkEnd; points[1].Y = points[0].Y; lineFormatRenderer.DrawLine(points[0], points[1]); } } // Axis. if (xari.LineFormat != null) { points[0].X = xari.X + xari.Width; points[0].Y = xari.Y; points[1].X = xari.X + xari.Width; points[1].Y = xari.Y + xari.Height; if (xari.MajorTickMark != TickMarkType.None) { points[0].Y -= xari.LineFormat.Width / 2; points[1].Y += xari.LineFormat.Width / 2; } lineFormatRenderer.DrawLine(points[0], points[1]); } // Draw axis title. AxisTitleRendererInfo atri = xari.axisTitleRendererInfo; if (atri != null && atri.AxisTitleText != null && atri.AxisTitleText.Length > 0) { XRect rect = new XRect(xari.X, xari.Y + xari.Height / 2, atri.AxisTitleSize.Width, 0); gfx.DrawString(atri.AxisTitleText, atri.AxisTitleFont, atri.AxisTitleBrush, rect); } }
/// <summary> /// Draws the gridlines into the plot area. /// </summary> internal override void Draw() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; XRect plotAreaRect = cri.plotAreaRendererInfo.Rect; if (plotAreaRect.IsEmpty) { return; } AxisRendererInfo xari = cri.xAxisRendererInfo; AxisRendererInfo yari = cri.yAxisRendererInfo; double xMin = xari.MinimumScale; double xMax = xari.MaximumScale; double yMin = yari.MinimumScale; double yMax = yari.MaximumScale; double xMajorTick = xari.MajorTick; double yMajorTick = yari.MajorTick; double xMinorTick = xari.MinorTick; double yMinorTick = yari.MinorTick; double xMaxExtension = xari.MajorTick; XMatrix matrix = cri.plotAreaRendererInfo.matrix; LineFormatRenderer lineFormatRenderer; XGraphics gfx = this.rendererParms.Graphics; XPoint[] points = new XPoint[2]; if (xari.MinorGridlinesLineFormat != null) { lineFormatRenderer = new LineFormatRenderer(gfx, xari.MinorGridlinesLineFormat); for (double x = xMin + xMinorTick; x < xMax; x += xMinorTick) { points[0].Y = x; points[0].X = yMin; points[1].Y = x; points[1].X = yMax; matrix.TransformPoints(points); lineFormatRenderer.DrawLine(points[0], points[1]); } } if (xari.MajorGridlinesLineFormat != null) { lineFormatRenderer = new LineFormatRenderer(gfx, xari.MajorGridlinesLineFormat); for (double x = xMin; x <= xMax; x += xMajorTick) { points[0].Y = x; points[0].X = yMin; points[1].Y = x; points[1].X = yMax; matrix.TransformPoints(points); lineFormatRenderer.DrawLine(points[0], points[1]); } } if (yari.MinorGridlinesLineFormat != null) { lineFormatRenderer = new LineFormatRenderer(gfx, yari.MinorGridlinesLineFormat); for (double y = yMin + yMinorTick; y < yMax; y += yMinorTick) { points[0].Y = xMin; points[0].X = y; points[1].Y = xMax; points[1].X = y; matrix.TransformPoints(points); lineFormatRenderer.DrawLine(points[0], points[1]); } } if (yari.MajorGridlinesLineFormat != null) { lineFormatRenderer = new LineFormatRenderer(gfx, yari.MajorGridlinesLineFormat); for (double y = yMin; y <= yMax; y += yMajorTick) { points[0].Y = xMin; points[0].X = y; points[1].Y = xMax; points[1].X = y; matrix.TransformPoints(points); lineFormatRenderer.DrawLine(points[0], points[1]); } } }
/// <summary> /// Draws the horizontal X axis. /// </summary> internal override void Draw() { XGraphics gfx = this.rendererParms.Graphics; ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; AxisRendererInfo xari = cri.xAxisRendererInfo; LineFormatRenderer lineFormatRenderer = new LineFormatRenderer(gfx, xari.LineFormat); double xMin = xari.MinimumScale; double xMax = xari.MaximumScale; double xMajorTick = xari.MajorTick; double xMinorTick = xari.MinorTick; double xMaxExtension = xari.MajorTick; bool isxy = false; double majorTickMarkStart = 0, majorTickMarkEnd = 0, minorTickMarkStart = 0, minorTickMarkEnd = 0; GetTickMarkPos(xari, ref majorTickMarkStart, ref majorTickMarkEnd, ref minorTickMarkStart, ref minorTickMarkEnd); XPoint[] points = new XPoint[2]; Chart chart = (Chart)this.rendererParms.DrawingItem; Series s = chart.seriesCollection[0]; double tickLabelStep = xari.Width; int countTickLabels = (int)xMax; // for non-xy if (countTickLabels != 0) { tickLabelStep = xari.Width / countTickLabels; } XPoint startPos = new XPoint(xari.X + tickLabelStep / 2, xari.Y + xari.TickLabelsHeight); if (s != null && s.Elements.getPointX(0) != null) { isxy = true; countTickLabels = (int)((xMax - xMin) / xMajorTick) + 1; if (countTickLabels != 0) { tickLabelStep = xari.Width / countTickLabels; } startPos = new XPoint(0, xari.Y + xari.TickLabelsHeight); XMatrix matrix = new XMatrix(); //XMatrix.Identity; //matrix.TranslatePrepend(xari.X, xari.InnerRect.Y ); //-xari.InnerRect.X, xMax); matrix.Scale(xari.InnerRect.Width / (xMax - xMin), 1, XMatrixOrder.Append); //matrix.ScalePrepend( 1, 1); // mirror Vertical matrix.Translate(xari.InnerRect.X, xari.InnerRect.Y, XMatrixOrder.Append); if (xari.MajorTickMark != TickMarkType.None) { startPos.Y += xari.MajorTickMarkWidth; } //matrix.OffsetX = startPos.X; // Draw axis. // First draw tick marks, second draw axis. LineFormatRenderer minorTickMarkLineFormat = new LineFormatRenderer(gfx, xari.MinorTickMarkLineFormat); LineFormatRenderer majorTickMarkLineFormat = new LineFormatRenderer(gfx, xari.MajorTickMarkLineFormat); // Draw minor tick marks. if (xari.MinorTickMark != TickMarkType.None) { for (double x = xMin + xMinorTick; x < xMax; x += xMinorTick) { points[0].X = x; points[0].Y = minorTickMarkStart; points[1].X = x; points[1].Y = minorTickMarkEnd; matrix.TransformPoints(points); minorTickMarkLineFormat.DrawLine(points[0], points[1]); } } double lineSpace = xari.TickLabelsFont.GetHeight(); int cellSpace = xari.TickLabelsFont.FontFamily.GetLineSpacing(xari.TickLabelsFont.Style); double xHeight = xari.TickLabelsFont.Metrics.XHeight; XSize labelSize = new XSize(0, 0); labelSize.Height = lineSpace * xHeight / cellSpace; for (int i = 0; i < countTickLabels; ++i) { double x = xMin + xMajorTick * i; string str = x.ToString(xari.TickLabelsFormat); labelSize = gfx.MeasureString(str, xari.TickLabelsFont); // Draw major tick marks. if (xari.MajorTickMark != TickMarkType.None) { labelSize.Width += xari.MajorTickMarkWidth * 1.5; points[0].X = x; points[0].Y = 0; // majorTickMarkStart; points[1].X = x; points[1].Y = 0; // majorTickMarkEnd; matrix.TransformPoints(points); points[1].Y += xari.MajorTickMarkWidth; majorTickMarkLineFormat.DrawLine(points[0], points[1]); } else { labelSize.Height += SpaceBetweenLabelAndTickmark; } // Draw label text. XPoint[] layoutText = new XPoint[1]; layoutText[0].X = x; layoutText[0].Y = 0; matrix.TransformPoints(layoutText); layoutText[0].Y += labelSize.Height; layoutText[0].X -= labelSize.Width / 2; // Center text horizontally gfx.DrawString(str, xari.TickLabelsFont, xari.TickLabelsBrush, layoutText[0]); } } if (!isxy) { // Draw tick labels. Each tick label will be aligned centered. //XPoint startPos = new XPoint(xari.X + tickLabelStep / 2, xari.Y + /*xari.TickLabelsHeight +*/ xari.MajorTickMarkWidth); if (xari.MajorTickMark != TickMarkType.None) { startPos.Y += xari.MajorTickMarkWidth; } foreach (XSeries xs in xari.XValues) { for (int idx = 0; idx < countTickLabels && idx < xs.Count; ++idx) { XValue xv = xs[idx]; if (xv != null) { string tickLabel = xv.Value; XSize size = gfx.MeasureString(tickLabel, xari.TickLabelsFont); gfx.DrawString(tickLabel, xari.TickLabelsFont, xari.TickLabelsBrush, startPos.X - size.Width / 2, startPos.Y); } startPos.X += tickLabelStep; } } // Minor ticks. if (xari.MinorTickMark != TickMarkType.None) { int countMinorTickMarks = (int)(xMax / xMinorTick); double minorTickMarkStep = xari.Width / countMinorTickMarks; startPos.X = xari.X; for (int x = 0; x <= countMinorTickMarks; x++) { points[0].X = startPos.X + minorTickMarkStep * x; points[0].Y = minorTickMarkStart; points[1].X = points[0].X; points[1].Y = minorTickMarkEnd; lineFormatRenderer.DrawLine(points[0], points[1]); } } // Major ticks. if (xari.MajorTickMark != TickMarkType.None) { int countMajorTickMarks = (int)(xMax / xMajorTick); double majorTickMarkStep = xari.Width; if (countMajorTickMarks != 0) { majorTickMarkStep = xari.Width / countMajorTickMarks; } startPos.X = xari.X; for (int x = 0; x <= countMajorTickMarks; x++) { points[0].X = startPos.X + majorTickMarkStep * x; points[0].Y = majorTickMarkStart; points[1].X = points[0].X; points[1].Y = majorTickMarkEnd; lineFormatRenderer.DrawLine(points[0], points[1]); } } } // Axis. if (xari.LineFormat != null) { points[0].X = xari.X; points[0].Y = xari.Y; points[1].X = xari.X + xari.Width; points[1].Y = xari.Y; if (xari.MajorTickMark != TickMarkType.None) { points[0].X -= xari.LineFormat.Width / 2; points[1].X += xari.LineFormat.Width / 2; } lineFormatRenderer.DrawLine(points[0], points[1]); } // Draw axis title. AxisTitleRendererInfo atri = xari.axisTitleRendererInfo; if (atri != null && atri.AxisTitleText != null && atri.AxisTitleText.Length > 0) { XSize size = gfx.MeasureString(atri.AxisTitleText, atri.AxisTitleFont); XRect rect = new XRect(xari.Rect.Right / 2 - atri.AxisTitleSize.Width / 2, xari.Rect.Bottom + size.Height * 2, atri.AxisTitleSize.Width, 0); gfx.DrawString(atri.AxisTitleText, atri.AxisTitleFont, atri.AxisTitleBrush, rect); } }
/// <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; } } } } }
/// <summary> /// Calculates the position, width and height of each column of all series. /// </summary> protected override void CalcColumns() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; if (cri.seriesRendererInfos.Length == 0) { return; } double xMin = cri.xAxisRendererInfo.MinimumScale; double yMin = cri.yAxisRendererInfo.MinimumScale; double yMax = cri.yAxisRendererInfo.MaximumScale; int pointCount = 0; foreach (SeriesRendererInfo sr in cri.seriesRendererInfos) { pointCount += sr.series.seriesElements.Count; } // Space shared by one clustered column. double groupWidth = cri.xAxisRendererInfo.MajorTick; // Space used by one column. double columnWidth = groupWidth * 3 / 4 / cri.seriesRendererInfos.Length; int seriesIdx = 0; XPoint[] points = new XPoint[2]; foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { // Set x to first clustered column for each series. double x = xMin + groupWidth / 2; // Offset for columns of a particular series from the start of a clustered cloumn. double dx = (columnWidth * seriesIdx) - (columnWidth / 2 * cri.seriesRendererInfos.Length); foreach (ColumnRendererInfo column in sri.pointRendererInfos) { if (column.point != null) { double x0 = x + dx; double x1 = x + dx + columnWidth; double y0 = yMin; double y1 = column.point.Value; // Draw from zero base line, if it exists. if (y0 < 0 && yMax >= 0) { y0 = 0; } // y0 should always be lower than y1, i. e. draw column from bottom to top. if (y1 < 0 && y1 < y0) { double y = y0; y0 = y1; y1 = y; } points[0].X = x0; // upper left points[0].Y = y1; points[1].X = x1; // lower right points[1].Y = y0; cri.plotAreaRendererInfo.matrix.TransformPoints(points); column.Rect = new XRect(points[0].X, points[0].Y, points[1].X - points[0].X, points[1].Y - points[0].Y); } x++; // Next clustered column. } seriesIdx++; } }
/// <summary> /// Layouts and calculates the space used by the legend. /// </summary> internal override void Format() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; LegendRendererInfo lri = cri.legendRendererInfo; if (lri == null) { return; } RendererParameters parms = new RendererParameters(); parms.Graphics = this.rendererParms.Graphics; bool verticalLegend = (lri.legend.docking == DockingType.Left || lri.legend.docking == DockingType.Right); XSize maxMarkerArea = new XSize(); LegendEntryRenderer ler = new LegendEntryRenderer(parms); foreach (LegendEntryRendererInfo leri in lri.Entries) { parms.RendererInfo = leri; ler.Format(); maxMarkerArea.Width = Math.Max(leri.MarkerArea.Width, maxMarkerArea.Width); maxMarkerArea.Height = Math.Max(leri.MarkerArea.Height, maxMarkerArea.Height); if (verticalLegend) { lri.Width = Math.Max(lri.Width, leri.Width); lri.Height += leri.Height; } else { lri.Width += leri.Width; lri.Height = Math.Max(lri.Height, leri.Height); } } // Add padding to left, right, top and bottom int paddingFactor = 1; if (lri.BorderPen != null) { paddingFactor = 2; } lri.Width += (LegendRenderer.LeftPadding + LegendRenderer.RightPadding) * paddingFactor; lri.Height += (LegendRenderer.TopPadding + LegendRenderer.BottomPadding) * paddingFactor; if (verticalLegend) { lri.Height += LegendRenderer.EntrySpacing * (lri.Entries.Length - 1); } else { lri.Width += LegendRenderer.EntrySpacing * (lri.Entries.Length - 1); } foreach (LegendEntryRendererInfo leri in lri.Entries) { leri.MarkerArea = maxMarkerArea; } }
/// <summary> /// Draws the content of the line plot area. /// </summary> internal override void Draw() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; XRect plotAreaRect = cri.plotAreaRendererInfo.Rect; if (plotAreaRect.IsEmpty) { return; } XGraphics gfx = this.rendererParms.Graphics; XGraphicsState state = gfx.Save(); //gfx.SetClip(plotAreaRect, XCombineMode.Intersect); gfx.IntersectClip(plotAreaRect); //TODO null-Values müssen berücksichtigt werden. // Verbindungspunkte können fehlen, je nachdem wie null-Values behandelt werden sollen. // (NotPlotted, Interpolate etc.) // Draw lines and markers for each data series. XMatrix matrix = cri.plotAreaRendererInfo.matrix; double xMajorTick = cri.xAxisRendererInfo.MajorTick; foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { bool isxy = false; int count = sri.series.Elements.Count; XPoint[] points = new XPoint[count]; double v; PointX px = sri.series.Elements.getPointX(0); if (px != null) { isxy = true; for (int idx = 0; idx < count; idx++) { px = sri.series.Elements.getPointX(idx); if (double.IsNaN(px.yvalue)) { v = 0; } else { v = px.yvalue; } points[idx] = new XPoint(px.xvalue, v); } } if (!isxy) { for (int idx = 0; idx < count; idx++) { v = sri.series.Elements[idx].Value; if (double.IsNaN(v)) { v = 0; } points[idx] = new XPoint(idx + xMajorTick / 2, v); } } matrix.TransformPoints(points); gfx.DrawLines(sri.LineFormat, points); DrawMarker(gfx, points, sri); } //gfx.ResetClip(); gfx.Restore(state); }
/// <summary> /// Draws the legend. /// </summary> internal override void Draw() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; LegendRendererInfo lri = cri.legendRendererInfo; if (lri == null) { return; } XGraphics gfx = this.rendererParms.Graphics; RendererParameters parms = new RendererParameters(); parms.Graphics = gfx; LegendEntryRenderer ler = new LegendEntryRenderer(parms); bool verticalLegend = (lri.legend.docking == DockingType.Left || lri.legend.docking == DockingType.Right); int paddingFactor = 1; if (lri.BorderPen != null) { paddingFactor = 2; } XRect legendRect = lri.Rect; legendRect.X += LegendRenderer.LeftPadding * paddingFactor; if (verticalLegend) { legendRect.Y = legendRect.Bottom - LegendRenderer.BottomPadding * paddingFactor; } else { legendRect.Y += LegendRenderer.TopPadding * paddingFactor; } foreach (LegendEntryRendererInfo leri in cri.legendRendererInfo.Entries) { if (verticalLegend) { legendRect.Y -= leri.Height; } XRect entryRect = legendRect; entryRect.Width = leri.Width; entryRect.Height = leri.Height; leri.Rect = entryRect; parms.RendererInfo = leri; ler.Draw(); if (verticalLegend) { legendRect.Y -= LegendRenderer.EntrySpacing; } else { legendRect.X += entryRect.Width + LegendRenderer.EntrySpacing; } } // Draw border around legend if (lri.BorderPen != null) { XRect borderRect = lri.Rect; borderRect.X += LegendRenderer.LeftPadding; borderRect.Y += LegendRenderer.TopPadding; borderRect.Width -= LegendRenderer.LeftPadding + LegendRenderer.RightPadding; borderRect.Height -= LegendRenderer.TopPadding + LegendRenderer.BottomPadding; gfx.DrawRectangle(lri.BorderPen, borderRect); } }
/// <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> /// Draws the content of the column plot area. /// </summary> internal override void Draw() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; XRect plotAreaBox = cri.plotAreaRendererInfo.Rect; if (plotAreaBox.IsEmpty) { return; } XGraphics gfx = this.rendererParms.Graphics; double xMin = cri.xAxisRendererInfo.MinimumScale; double xMax = cri.xAxisRendererInfo.MaximumScale; double yMin = cri.yAxisRendererInfo.MinimumScale; double yMax = cri.yAxisRendererInfo.MaximumScale; LineFormatRenderer lineFormatRenderer; // Under some circumstances it is possible that no zero base line will be drawn, // e. g. because of unfavourable minimum/maximum scale and/or major tick, so force to draw // a zero base line if necessary. if (cri.yAxisRendererInfo.MajorGridlinesLineFormat != null || cri.yAxisRendererInfo.MinorGridlinesLineFormat != null) { if (yMin < 0 && yMax > 0) { XPoint[] points = new XPoint[2]; points[0].X = xMin; points[0].Y = 0; points[1].X = xMax; points[1].Y = 0; cri.plotAreaRendererInfo.matrix.TransformPoints(points); if (cri.yAxisRendererInfo.MinorGridlinesLineFormat != null) { lineFormatRenderer = new LineFormatRenderer(gfx, cri.yAxisRendererInfo.MinorGridlinesLineFormat); } else { lineFormatRenderer = new LineFormatRenderer(gfx, cri.yAxisRendererInfo.MajorGridlinesLineFormat); } lineFormatRenderer.DrawLine(points[0], points[1]); } } // Draw columns XGraphicsState state = gfx.Save(); foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { foreach (ColumnRendererInfo column in sri.pointRendererInfos) { // Do not draw column if value is outside yMin/yMax range. Clipping does not make sense. if (IsDataInside(yMin, yMax, column.point.value)) { XLinearGradientBrush brush = new XLinearGradientBrush(column.Rect.BottomLeft, column.Rect.TopLeft, _orange, _orangeGradientEnd); gfx.DrawRectangle(brush, column.Rect); } } } // Draw borders around column. // A border can overlap neighbor columns, so it is important to draw borders at the end. //foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) //{ // foreach (ColumnRendererInfo column in sri.pointRendererInfos) // { // // Do not draw column if value is outside yMin/yMax range. Clipping does not make sense. // if (IsDataInside(yMin, yMax, column.point.value) && column.LineFormat.Width > 0) // { // lineFormatRenderer = new LineFormatRenderer(gfx, column.LineFormat); // lineFormatRenderer.DrawRectangle(column.Rect); // } // } //} gfx.Restore(state); }
/// <summary> /// Draws the horizontal X axis. /// </summary> internal override void Draw() { XGraphics gfx = this.rendererParms.Graphics; ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; AxisRendererInfo xari = cri.xAxisRendererInfo; double xMin = xari.MinimumScale; double xMax = xari.MaximumScale; double xMajorTick = xari.MajorTick; double xMinorTick = xari.MinorTick; double xMaxExtension = xari.MajorTick; // Draw tick labels. Each tick label will be aligned centered. int countTickLabels = (int)xMax; double tickLabelStep = xari.Width; if (countTickLabels != 0) { tickLabelStep = xari.Width / countTickLabels; } //XPoint startPos = new XPoint(xari.X + tickLabelStep / 2, xari.Y + /*xari.TickLabelsHeight +*/ xari.MajorTickMarkWidth); XPoint startPos = new XPoint(xari.X + tickLabelStep / 2, xari.Y + xari.TickLabelsHeight); if (xari.MajorTickMark != TickMarkType.None) { startPos.Y += xari.MajorTickMarkWidth; } foreach (XSeries xs in xari.XValues) { for (int idx = 0; idx < countTickLabels && idx < xs.Count; ++idx) { XValue xv = xs[idx]; if (xv != null) { string tickLabel = xv.Value; XSize size = gfx.MeasureString(tickLabel, xari.TickLabelsFont); XGraphicsState state = null; int margin = 0; if (xs.TextRotation != default) { state = gfx.Save(); margin = 20; gfx.RotateAtTransform(xs.TextRotation, new XPoint(startPos.X - size.Width / 2, startPos.Y + margin)); } gfx.DrawString(tickLabel, xari.TickLabelsFont, xari.TickLabelsBrush, startPos.X - size.Width / 2, startPos.Y + margin); if (xs.TextRotation != default && state != null) { gfx.Restore(state); } } startPos.X += tickLabelStep; } } // Draw axis. // First draw tick marks, second draw axis. double majorTickMarkStart = 0, majorTickMarkEnd = 0, minorTickMarkStart = 0, minorTickMarkEnd = 0; GetTickMarkPos(xari, ref majorTickMarkStart, ref majorTickMarkEnd, ref minorTickMarkStart, ref minorTickMarkEnd); LineFormatRenderer lineFormatRenderer = new LineFormatRenderer(gfx, xari.LineFormat); XPoint[] points = new XPoint[2]; // Minor ticks. if (xari.MinorTickMark != TickMarkType.None) { int countMinorTickMarks = (int)(xMax / xMinorTick); double minorTickMarkStep = xari.Width / countMinorTickMarks; startPos.X = xari.X; for (int x = 0; x <= countMinorTickMarks; x++) { points[0].X = startPos.X + minorTickMarkStep * x; points[0].Y = minorTickMarkStart; points[1].X = points[0].X; points[1].Y = minorTickMarkEnd; lineFormatRenderer.DrawLine(points[0], points[1]); } } // Major ticks. if (xari.MajorTickMark != TickMarkType.None) { int countMajorTickMarks = (int)(xMax / xMajorTick); double majorTickMarkStep = xari.Width; if (countMajorTickMarks != 0) { majorTickMarkStep = xari.Width / countMajorTickMarks; } startPos.X = xari.X; for (int x = 0; x <= countMajorTickMarks; x++) { points[0].X = startPos.X + majorTickMarkStep * x; points[0].Y = majorTickMarkStart; points[1].X = points[0].X; points[1].Y = majorTickMarkEnd; lineFormatRenderer.DrawLine(points[0], points[1]); } } // Axis. if (xari.LineFormat != null) { points[0].X = xari.X; points[0].Y = xari.Y; points[1].X = xari.X + xari.Width; points[1].Y = xari.Y; if (xari.MajorTickMark != TickMarkType.None) { points[0].X -= xari.LineFormat.Width / 2; points[1].X += xari.LineFormat.Width / 2; } lineFormatRenderer.DrawLine(points[0], points[1]); } // Draw axis title. AxisTitleRendererInfo atri = xari.axisTitleRendererInfo; if (atri != null && atri.AxisTitleText != null && atri.AxisTitleText.Length > 0) { XRect rect = new XRect(xari.Rect.Right / 2 - atri.AxisTitleSize.Width / 2, xari.Rect.Bottom, atri.AxisTitleSize.Width, 0); gfx.DrawString(atri.AxisTitleText, atri.AxisTitleFont, atri.AxisTitleBrush, rect); } }
/// <summary> /// Calculates the position, width and height of each column of all series. /// </summary> protected override void CalcColumns() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; if (cri.seriesRendererInfos.Length == 0) { return; } double xMin = cri.xAxisRendererInfo.MinimumScale; double xMajorTick = cri.xAxisRendererInfo.MajorTick; int maxPoints = 0; foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { maxPoints = Math.Max(maxPoints, sri.series.seriesElements.Count); } double x = xMin + xMajorTick / 2; // Space used by one column. double columnWidth = xMajorTick * 0.75 / 2; XPoint[] points = new XPoint[2]; for (int pointIdx = 0; pointIdx < maxPoints; ++pointIdx) { // Set x to first clustered column for each series. double yMin = 0, yMax = 0, y0 = 0, y1 = 0; double x0 = x - columnWidth; double x1 = x + columnWidth; foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { if (sri.pointRendererInfos.Length <= pointIdx) { break; } ColumnRendererInfo column = (ColumnRendererInfo)sri.pointRendererInfos[pointIdx]; if (column.point != null && !double.IsNaN(column.point.value)) { double y = column.point.value; if (y < 0) { y0 = yMin + y; y1 = yMin; yMin += y; } else { y0 = yMax; y1 = yMax + y; yMax += y; } points[0].X = x0; // upper left points[0].Y = y1; points[1].X = x1; // lower right points[1].Y = y0; cri.plotAreaRendererInfo.matrix.TransformPoints(points); column.Rect = new XRect(points[0].X, points[0].Y, points[1].X - points[0].X, points[1].Y - points[0].Y); } } x++; // Next stacked column. } }
/// <summary> /// Creates a data label rendererInfo. /// Does not return any renderer info. /// </summary> internal override RendererInfo Init() { ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo; foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { if (cri.chart.hasDataLabel || cri.chart.dataLabel != null || sri.series.hasDataLabel || sri.series.dataLabel != null) { DataLabelRendererInfo dlri = new DataLabelRendererInfo(); DataLabel dl = sri.series.dataLabel; if (dl == null) { dl = cri.chart.dataLabel; } if (dl == null) { dlri.Format = "0"; dlri.Font = cri.DefaultDataLabelFont; dlri.FontColor = new XSolidBrush(XColors.Black); dlri.Position = DataLabelPosition.InsideEnd; if (cri.chart.type == ChartType.Pie2D || cri.chart.type == ChartType.PieExploded2D) { dlri.Type = DataLabelType.Percent; } else { dlri.Type = DataLabelType.Value; } } else { dlri.Format = dl.Format.Length > 0 ? dl.Format : "0"; dlri.Font = Converter.ToXFont(dl.font, cri.DefaultDataLabelFont); dlri.FontColor = Converter.ToXBrush(dl.font, XColors.Black); if (dl.positionInitialized) { dlri.Position = dl.position; } else { dlri.Position = DataLabelPosition.OutsideEnd; } if (dl.typeInitialized) { dlri.Type = dl.type; } else { if (cri.chart.type == ChartType.Pie2D || cri.chart.type == ChartType.PieExploded2D) { dlri.Type = DataLabelType.Percent; } else { dlri.Type = DataLabelType.Value; } } } sri.dataLabelRendererInfo = dlri; } } return(null); }