protected override Point GetToolTipPosition(ShapeMap sender, List <ShapeMap> sibilings) { DataTooltip.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); var unitW = Methods.GetUnitWidth((Invert ? AxisTags.Y : AxisTags.X), this, (Invert ? sender.Series.ScalesYAt : sender.Series.ScalesXAt)); var overflow = unitW - MaxColumnWidth * 3 > 0 ? unitW - MaxColumnWidth * 3 : 0; unitW = unitW > MaxColumnWidth * 3 ? MaxColumnWidth * 3 : unitW; var targetAxis = Invert ? sender.Series.ScalesYAt : sender.Series.ScalesXAt; var x = sender.ChartPoint.X + 1 > (AxisX[targetAxis].MaxLimit + AxisX[targetAxis].MaxLimit) / 2 ? ToPlotArea(sender.ChartPoint.X, AxisTags.X) + overflow * .5 - DataTooltip.DesiredSize.Width : ToPlotArea(sender.ChartPoint.X, AxisTags.X) + unitW + overflow * .5; var y = ToPlotArea(sibilings.Select(s => s.ChartPoint.Y).DefaultIfEmpty(0).Sum() / sibilings.Count, AxisTags.Y); y = y + DataTooltip.DesiredSize.Height > ActualHeight ? y - (y + DataTooltip.DesiredSize.Height - ActualHeight) - 5 : y; return(new Point(x, y)); }
private void PlotRow() { var stackedChart = Chart as IStackedBar; if (stackedChart == null) { return; } var stackedSeries = Chart.Series.OfType <StackedBarSeries>().ToList(); var serieIndex = stackedSeries.IndexOf(this); var unitW = Methods.GetUnitWidth(AxisTags.Y, Chart, ScalesYAt); var overflow = unitW - stackedChart.MaxColumnWidth > 0 ? unitW - stackedChart.MaxColumnWidth : 0; unitW = unitW > stackedChart.MaxColumnWidth ? stackedChart.MaxColumnWidth : unitW; var pointPadding = .1 * unitW; const int seriesPadding = 2; var h = unitW - 2 * pointPadding; var f = (Chart.Invert ? CurrentXAxis : CurrentYAxis).GetFormatter(); foreach (var point in Values.Points) { var visual = GetVisual(point); var helper = stackedChart.IndexTotals[(int)point.Y]; var w = ToPlotArea(helper.Total, AxisTags.X, ScalesXAt) - ToPlotArea(CurrentXAxis.MinLimit, AxisTags.X, ScalesXAt); var rh = w * (point.X / helper.Total); if (double.IsNaN(rh)) { return; } var stackedW = w * (helper.Stacked.ContainsKey(serieIndex) ? (helper.Stacked[serieIndex].Stacked / helper.Total) : 0); var height = Math.Max(0, h - seriesPadding); visual.PointShape.Height = height; visual.HoverShape.Height = height; visual.HoverShape.Width = rh; Canvas.SetTop(visual.PointShape, ToPlotArea(point.Y, AxisTags.Y, ScalesYAt) + pointPadding + overflow / 2); Canvas.SetTop(visual.HoverShape, ToPlotArea(point.Y, AxisTags.Y, ScalesYAt) + pointPadding + overflow / 2); Canvas.SetLeft(visual.HoverShape, ToPlotArea(CurrentXAxis.MinLimit, AxisTags.X, ScalesXAt) + stackedW); Panel.SetZIndex(visual.HoverShape, int.MaxValue); if (!Chart.DisableAnimations) { var wAnim = new DoubleAnimation { From = visual.IsNew ? 0 : visual.PointShape.Width, To = rh, Duration = TimeSpan.FromMilliseconds(500) }; var leftAnim = new DoubleAnimation { From = visual.IsNew ? ToPlotArea(CurrentXAxis.MinLimit, AxisTags.X, ScalesXAt) : Canvas.GetLeft(visual.PointShape), To = ToPlotArea(CurrentXAxis.MinLimit, AxisTags.X, ScalesXAt) + stackedW, Duration = TimeSpan.FromMilliseconds(500) }; visual.PointShape.BeginAnimation(WidthProperty, wAnim); visual.PointShape.BeginAnimation(Canvas.LeftProperty, leftAnim); } else { visual.PointShape.Width = rh; Canvas.SetLeft(visual.PointShape, ToPlotArea(CurrentXAxis.MinLimit, AxisTags.X, ScalesXAt) + stackedW); } if (DataLabels) { var tb = BindATextBlock(0); var te = f(Chart.Invert ? point.X : point.Y); var ft = new FormattedText( te, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(FontFamily, FontStyle, FontWeight, FontStretch), FontSize, Brushes.Black); Canvas.SetLeft(tb, Canvas.GetLeft(visual.HoverShape) + visual.HoverShape.Width * .5 - ft.Width * .5); Canvas.SetTop(tb, Canvas.GetTop(visual.HoverShape) + visual.HoverShape.Height * .5 - ft.Height * .5); Panel.SetZIndex(tb, int.MaxValue - 1); tb.Text = te; tb.Visibility = Visibility.Hidden; Chart.Canvas.Children.Add(tb); Chart.Shapes.Add(tb); if (!Chart.DisableAnimations) { var t = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(animationSpeed) }; t.Tick += (sender, args) => { tb.Visibility = Visibility.Visible; var fadeIn = new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(animationSpeed)); tb.BeginAnimation(OpacityProperty, fadeIn); t.Stop(); }; t.Start(); } else { tb.Visibility = Visibility.Visible; } } if (visual.IsNew) { Chart.ShapesMapper.Add(new ShapeMap { Series = this, HoverShape = visual.HoverShape, Shape = visual.PointShape, ChartPoint = point }); Chart.Canvas.Children.Add(visual.PointShape); Chart.Canvas.Children.Add(visual.HoverShape); //Shapes.Add(visual.PointShape); //Shapes.Add(visual.HoverShape); Panel.SetZIndex(visual.HoverShape, int.MaxValue); Panel.SetZIndex(visual.PointShape, int.MaxValue - 2); visual.HoverShape.MouseDown += Chart.DataMouseDown; visual.HoverShape.MouseEnter += Chart.DataMouseEnter; visual.HoverShape.MouseLeave += Chart.DataMouseLeave; } } }
private bool GetArea(int s, bool isUp, out LineAndAreaShape area, out Point ofPt) { var isNew = false; ofPt = new Point(); if (_areas.Count <= s) { var path = new Path(); BindingOperations.SetBinding(path, Shape.StrokeProperty, new Binding { Path = new PropertyPath("Stroke"), Source = this }); BindingOperations.SetBinding(path, Shape.FillProperty, new Binding { Path = new PropertyPath("Fill"), Source = this }); BindingOperations.SetBinding(path, Shape.StrokeThicknessProperty, new Binding { Path = new PropertyPath("StrokeThickness"), Source = this }); BindingOperations.SetBinding(path, VisibilityProperty, new Binding { Path = new PropertyPath("Visibility"), Source = this }); BindingOperations.SetBinding(path, Panel.ZIndexProperty, new Binding { Path = new PropertyPath(Panel.ZIndexProperty), Source = this }); BindingOperations.SetBinding(path, Shape.StrokeDashArrayProperty, new Binding { Path = new PropertyPath(StrokeDashArrayProperty), Source = this }); var geometry = new PathGeometry(); area = new LineAndAreaShape(new PathFigure(), path); geometry.Figures.Add(area.Figure); path.Data = geometry; _areas.Add(area); Chart.DrawMargin.Children.Add(path); isNew = true; if (isUp) { if (Chart.Invert) { ofPt = new Point(0, Methods.GetUnitWidth(AxisTags.Y, Chart, ScalesYAt) * .5); Canvas.SetTop(path, ofPt.Y); } else { ofPt = new Point(Methods.GetUnitWidth(AxisTags.X, Chart, ScalesXAt) * .5, 0); Canvas.SetLeft(path, ofPt.X); } } } else { area = _areas[s]; if (isUp) { if (Chart.Invert) { ofPt = new Point(0, Methods.GetUnitWidth(AxisTags.Y, Chart, ScalesYAt) * .5); Canvas.SetTop(area.Path, ofPt.Y); } else { ofPt = new Point(Methods.GetUnitWidth(AxisTags.X, Chart, ScalesXAt) * .5, 0); Canvas.SetLeft(area.Path, ofPt.X); } } } return(isNew); }
public override void Plot(bool animate = true) { _isPrimitive = Values.Count >= 1 && Values[0].GetType().IsPrimitive; var rr = PointRadius < 5 ? 5 : PointRadius; var f = (Chart.Invert ? CurrentXAxis : CurrentYAxis).GetFormatter(); var s = 0; var so = 0; var isUp = Chart is IUnitaryPoints; foreach (var segment in Values.Points.AsSegments().Where(segment => segment.Count != 0)) { LineAndAreaShape area; bool isNew = false; var ofPt = new Point(); if (_areas.Count <= s) { var path = new Path(); BindingOperations.SetBinding(path, Shape.StrokeProperty, new Binding { Path = new PropertyPath("Stroke"), Source = this }); BindingOperations.SetBinding(path, Shape.FillProperty, new Binding { Path = new PropertyPath("Fill"), Source = this }); BindingOperations.SetBinding(path, Shape.StrokeThicknessProperty, new Binding { Path = new PropertyPath("StrokeThickness"), Source = this }); BindingOperations.SetBinding(path, VisibilityProperty, new Binding { Path = new PropertyPath("Visibility"), Source = this }); BindingOperations.SetBinding(path, Panel.ZIndexProperty, new Binding { Path = new PropertyPath(Panel.ZIndexProperty), Source = this }); BindingOperations.SetBinding(path, Shape.StrokeDashArrayProperty, new Binding { Path = new PropertyPath(StrokeDashArrayProperty), Source = this }); var geometry = new PathGeometry(); area = new LineAndAreaShape(new PathFigure(), path); geometry.Figures.Add(area.Figure); path.Data = geometry; _areas.Add(area); Chart.DrawMargin.Children.Add(path); isNew = true; if (isUp) { if (Chart.Invert) { ofPt = new Point(0, Methods.GetUnitWidth(AxisTags.Y, Chart, ScalesYAt) * .5); Canvas.SetTop(path, ofPt.Y); } else { ofPt = new Point(Methods.GetUnitWidth(AxisTags.X, Chart, ScalesYAt) * .5, 0); Canvas.SetLeft(path, ofPt.X); } } } else { area = _areas[s]; if (isUp) { if (Chart.Invert) { ofPt = new Point(0, Methods.GetUnitWidth(AxisTags.Y, Chart, ScalesYAt) * .5); Canvas.SetTop(area.Path, ofPt.Y); } else { ofPt = new Point(Methods.GetUnitWidth(AxisTags.X, Chart, ScalesYAt) * .5, 0); Canvas.SetLeft(area.Path, ofPt.X); } } } var p0 = ToDrawMargin(segment[0], ScalesXAt, ScalesYAt).AsPoint(); area.Figure.StartPoint = isNew ? (Chart.Invert ? new Point(ToPlotArea(CurrentXAxis.MinLimit, AxisTags.X, ScalesXAt), p0.X) : new Point(p0.X, ToPlotArea(CurrentYAxis.MinLimit, AxisTags.Y, ScalesYAt))) : p0; area.Figure.BeginAnimation(PathFigure.StartPointProperty, new PointAnimation(area.Figure.StartPoint, segment.Count > 0 ? p0 : new Point(), AnimSpeed)); AnimatableSegments previous = null; var isVirgin = true; var first = new Point(); var last = new Point(); for (var i = 0; i < segment.Count; i++) { var point = segment[i]; point.ChartLocation = ToDrawMargin(point, ScalesXAt, ScalesYAt).AsPoint(); if (isUp) { point.ChartLocation = new Point(point.ChartLocation.X + ofPt.X, point.ChartLocation.Y + ofPt.Y); } if (isVirgin) { isVirgin = false; first = point.ChartLocation; } var visual = GetVisual(segment[i]); PlaceVisual(visual, point.ChartLocation, rr); if (DataLabels) { Label(point, f, point.ChartLocation); } if (visual.IsNew) { AddToCanvas(visual, point); } var helper = GetSegmentHelper(point.Key, segment[i].Instance, area.Figure); helper.Data = i == segment.Count - 1 ? new BezierData(previous != null ? previous.Data.P3 : area.Figure.StartPoint) //last line is a dummy line, just to keep algorithm simple. : CalculateBezier(i, segment); helper.Previous = previous != null && previous.IsNew ? previous.Previous : previous; helper.Animate(i + so, Chart, so); previous = helper; last = point.ChartLocation; } if (area != null) { area.DrawLimits(first, last, new Point(ToDrawMargin(CurrentXAxis.MinLimit, AxisTags.X, ScalesXAt), ToDrawMargin(CurrentYAxis.MinLimit, AxisTags.Y, ScalesYAt)), Chart.Invert); } #if DEBUG Trace.WriteLine("Segments count: " + area.Figure.Segments.Count); #endif s++; so += segment.Count; } }