/// <summary> /// Initializes a new instance of the <see cref="ChartCore"/> class. /// </summary> /// <param name="view">The view.</param> /// <param name="updater">The updater.</param> protected ChartCore(IChartView view, ChartUpdater updater) { View = view; Updater = updater; DrawMargin = new CoreRectangle(); DrawMargin.SetHeight += view.SetDrawMarginHeight; DrawMargin.SetWidth += view.SetDrawMarginWidth; DrawMargin.SetTop += view.SetDrawMarginTop; DrawMargin.SetLeft += view.SetDrawMarginLeft; }
private void chart_wave_UpdaterTick(object sender) { var p = (sender as CartesianChart); chartCore = p.Model.DrawMargin; if (cutChart != null && sumChart != null) { DrawFourLine(cutChart, sumChart); } }
public override void PrepareAxes() { PivotZoomingAxis = AxisOrientation.None; View.Zoom = ZoomingOptions.None; if (View.Series.Any(x => !(x.Model is IPieSeries))) { throw new LiveChartsException( "There is a invalid series in the series collection, " + "verify that all the series implement IPieSeries."); } foreach (var xi in AxisX) { xi.S = 1; xi.MinLimit = View.Series.Select(x => x.Values.Limit1.Min) .DefaultIfEmpty(0).Min(); xi.MaxLimit = View.Series.Select(x => x.Values.Limit1.Max) .DefaultIfEmpty(0).Max(); if (Math.Abs(xi.MinLimit - xi.MaxLimit) < xi.S * .01) { xi.MinLimit -= xi.S; xi.MaxLimit += xi.S; } } foreach (var yi in AxisY) { //yi.CalculateSeparator(this, AxisTags.X); yi.MinLimit = View.Series.Select(x => x.Values.Limit2.Min) .DefaultIfEmpty(0).Min(); yi.MaxLimit = View.Series.Select(x => x.Values.Limit2.Max) .DefaultIfEmpty(0).Max(); if (Math.Abs(yi.MinLimit - yi.MaxLimit) < yi.S * .01) { yi.MinLimit -= yi.S; yi.MaxLimit += yi.S; } } StackPoints(View.Series, AxisOrientation.Y, 0); var curSize = new CoreRectangle(0, 0, ControlSize.Width, ControlSize.Height); curSize = PlaceLegend(curSize); DrawMargin.Top = curSize.Top; DrawMargin.Left = curSize.Left; DrawMargin.Width = curSize.Width; DrawMargin.Height = curSize.Height; }
public CoreRectangle PlaceLegend(CoreRectangle drawMargin) { var legendSize = View.LoadLegend(); const int padding = 10; switch (View.LegendLocation) { case LegendLocation.None: View.HideLegend(); break; case LegendLocation.Top: var top = new CorePoint(ChartControlSize.Width * .5 - legendSize.Width * .5, 0); var y = drawMargin.Top; drawMargin.Top = y + top.Y + legendSize.Height + padding; drawMargin.Height -= legendSize.Height - padding; View.ShowLegend(top); break; case LegendLocation.Bottom: var bot = new CorePoint(ChartControlSize.Width * .5 - legendSize.Width * .5, ChartControlSize.Height - legendSize.Height); drawMargin.Height -= legendSize.Height; View.ShowLegend(new CorePoint(bot.X, ChartControlSize.Height - legendSize.Height)); break; case LegendLocation.Left: drawMargin.Left = drawMargin.Left + legendSize.Width; View.ShowLegend(new CorePoint(0, ChartControlSize.Height * .5 - legendSize.Height * .5)); break; case LegendLocation.Right: drawMargin.Width -= legendSize.Width + padding; View.ShowLegend(new CorePoint(ChartControlSize.Width - legendSize.Width, ChartControlSize.Height * .5 - legendSize.Height * .5)); break; default: throw new ArgumentOutOfRangeException(); } return(drawMargin); }
/// <summary> /// Calculates the components and margin. /// </summary> public void CalculateComponentsAndMargin() { var curSize = new CoreRectangle(0, 0, ControlSize.Width, ControlSize.Height); curSize = PlaceLegend(curSize); const double padding = 4; for (int index = 0; index < AxisY.Count; index++) { var ax = AxisY[index]; var titleSize = ax.View.UpdateTitle(this, -90d); var biggest = ax.PrepareChart(AxisOrientation.Y, this); var x = curSize.Left; if (ax.Position == AxisPosition.LeftBottom) { ax.View.SetTitleLeft(x); curSize.Left += titleSize.Height + biggest.Width + padding; curSize.Width -= (titleSize.Height + biggest.Width + padding); ax.Tab = curSize.Left; } else { ax.View.SetTitleLeft(x + curSize.Width - titleSize.Height); curSize.Width -= (titleSize.Height + biggest.Width + padding); ax.Tab = curSize.Left + curSize.Width; } var uw = ax.EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(AxisOrientation.Y, this, index) / 2 : 0; var topE = biggest.Top - uw; if (topE > curSize.Top) { var dif = topE - curSize.Top; curSize.Top += dif; curSize.Height -= dif; } var botE = biggest.Bottom - uw; if (botE > ControlSize.Height - (curSize.Top + curSize.Height)) { var dif = botE - (ControlSize.Height - (curSize.Top + curSize.Height)); curSize.Height -= dif; } } for (var index = 0; index < AxisX.Count; index++) { var xi = AxisX[index]; var titleSize = xi.View.UpdateTitle(this); var biggest = xi.PrepareChart(AxisOrientation.X, this); var top = curSize.Top; if (xi.Position == AxisPosition.LeftBottom) { xi.View.SetTitleTop(top + curSize.Height - titleSize.Height); curSize.Height -= (titleSize.Height + biggest.Height); xi.Tab = curSize.Top + curSize.Height; } else { xi.View.SetTitleTop(top); curSize.Top += titleSize.Height + biggest.Height; curSize.Height -= (titleSize.Height + biggest.Height); xi.Tab = curSize.Top; } //Notice the unit width is not exact at this point... var uw = xi.EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(AxisOrientation.X, this, index) / 2 : 0; var leftE = biggest.Left - uw > 0 ? biggest.Left - uw : 0; if (leftE > curSize.Left) { var dif = leftE - curSize.Left; curSize.Left += dif; curSize.Width -= dif; foreach (var correctedAxis in AxisY .Where(correctedAxis => correctedAxis.Position == AxisPosition.LeftBottom)) { correctedAxis.Tab += dif; } } var rightE = biggest.Right - uw > 0 ? biggest.Right - uw : 0; if (rightE > ControlSize.Width - (curSize.Left + curSize.Width)) { var dif = rightE - (ControlSize.Width - (curSize.Left + curSize.Width)); curSize.Width -= dif; foreach (var correctedAxis in AxisY .Where(correctedAxis => correctedAxis.Position == AxisPosition.RightTop)) { correctedAxis.Tab -= dif; } } } DrawMargin.Top = curSize.Top; DrawMargin.Left = curSize.Left; DrawMargin.Width = curSize.Width; DrawMargin.Height = curSize.Height; for (var index = 0; index < AxisY.Count; index++) { var ax = AxisY[index]; var pr = ChartFunctions.FromPlotArea(ax.MaxPointRadius, AxisOrientation.Y, this, index) - ChartFunctions.FromPlotArea(0, AxisOrientation.Y, this, index); if (!double.IsNaN(pr)) { ax.BotLimit += pr; ax.TopLimit -= pr; } ax.UpdateSeparators(AxisOrientation.Y, this, index); ax.View.SetTitleTop(curSize.Top + curSize.Height * .5 + ax.View.GetLabelSize().Width *.5); } for (var index = 0; index < AxisX.Count; index++) { var xi = AxisX[index]; var pr = ChartFunctions.FromPlotArea(xi.MaxPointRadius, AxisOrientation.X, this, index) - ChartFunctions.FromPlotArea(0, AxisOrientation.X, this, index); if (!double.IsNaN(pr)) { xi.BotLimit -= pr; xi.TopLimit += pr; } xi.UpdateSeparators(AxisOrientation.X, this, index); xi.View.SetTitleLeft(curSize.Left + curSize.Width * .5 - xi.View.GetLabelSize().Width *.5); } }
public override void DrawOrMove(ChartPoint previousDrawn, ChartPoint current, int index, ChartCore chart) { var previosPbv = previousDrawn == null ? null : (VerticalBezierPointView)previousDrawn.View; Container.Segments.Remove(Segment); Container.Segments.Insert(index, Segment); ValidArea = new CoreRectangle(current.ChartLocation.X - 7.5, current.ChartLocation.Y - 7.5, 15, 15); if (IsNew) { if (previosPbv != null && !previosPbv.IsNew) { Segment.Point1 = previosPbv.Segment.Point3; Segment.Point2 = previosPbv.Segment.Point3; Segment.Point3 = previosPbv.Segment.Point3; if (DataLabel != null) { Canvas.SetTop(DataLabel, Canvas.GetTop(previosPbv.DataLabel)); Canvas.SetLeft(DataLabel, Canvas.GetLeft(previosPbv.DataLabel)); } if (Shape != null) { Canvas.SetTop(Shape, Canvas.GetTop(previosPbv.Shape)); Canvas.SetLeft(Shape, Canvas.GetLeft(previosPbv.Shape)); } } else { if (current.SeriesView.IsFirstDraw) { Segment.Point1 = new Point(0, Data.Point1.Y); Segment.Point2 = new Point(0, Data.Point2.Y); Segment.Point3 = new Point(0, Data.Point3.Y); if (Shape != null) { Canvas.SetTop(Shape, current.ChartLocation.Y - Shape.Height * .5); Canvas.SetLeft(Shape, 0); } if (DataLabel != null) { Canvas.SetTop(DataLabel, current.ChartLocation.Y - DataLabel.ActualHeight * .5); Canvas.SetLeft(DataLabel, 0); } } else { var startPoint = ((LineSeries)current.SeriesView).Splitters[0].Left.Point; Segment.Point1 = startPoint; Segment.Point2 = startPoint; Segment.Point3 = startPoint; if (Shape != null) { Canvas.SetTop(Shape, startPoint.Y - Shape.Height * .5); Canvas.SetLeft(Shape, startPoint.X); } if (DataLabel != null) { Canvas.SetTop(DataLabel, startPoint.Y - DataLabel.ActualHeight * .5); Canvas.SetLeft(DataLabel, startPoint.X); } } } } else if (DataLabel != null && double.IsNaN(Canvas.GetLeft(DataLabel))) { Canvas.SetTop(DataLabel, current.ChartLocation.Y - DataLabel.ActualHeight * .5); Canvas.SetLeft(DataLabel, 0); } #region No Animated if (chart.View.DisableAnimations) { Segment.Point1 = Data.Point1.AsPoint(); Segment.Point2 = Data.Point2.AsPoint(); Segment.Point3 = Data.Point3.AsPoint(); if (HoverShape != null) { Canvas.SetLeft(HoverShape, current.ChartLocation.X - HoverShape.Width * .5); Canvas.SetTop(HoverShape, current.ChartLocation.Y - HoverShape.Height * .5); } if (Shape != null) { Canvas.SetLeft(Shape, current.ChartLocation.X - Shape.Width * .5); Canvas.SetTop(Shape, current.ChartLocation.Y - Shape.Height * .5); } if (DataLabel != null) { DataLabel.UpdateLayout(); var xl = CorrectXLabel(current.ChartLocation.X - DataLabel.ActualWidth * .5, chart); var yl = CorrectYLabel(current.ChartLocation.Y - DataLabel.ActualHeight * .5, chart); Canvas.SetLeft(DataLabel, xl); Canvas.SetTop(DataLabel, yl); } return; } #endregion Segment.BeginAnimation(BezierSegment.Point1Property, new PointAnimation(Segment.Point1, Data.Point1.AsPoint(), chart.View.AnimationsSpeed)); Segment.BeginAnimation(BezierSegment.Point2Property, new PointAnimation(Segment.Point2, Data.Point2.AsPoint(), chart.View.AnimationsSpeed)); Segment.BeginAnimation(BezierSegment.Point3Property, new PointAnimation(Segment.Point3, Data.Point3.AsPoint(), chart.View.AnimationsSpeed)); if (Shape != null) { if (double.IsNaN(Canvas.GetLeft(Shape))) { Canvas.SetLeft(Shape, current.ChartLocation.X - Shape.Width * .5); Canvas.SetTop(Shape, current.ChartLocation.Y - Shape.Height * .5); } else { Shape.BeginAnimation(Canvas.LeftProperty, new DoubleAnimation(current.ChartLocation.X - Shape.Width * .5, chart.View.AnimationsSpeed)); Shape.BeginAnimation(Canvas.TopProperty, new DoubleAnimation(current.ChartLocation.Y - Shape.Height * .5, chart.View.AnimationsSpeed)); } } if (DataLabel != null) { DataLabel.UpdateLayout(); var xl = CorrectXLabel(current.ChartLocation.X - DataLabel.ActualWidth * .5, chart); var yl = CorrectYLabel(current.ChartLocation.Y - DataLabel.ActualHeight * .5, chart); DataLabel.BeginAnimation(Canvas.LeftProperty, new DoubleAnimation(xl, chart.View.AnimationsSpeed)); DataLabel.BeginAnimation(Canvas.TopProperty, new DoubleAnimation(yl, chart.View.AnimationsSpeed)); } if (HoverShape != null) { Canvas.SetLeft(HoverShape, current.ChartLocation.X - HoverShape.Width * .5); Canvas.SetTop(HoverShape, current.ChartLocation.Y - HoverShape.Height * .5); } }
internal void UpdateSeparators(AxisOrientation source, ChartCore chart, int axisIndex) { foreach (var element in Cache.Values.ToArray()) { if (element.GarbageCollectorIndex < GarbageCollectorIndex) { element.State = SeparationState.Remove; Cache.Remove(element.Key); } var toLine = ChartFunctions.ToPlotArea(element.Value, source, chart, axisIndex); var direction = source == AxisOrientation.X ? 1 : -1; toLine += EvaluatesUnitWidth ? direction*ChartFunctions.GetUnitWidth(source, chart, this)/2 : 0; var toLabel = toLine + element.View.LabelModel.GetOffsetBySource(source); if (IsMerged) { const double padding = 4; if (source == AxisOrientation.Y) { if (toLabel + element.View.LabelModel.ActualHeight > chart.DrawMargin.Top + chart.DrawMargin.Height) toLabel -= element.View.LabelModel.ActualHeight + padding; } else { if (toLabel + element.View.LabelModel.ActualWidth > chart.DrawMargin.Left + chart.DrawMargin.Width) toLabel -= element.View.LabelModel.ActualWidth + padding; } } var labelTab = Tab; labelTab += element.View.LabelModel.GetOffsetBySource(source.Invert()); switch (element.State) { case SeparationState.Remove: if (!chart.View.DisableAnimations && !View.DisableAnimations) { element.View.Move(chart, this, source, axisIndex, toLabel, toLine, labelTab); element.View.FadeOutAndRemove(chart); } else { element.View.Remove(chart); } break; case SeparationState.Keep: if (!chart.View.DisableAnimations && !View.DisableAnimations) { if (element.IsNew) { var toLinePrevious = FromPreviousState(element.Value, source, chart); toLinePrevious += EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(source, chart, this) / 2 : 0; var toLabelPrevious = toLinePrevious + element.View.LabelModel.GetOffsetBySource(source); element.View.Place(chart, this, source, axisIndex, toLabelPrevious, toLinePrevious, labelTab); element.View.FadeIn(this, chart); } element.View.Move(chart, this, source, axisIndex, toLabel, toLine, labelTab); } else { element.View.Place(chart, this, source, axisIndex, toLabel, toLine, labelTab); } break; case SeparationState.InitialAdd: element.View.Place(chart, this, source, axisIndex, toLabel, toLine, labelTab); break; default: throw new ArgumentOutOfRangeException(); } } LastAxisMax = TopLimit; LastAxisMin = BotLimit; LastPlotArea = new CoreRectangle(chart.DrawMargin.Left, chart.DrawMargin.Top, chart.DrawMargin.Width, chart.DrawMargin.Height); #if DEBUG Debug.WriteLine("Axis.Separations: " + Cache.Count); #endif }
public void CalculateComponentsAndMargin() { var curSize = new CoreRectangle(0, 0, ControlSize.Width, ControlSize.Height); curSize = PlaceLegend(curSize); const double padding = 4; for (int index = 0; index < AxisY.Count; index++) { var yi = AxisY[index]; var titleSize = yi.View.UpdateTitle(this, -90d); var biggest = yi.PrepareChart(AxisOrientation.Y, this); var x = curSize.Left; if (yi.Position == AxisPosition.LeftBottom) { yi.View.SetTitleLeft(x); curSize.Left += titleSize.Height + biggest.Width + padding; curSize.Width -= (titleSize.Height + biggest.Width + padding); yi.Tab = curSize.Left; } else { yi.View.SetTitleLeft(x + curSize.Width - titleSize.Height); curSize.Width -= (titleSize.Height + biggest.Width + padding); yi.Tab = curSize.Left + curSize.Width; } var uw = yi.EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(AxisOrientation.Y, this, index) / 2 : 0; var topE = biggest.Top - uw; if (topE > curSize.Top) { var dif = topE - curSize.Top; curSize.Top += dif; curSize.Height -= dif; } var botE = biggest.Bottom - uw; if (botE > ControlSize.Height - (curSize.Top + curSize.Height)) { var dif = botE - (ControlSize.Height - (curSize.Top + curSize.Height)); curSize.Height -= dif; } } for (var index = 0; index < AxisX.Count; index++) { var xi = AxisX[index]; var titleSize = xi.View.UpdateTitle(this); var biggest = xi.PrepareChart(AxisOrientation.X, this); var top = curSize.Top; if (xi.Position == AxisPosition.LeftBottom) { xi.View.SetTitleTop(top + curSize.Height - titleSize.Height); curSize.Height -= (titleSize.Height + biggest.Height); xi.Tab = curSize.Top + curSize.Height; } else { xi.View.SetTitleTop(top); curSize.Top += titleSize.Height + biggest.Height; curSize.Height -= (titleSize.Height + biggest.Height); xi.Tab = curSize.Top; } //Notice the unit width is not exact at this point... var uw = xi.EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(AxisOrientation.X, this, index) / 2 : 0; var leftE = biggest.Left - uw > 0 ? biggest.Left - uw : 0; if (leftE > curSize.Left) { var dif = leftE - curSize.Left; curSize.Left += dif; curSize.Width -= dif; foreach (var correctedAxis in AxisY .Where(correctedAxis => correctedAxis.Position == AxisPosition.LeftBottom)) { correctedAxis.Tab += dif; } } var rightE = biggest.Right - uw > 0 ? biggest.Right - uw : 0; if (rightE > ControlSize.Width - (curSize.Left + curSize.Width)) { var dif = rightE - (ControlSize.Width - (curSize.Left + curSize.Width)); curSize.Width -= dif; foreach (var correctedAxis in AxisY .Where(correctedAxis => correctedAxis.Position == AxisPosition.RightTop)) { correctedAxis.Tab -= dif; } } } //if (curSize.Left < l) //{ // var cor = l - curSize.Left; // curSize.Left = l; // curSize.Width -= cor; // foreach (var yi in AxisY.Where(x => x.Position == AxisPosition.LeftBottom)) // { // yi.View.SetTitleLeft(yi.View.GetTitleLeft() + cor); // } //} //var rp = ChartControlSize.Width - curSize.Left - curSize.Width; //if (r > rp) //{ // var cor = r - rp; // curSize.Width -= cor; // foreach (var yi in AxisY.Where(x => x.Position == AxisPosition.RightTop)) // { // yi.View.SetTitleLeft(yi.View.GetTitleLeft() - cor); // } //} DrawMargin.Top = curSize.Top; DrawMargin.Left = curSize.Left; DrawMargin.Width = curSize.Width; DrawMargin.Height = curSize.Height; for (var index = 0; index < AxisY.Count; index++) { var yi = AxisY[index]; yi.UpdateSeparators(AxisOrientation.Y, this, index); yi.View.SetTitleTop(curSize.Top + curSize.Height * .5 + yi.View.GetLabelSize().Width *.5); } for (var index = 0; index < AxisX.Count; index++) { var xi = AxisX[index]; xi.UpdateSeparators(AxisOrientation.X, this, index); xi.View.SetTitleLeft(curSize.Left + curSize.Width * .5 - xi.View.GetLabelSize().Width *.5); } }
public void CalculateComponentsAndMargin() { var curSize = new CoreRectangle(0, 0, ChartControlSize.Width, ChartControlSize.Height); curSize = PlaceLegend(curSize); double t = curSize.Top, b = 0d, bm = 0d, l = curSize.Left, r = 0d; foreach (var yi in AxisY) { var titleSize = yi.View.UpdateTitle(this, -90d); var biggest = yi.PrepareChart(AxisTags.Y, this); var x = curSize.Left; var merged = yi.IsMerged ? 0 : biggest.Width + 2; if (yi.Position == AxisPosition.LeftBottom) { yi.View.SetTitleLeft(x); yi.View.LabelsReference = x + titleSize.Height + merged; curSize.Left = curSize.Left + titleSize.Height + merged; curSize.Width -= (titleSize.Height + merged); } else { yi.View.SetTitleLeft(x + curSize.Width - titleSize.Height); yi.View.LabelsReference = x + curSize.Width - titleSize.Height - merged; curSize.Width -= (titleSize.Height + merged); } var top = yi.IsMerged ? 0 : biggest.Height * .5; if (t < top) { t = top; } var bot = yi.IsMerged ? 0 : biggest.Height * .5; if (b < bot) { b = bot; } if (yi.IsMerged && bm < biggest.Height) { bm = biggest.Height; } } if (t > 0) { curSize.Top = t; curSize.Height -= t; } if (b > 0 && !(AxisX.Count > 0)) { curSize.Height = curSize.Height - b; } foreach (var xi in AxisX) { var titleSize = xi.View.UpdateTitle(this); var biggest = xi.PrepareChart(AxisTags.X, this); var top = curSize.Top; var merged = xi.IsMerged ? 0 : biggest.Height; if (xi.Position == AxisPosition.LeftBottom) { xi.View.SetTitleTop(top + curSize.Height - titleSize.Height); xi.View.LabelsReference = top + b - (xi.IsMerged ? bm : 0) + (curSize.Height - (titleSize.Height + merged + b)) - (xi.IsMerged ? b : 0); curSize.Height -= (titleSize.Height + merged + b); } else { xi.View.SetTitleTop(top - t); xi.View.LabelsReference = (top - t) + titleSize.Height + (xi.IsMerged ? bm : 0); curSize.Top = curSize.Top + titleSize.Height + merged; curSize.Height -= (titleSize.Height + merged); } var left = xi.IsMerged ? 0 : biggest.Width * .5; if (l < left) { l = left; } var right = xi.IsMerged ? 0 : biggest.Width * .5; if (r < right) { r = right; } } if (curSize.Left < l) { var cor = l - curSize.Left; curSize.Left = l; curSize.Width -= cor; foreach (var yi in AxisY.Where(x => x.Position == AxisPosition.LeftBottom)) { yi.View.SetTitleLeft(yi.View.GetTitleLeft() + cor); yi.View.LabelsReference += cor; } } var rp = ChartControlSize.Width - curSize.Left - curSize.Width; if (r > rp) { var cor = r - rp; curSize.Width -= cor; foreach (var yi in AxisY.Where(x => x.Position == AxisPosition.RightTop)) { yi.View.SetTitleLeft(yi.View.GetTitleLeft() - cor); yi.View.LabelsReference -= cor; } } DrawMargin.Top = curSize.Top; DrawMargin.Left = curSize.Left; DrawMargin.Width = curSize.Width; DrawMargin.Height = curSize.Height; for (var index = 0; index < AxisY.Count; index++) { var yi = AxisY[index]; if (HasUnitaryPoints) { yi.View.UnitWidth = ChartFunctions.GetUnitWidth(AxisTags.Y, this, index); } yi.UpdateSeparators(AxisTags.Y, this, index); yi.View.SetTitleTop(curSize.Top + curSize.Height * .5 + yi.View.GetLabelSize().Width *.5); } for (var index = 0; index < AxisX.Count; index++) { var xi = AxisX[index]; if (HasUnitaryPoints) { xi.View.UnitWidth = ChartFunctions.GetUnitWidth(AxisTags.X, this, index); } xi.UpdateSeparators(AxisTags.X, this, index); xi.View.SetTitleLeft(curSize.Left + curSize.Width * .5 - xi.View.GetLabelSize().Width *.5); } }
internal void UpdateSeparators(AxisOrientation source, ChartCore chart, int axisIndex) { foreach (var element in Cache.Values.ToArray()) { if (element.GarbageCollectorIndex < GarbageCollectorIndex) { element.State = SeparationState.Remove; Cache.Remove(element.Key); } var toLine = ChartFunctions.ToPlotArea(element.Value, source, chart, axisIndex); var direction = source == AxisOrientation.X ? 1 : -1; toLine += EvaluatesUnitWidth ? direction * ChartFunctions.GetUnitWidth(source, chart, this) / 2 : 0; var toLabel = toLine + element.View.LabelModel.GetOffsetBySource(source); if (IsMerged) { const double padding = 4; if (source == AxisOrientation.Y) { if (toLabel + element.View.LabelModel.ActualHeight > chart.DrawMargin.Top + chart.DrawMargin.Height) { toLabel -= element.View.LabelModel.ActualHeight + padding; } } else { if (toLabel + element.View.LabelModel.ActualWidth > chart.DrawMargin.Left + chart.DrawMargin.Width) { toLabel -= element.View.LabelModel.ActualWidth + padding; } } } var labelTab = Tab; labelTab += element.View.LabelModel.GetOffsetBySource(source.Invert()); switch (element.State) { case SeparationState.Remove: if (!chart.View.DisableAnimations && !View.DisableAnimations) { element.View.Move(chart, this, source, axisIndex, toLabel, toLine, labelTab); element.View.FadeOutAndRemove(chart); } else { element.View.Remove(chart); } break; case SeparationState.Keep: if (!chart.View.DisableAnimations && !View.DisableAnimations) { if (element.IsNew) { var toLinePrevious = FromPreviousState(element.Value, source, chart); toLinePrevious += EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(source, chart, this) / 2 : 0; var toLabelPrevious = toLinePrevious + element.View.LabelModel.GetOffsetBySource(source); element.View.Place(chart, this, source, axisIndex, toLabelPrevious, toLinePrevious, labelTab); element.View.FadeIn(this, chart); } element.View.Move(chart, this, source, axisIndex, toLabel, toLine, labelTab); } else { element.View.Place(chart, this, source, axisIndex, toLabel, toLine, labelTab); } break; case SeparationState.InitialAdd: element.View.Place(chart, this, source, axisIndex, toLabel, toLine, labelTab); break; default: throw new ArgumentOutOfRangeException(); } } LastAxisMax = TopLimit; LastAxisMin = BotLimit; LastPlotArea = new CoreRectangle(chart.DrawMargin.Left, chart.DrawMargin.Top, chart.DrawMargin.Width, chart.DrawMargin.Height); }