/// <summary> /// Gets called whenever figures get added/removed from the figure collection. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnFigureListEntriesChanged(object sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Add: foreach (var o in e.NewItems) { FigureAccess access = new FigureAccess(o, OnFigureValueChanged, easeInValue: true); FigureAccesses.Add(access); var entryAnimation = new Animation((v) => { access.Entrance = (float)v; Redraw(); }, 0, 1, Easing.CubicInOut); entryAnimation.Commit(this, access.EntranceHandle, _animationFramerate, 500u); } break; case NotifyCollectionChangedAction.Move: break; case NotifyCollectionChangedAction.Remove: foreach (var o in e.OldItems) { var access = FigureAccesses[o]; if (access == null) { continue; } if (this.AnimationIsRunning(access.EntranceHandle)) { this.AbortAnimation(access.EntranceHandle); } access.Unsubscribe(); var leaveAnimation = new Animation((v) => { access.Entrance = (float)v; Redraw(); }, access.Entrance, 0, Easing.CubicInOut); leaveAnimation.Commit(this, access.EntranceHandle, _animationFramerate, 500u, finished: (v, c) => { FigureAccesses.Remove(o); Redraw(force: true); }); } break; case NotifyCollectionChangedAction.Replace: break; case NotifyCollectionChangedAction.Reset: break; default: break; } }
/// <summary> /// Draw the describtions. So far, this is chart unspecific. /// </summary> protected void DrawValueLabels(SKCanvas canvas, int width, int height) { if (FigureAccesses == null || FigureAccesses.Count == 0) { return; } using (var describtionPaint = new SKPaint() { TextSize = 20f, IsAntialias = IsAntiAliased, Color = SKColors.Black, IsStroke = false }) { //Calculating the maximum line height, that is then used for every line. float maxDescribtionHeight = 0f; foreach (FigureAccess fig in FigureAccesses) { if (!string.IsNullOrWhiteSpace(fig.Describtion)) { var describtionBounds = new SKRect(); describtionPaint.MeasureText(fig.Describtion, ref describtionBounds); maxDescribtionHeight = Math.Max(maxDescribtionHeight, describtionBounds.Height); } } DrawDescribtionBackGround(canvas, width, height, maxDescribtionHeight, FigureAccesses.Count); for (int i = 0; i < this.FigureAccesses.Count(); i++) { FigureAccess figure = FigureAccesses.ElementAt(i); if (!string.IsNullOrEmpty(figure.Describtion)) { var describtionBounds = new SKRect(); string text = figure.Describtion; describtionPaint.MeasureText(text, ref describtionBounds); maxDescribtionHeight = Math.Max(maxDescribtionHeight, describtionBounds.Height); float xOffset = 0; float yOffset = 0; float xStep = 0; float yStep = 0; int adjustedIndex = i; switch (DescribtionPosition) { case DescribtionArea.Default: case DescribtionArea.LeftAndRight: bool halfDone = i < (this.FigureAccesses.Count() + 1) / 2; adjustedIndex = halfDone ? i : i - this.FigureAccesses.Count() % 2 - this.FigureAccesses.Count() / 2; xOffset = halfDone ? width - Padding - DescribtionSpace + DescribtionPadding : +Padding + DescribtionPadding; yOffset = halfDone ? Padding + DescribtionPadding : +Padding + DescribtionPadding + ((height - 2 * Padding) - Math.Min((this.FigureAccesses.Count() / 2) * maxDescribtionHeight * DescribtionSpacing + DescribtionPadding, height - 2 * Padding)); xStep = 0; yStep = maxDescribtionHeight * DescribtionSpacing; break; case DescribtionArea.Right: xOffset = width - Padding - DescribtionSpace + DescribtionPadding; yOffset = Padding + DescribtionPadding; xStep = 0; yStep = maxDescribtionHeight * DescribtionSpacing; break; case DescribtionArea.Left: xOffset = +Padding + DescribtionPadding; yOffset = +Padding + DescribtionPadding; xStep = 0; yStep = maxDescribtionHeight * DescribtionSpacing; break; case DescribtionArea.Top: break; case DescribtionArea.Bottom: break; default: break; } SKRect colorRect = SKRect.Create( x: xOffset + xStep * adjustedIndex, y: yOffset + yStep * adjustedIndex, width: maxDescribtionHeight, height: maxDescribtionHeight ); using (var paint = new SKPaint() { IsAntialias = IsAntiAliased, Color = figure.Color, Style = SKPaintStyle.Fill }) canvas.DrawRect(colorRect, paint); canvas.DrawText(text, x: colorRect.Right + 3f, y: colorRect.Bottom, paint: describtionPaint); float valToShow = AnimateVisibleValues ? figure.AnimatedValue : figure.Value; string valText = Math.Round(valToShow, FractionalDigits).ToString("n" + FractionalDigits); canvas.DrawText( text: valText, x: colorRect.Right + describtionBounds.Width + 9f, y: colorRect.Bottom, paint: describtionPaint); } } } }
/// <summary> /// Gets called when the value of a figure changes. /// Animates the change of the value, visible through the chart. /// </summary> /// <param name="access">The figure access object of the figure whichs value changed.</param> private void OnFigureValueChanged(FigureAccess access) { var valueAnimation = new Animation((v) => { access.ValueDeltaProportion = (float)v; Redraw(); }, access.ValueDeltaProportion, 1, Easing.CubicInOut); valueAnimation.Commit(this, access.ValueAnimationHandle, _animationFramerate, 500u); }