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);
_rightTm = RightEditor.InstallTextMate(Registry);
InstallRenderers();
Rebuild();
ReloadFile();
HookScrollSync();
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == FileProperty || change.Property == IsSplitProperty)
Rebuild();
if (change.Property == FileProperty)
ReloadFile();
else if (change.Property == IsSplitProperty)
RefreshLayout();
else if (change.Property == WrapLinesProperty)
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);
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;
RightEditor.IsVisible = split;
PaneDivider.IsVisible = split;
@@ -181,7 +192,7 @@ public partial class DiffTextView : UserControl
}
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
: new SolidColorBrush(fallback);
@@ -235,11 +246,20 @@ public partial class DiffTextView : UserControl
if (WrapLines)
{
// 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
? visualLines[0].FirstDocumentLine.LineNumber
: (int?)null;
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)
{