diff --git a/src/Views/Blame.axaml b/src/Views/Blame.axaml index ee07edd1..9cf8b78a 100644 --- a/src/Views/Blame.axaml +++ b/src/Views/Blame.axaml @@ -50,14 +50,14 @@ - + diff --git a/src/Views/Blame.axaml.cs b/src/Views/Blame.axaml.cs index 6e500e8e..322d94c7 100644 --- a/src/Views/Blame.axaml.cs +++ b/src/Views/Blame.axaml.cs @@ -174,7 +174,11 @@ namespace SourceGit.Views var rect = new Rect(0, y, shaLink.Width, shaLink.Height); if (rect.Contains(pos)) { - _editor.OnCommitSHAClicked(info.CommitSHA); + if (DataContext is ViewModels.Blame blame) + { + blame.NavigateToCommit(info.CommitSHA); + } + e.Handled = true; break; } @@ -229,6 +233,8 @@ namespace SourceGit.Views TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this)); TextArea.LeftMargins.Add(new CommitInfoMargin(this) { Margin = new Thickness(8, 0) }); TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this)); + TextArea.LayoutUpdated += OnTextAreaLayoutUpdated; + TextArea.Caret.PositionChanged += OnCaretPositionChanged; TextArea.TextView.ContextRequested += OnTextViewContextRequested; TextArea.TextView.VisualLinesChanged += OnTextViewVisualLinesChanged; TextArea.TextView.Margin = new Thickness(4, 0); @@ -236,11 +242,35 @@ namespace SourceGit.Views TextArea.TextView.Options.EnableEmailHyperlinks = false; } - public void OnCommitSHAClicked(string sha) + public override void Render(DrawingContext context) { - if (DataContext is ViewModels.Blame blame) + base.Render(context); + + if (string.IsNullOrEmpty(_highlight)) + return; + + var view = TextArea.TextView; + if (view == null || !view.VisualLinesValid) + return; + + var color = (Color)this.FindResource("SystemAccentColor")!; + var brush = new SolidColorBrush(color, 0.4); + foreach (var line in view.VisualLines) { - blame.NavigateToCommit(sha); + if (line.IsDisposed || line.FirstDocumentLine == null || line.FirstDocumentLine.IsDeleted) + continue; + + var lineNumber = line.FirstDocumentLine.LineNumber; + if (lineNumber >= BlameData.LineInfos.Count) + break; + + var info = BlameData.LineInfos[lineNumber - 1]; + if (info.CommitSHA != _highlight) + continue; + + var startY = line.GetTextLineVisualYPosition(line.TextLines[0], VisualYPosition.LineTop) - view.VerticalOffset; + var endY = line.GetTextLineVisualYPosition(line.TextLines[^1], VisualYPosition.LineBottom) - view.VerticalOffset; + context.FillRectangle(brush, new Rect(0, startY, Bounds.Width, endY - startY)); } } @@ -249,6 +279,8 @@ namespace SourceGit.Views base.OnUnloaded(e); TextArea.LeftMargins.Clear(); + TextArea.LayoutUpdated += OnTextAreaLayoutUpdated; + TextArea.Caret.PositionChanged -= OnCaretPositionChanged; TextArea.TextView.ContextRequested -= OnTextViewContextRequested; TextArea.TextView.VisualLinesChanged -= OnTextViewVisualLinesChanged; @@ -281,6 +313,28 @@ namespace SourceGit.Views } } + private void OnTextAreaLayoutUpdated(object sender, EventArgs e) + { + InvalidateVisual(); + } + + private void OnCaretPositionChanged(object sender, EventArgs e) + { + if (!TextArea.IsFocused) + return; + + var caret = TextArea.Caret; + if (caret.Line >= BlameData.LineInfos.Count) + return; + + var info = BlameData.LineInfos[caret.Line - 1]; + if (_highlight != info.CommitSHA) + { + _highlight = info.CommitSHA; + InvalidateVisual(); + } + } + private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e) { var selected = SelectedText; @@ -325,6 +379,7 @@ namespace SourceGit.Views } private TextMate.Installation _textMate = null; + private string _highlight = string.Empty; } public partial class Blame : ChromelessWindow