refactor: text diff view block navigation

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo 2025-03-21 17:35:59 +08:00
parent 39f4cd1732
commit 03f49ccff0
No known key found for this signature in database
3 changed files with 77 additions and 86 deletions

View file

@ -285,10 +285,9 @@
<!-- Text Diff --> <!-- Text Diff -->
<DataTemplate DataType="m:TextDiff"> <DataTemplate DataType="m:TextDiff">
<v:TextDiffView <v:TextDiffView UseSideBySideDiff="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"
UseSideBySideDiff="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSideBySideDiff, Mode=OneWay}" UseBlockNavigation="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseBlockNavigationInDiffView, Mode=OneWay}"
UseBlockNavigation="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseBlockNavigationInDiffView, Mode=OneWay}" BlockNavigationChanged="OnBlockNavigationChanged"/>
BlockNavigationIndicator="{Binding #BlockNavigationIndicator.Text, Mode=OneWayToSource}"/>
</DataTemplate> </DataTemplate>
<!-- Empty or only EOL changes --> <!-- Empty or only EOL changes -->

View file

@ -13,30 +13,32 @@ namespace SourceGit.Views
private void OnGotoFirstChange(object _, RoutedEventArgs e) private void OnGotoFirstChange(object _, RoutedEventArgs e)
{ {
var textDiff = this.FindDescendantOfType<TextDiffView>(); this.FindDescendantOfType<TextDiffView>()?.GotoFirstChange();
textDiff?.GotoFirstChange();
e.Handled = true; e.Handled = true;
} }
private void OnGotoPrevChange(object _, RoutedEventArgs e) private void OnGotoPrevChange(object _, RoutedEventArgs e)
{ {
var textDiff = this.FindDescendantOfType<TextDiffView>(); this.FindDescendantOfType<TextDiffView>()?.GotoPrevChange();
textDiff?.GotoPrevChange();
e.Handled = true; e.Handled = true;
} }
private void OnGotoNextChange(object _, RoutedEventArgs e) private void OnGotoNextChange(object _, RoutedEventArgs e)
{ {
var textDiff = this.FindDescendantOfType<TextDiffView>(); this.FindDescendantOfType<TextDiffView>()?.GotoNextChange();
textDiff?.GotoNextChange();
e.Handled = true; e.Handled = true;
} }
private void OnGotoLastChange(object _, RoutedEventArgs e) private void OnGotoLastChange(object _, RoutedEventArgs e)
{ {
var textDiff = this.FindDescendantOfType<TextDiffView>(); this.FindDescendantOfType<TextDiffView>()?.GotoLastChange();
textDiff?.GotoLastChange();
e.Handled = true; e.Handled = true;
} }
private void OnBlockNavigationChanged(object sender, RoutedEventArgs e)
{
if (sender is TextDiffView { UseBlockNavigation: true } textDiff)
BlockNavigationIndicator.Text = textDiff.BlockNavigation?.Indicator ?? string.Empty;
}
} }
} }

View file

