refactor: text diff navigation

- Remove navigation by prev/next change of first/last visible block. Always use Block-Navigation
- Remove auto-updating current actived block on text view scrolling
- Auto update current active block when caret position changed
- Clean up unused resources

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo
2025-08-21 10:42:16 +08:00
parent 2da8a1d6bf
commit 8ac5896280
9 changed files with 95 additions and 300 deletions

View File

@@ -21,7 +21,6 @@
<StreamGeometry x:Key="Icons.Clone">M1280 704c0 141-115 256-256 256H288C129 960 0 831 0 672c0-126 80-232 192-272A327 327 0 01192 384c0-177 143-320 320-320 119 0 222 64 277 160C820 204 857 192 896 192c106 0 192 86 192 192 0 24-5 48-13 69C1192 477 1280 580 1280 704zm-493-128H656V352c0-18-14-32-32-32h-96c-18 0-32 14-32 32v224h-131c-29 0-43 34-23 55l211 211c12 12 33 12 45 0l211-211c20-20 6-55-23-55z</StreamGeometry>
<StreamGeometry x:Key="Icons.Close">M523 398 918 3l113 113-396 396 397 397-113 113-397-397-397 397-113-113 397-397L14 116l113-113 396 396z</StreamGeometry>
<StreamGeometry x:Key="Icons.Code">M853 102H171C133 102 102 133 102 171v683C102 891 133 922 171 922h683C891 922 922 891 922 853V171C922 133 891 102 853 102zM390 600l-48 48L205 512l137-137 48 48L301 512l88 88zM465 819l-66-18L559 205l66 18L465 819zm218-171L634 600 723 512l-88-88 48-48L819 512 683 649z</StreamGeometry>
<StreamGeometry x:Key="Icons.CodeBlock">M684 736 340 736l0-53 344 1-0 53zM552 565l-213-2 0-53 212 2-0 53zM684 392 340 392l0-53 344 1-0 53zM301 825c-45 0-78-9-100-27-22-18-33-43-33-75v-116c0-22-4-37-12-45-7-9-20-13-40-13v-61c19 0 32-4 40-12 8-9 12-24 12-46v-116c0-32 11-57 33-75 22-18 56-27 100-27h24v61h-24a35 35 0 00-27 12 41 41 0 00-11 29v116c0 35-10 60-31 75a66 66 0 01-31 14c11 2 22 6 31 14 20 17 31 42 31 75v116c0 12 4 22 11 29 7 8 16 12 27 12h24v61h-24zM701 764h24c10 0 19-4 27-12a41 41 0 0011-29v-116c0-33 10-58 31-75 9-7 19-12 31-14a66 66 0 01-31-14c-20-15-31-40-31-75v-116a41 41 0 00-11-29 35 35 0 00-27-12h-24v-61h24c45 0 78 9 100 27 22 18 33 43 33 75v116c0 22 4 37 11 46 8 8 21 12 40 12v61c-19 0-33 4-40 13-7 8-11 23-11 45v116c0 32-11 57-33 75-22 18-55 27-100 27h-24v-61z</StreamGeometry>
<StreamGeometry x:Key="Icons.ColorPicker">M128 854h768v86H128zM390 797c13 13 29 19 48 19s35-6 45-19l291-288c26-22 26-64 0-90L435 83l-61 61L426 192l-272 269c-22 22-22 64 0 90l237 246zm93-544 211 211-32 32H240l243-243zM707 694c0 48 38 86 86 86 48 0 86-38 86-86 0-22-10-45-26-61L794 576l-61 61c-13 13-26 35-26 58z</StreamGeometry>
<StreamGeometry x:Key="Icons.Commit">M0 512M1024 512M512 0M512 1024M796 471A292 292 0 00512 256a293 293 0 00-284 215H0v144h228A293 293 0 00512 832a291 291 0 00284-217H1024V471h-228M512 688A146 146 0 01366 544A145 145 0 01512 400c80 0 146 63 146 144A146 146 0 01512 688</StreamGeometry>
<StreamGeometry x:Key="Icons.CommitMessageGenerator">M796 561a5 5 0 014 7l-39 90a5 5 0 004 7h100a5 5 0 014 8l-178 247a5 5 0 01-9-4l32-148a5 5 0 00-5-6h-89a5 5 0 01-4-7l86-191a5 5 0 014-3h88zM731 122a73 73 0 0173 73v318a54 54 0 00-8-1H731V195H244v634h408l-16 73H244a73 73 0 01-73-73V195a73 73 0 0173-73h488zm-219 366v73h-195v-73h195zm146-146v73H317v-73h341z</StreamGeometry>

