enhance: better sync scroll logic with two-side diff - if the width in each side is different

This commit is contained in:
leo 2024-03-12 15:50:00 +08:00
parent b8a230cf16
commit a37c11e32f
3 changed files with 36 additions and 12 deletions

View file

@ -145,7 +145,7 @@ namespace SourceGit.Models {
name.StartsWith("worktrees/")) { name.StartsWith("worktrees/")) {
_updateBranch = DateTime.Now.AddSeconds(.5).ToFileTime(); _updateBranch = DateTime.Now.AddSeconds(.5).ToFileTime();
} else if (name.StartsWith("objects/", StringComparison.Ordinal) || name.Equals("index", StringComparison.Ordinal)) { } else if (name.StartsWith("objects/", StringComparison.Ordinal) || name.Equals("index", StringComparison.Ordinal)) {
_updateWC = DateTime.Now.AddSeconds(.5).ToFileTime(); _updateWC = DateTime.Now.AddSeconds(1).ToFileTime();
} }
} }
@ -154,7 +154,7 @@ namespace SourceGit.Models {
var name = e.Name.Replace("\\", "/"); var name = e.Name.Replace("\\", "/");
if (name == ".git" || name.StartsWith(".git/", StringComparison.Ordinal)) return; if (name == ".git" || name.StartsWith(".git/", StringComparison.Ordinal)) return;
if (_updateWC == 0) _updateWC = DateTime.Now.AddSeconds(1).ToFileTime(); _updateWC = DateTime.Now.AddSeconds(1).ToFileTime();
} }
private IRepository _repo = null; private IRepository _repo = null;

View file

@ -1,5 +1,4 @@
using Avalonia; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections.Generic; using System.Collections.Generic;
namespace SourceGit.ViewModels { namespace SourceGit.ViewModels {

View file

@ -490,7 +490,7 @@ namespace SourceGit.Views {
} }
public static readonly StyledProperty<Vector> SyncScrollOffsetProperty = public static readonly StyledProperty<Vector> SyncScrollOffsetProperty =
AvaloniaProperty.Register<SingleSideTextDiffPresenter, Vector>(nameof(SyncScrollOffset)); AvaloniaProperty.Register<SingleSideTextDiffPresenter, Vector>(nameof(SyncScrollOffset), Vector.Zero);
public Vector SyncScrollOffset { public Vector SyncScrollOffset {
get => GetValue(SyncScrollOffsetProperty); get => GetValue(SyncScrollOffsetProperty);
@ -508,12 +508,17 @@ namespace SourceGit.Views {
protected override void OnLoaded(RoutedEventArgs e) { protected override void OnLoaded(RoutedEventArgs e) {
base.OnLoaded(e); base.OnLoaded(e);
_scrollViewer = this.FindDescendantOfType<ScrollViewer>();
if (_scrollViewer != null) {
_scrollViewer.Offset = SyncScrollOffset;
_scrollViewer.ScrollChanged += OnTextViewScrollChanged;
}
TextArea.LeftMargins.Add(new LineNumberMargin(this) { Margin = new Thickness(8, 0) }); TextArea.LeftMargins.Add(new LineNumberMargin(this) { Margin = new Thickness(8, 0) });
TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this)); TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this));
TextArea.TextView.Margin = new Thickness(4, 0); TextArea.TextView.Margin = new Thickness(4, 0);
TextArea.TextView.BackgroundRenderers.Add(new LineBackgroundRenderer(this)); TextArea.TextView.BackgroundRenderers.Add(new LineBackgroundRenderer(this));
TextArea.TextView.ContextRequested += OnTextViewContextRequested; TextArea.TextView.ContextRequested += OnTextViewContextRequested;
TextArea.TextView.ScrollOffsetChanged += OnTextViewScrollOffsetChanged;
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark) { if (App.Current?.ActualThemeVariant == ThemeVariant.Dark) {
_registryOptions = new RegistryOptions(ThemeName.DarkPlus); _registryOptions = new RegistryOptions(ThemeName.DarkPlus);
@ -531,19 +536,27 @@ namespace SourceGit.Views {
protected override void OnUnloaded(RoutedEventArgs e) { protected override void OnUnloaded(RoutedEventArgs e) {
base.OnUnloaded(e); base.OnUnloaded(e);
if (_scrollViewer != null) {
_scrollViewer.ScrollChanged -= OnTextViewScrollChanged;
_scrollViewer = null;
}
TextArea.LeftMargins.Clear(); TextArea.LeftMargins.Clear();
TextArea.TextView.BackgroundRenderers.Clear(); TextArea.TextView.BackgroundRenderers.Clear();
TextArea.TextView.LineTransformers.Clear(); TextArea.TextView.LineTransformers.Clear();
TextArea.TextView.ContextRequested -= OnTextViewContextRequested; TextArea.TextView.ContextRequested -= OnTextViewContextRequested;
TextArea.TextView.ScrollOffsetChanged -= OnTextViewScrollOffsetChanged;
_registryOptions = null; _registryOptions = null;
_textMate.Dispose(); _textMate.Dispose();
_textMate = null; _textMate = null;
GC.Collect(); GC.Collect();
} }
private void OnTextViewScrollOffsetChanged(object sender, EventArgs e) { private void OnTextViewScrollChanged(object sender, ScrollChangedEventArgs e) {
SyncScrollOffset = TextArea.TextView.ScrollOffset; if (_syncScrollingByOthers) {
_syncScrollingByOthers = false;
} else {
SyncScrollOffset = _scrollViewer.Offset;
}
} }
private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e) { private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e) {
@ -591,9 +604,18 @@ namespace SourceGit.Views {
Text = string.Empty; Text = string.Empty;
} }
} else if (change.Property == SyncScrollOffsetProperty) { } else if (change.Property == SyncScrollOffsetProperty) {
if (TextArea.TextView.ScrollOffset != SyncScrollOffset) { if (_scrollViewer == null) return;
IScrollable scrollable = TextArea.TextView;
scrollable.Offset = SyncScrollOffset; var curOffset = _scrollViewer.Offset;
if (!curOffset.Equals(SyncScrollOffset)) {
_syncScrollingByOthers = true;
if (curOffset.X != SyncScrollOffset.X) {
var offset = new Vector(Math.Min(_scrollViewer.ScrollBarMaximum.X, SyncScrollOffset.X), SyncScrollOffset.Y);
_scrollViewer.Offset = offset;
} else {
_scrollViewer.Offset = SyncScrollOffset;
}
} }
} else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null && _textMate != null) { } else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null && _textMate != null) {
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark) { if (App.Current?.ActualThemeVariant == ThemeVariant.Dark) {
@ -617,6 +639,9 @@ namespace SourceGit.Views {
private RegistryOptions _registryOptions; private RegistryOptions _registryOptions;
private TextMate.Installation _textMate; private TextMate.Installation _textMate;
private ScrollViewer _scrollViewer = null;
private bool _syncScrollingByOthers = false;
} }
public partial class TextDiffView : UserControl { public partial class TextDiffView : UserControl {