diff --git a/src/Models/CommitGraph.cs b/src/Models/CommitGraph.cs index 916a79b1b..19b9f1191 100644 --- a/src/Models/CommitGraph.cs +++ b/src/Models/CommitGraph.cs @@ -20,6 +20,8 @@ public enum CommitGraphHighlighting public class CommitGraph { public static List Pens { get; } = []; + public static Pen GrayedCurvePen { get; private set; } = null; + public static Pen GrayedDotPen { get; private set; } = null; public static void SetDefaultPens(double thickness = 2) { @@ -33,6 +35,8 @@ public static void SetPens(List colors, double thickness) foreach (var c in colors) Pens.Add(new Pen(c.ToUInt32(), thickness)); + GrayedCurvePen = new Pen(new SolidColorBrush(Colors.Gray, 0.4), thickness); + GrayedDotPen = new Pen(Brushes.Gray, thickness); s_penCount = colors.Count; } diff --git a/src/Views/CommitGraph.cs b/src/Views/CommitGraph.cs index 88a8217c6..aa2f41570 100644 --- a/src/Views/CommitGraph.cs +++ b/src/Views/CommitGraph.cs @@ -1,4 +1,7 @@ -using Avalonia; +using System; +using System.Collections.Generic; + +using Avalonia; using Avalonia.Controls; using Avalonia.Media; @@ -64,6 +67,9 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang { base.OnPropertyChanged(change); + if (change.Property == DotBrushProperty) + _dotFillPen = null; + if (change.Property == GraphProperty || change.Property == LayoutProperty || change.Property == DotBrushProperty) @@ -72,10 +78,13 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang private void DrawCurves(DrawingContext context, Models.CommitGraph graph, double top, double bottom, double rowHeight) { - var grayedPen = new Pen(new SolidColorBrush(Colors.Gray, 0.4), Models.CommitGraph.Pens[0].Thickness); + var grayedPen = Models.CommitGraph.GrayedCurvePen; - foreach (var link in graph.Links) + // Links are ordered by their end (each link ends half a row below the commit it starts from). + var links = graph.Links; + for (var idx = FindFirstVisible(links, static l => l.End.Y, top, rowHeight); idx < links.Count; idx++) { + var link = links[idx]; var startY = link.Start.Y * rowHeight; var endY = link.End.Y * rowHeight; @@ -168,11 +177,14 @@ private void DrawCurves(DrawingContext context, Models.CommitGraph graph, double private void DrawAnchors(DrawingContext context, Models.CommitGraph graph, double top, double bottom, double rowHeight) { var dotFill = DotBrush; - var dotFillPen = new Pen(dotFill, 2); - var grayedPen = new Pen(Brushes.Gray, Models.CommitGraph.Pens[0].Thickness); + var dotFillPen = _dotFillPen ??= new Pen(dotFill, 2); + var grayedPen = Models.CommitGraph.GrayedDotPen; - foreach (var dot in graph.Dots) + // Dots are ordered by their center (one dot per commit row). + var dots = graph.Dots; + for (var idx = FindFirstVisible(dots, static d => d.Center.Y, top, rowHeight); idx < dots.Count; idx++) { + var dot = dots[idx]; var center = new Point(dot.Center.X, dot.Center.Y * rowHeight); if (center.Y < top) @@ -199,7 +211,24 @@ private void DrawAnchors(DrawingContext context, Models.CommitGraph graph, doubl } } + private static int FindFirstVisible(List items, Func getBottom, double top, double rowHeight) + { + var lo = 0; + var hi = items.Count; + while (lo < hi) + { + var mid = lo + (hi - lo) / 2; + if (getBottom(items[mid]) * rowHeight < top) + lo = mid + 1; + else + hi = mid; + } + + return lo; + } + private Models.CommitGraph _graph = null; private Models.CommitGraphLayout _layout = null; + private Pen _dotFillPen = null; } }