View File

@@ -328,7 +328,6 @@
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">Swap</x:String>
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Syntax Highlighting</x:String>
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">Line Word Wrap</x:String>
<x:String x:Key="Text.Diff.UseBlockNavigation" xml:space="preserve">Enable Block-Navigation</x:String>
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">Open in Merge Tool</x:String>
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">Show All Lines</x:String>
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">Decrease Number of Visible Lines</x:String>
@@ -560,7 +559,6 @@
<x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">Show children in the commit details</x:String>
<x:String x:Key="Text.Preferences.General.ShowTagsInGraph" xml:space="preserve">Show tags in commit graph</x:String>
<x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">Subject Guide Length</x:String>
<x:String x:Key="Text.Preferences.General.UpdateBlockNavigationOnScroll" xml:space="preserve">Update current block while scrolling in diff view (Block-Navigation)</x:String>
<x:String x:Key="Text.Preferences.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Preferences.Git.CRLF" xml:space="preserve">Enable Auto CRLF</x:String>
<x:String x:Key="Text.Preferences.Git.DefaultCloneDir" xml:space="preserve">Default Clone Dir</x:String>

View File

@@ -1,57 +1,36 @@
using System.Collections.Generic;
using Avalonia.Collections;
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
{
public class BlockNavigation : ObservableObject
{
public class Block
public record Block(int Start, int End)
{
public int Start { get; set; } = 0;
public int End { get; set; } = 0;
public Block(int start, int end)
{
Start = start;
End = end;
}
public bool IsInRange(int line)
{
return line >= Start && line <= End;
}
}
public AvaloniaList<Block> Blocks
{
get;
} = [];
public int Current
{
get => _current;
private set => SetProperty(ref _current, value);
}
public string Indicator
{
get
{
if (Blocks.Count == 0)
if (_blocks.Count == 0)
return "-/-";
if (_current >= 0 && _current < Blocks.Count)
return $"{_current + 1}/{Blocks.Count}";
if (_current >= 0 && _current < _blocks.Count)
return $"{_current + 1}/{_blocks.Count}";
return $"-/{Blocks.Count}";
return $"-/{_blocks.Count}";
}
}
public BlockNavigation(List<Models.TextDiffLine> lines)
{
Blocks.Clear();
Current = -1;
_blocks.Clear();
_current = -1;
if (lines.Count == 0)
return;
@@ -85,90 +64,89 @@ namespace SourceGit.ViewModels
if (!isNewBlock)
blocks.Add(new Block(blockStartIdx, lines.Count - 1));
Blocks.AddRange(blocks);
_blocks.AddRange(blocks);
}
public Block GetCurrentBlock()
{
if (_current >= 0 && _current < Blocks.Count)
return Blocks[_current];
if (_current >= 0 && _current < _blocks.Count)
return _blocks[_current];
return null;
}
public Block GotoFirst()
{
if (Blocks.Count == 0)
if (_blocks.Count == 0)
return null;
Current = 0;
_current = 0;
OnPropertyChanged(nameof(Indicator));
return Blocks[_current];
return _blocks[_current];
}
public Block GotoPrev()
{
if (Blocks.Count == 0)
if (_blocks.Count == 0)
return null;
if (_current == -1)
Current = 0;
_current = 0;
else if (_current > 0)
Current = _current - 1;
_current--;
OnPropertyChanged(nameof(Indicator));
return Blocks[_current];
return _blocks[_current];
}
public Block GotoNext()
{
if (Blocks.Count == 0)
if (_blocks.Count == 0)
return null;
if (_current < Blocks.Count - 1)
Current = _current + 1;
if (_current < _blocks.Count - 1)
_current++;
OnPropertyChanged(nameof(Indicator));
return Blocks[_current];
return _blocks[_current];
}
public Block GotoLast()
{
if (Blocks.Count == 0)
if (_blocks.Count == 0)
return null;
Current = Blocks.Count - 1;
_current = _blocks.Count - 1;
OnPropertyChanged(nameof(Indicator));
return Blocks[_current];
return _blocks[_current];
}
public bool AutoUpdate(int start, int end)
public void UpdateByCaretPosition(int caretLine)
{
if (_current >= 0 && _current < Blocks.Count)
if (_current >= 0 && _current < _blocks.Count)
{
var block = Blocks[_current];
if ((block.Start >= start && block.Start <= end) ||
(block.End >= start && block.End <= end) ||
(block.Start <= start && block.End >= end))
return false;
var block = _blocks[_current];
if (block.IsInRange(caretLine))
return;
}
for (var i = 0; i < Blocks.Count; i++)
for (var i = 0; i < _blocks.Count; i++)
{
var block = Blocks[i];
if ((block.Start >= start && block.Start <= end) ||
(block.End >= start && block.End <= end) ||
(block.Start <= start && block.End >= end))
{
Current = i;
OnPropertyChanged(nameof(Indicator));
return true;
}
}
var block = _blocks[i];
if (block.End < caretLine)
continue;
return false;
if (block.Start > caretLine)
_current = i - 1;
else
_current = i;
OnPropertyChanged(nameof(Indicator));
break;
}
}
private int _current = -1;
private int _current;
private List<Block> _blocks = [];
}
}

