From bc404de9379f8ad301a255dc22a3d69f5cd43f65 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 13 Jan 2022 10:54:45 +0800 Subject: [PATCH] feature: show hovered sample tooltip in chart --- src/Views/Controls/Chart.cs | 57 ++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/src/Views/Controls/Chart.cs b/src/Views/Controls/Chart.cs index faa0652d..aed1fecb 100644 --- a/src/Views/Controls/Chart.cs +++ b/src/Views/Controls/Chart.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Globalization; using System.Windows; +using System.Windows.Input; using System.Windows.Media; namespace SourceGit.Views.Controls { @@ -34,8 +35,9 @@ namespace SourceGit.Views.Controls { set { SetValue(ChartBrushProperty, value); } } - private int maxV = 0; private List samples = new List(); + private List hitboxes = new List(); + private int maxV = 0; /// /// 设置绘制数据 @@ -43,13 +45,19 @@ namespace SourceGit.Views.Controls { /// 数据源 public void SetData(List samples) { this.samples = samples; - maxV = 0; + this.hitboxes.Clear(); + maxV = 0; foreach (var s in samples) { if (maxV < s.Count) maxV = s.Count; } - maxV = (int)Math.Ceiling(maxV / 10.0) * 10; + + InvalidateVisual(); + } + + protected override void OnMouseMove(MouseEventArgs e) { + base.OnMouseMove(e); InvalidateVisual(); } @@ -78,18 +86,25 @@ namespace SourceGit.Views.Controls { var dashHeight = i * stepV; var vy = Math.Max(0, dashHeight - vLabel.Height * 0.5); + dc.PushOpacity(.1); dc.DrawLine(gridPen, new Point(LABEL_UNIT + 1, dashHeight), new Point(ActualWidth, dashHeight)); + dc.Pop(); dc.DrawText(vLabel, new Point(0, vy)); } var stepX = (ActualWidth - LABEL_UNIT) / samples.Count; - var shapeWidth = Math.Min(LABEL_UNIT, stepX - 4); - for (int i = 0; i < samples.Count; i++) { - var h = samples[i].Count * (ActualHeight - LABEL_UNIT) / maxV; - var x = LABEL_UNIT + 1 + stepX * i + (stepX - shapeWidth) * 0.5; - var y = ActualHeight - LABEL_UNIT - h; - var rect = new Rect(x, y, shapeWidth, h); + if (hitboxes.Count == 0) { + var shapeWidth = Math.Min(LABEL_UNIT, stepX - 4); + for (int i = 0; i < samples.Count; i++) { + var h = samples[i].Count * (ActualHeight - LABEL_UNIT) / maxV; + var x = LABEL_UNIT + 1 + stepX * i + (stepX - shapeWidth) * 0.5; + var y = ActualHeight - LABEL_UNIT - h; + hitboxes.Add(new Rect(x, y, shapeWidth, h)); + } + } + var mouse = Mouse.GetPosition(this); + for (int i = 0; i < samples.Count; i++) { var hLabel = new FormattedText( samples[i].Name, CultureInfo.CurrentCulture, @@ -98,7 +113,8 @@ namespace SourceGit.Views.Controls { 10.0, LineBrush, VisualTreeHelper.GetDpi(this).PixelsPerDip); - var xLabel = x - (hLabel.Width - shapeWidth) * 0.5; + var rect = hitboxes[i]; + var xLabel = rect.X - (hLabel.Width - rect.Width) * 0.5; var yLabel = ActualHeight - LABEL_UNIT + 4; dc.DrawRectangle(ChartBrush, null, rect); @@ -111,7 +127,26 @@ namespace SourceGit.Views.Controls { dc.Pop(); } else { dc.DrawText(hLabel, new Point(xLabel, yLabel)); - } + } + } + + for (int i = 0; i < samples.Count; i++) { + var rect = hitboxes[i]; + if (rect.Contains(mouse)) { + var tooltip = new FormattedText( + $"{samples[i].Count}", + CultureInfo.CurrentCulture, + FlowDirection.LeftToRight, + new Typeface(font, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal), + 12.0, + FindResource("Brush.FG1") as Brush, + VisualTreeHelper.GetDpi(this).PixelsPerDip); + + var tx = rect.X - (tooltip.Width - rect.Width) * 0.5; + var ty = rect.Y - tooltip.Height - 4; + dc.DrawText(tooltip, new Point(tx, ty)); + break; + } } } }