From 7d91c21b87e4cfa1f59bc3a4b4ed509a0d23c7af Mon Sep 17 00:00:00 2001 From: goran-w Date: Tue, 5 Nov 2024 16:55:03 +0100 Subject: [PATCH 1/8] Corrected misspelled local variable nextHigh(t)light --- src/ViewModels/DiffContext.cs | 10 ++++++++++ src/Views/TextDiffView.axaml.cs | 8 ++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/ViewModels/DiffContext.cs b/src/ViewModels/DiffContext.cs index 87b1a6de..e9bb703d 100644 --- a/src/ViewModels/DiffContext.cs +++ b/src/ViewModels/DiffContext.cs @@ -73,6 +73,16 @@ namespace SourceGit.ViewModels LoadDiffContent(); } + public void PrevChange() + { + // To be implemented... + } + + public void NextChange() + { + // To be implemented... + } + public void ToggleFullTextDiff() { Preference.Instance.UseFullTextDiff = !Preference.Instance.UseFullTextDiff; diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index da2d9ed1..76a1e65a 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -279,7 +279,7 @@ namespace SourceGit.Views var highlightBG = info.Type == Models.TextDiffLineType.Added ? _presenter.AddedHighlightBrush : _presenter.DeletedHighlightBrush; var processingIdxStart = 0; var processingIdxEnd = 0; - var nextHightlight = 0; + var nextHighlight = 0; foreach (var tl in line.TextLines) { @@ -288,9 +288,9 @@ namespace SourceGit.Views var y = line.GetTextLineVisualYPosition(tl, VisualYPosition.LineTop) - textView.VerticalOffset; var h = line.GetTextLineVisualYPosition(tl, VisualYPosition.LineBottom) - textView.VerticalOffset - y; - while (nextHightlight < info.Highlights.Count) + while (nextHighlight < info.Highlights.Count) { - var highlight = info.Highlights[nextHightlight]; + var highlight = info.Highlights[nextHighlight]; if (highlight.Start >= processingIdxEnd) break; @@ -305,7 +305,7 @@ namespace SourceGit.Views if (highlight.End >= processingIdxEnd) break; - nextHightlight++; + nextHighlight++; } processingIdxStart = processingIdxEnd; From 392ab5061e88f012e19c5d1a0a2ae2138d0906b0 Mon Sep 17 00:00:00 2001 From: goran-w Date: Thu, 7 Nov 2024 16:32:50 +0100 Subject: [PATCH 2/8] Implemented change-block navigation Modified behavior of the Prev/Next Change buttons in DiffView toolbar. Well-defined change-blocks are pre-calculated and can be navigated between. Current change-block is highlighted in the Diff panel(s). --- src/Commands/Diff.cs | 3 + src/Models/DiffResult.cs | 60 +++++++++++- src/ViewModels/DiffContext.cs | 14 ++- src/ViewModels/TwoSideTextDiff.cs | 33 +++++++ src/Views/DiffView.axaml | 3 +- src/Views/TextDiffView.axaml | 3 + src/Views/TextDiffView.axaml.cs | 147 ++++++++++++++++++++++++------ 7 files changed, 230 insertions(+), 33 deletions(-) diff --git a/src/Commands/Diff.cs b/src/Commands/Diff.cs index dea15592..02ad7319 100644 --- a/src/Commands/Diff.cs +++ b/src/Commands/Diff.cs @@ -51,6 +51,9 @@ namespace SourceGit.Commands _result.TextDiff.MaxLineNumber = Math.Max(_newLine, _oldLine); } + if (_result.TextDiff != null) + _result.TextDiff.ProcessChangeBlocks(); + return _result; } diff --git a/src/Models/DiffResult.cs b/src/Models/DiffResult.cs index e0ae82e0..afe22ad4 100644 --- a/src/Models/DiffResult.cs +++ b/src/Models/DiffResult.cs @@ -2,6 +2,8 @@ using System.Text; using System.Text.RegularExpressions; +using CommunityToolkit.Mvvm.ComponentModel; + using Avalonia; using Avalonia.Media.Imaging; @@ -59,16 +61,70 @@ namespace SourceGit.Models } } - public partial class TextDiff + public class TextDiffChangeBlock + { + public TextDiffChangeBlock(int startLine, int endLine) + { + StartLine = startLine; + EndLine = endLine; + } + + public int StartLine { get; set; } = 0; + public int EndLine { get; set; } = 0; + + public bool IsInRange(int line) + { + return line >= StartLine && line <= EndLine; + } + } + + public partial class TextDiff : ObservableObject { public string File { get; set; } = string.Empty; public List Lines { get; set; } = new List(); public Vector ScrollOffset { get; set; } = Vector.Zero; public int MaxLineNumber = 0; + public int CurrentChangeBlockIdx + { + get => _currentChangeBlockIdx; + set => SetProperty(ref _currentChangeBlockIdx, value); + } + public string Repo { get; set; } = null; public DiffOption Option { get; set; } = null; + public List ChangeBlocks { get; set; } = []; + + public void ProcessChangeBlocks() + { + ChangeBlocks.Clear(); + int lineIdx = 0, blockStartIdx = 0; + bool isNewBlock = true; + foreach (var line in Lines) + { + lineIdx++; + if (line.Type == Models.TextDiffLineType.Added || + line.Type == Models.TextDiffLineType.Deleted || + line.Type == Models.TextDiffLineType.None) // Empty + { + if (isNewBlock) + { + isNewBlock = false; + blockStartIdx = lineIdx; + } + } + else + { + if (!isNewBlock) + { + ChangeBlocks.Add(new TextDiffChangeBlock(blockStartIdx, lineIdx - 1)); + isNewBlock = true; + } + } + } + } + public TextDiffSelection MakeSelection(int startLine, int endLine, bool isCombined, bool isOldSide) { var rs = new TextDiffSelection(); @@ -626,6 +682,8 @@ namespace SourceGit.Models return true; } + private int _currentChangeBlockIdx = -1; // NOTE: Use -1 as "not set". + [GeneratedRegex(@"^@@ \-(\d+),?\d* \+(\d+),?\d* @@")] private static partial Regex REG_INDICATOR(); } diff --git a/src/ViewModels/DiffContext.cs b/src/ViewModels/DiffContext.cs index e9bb703d..a87e0bd3 100644 --- a/src/ViewModels/DiffContext.cs +++ b/src/ViewModels/DiffContext.cs @@ -75,12 +75,22 @@ namespace SourceGit.ViewModels public void PrevChange() { - // To be implemented... + if (_content is Models.TextDiff textDiff) + { + if (textDiff.CurrentChangeBlockIdx > 0) + textDiff.CurrentChangeBlockIdx--; + else if (textDiff.CurrentChangeBlockIdx == -1 && textDiff.ChangeBlocks.Count > 0) + textDiff.CurrentChangeBlockIdx = 0; // Jump to first change block + } } public void NextChange() { - // To be implemented... + if (_content is Models.TextDiff textDiff) + { + if (textDiff.CurrentChangeBlockIdx < textDiff.ChangeBlocks.Count - 1) + textDiff.CurrentChangeBlockIdx++; + } } public void ToggleFullTextDiff() diff --git a/src/ViewModels/TwoSideTextDiff.cs b/src/ViewModels/TwoSideTextDiff.cs index 3fb1e63b..493174e0 100644 --- a/src/ViewModels/TwoSideTextDiff.cs +++ b/src/ViewModels/TwoSideTextDiff.cs @@ -45,10 +45,43 @@ namespace SourceGit.ViewModels FillEmptyLines(); + ProcessChangeBlocks(); + if (previous != null && previous.File == File) _syncScrollOffset = previous._syncScrollOffset; } + public List ChangeBlocks { get; set; } = []; + + public void ProcessChangeBlocks() + { + ChangeBlocks.Clear(); + int lineIdx = 0, blockStartIdx = 0; + bool isNewBlock = true; + foreach (var line in Old) // NOTE: Same block size in both Old and New lines. + { + lineIdx++; + if (line.Type == Models.TextDiffLineType.Added || + line.Type == Models.TextDiffLineType.Deleted || + line.Type == Models.TextDiffLineType.None) // Empty + { + if (isNewBlock) + { + isNewBlock = false; + blockStartIdx = lineIdx; + } + } + else + { + if (!isNewBlock) + { + ChangeBlocks.Add(new Models.TextDiffChangeBlock(blockStartIdx, lineIdx - 1)); + isNewBlock = true; + } + } + } + } + public void ConvertsToCombinedRange(Models.TextDiff combined, ref int startLine, ref int endLine, bool isOldSide) { endLine = Math.Min(endLine, combined.Lines.Count - 1); diff --git a/src/Views/DiffView.axaml b/src/Views/DiffView.axaml index e0627ad8..360ac8fc 100644 --- a/src/Views/DiffView.axaml +++ b/src/Views/DiffView.axaml @@ -241,7 +241,8 @@ + UseFullTextDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFullTextDiff, Mode=OneWay}" + CurrentChangeBlockIdx="{Binding CurrentChangeBlockIdx, Mode=OneWay}"/> diff --git a/src/Views/TextDiffView.axaml b/src/Views/TextDiffView.axaml index d9d6dde3..7c823b49 100644 --- a/src/Views/TextDiffView.axaml +++ b/src/Views/TextDiffView.axaml @@ -30,6 +30,7 @@ UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}" WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}" ShowHiddenSymbols="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView}" + CurrentChangeBlockIdx="{Binding #ThisControl.CurrentChangeBlockIdx}" EnableChunkSelection="{Binding #ThisControl.EnableChunkSelection}" SelectedChunk="{Binding #ThisControl.SelectedChunk, Mode=TwoWay}"/> @@ -61,6 +62,7 @@ UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}" WordWrap="False" ShowHiddenSymbols="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView}" + CurrentChangeBlockIdx="{Binding #ThisControl.CurrentChangeBlockIdx}" EnableChunkSelection="{Binding #ThisControl.EnableChunkSelection}" SelectedChunk="{Binding #ThisControl.SelectedChunk, Mode=TwoWay}"/> @@ -82,6 +84,7 @@ UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}" WordWrap="False" ShowHiddenSymbols="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView}" + CurrentChangeBlockIdx="{Binding #ThisControl.CurrentChangeBlockIdx}" EnableChunkSelection="{Binding #ThisControl.EnableChunkSelection}" SelectedChunk="{Binding #ThisControl.SelectedChunk, Mode=TwoWay}"/> diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index 76a1e65a..09ca0dc9 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Globalization; using System.IO; +using System.Linq; using System.Text; using Avalonia; @@ -254,6 +255,10 @@ namespace SourceGit.Views if (_presenter.Document == null || !textView.VisualLinesValid) return; + var changeBlock = _presenter.GetCurrentChangeBlock(); + Brush changeBlockBG = new SolidColorBrush(Colors.Gray, 0.25); + Pen changeBlockFG = new Pen(Brushes.Gray, 1); + var lines = _presenter.GetLines(); var width = textView.Bounds.Width; foreach (var line in textView.VisualLines) @@ -266,51 +271,63 @@ namespace SourceGit.Views break; var info = lines[index - 1]; - var bg = GetBrushByLineType(info.Type); - if (bg == null) - continue; var startY = line.GetTextLineVisualYPosition(line.TextLines[0], VisualYPosition.LineTop) - textView.VerticalOffset; var endY = line.GetTextLineVisualYPosition(line.TextLines[^1], VisualYPosition.LineBottom) - textView.VerticalOffset; - drawingContext.DrawRectangle(bg, null, new Rect(0, startY, width, endY - startY)); - if (info.Highlights.Count > 0) + var bg = GetBrushByLineType(info.Type); + if (bg != null) { - var highlightBG = info.Type == Models.TextDiffLineType.Added ? _presenter.AddedHighlightBrush : _presenter.DeletedHighlightBrush; - var processingIdxStart = 0; - var processingIdxEnd = 0; - var nextHighlight = 0; + if (bg != null) + drawingContext.DrawRectangle(bg, null, new Rect(0, startY, width, endY - startY)); - foreach (var tl in line.TextLines) + if (info.Highlights.Count > 0) { - processingIdxEnd += tl.Length; + var highlightBG = info.Type == Models.TextDiffLineType.Added ? _presenter.AddedHighlightBrush : _presenter.DeletedHighlightBrush; + var processingIdxStart = 0; + var processingIdxEnd = 0; + var nextHighlight = 0; - var y = line.GetTextLineVisualYPosition(tl, VisualYPosition.LineTop) - textView.VerticalOffset; - var h = line.GetTextLineVisualYPosition(tl, VisualYPosition.LineBottom) - textView.VerticalOffset - y; - - while (nextHighlight < info.Highlights.Count) + foreach (var tl in line.TextLines) { - var highlight = info.Highlights[nextHighlight]; - if (highlight.Start >= processingIdxEnd) - break; + processingIdxEnd += tl.Length; - var start = line.GetVisualColumn(highlight.Start < processingIdxStart ? processingIdxStart : highlight.Start); - var end = line.GetVisualColumn(highlight.End >= processingIdxEnd ? processingIdxEnd : highlight.End + 1); + var y = line.GetTextLineVisualYPosition(tl, VisualYPosition.LineTop) - textView.VerticalOffset; + var h = line.GetTextLineVisualYPosition(tl, VisualYPosition.LineBottom) - textView.VerticalOffset - y; - var x = line.GetTextLineVisualXPosition(tl, start) - textView.HorizontalOffset; - var w = line.GetTextLineVisualXPosition(tl, end) - textView.HorizontalOffset - x; - var rect = new Rect(x, y, w, h); - drawingContext.DrawRectangle(highlightBG, null, rect); + while (nextHighlight < info.Highlights.Count) + { + var highlight = info.Highlights[nextHighlight]; + if (highlight.Start >= processingIdxEnd) + break; - if (highlight.End >= processingIdxEnd) - break; + var start = line.GetVisualColumn(highlight.Start < processingIdxStart ? processingIdxStart : highlight.Start); + var end = line.GetVisualColumn(highlight.End >= processingIdxEnd ? processingIdxEnd : highlight.End + 1); - nextHighlight++; + var x = line.GetTextLineVisualXPosition(tl, start) - textView.HorizontalOffset; + var w = line.GetTextLineVisualXPosition(tl, end) - textView.HorizontalOffset - x; + var rect = new Rect(x, y, w, h); + drawingContext.DrawRectangle(highlightBG, null, rect); + + if (highlight.End >= processingIdxEnd) + break; + + nextHighlight++; + } + + processingIdxStart = processingIdxEnd; } - - processingIdxStart = processingIdxEnd; } } + + if (changeBlock != null && changeBlock.IsInRange(index)) + { + drawingContext.DrawRectangle(changeBlockBG, null, new Rect(0, startY, width, endY - startY)); + if (index == changeBlock.StartLine) + drawingContext.DrawLine(changeBlockFG, new Point(0, startY), new Point(width, startY)); + if (index == changeBlock.EndLine) + drawingContext.DrawLine(changeBlockFG, new Point(0, endY), new Point(width, endY)); + } } } @@ -486,6 +503,15 @@ namespace SourceGit.Views set => SetValue(DisplayRangeProperty, value); } + public static readonly StyledProperty CurrentChangeBlockIdxProperty = + AvaloniaProperty.Register(nameof(CurrentChangeBlockIdx)); + + public int CurrentChangeBlockIdx + { + get => GetValue(CurrentChangeBlockIdxProperty); + set => SetValue(CurrentChangeBlockIdxProperty, value); + } + protected override Type StyleKeyOverride => typeof(TextEditor); public ThemedTextDiffPresenter(TextArea area, TextDocument doc) : base(area, doc) @@ -590,6 +616,27 @@ namespace SourceGit.Views } } + public Models.TextDiffChangeBlock GetCurrentChangeBlock() + { + return GetChangeBlock(CurrentChangeBlockIdx); + } + + public virtual Models.TextDiffChangeBlock GetChangeBlock(int changeBlockIdx) + { + return null; + } + + public void JumpToChangeBlock(int changeBlockIdx) + { + var changeBlock = GetChangeBlock(changeBlockIdx); + if (changeBlock != null) + { + TextArea.Caret.Line = changeBlock.StartLine; + //TextArea.Caret.BringCaretToView(); // NOTE: Brings caret line (barely) into view. + ScrollToLine(changeBlock.StartLine); // NOTE: Brings specified line into center of view. + } + } + public override void Render(DrawingContext context) { base.Render(context); @@ -1017,6 +1064,16 @@ namespace SourceGit.Views } } + public override Models.TextDiffChangeBlock GetChangeBlock(int changeBlockIdx) + { + if (DataContext is Models.TextDiff diff) + { + if (changeBlockIdx >= 0 && changeBlockIdx < diff.ChangeBlocks.Count) + return diff.ChangeBlocks[changeBlockIdx]; + } + return null; + } + protected override void OnLoaded(RoutedEventArgs e) { base.OnLoaded(e); @@ -1233,6 +1290,16 @@ namespace SourceGit.Views } } + public override Models.TextDiffChangeBlock GetChangeBlock(int changeBlockIdx) + { + if (DataContext is ViewModels.TwoSideTextDiff diff) + { + if (changeBlockIdx >= 0 && changeBlockIdx < diff.ChangeBlocks.Count) + return diff.ChangeBlocks[changeBlockIdx]; + } + return null; + } + protected override void OnLoaded(RoutedEventArgs e) { base.OnLoaded(e); @@ -1479,6 +1546,15 @@ namespace SourceGit.Views set => SetValue(EnableChunkSelectionProperty, value); } + public static readonly StyledProperty CurrentChangeBlockIdxProperty = + AvaloniaProperty.Register(nameof(CurrentChangeBlockIdx)); + + public int CurrentChangeBlockIdx + { + get => GetValue(CurrentChangeBlockIdxProperty); + set => SetValue(CurrentChangeBlockIdxProperty, value); + } + static TextDiffView() { UseSideBySideDiffProperty.Changed.AddClassHandler((v, _) => @@ -1505,6 +1581,17 @@ namespace SourceGit.Views v.Popup.Margin = new Thickness(0, top, right, 0); v.Popup.IsVisible = true; }); + + CurrentChangeBlockIdxProperty.Changed.AddClassHandler((v, e) => + { + if (v.Editor.Presenter != null) + { + foreach (var p in v.Editor.Presenter.GetVisualDescendants().OfType()) + { + p.JumpToChangeBlock((int)e.NewValue); + } + } + }); } public TextDiffView() @@ -1552,6 +1639,8 @@ namespace SourceGit.Views IsUnstagedChange = diff.Option.IsUnstaged; EnableChunkSelection = diff.Option.WorkingCopyChange != null; + + diff.CurrentChangeBlockIdx = -1; // Unset current change block. } private void OnStageChunk(object _1, RoutedEventArgs _2) From 2edf01db3bc7e9fb87a22713852e1d3cbac49191 Mon Sep 17 00:00:00 2001 From: goran-w Date: Fri, 15 Nov 2024 13:43:05 +0100 Subject: [PATCH 3/8] Improve navigation behavior Prev/next at start/end of range now (re-)scrolls to first/last change-block (I.e when unset, or already at first/last change-block, or at the only one.) Current change-block is now unset in RefreshContent(). --- src/ViewModels/DiffContext.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/ViewModels/DiffContext.cs b/src/ViewModels/DiffContext.cs index a87e0bd3..51418baf 100644 --- a/src/ViewModels/DiffContext.cs +++ b/src/ViewModels/DiffContext.cs @@ -78,9 +78,15 @@ namespace SourceGit.ViewModels if (_content is Models.TextDiff textDiff) { if (textDiff.CurrentChangeBlockIdx > 0) + { textDiff.CurrentChangeBlockIdx--; - else if (textDiff.CurrentChangeBlockIdx == -1 && textDiff.ChangeBlocks.Count > 0) - textDiff.CurrentChangeBlockIdx = 0; // Jump to first change block + } + else if (textDiff.ChangeBlocks.Count > 0) + { + // Force property value change and (re-)jump to first change block + textDiff.CurrentChangeBlockIdx = -1; + textDiff.CurrentChangeBlockIdx = 0; + } } } @@ -89,7 +95,15 @@ namespace SourceGit.ViewModels if (_content is Models.TextDiff textDiff) { if (textDiff.CurrentChangeBlockIdx < textDiff.ChangeBlocks.Count - 1) + { textDiff.CurrentChangeBlockIdx++; + } + else if (textDiff.ChangeBlocks.Count > 0) + { + // Force property value change and (re-)jump to last change block + textDiff.CurrentChangeBlockIdx = -1; + textDiff.CurrentChangeBlockIdx = textDiff.ChangeBlocks.Count - 1; + } } } From cabf1e84d3925f67bed20c168054a03f68e6a286 Mon Sep 17 00:00:00 2001 From: goran-w Date: Sat, 16 Nov 2024 13:31:39 +0100 Subject: [PATCH 4/8] Make sure SyncScrollOffset is updated after JumpToChangeBlock() --- src/Views/TextDiffView.axaml.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index 09ca0dc9..26aed977 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -1589,6 +1589,8 @@ namespace SourceGit.Views foreach (var p in v.Editor.Presenter.GetVisualDescendants().OfType()) { p.JumpToChangeBlock((int)e.NewValue); + if (p is SingleSideTextDiffPresenter ssp) + ssp.ForceSyncScrollOffset(); } } }); From 52550fe53ee2ff2cbaa9383510caf8d26b6f8463 Mon Sep 17 00:00:00 2001 From: goran-w Date: Sat, 16 Nov 2024 13:33:10 +0100 Subject: [PATCH 5/8] Added indicator of current/total change-blocks in DiffView toolbar --- src/ViewModels/DiffContext.cs | 25 ++++++++++++++++++++++++- src/Views/DiffView.axaml | 7 +++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/ViewModels/DiffContext.cs b/src/ViewModels/DiffContext.cs index 51418baf..9d3486a1 100644 --- a/src/ViewModels/DiffContext.cs +++ b/src/ViewModels/DiffContext.cs @@ -51,6 +51,12 @@ namespace SourceGit.ViewModels private set => SetProperty(ref _unifiedLines, value); } + public string ChangeBlockIndicator + { + get => _changeBlockIndicator; + private set => SetProperty(ref _changeBlockIndicator, value); + } + public DiffContext(string repo, Models.DiffOption option, DiffContext previous = null) { _repo = repo; @@ -88,6 +94,7 @@ namespace SourceGit.ViewModels textDiff.CurrentChangeBlockIdx = 0; } } + RefreshChangeBlockIndicator(); } public void NextChange() @@ -104,9 +111,22 @@ namespace SourceGit.ViewModels textDiff.CurrentChangeBlockIdx = -1; textDiff.CurrentChangeBlockIdx = textDiff.ChangeBlocks.Count - 1; } + RefreshChangeBlockIndicator(); } } + public void RefreshChangeBlockIndicator() + { + string curr = "-", tot = "-"; + if (_content is Models.TextDiff textDiff) + { + if (textDiff.CurrentChangeBlockIdx >= 0) + curr = (textDiff.CurrentChangeBlockIdx + 1).ToString(); + tot = (textDiff.ChangeBlocks.Count).ToString(); + } + ChangeBlockIndicator = curr + "/" + tot; + } + public void ToggleFullTextDiff() { Preference.Instance.UseFullTextDiff = !Preference.Instance.UseFullTextDiff; @@ -251,7 +271,9 @@ namespace SourceGit.ViewModels FileModeChange = latest.FileModeChange; Content = rs; IsTextDiff = rs is Models.TextDiff; - }); + + RefreshChangeBlockIndicator(); + }); }); } @@ -315,6 +337,7 @@ namespace SourceGit.ViewModels private string _title; private string _fileModeChange = string.Empty; private int _unifiedLines = 4; + private string _changeBlockIndicator = "-/-"; private bool _isTextDiff = false; private bool _ignoreWhitespace = false; private object _content = null; diff --git a/src/Views/DiffView.axaml b/src/Views/DiffView.axaml index 360ac8fc..e904f4a4 100644 --- a/src/Views/DiffView.axaml +++ b/src/Views/DiffView.axaml @@ -42,6 +42,13 @@ + +