View File

@@ -46,20 +46,6 @@ namespace SourceGit.ViewModels
}
}
public bool UseBlockNavigation
{
get => Preferences.Instance.UseBlockNavigationInDiffView;
set
{
if (value != Preferences.Instance.UseBlockNavigationInDiffView)
{
Preferences.Instance.UseBlockNavigationInDiffView = value;
OnPropertyChanged();
(Content as TextDiffContext)?.ResetBlockNavigation(value);
}
}
}
public bool UseSideBySide
{
get => Preferences.Instance.UseSideBySideDiff;
@@ -156,8 +142,6 @@ namespace SourceGit.ViewModels
ctx = ctx.SwitchMode();
Content = ctx;
}
ctx.ResetBlockNavigation(UseBlockNavigation);
}
}
@@ -297,11 +281,10 @@ namespace SourceGit.ViewModels
{
IsTextDiff = true;
var hasBlockNavigation = Preferences.Instance.UseBlockNavigationInDiffView;
if (Preferences.Instance.UseSideBySideDiff)
Content = new TwoSideTextDiff(cur, hasBlockNavigation, _content as TwoSideTextDiff);
Content = new TwoSideTextDiff(cur, _content as TwoSideTextDiff);
else
Content = new CombinedTextDiff(cur, hasBlockNavigation, _content as CombinedTextDiff);
Content = new CombinedTextDiff(cur, _content as CombinedTextDiff);
}
else
{

View File

@@ -261,18 +261,6 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _useFullTextDiff, value);
}
public bool UseBlockNavigationInDiffView
{
get => _useBlockNavigationInDiffView;
set => SetProperty(ref _useBlockNavigationInDiffView, value);
}
public bool UpdateBlockNavigationOnScroll
{
get => _updateBlockNavigationOnScroll;
set => SetProperty(ref _updateBlockNavigationOnScroll, value);
}
public int LFSImageActiveIdx
{
get => _lfsImageActiveIdx;
@@ -713,7 +701,7 @@ namespace SourceGit.ViewModels
private double _defaultFontSize = 13;
private double _editorFontSize = 13;
private int _editorTabWidth = 4;
private LayoutInfo _layout = new LayoutInfo();
private LayoutInfo _layout = new();
private int _maxHistoryCommits = 20000;
private int _subjectGuideLength = 50;
@@ -734,8 +722,6 @@ namespace SourceGit.ViewModels
private bool _enableDiffViewWordWrap = false;
private bool _showHiddenSymbolsInDiffView = false;
private bool _useFullTextDiff = false;
private bool _useBlockNavigationInDiffView = false;
private bool _updateBlockNavigationOnScroll = true;
private int _lfsImageActiveIdx = 0;
private bool _enableCompactFoldersInChangesTree = false;

View File

@@ -5,15 +5,8 @@ using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
{
public record TextDiffSelectedChunk(double y, double h, int start, int end, bool combined, bool isOldSide)
public record TextDiffSelectedChunk(double Y, double Height, int StartIdx, int EndIdx, bool Combined, bool IsOldSide)
{
public double Y { get; set; } = y;
public double Height { get; set; } = h;
public int StartIdx { get; set; } = start;
public int EndIdx { get; set; } = end;
public bool Combined { get; set; } = combined;
public bool IsOldSide { get; set; } = isOldSide;
public static bool IsChanged(TextDiffSelectedChunk oldValue, TextDiffSelectedChunk newValue)
{
if (newValue == null)
@@ -31,10 +24,8 @@ namespace SourceGit.ViewModels
}
}
public record TextDiffDisplayRange(int start, int end)
public record TextDiffDisplayRange(int Start, int End)
{
public int Start { get; set; } = start;
public int End { get; set; } = end;
}
public class TextDiffContext : ObservableObject
@@ -68,14 +59,6 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _selectedChunk, value);
}
public void ResetBlockNavigation(bool enabled)
{
if (!enabled)
BlockNavigation = null;
else if (_blockNavigation == null)
BlockNavigation = CreateBlockNavigation();
}
public (int, int) FindRangeByIndex(List<Models.TextDiffLine> lines, int lineIdx)
{
var startIdx = -1;
@@ -151,43 +134,37 @@ namespace SourceGit.ViewModels
return null;
}
public virtual BlockNavigation CreateBlockNavigation()
{
return new BlockNavigation(_data.Lines);
}
protected Models.TextDiff _data = null;
protected Vector _scrollOffset = Vector.Zero;
protected BlockNavigation _blockNavigation = null;
protected TextDiffDisplayRange _displayRange = null;
protected TextDiffSelectedChunk _selectedChunk = null;
private TextDiffDisplayRange _displayRange = null;
private TextDiffSelectedChunk _selectedChunk = null;
}
public class CombinedTextDiff : TextDiffContext
{
public CombinedTextDiff(Models.TextDiff diff, bool hasBlockNavigation, CombinedTextDiff previous = null)
public CombinedTextDiff(Models.TextDiff diff, CombinedTextDiff previous = null)
{
_data = diff;
_blockNavigation = new BlockNavigation(_data.Lines);
if (previous != null && previous.File.Equals(File, StringComparison.Ordinal))
_scrollOffset = previous.ScrollOffset;
if (hasBlockNavigation)
_blockNavigation = CreateBlockNavigation();
}
public override TextDiffContext SwitchMode()
{
return new TwoSideTextDiff(_data, _blockNavigation != null);
return new TwoSideTextDiff(_data);
}
}
public class TwoSideTextDiff : TextDiffContext
{
public List<Models.TextDiffLine> Old { get; } = new List<Models.TextDiffLine>();
public List<Models.TextDiffLine> New { get; } = new List<Models.TextDiffLine>();
public List<Models.TextDiffLine> Old { get; } = [];
public List<Models.TextDiffLine> New { get; } = [];
public TwoSideTextDiff(Models.TextDiff diff, bool hasBlockNavigation, TwoSideTextDiff previous = null)
public TwoSideTextDiff(Models.TextDiff diff, TwoSideTextDiff previous = null)
{
_data = diff;
@@ -210,12 +187,10 @@ namespace SourceGit.ViewModels
}
FillEmptyLines();
_blockNavigation = new BlockNavigation(Old);
if (previous != null && previous.File.Equals(File, StringComparison.Ordinal))
_scrollOffset = previous._scrollOffset;
if (hasBlockNavigation)
_blockNavigation = CreateBlockNavigation();
}
public override bool IsSideBySide()
@@ -225,12 +200,7 @@ namespace SourceGit.ViewModels
public override TextDiffContext SwitchMode()
{
return new CombinedTextDiff(_data, _blockNavigation != null);
}
public override BlockNavigation CreateBlockNavigation()
{
return new BlockNavigation(Old);
return new CombinedTextDiff(_data);
}
public void ConvertsToCombinedRange(ref int startLine, ref int endLine, bool isOldSide)

