From 3b09ea45f5481ebd36983e1368bb3069bf9f205f Mon Sep 17 00:00:00 2001 From: leo Date: Sun, 17 Nov 2024 21:49:33 +0800 Subject: [PATCH] feature: add change minimap for text diff view Signed-off-by: leo --- src/Views/CommitRefsPresenter.cs | 5 +- src/Views/TextDiffView.axaml | 53 +++++--- src/Views/TextDiffView.axaml.cs | 224 ++++++++++++++++++++++++------- 3 files changed, 216 insertions(+), 66 deletions(-) diff --git a/src/Views/CommitRefsPresenter.cs b/src/Views/CommitRefsPresenter.cs index fc3233a5..e8a66da0 100644 --- a/src/Views/CommitRefsPresenter.cs +++ b/src/Views/CommitRefsPresenter.cs @@ -38,7 +38,7 @@ namespace SourceGit.Views } public static readonly StyledProperty BackgroundProperty = - AvaloniaProperty.Register(nameof(Background), null); + AvaloniaProperty.Register(nameof(Background), Brushes.Transparent); public IBrush Background { @@ -56,7 +56,7 @@ namespace SourceGit.Views } public static readonly StyledProperty UseGraphColorProperty = - AvaloniaProperty.Register(nameof(UseGraphColor), false); + AvaloniaProperty.Register(nameof(UseGraphColor)); public bool UseGraphColor { @@ -96,7 +96,6 @@ namespace SourceGit.Views var x = 1.0; foreach (var item in _items) { - var iconRect = new RoundedRect(new Rect(x, 0, 16, 16), new CornerRadius(2, 0, 0, 2)); var entireRect = new RoundedRect(new Rect(x, 0, item.Width, 16), new CornerRadius(2)); if (item.IsHead) diff --git a/src/Views/TextDiffView.axaml b/src/Views/TextDiffView.axaml index 57427321..f2a5beaf 100644 --- a/src/Views/TextDiffView.axaml +++ b/src/Views/TextDiffView.axaml @@ -13,27 +13,39 @@ - + + + + + + + - + + + + + diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index bf4ffe60..242f8c4c 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -45,6 +45,18 @@ namespace SourceGit.Views } } + public record TextDiffViewRange + { + public int StartIdx { get; set; } = 0; + public int EndIdx { get; set; } = 0; + + public TextDiffViewRange(int startIdx, int endIdx) + { + StartIdx = startIdx; + EndIdx = endIdx; + } + } + public class ThemedTextDiffPresenter : TextEditor { public class VerticalSeperatorMargin : AbstractMargin @@ -210,7 +222,6 @@ namespace SourceGit.Views if (presenter == null) return new Size(0, 0); - var maxLineNumber = presenter.GetMaxLineNumber(); var typeface = TextView.CreateTypeface(); var test = new FormattedText( $"-", @@ -465,6 +476,15 @@ namespace SourceGit.Views get => GetValue(SelectedChunkProperty); set => SetValue(SelectedChunkProperty, value); } + + public static readonly StyledProperty DisplayRangeProperty = + AvaloniaProperty.Register(nameof(DisplayRange), new TextDiffViewRange(0, 0)); + + public TextDiffViewRange DisplayRange + { + get => GetValue(DisplayRangeProperty); + set => SetValue(DisplayRangeProperty, value); + } protected override Type StyleKeyOverride => typeof(TextEditor); @@ -500,25 +520,11 @@ namespace SourceGit.Views public void GotoPrevChange() { - var view = TextArea.TextView; - var lines = GetLines(); - var firstLineIdx = lines.Count; - foreach (var line in view.VisualLines) - { - if (line.IsDisposed || line.FirstDocumentLine == null || line.FirstDocumentLine.IsDeleted) - continue; - - var index = line.FirstDocumentLine.LineNumber - 1; - if (index >= lines.Count) - continue; - - if (firstLineIdx > index) - firstLineIdx = index; - } - + var firstLineIdx = DisplayRange.StartIdx; if (firstLineIdx <= 1) return; - + + var lines = GetLines(); var firstLineType = lines[firstLineIdx].Type; var prevLineType = lines[firstLineIdx - 1].Type; var isChangeFirstLine = firstLineType != Models.TextDiffLineType.Normal && firstLineType != Models.TextDiffLineType.Indicator; @@ -557,22 +563,8 @@ namespace SourceGit.Views public void GotoNextChange() { - var view = TextArea.TextView; var lines = GetLines(); - var lastLineIdx = -1; - foreach (var line in view.VisualLines) - { - if (line.IsDisposed || line.FirstDocumentLine == null || line.FirstDocumentLine.IsDeleted) - continue; - - var index = line.FirstDocumentLine.LineNumber - 1; - if (index >= lines.Count) - continue; - - if (lastLineIdx < index) - lastLineIdx = index; - } - + var lastLineIdx = DisplayRange.EndIdx; if (lastLineIdx >= lines.Count - 1) return; @@ -624,6 +616,7 @@ namespace SourceGit.Views TextArea.TextView.PointerEntered += OnTextViewPointerChanged; TextArea.TextView.PointerMoved += OnTextViewPointerChanged; TextArea.TextView.PointerWheelChanged += OnTextViewPointerWheelChanged; + TextArea.TextView.VisualLinesChanged += OnTextViewVisualLinesChanged; UpdateTextMate(); } @@ -636,6 +629,7 @@ namespace SourceGit.Views TextArea.TextView.PointerEntered -= OnTextViewPointerChanged; TextArea.TextView.PointerMoved -= OnTextViewPointerChanged; TextArea.TextView.PointerWheelChanged -= OnTextViewPointerWheelChanged; + TextArea.TextView.VisualLinesChanged -= OnTextViewVisualLinesChanged; if (_textMate != null) { @@ -743,6 +737,34 @@ namespace SourceGit.Views } } + private void OnTextViewVisualLinesChanged(object sender, EventArgs e) + { + if (!TextArea.TextView.VisualLinesValid) + { + SetCurrentValue(DisplayRangeProperty, new TextDiffViewRange(0, 0)); + return; + } + + var lines = GetLines(); + var start = int.MaxValue; + var count = 0; + foreach (var line in TextArea.TextView.VisualLines) + { + if (line.IsDisposed || line.FirstDocumentLine == null || line.FirstDocumentLine.IsDeleted) + continue; + + var index = line.FirstDocumentLine.LineNumber - 1; + if (index >= lines.Count) + continue; + + count++; + if (start > index) + start = index; + } + + SetCurrentValue(DisplayRangeProperty, new TextDiffViewRange(start, start + count)); + } + protected void TrySetChunk(TextDiffViewChunk chunk) { var old = SelectedChunk; @@ -1050,12 +1072,8 @@ namespace SourceGit.Views private void OnTextViewScrollGotFocus(object sender, GotFocusEventArgs e) { - if (EnableChunkSelection && sender is ScrollViewer viewer) - { - var area = viewer.FindDescendantOfType