@ -553,7 +553,7 @@ namespace SourceGit.Views
{ {
} }
public void GotoFirstChange() public virtual void GotoFirstChange()
{ {
var blockNavigation = BlockNavigation; var blockNavigation = BlockNavigation;
if (blockNavigation != null) if (blockNavigation != null)
@ -567,7 +567,7 @@ namespace SourceGit.Views
} }
} }
public void GotoPrevChange() public virtual void GotoPrevChange()
{ {
var blockNavigation = BlockNavigation; var blockNavigation = BlockNavigation;
if (blockNavigation != null) if (blockNavigation != null)
@ -623,7 +623,7 @@ namespace SourceGit.Views
} }
} }
public void GotoNextChange() public virtual void GotoNextChange()
{ {
var blockNavigation = BlockNavigation; var blockNavigation = BlockNavigation;
if (blockNavigation != null) if (blockNavigation != null)
@ -665,7 +665,7 @@ namespace SourceGit.Views
} }
} }
public void GotoLastChange() public virtual void GotoLastChange()
{ {
var blockNavigation = BlockNavigation; var blockNavigation = BlockNavigation;
if (blockNavigation != null) if (blockNavigation != null)
@ -766,15 +766,13 @@ namespace SourceGit.Views
{ {
var oldValue = change.OldValue as ViewModels.BlockNavigation; var oldValue = change.OldValue as ViewModels.BlockNavigation;
if (oldValue != null) if (oldValue != null)
{
oldValue.PropertyChanged -= OnBlockNavigationPropertyChanged; oldValue.PropertyChanged -= OnBlockNavigationPropertyChanged;
if (oldValue.Current != -1)
TextArea?.TextView?.Redraw();
}
var newValue = change.NewValue as ViewModels.BlockNavigation; var newValue = change.NewValue as ViewModels.BlockNavigation;
if (newValue != null) if (newValue != null)
newValue.PropertyChanged += OnBlockNavigationPropertyChanged; newValue.PropertyChanged += OnBlockNavigationPropertyChanged;
TextArea?.TextView?.Redraw();
} }
} }
@ -793,9 +791,10 @@ namespace SourceGit.Views
base.OnKeyDown(e); base.OnKeyDown(e);
} }
private void OnBlockNavigationPropertyChanged(object _1, PropertyChangedEventArgs _2) private void OnBlockNavigationPropertyChanged(object _1, PropertyChangedEventArgs e)
{ {
TextArea?.TextView?.Redraw(); if (e.PropertyName == "Current")
TextArea?.TextView?.Redraw();
} }
private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e) private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e)
@ -1223,19 +1222,18 @@ namespace SourceGit.Views
{ {
base.OnLoaded(e); base.OnLoaded(e);
var scroller = this.FindDescendantOfType<ScrollViewer>(); _scrollViewer = this.FindDescendantOfType<ScrollViewer>();
if (scroller != null) if (_scrollViewer != null)
{ {
scroller.Bind(ScrollViewer.OffsetProperty, new Binding("ScrollOffset", BindingMode.TwoWay)); _scrollViewer.Bind(ScrollViewer.OffsetProperty, new Binding("ScrollOffset", BindingMode.TwoWay));
scroller.ScrollChanged += OnTextViewScrollChanged; _scrollViewer.ScrollChanged += OnTextViewScrollChanged;
} }
} }
protected override void OnUnloaded(RoutedEventArgs e) protected override void OnUnloaded(RoutedEventArgs e)
{ {
var scroller = this.FindDescendantOfType<ScrollViewer>(); if (_scrollViewer != null)
if (scroller != null) _scrollViewer.ScrollChanged -= OnTextViewScrollChanged;
scroller.ScrollChanged -= OnTextViewScrollChanged;
base.OnUnloaded(e); base.OnUnloaded(e);
} }
@ -1274,9 +1272,11 @@ namespace SourceGit.Views
private void OnTextViewScrollChanged(object sender, ScrollChangedEventArgs e) private void OnTextViewScrollChanged(object sender, ScrollChangedEventArgs e)
{ {
if (sender is ScrollViewer { IsExpanded: true, IsPointerOver: true } scroller) if (_scrollViewer is { IsExpanded: true, IsPointerOver: true })
TrySetChunk(null); TrySetChunk(null);
} }
private ScrollViewer _scrollViewer = null;
} }
public class SingleSideTextDiffPresenter : ThemedTextDiffPresenter public class SingleSideTextDiffPresenter : ThemedTextDiffPresenter
@ -1288,14 +1288,6 @@ namespace SourceGit.Views
TextArea.LeftMargins.Add(new LineModifyTypeMargin()); TextArea.LeftMargins.Add(new LineModifyTypeMargin());
} }
public void ForceSyncScrollOffset()
{
if (_scrollViewer == null)
return;
if (DataContext is ViewModels.TwoSideTextDiff diff)
diff.SyncScrollOffset = _scrollViewer?.Offset ?? Vector.Zero;
}
public override List<Models.TextDiffLine> GetLines() public override List<Models.TextDiffLine> GetLines()
{ {
if (DataContext is ViewModels.TwoSideTextDiff diff) if (DataContext is ViewModels.TwoSideTextDiff diff)
@ -1310,6 +1302,30 @@ namespace SourceGit.Views
return 0; return 0;
} }
public override void GotoFirstChange()
{
base.GotoFirstChange();
DirectSyncScrollOffset();
}
public override void GotoPrevChange()
{
base.GotoPrevChange();
DirectSyncScrollOffset();
}
public override void GotoNextChange()
{
base.GotoNextChange();
DirectSyncScrollOffset();
}
public override void GotoLastChange()
{
base.GotoLastChange();
DirectSyncScrollOffset();
}
public override void UpdateSelectedChunk(double y) public override void UpdateSelectedChunk(double y)
{ {
var diff = DataContext as ViewModels.TwoSideTextDiff; var diff = DataContext as ViewModels.TwoSideTextDiff;
@ -1497,11 +1513,17 @@ namespace SourceGit.Views
{ {
diff.SyncScrollOffset = _scrollViewer?.Offset ?? Vector.Zero; diff.SyncScrollOffset = _scrollViewer?.Offset ?? Vector.Zero;
if (sender is ScrollViewer { IsExpanded: true, IsPointerOver: true } scroller ) if (_scrollViewer is { IsExpanded: true, IsPointerOver: true } )
TrySetChunk(null); TrySetChunk(null);
} }
} }
private void DirectSyncScrollOffset()
{
if (_scrollViewer is { } && DataContext is ViewModels.TwoSideTextDiff diff)
diff.SyncScrollOffset = _scrollViewer?.Offset ?? Vector.Zero;
}
private ScrollViewer _scrollViewer = null; private ScrollViewer _scrollViewer = null;
} }
@ -1679,13 +1701,13 @@ namespace SourceGit.Views
set => SetValue(BlockNavigationProperty, value); set => SetValue(BlockNavigationProperty, value);
} }
public static readonly StyledProperty<string> BlockNavigationIndicatorProperty = public static readonly RoutedEvent<RoutedEventArgs> BlockNavigationChangedEvent =
AvaloniaProperty.Register<TextDiffView, string>(nameof(BlockNavigationIndicator)); RoutedEvent.Register<TextDiffView, RoutedEventArgs>(nameof(BlockNavigationChanged), RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
public string BlockNavigationIndicator public event EventHandler<RoutedEventArgs> BlockNavigationChanged
{ {
get => GetValue(BlockNavigationIndicatorProperty); add { AddHandler(BlockNavigationChangedEvent, value); }
set => SetValue(BlockNavigationIndicatorProperty, value); remove { RemoveHandler(BlockNavigationChangedEvent, value); }
} }
static TextDiffView() static TextDiffView()
@ -1723,54 +1745,26 @@ namespace SourceGit.Views
public void GotoFirstChange() public void GotoFirstChange()
{ {
var presenter = this.FindDescendantOfType<ThemedTextDiffPresenter>(); this.FindDescendantOfType<ThemedTextDiffPresenter>()?.GotoFirstChange();
if (presenter == null) RaiseEvent(new RoutedEventArgs(BlockNavigationChangedEvent));
return;
presenter.GotoFirstChange();
if (presenter is SingleSideTextDiffPresenter singleSide)
singleSide.ForceSyncScrollOffset();
BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty;
} }
public void GotoPrevChange() public void GotoPrevChange()
{ {
var presenter = this.FindDescendantOfType<ThemedTextDiffPresenter>(); this.FindDescendantOfType<ThemedTextDiffPresenter>()?.GotoPrevChange();
if (presenter == null) RaiseEvent(new RoutedEventArgs(BlockNavigationChangedEvent));
return;
presenter.GotoPrevChange();
if (presenter is SingleSideTextDiffPresenter singleSide)
singleSide.ForceSyncScrollOffset();
BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty;
} }
public void GotoNextChange() public void GotoNextChange()
{ {
var presenter = this.FindDescendantOfType<ThemedTextDiffPresenter>(); this.FindDescendantOfType<ThemedTextDiffPresenter>()?.GotoNextChange();
if (presenter == null) RaiseEvent(new RoutedEventArgs(BlockNavigationChangedEvent));
return;
presenter.GotoNextChange();
if (presenter is SingleSideTextDiffPresenter singleSide)
singleSide.ForceSyncScrollOffset();
BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty;
} }
public void GotoLastChange() public void GotoLastChange()
{ {
var presenter = this.FindDescendantOfType<ThemedTextDiffPresenter>(); this.FindDescendantOfType<ThemedTextDiffPresenter>()?.GotoLastChange();
if (presenter == null) RaiseEvent(new RoutedEventArgs(BlockNavigationChangedEvent));
return;
presenter.GotoLastChange();
if (presenter is SingleSideTextDiffPresenter singleSide)
singleSide.ForceSyncScrollOffset();
BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty;
} }
protected override void OnDataContextChanged(EventArgs e) protected override void OnDataContextChanged(EventArgs e)
@ -1820,15 +1814,11 @@ namespace SourceGit.Views
private void RefreshBlockNavigation() private void RefreshBlockNavigation()
{ {
if (UseBlockNavigation) if (UseBlockNavigation)
{
BlockNavigation = new ViewModels.BlockNavigation(Editor.Content); BlockNavigation = new ViewModels.BlockNavigation(Editor.Content);
BlockNavigationIndicator = BlockNavigation.Indicator;
}
else else
{
BlockNavigation = null; BlockNavigation = null;
BlockNavigationIndicator = "-/-";
} RaiseEvent(new RoutedEventArgs(BlockNavigationChangedEvent));
} }
private void OnStageChunk(object _1, RoutedEventArgs _2) private void OnStageChunk(object _1, RoutedEventArgs _2)