View File

@@ -37,6 +37,7 @@
<Button Classes="icon_button"
Width="28"
Click="OnGotoFirstChange"
IsVisible="{Binding IsTextDiff}"
HotKey="{OnPlatform Ctrl+Alt+Home, macOS=⌘+Alt+Home}">
<ToolTip.Tip>
<TextBlock>
@@ -45,12 +46,6 @@
<Run Text="{OnPlatform Ctrl+Alt+Home, macOS=⌘+⌥+Home}" FontSize="11" Foreground="{DynamicResource MenuFlyoutItemKeyboardAcceleratorTextForeground}"/>
</TextBlock>
</ToolTip.Tip>
<Button.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="IsTextDiff"/>
<Binding Path="UseBlockNavigation"/>
</MultiBinding>
</Button.IsVisible>
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Top}"/>
</Button>
@@ -69,25 +64,13 @@
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Up}"/>
</Button>
<Border>
<Border.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="IsTextDiff"/>
<Binding Path="UseBlockNavigation"/>
</MultiBinding>
</Border.IsVisible>
<ContentControl Content="{Binding Content, Mode=OneWay}">
<ContentControl.DataTemplates>
<DataTemplate DataType="vm:TextDiffContext">
<ContentControl Content="{Binding BlockNavigation}"/>
</DataTemplate>
<DataTemplate DataType="vm:BlockNavigation">
<TextBlock Classes="primary" Margin="0,0,0,0" FontSize="11" Text="{Binding Indicator}"/>
</DataTemplate>
</ContentControl.DataTemplates>
</ContentControl>
</Border>
<ContentControl Content="{Binding Content, Mode=OneWay}" IsVisible="{Binding IsTextDiff}">
<ContentControl.DataTemplates>
<DataTemplate DataType="vm:TextDiffContext">
<TextBlock Classes="primary" Margin="0,0,0,0" FontSize="11" Text="{Binding BlockNavigation.Indicator}"/>
</DataTemplate>
</ContentControl.DataTemplates>
</ContentControl>
<Button Classes="icon_button"
Width="28"
@@ -107,6 +90,7 @@
<Button Classes="icon_button"
Width="28"
Click="OnGotoLastChange"
IsVisible="{Binding IsTextDiff}"
HotKey="{OnPlatform Ctrl+Alt+End, macOS=⌘+Alt+End}">
<ToolTip.Tip>
<TextBlock>
@@ -115,23 +99,9 @@
<Run Text="{OnPlatform Ctrl+Alt+End, macOS=⌘+⌥+End}" FontSize="11" Foreground="{DynamicResource MenuFlyoutItemKeyboardAcceleratorTextForeground}"/>
</TextBlock>
</ToolTip.Tip>
<Button.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="IsTextDiff"/>
<Binding Path="UseBlockNavigation"/>
</MultiBinding>
</Button.IsVisible>
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Bottom}"/>
</Button>
<ToggleButton Classes="line_path"
Width="28"
IsChecked="{Binding UseBlockNavigation, Mode=TwoWay}"
IsVisible="{Binding IsTextDiff}"
ToolTip.Tip="{DynamicResource Text.Diff.UseBlockNavigation}">
<Path Width="13" Height="13" Data="{StaticResource Icons.CodeBlock}" Margin="0,3,0,0"/>
</ToggleButton>
<Button Classes="icon_button"
Width="28"
Command="{Binding IncrUnified}"

