fix(diff): resolve themed brushes and stop recomputing alignment on layout toggle

This commit is contained in:
mika kuns
2026-08-07 10:23:45 +02:00
parent f7fa8292e0
commit 54b179fb0b
@@ -76,23 +76,34 @@ public partial class DiffTextView : UserControl
_leftTm = LeftEditor.InstallTextMate(Registry); _leftTm = LeftEditor.InstallTextMate(Registry);
_rightTm = RightEditor.InstallTextMate(Registry); _rightTm = RightEditor.InstallTextMate(Registry);
InstallRenderers(); InstallRenderers();
Rebuild(); ReloadFile();
HookScrollSync(); HookScrollSync();
} }
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{ {
base.OnPropertyChanged(change); base.OnPropertyChanged(change);
if (change.Property == FileProperty || change.Property == IsSplitProperty) if (change.Property == FileProperty)
Rebuild(); ReloadFile();
else if (change.Property == IsSplitProperty)
RefreshLayout();
else if (change.Property == WrapLinesProperty) else if (change.Property == WrapLinesProperty)
ApplyWrap(); ApplyWrap();
} }
private void Rebuild() /// Recomputes the alignment (word-diff LCS) for the current <see cref="File"/> and then
/// refreshes everything downstream of it. Only ever needed when the file actually changes.
private void ReloadFile()
{ {
_aligned = DiffAlignment.Build(File?.Lines); _aligned = DiffAlignment.Build(File?.Lines);
RefreshLayout();
}
/// Re-applies the current <see cref="_aligned"/> to the editors for the current layout
/// (split vs unified). A single <see cref="AlignedDiff"/> already carries both row sets,
/// so toggling <see cref="IsSplit"/> never needs to re-run the alignment.
private void RefreshLayout()
{
var split = IsSplit; var split = IsSplit;
RightEditor.IsVisible = split; RightEditor.IsVisible = split;
PaneDivider.IsVisible = split; PaneDivider.IsVisible = split;
@@ -181,7 +192,7 @@ public partial class DiffTextView : UserControl
} }
private IBrush Brush(string key, Color fallback) => private IBrush Brush(string key, Color fallback) =>
this.TryGetResource(key, ActualThemeVariant, out var value) && value is IBrush brush this.TryFindResource(key, out var value) && value is IBrush brush
? brush ? brush
: new SolidColorBrush(fallback); : new SolidColorBrush(fallback);
@@ -235,11 +246,20 @@ public partial class DiffTextView : UserControl
if (WrapLines) if (WrapLines)
{ {
// Line heights differ once lines wrap, so anchor on the top visible line. // Line heights differ once lines wrap, so anchor on the top visible line.
// ScrollToLine/ScrollTo are "bring into view" primitives (they park the line
// near mid-viewport past a hysteresis threshold) — top-align by computing the
// target's own vertical offset for that document line and assigning it
// directly, the same way the non-wrap branch assigns Offset below. That is
// synchronous, so the same offset-comparison guard makes the echo self-terminate.
var topLine = sourceEditor.TextArea.TextView.VisualLines is { Count: > 0 } visualLines var topLine = sourceEditor.TextArea.TextView.VisualLines is { Count: > 0 } visualLines
? visualLines[0].FirstDocumentLine.LineNumber ? visualLines[0].FirstDocumentLine.LineNumber
: (int?)null; : (int?)null;
if (topLine is { } line && line >= 1 && line <= targetEditor.Document.LineCount) if (topLine is { } line && line >= 1 && line <= targetEditor.Document.LineCount)
targetEditor.ScrollToLine(line); {
var targetTop = targetEditor.TextArea.TextView.GetVisualTopByDocumentLine(line);
if (Math.Abs(target.Offset.Y - targetTop) > 0.5)
target.Offset = new Vector(target.Offset.X, targetTop);
}
} }
else if (Math.Abs(target.Offset.Y - source.Offset.Y) > 0.5) else if (Math.Abs(target.Offset.Y - source.Offset.Y) > 0.5)
{ {