View File

@@ -46,7 +46,7 @@
<TabItem.Header>
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preferences.General}"/>
</TabItem.Header>
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*">
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*">
<TextBlock Grid.Row="0" Grid.Column="0"
Text="{DynamicResource Text.Preferences.General.Locale}"
HorizontalAlignment="Right"
@@ -158,11 +158,6 @@
IsChecked="{Binding EnableCompactFoldersInChangesTree, Mode=TwoWay}"/>
<CheckBox Grid.Row="10" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Preferences.General.UpdateBlockNavigationOnScroll}"
IsChecked="{Binding UpdateBlockNavigationOnScroll, Mode=TwoWay}"/>
<CheckBox Grid.Row="11" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Preferences.General.Check4UpdatesOnStartup}"
IsVisible="{x:Static s:App.IsCheckForUpdateCommandVisible}"

View File

@@ -221,8 +221,8 @@ namespace SourceGit.Views
return;
var changeBlock = _presenter.BlockNavigation?.GetCurrentBlock();
Brush changeBlockBG = new SolidColorBrush(Colors.Gray, 0.25);
Pen changeBlockFG = new Pen(Brushes.Gray);
var changeBlockBG = new SolidColorBrush(Colors.Gray, 0.25);
var changeBlockFG = new Pen(Brushes.Gray);
var lines = _presenter.GetLines();
var width = textView.Bounds.Width;
@@ -496,8 +496,17 @@ namespace SourceGit.Views
public virtual void GotoFirstChange()
{
var blockNavigation = BlockNavigation;
var prev = blockNavigation?.GotoFirst();
var first = BlockNavigation?.GotoFirst();
if (first != null)
{
TextArea.Caret.Line = first.Start;
ScrollToLine(first.Start);
}
}
public virtual void GotoPrevChange()
{
var prev = BlockNavigation?.GotoPrev();
if (prev != null)
{
TextArea.Caret.Line = prev.Start;
@@ -505,112 +514,19 @@ namespace SourceGit.Views
}
}
public virtual void GotoPrevChange()
{
var blockNavigation = BlockNavigation;
if (blockNavigation != null)
{
var prev = blockNavigation.GotoPrev();
if (prev != null)
{
TextArea.Caret.Line = prev.Start;
ScrollToLine(prev.Start);
}
return;
}
if (DataContext is not ViewModels.TextDiffContext { DisplayRange: { } range })
return;
var firstLineIdx = range.Start;
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;
var isChangePrevLine = prevLineType != Models.TextDiffLineType.Normal && prevLineType != Models.TextDiffLineType.Indicator;
if (isChangeFirstLine && isChangePrevLine)
{
for (var i = firstLineIdx - 2; i >= 0; i--)
{
var prevType = lines[i].Type;
if (prevType == Models.TextDiffLineType.Normal || prevType == Models.TextDiffLineType.Indicator)
{
ScrollToLine(i + 2);
return;
}
}
}
var findChange = false;
for (var i = firstLineIdx - 1; i >= 0; i--)
{
var prevType = lines[i].Type;
if (prevType == Models.TextDiffLineType.Normal || prevType == Models.TextDiffLineType.Indicator)
{
if (findChange)
{
ScrollToLine(i + 2);
return;
}
}
else if (!findChange)
{
findChange = true;
}
}
}
public virtual void GotoNextChange()
{
var blockNavigation = BlockNavigation;
if (blockNavigation != null)
var next = BlockNavigation?.GotoNext();
if (next != null)
{
var next = blockNavigation.GotoNext();
if (next != null)
{
TextArea.Caret.Line = next.Start;
ScrollToLine(next.Start);
}
return;
}
if (DataContext is not ViewModels.TextDiffContext { DisplayRange: { } range })
return;
var lines = GetLines();
var lastLineIdx = range.End;
if (lastLineIdx >= lines.Count - 1)
return;
var lastLineType = lines[lastLineIdx].Type;
var findNormalLine = lastLineType == Models.TextDiffLineType.Normal || lastLineType == Models.TextDiffLineType.Indicator;
for (var idx = lastLineIdx + 1; idx < lines.Count; idx++)
{
var nextType = lines[idx].Type;
if (nextType is Models.TextDiffLineType.None or Models.TextDiffLineType.Added or Models.TextDiffLineType.Deleted)
{
if (findNormalLine)
{
ScrollToLine(idx + 1);
return;
}
}
else if (!findNormalLine)
{
findNormalLine = true;
}
TextArea.Caret.Line = next.Start;
ScrollToLine(next.Start);
}
}
public virtual void GotoLastChange()
{
var blockNavigation = BlockNavigation;
var next = blockNavigation?.GotoLast();
var next = BlockNavigation?.GotoLast();
if (next != null)
{
TextArea.Caret.Line = next.Start;
@@ -640,6 +556,7 @@ namespace SourceGit.Views
{
base.OnLoaded(e);
TextArea.Caret.PositionChanged += OnTextAreaCaretPositionChanged;
TextArea.TextView.ContextRequested += OnTextViewContextRequested;
TextArea.TextView.PointerEntered += OnTextViewPointerChanged;
TextArea.TextView.PointerMoved += OnTextViewPointerChanged;
@@ -658,6 +575,7 @@ namespace SourceGit.Views
TextArea.RemoveHandler(KeyDownEvent, OnTextAreaKeyDown);
TextArea.Caret.PositionChanged -= OnTextAreaCaretPositionChanged;
TextArea.TextView.ContextRequested -= OnTextViewContextRequested;
TextArea.TextView.PointerEntered -= OnTextViewPointerChanged;
TextArea.TextView.PointerMoved -= OnTextViewPointerChanged;
@@ -722,6 +640,11 @@ namespace SourceGit.Views
base.OnKeyDown(e);
}
private void OnTextAreaCaretPositionChanged(object sender, EventArgs e)
{
BlockNavigation?.UpdateByCaretPosition(TextArea?.Caret?.Line ?? 0);
}
private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e)
{
var selection = TextArea.Selection;
@@ -825,13 +748,6 @@ namespace SourceGit.Views
}
ctx.DisplayRange = new ViewModels.TextDiffDisplayRange(start, start + count);
if (ViewModels.Preferences.Instance.UpdateBlockNavigationOnScroll)
{
var changed = BlockNavigation?.AutoUpdate(start + 1, start + count) ?? false;
if (changed)
TextArea?.TextView?.Redraw();
}
}
protected void TrySetChunk(ViewModels.TextDiffSelectedChunk chunk)
@@ -1356,7 +1272,7 @@ namespace SourceGit.Views
private void OnBlockNavigationPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals("Current", StringComparison.Ordinal))
if ("Indicator".Equals(e.PropertyName, StringComparison.Ordinal))
TextArea?.TextView?.Redraw();
}