refactor(ui): share color-coded diff rendering between per-task and combined diff viewers
Extract the unified-diff parser into UnifiedDiffParser and the styled line renderer into a reusable DiffLinesView control. The combined (planning) diff now parses its unified-diff string and renders color-coded rows (green additions / red deletions, file headers) identical to the per-task viewer instead of dumping plain text into a TextBox. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,7 @@ using ClaudeDo.Ui.Localization;
|
|||||||
|
|
||||||
namespace ClaudeDo.Ui.ViewModels.Modals;
|
namespace ClaudeDo.Ui.ViewModels.Modals;
|
||||||
|
|
||||||
public enum DiffLineKind { Add, Del, Ctx }
|
public enum DiffLineKind { Add, Del, Ctx, File }
|
||||||
|
|
||||||
public sealed class DiffLineViewModel
|
public sealed class DiffLineViewModel
|
||||||
{
|
{
|
||||||
@@ -18,6 +18,7 @@ public sealed class DiffLineViewModel
|
|||||||
{
|
{
|
||||||
DiffLineKind.Add => "add",
|
DiffLineKind.Add => "add",
|
||||||
DiffLineKind.Del => "del",
|
DiffLineKind.Del => "del",
|
||||||
|
DiffLineKind.File => "file",
|
||||||
_ => "ctx",
|
_ => "ctx",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -102,90 +103,10 @@ public sealed partial class DiffModalViewModel : ViewModelBase
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse unified diff — state machine over lines
|
foreach (var file in UnifiedDiffParser.Parse(raw))
|
||||||
DiffFileViewModel? current = null;
|
Files.Add(file);
|
||||||
int oldLine = 0, newLine = 0;
|
|
||||||
|
|
||||||
foreach (var line in raw.Split('\n'))
|
|
||||||
{
|
|
||||||
if (line.StartsWith("diff --git ", StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
// e.g. "diff --git a/src/Foo.cs b/src/Foo.cs"
|
|
||||||
var parts = line.Split(' ');
|
|
||||||
var path = parts.Length >= 4 ? parts[3][2..] : line;
|
|
||||||
current = new DiffFileViewModel { Path = path };
|
|
||||||
Files.Add(current);
|
|
||||||
oldLine = 0; newLine = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current == null) continue;
|
|
||||||
|
|
||||||
if (line.StartsWith("@@ ", StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
// e.g. "@@ -10,7 +10,9 @@"
|
|
||||||
ParseHunkHeader(line, out oldLine, out newLine);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip diff metadata lines
|
|
||||||
if (line.StartsWith("--- ", StringComparison.Ordinal) ||
|
|
||||||
line.StartsWith("+++ ", StringComparison.Ordinal) ||
|
|
||||||
line.StartsWith("index ", StringComparison.Ordinal) ||
|
|
||||||
line.StartsWith("new file", StringComparison.Ordinal) ||
|
|
||||||
line.StartsWith("deleted file", StringComparison.Ordinal) ||
|
|
||||||
line.StartsWith("Binary ", StringComparison.Ordinal))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (line.StartsWith('+'))
|
|
||||||
{
|
|
||||||
current.Lines.Add(new DiffLineViewModel
|
|
||||||
{
|
|
||||||
Kind = DiffLineKind.Add,
|
|
||||||
NewNo = newLine++,
|
|
||||||
Text = line.Length > 1 ? line[1..] : "",
|
|
||||||
});
|
|
||||||
current.Additions++;
|
|
||||||
}
|
|
||||||
else if (line.StartsWith('-'))
|
|
||||||
{
|
|
||||||
current.Lines.Add(new DiffLineViewModel
|
|
||||||
{
|
|
||||||
Kind = DiffLineKind.Del,
|
|
||||||
OldNo = oldLine++,
|
|
||||||
Text = line.Length > 1 ? line[1..] : "",
|
|
||||||
});
|
|
||||||
current.Deletions++;
|
|
||||||
}
|
|
||||||
else if (line.StartsWith(' '))
|
|
||||||
{
|
|
||||||
current.Lines.Add(new DiffLineViewModel
|
|
||||||
{
|
|
||||||
Kind = DiffLineKind.Ctx,
|
|
||||||
OldNo = oldLine++,
|
|
||||||
NewNo = newLine++,
|
|
||||||
Text = line.Length > 1 ? line[1..] : "",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SelectedFile = Files.Count > 0 ? Files[0] : null;
|
SelectedFile = Files.Count > 0 ? Files[0] : null;
|
||||||
if (Files.Count == 0) StatusMessage = Loc.T("vm.diff.noChanges");
|
if (Files.Count == 0) StatusMessage = Loc.T("vm.diff.noChanges");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ParseHunkHeader(string header, out int oldStart, out int newStart)
|
|
||||||
{
|
|
||||||
oldStart = 1; newStart = 1;
|
|
||||||
// Format: @@ -<old>,<count> +<new>,<count> @@
|
|
||||||
var at = header.IndexOf("@@", 3, StringComparison.Ordinal);
|
|
||||||
var inner = at > 0 ? header[3..at].Trim() : header;
|
|
||||||
var segs = inner.Split(' ');
|
|
||||||
foreach (var seg in segs)
|
|
||||||
{
|
|
||||||
if (seg.StartsWith('-') && int.TryParse(seg[1..].Split(',')[0], out var o))
|
|
||||||
oldStart = o;
|
|
||||||
else if (seg.StartsWith('+') && int.TryParse(seg[1..].Split(',')[0], out var n))
|
|
||||||
newStart = n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
111
src/ClaudeDo.Ui/ViewModels/Modals/UnifiedDiffParser.cs
Normal file
111
src/ClaudeDo.Ui/ViewModels/Modals/UnifiedDiffParser.cs
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
namespace ClaudeDo.Ui.ViewModels.Modals;
|
||||||
|
|
||||||
|
/// Shared unified-diff parser used by both the per-task diff viewer and the
|
||||||
|
/// combined (planning) diff viewer so they render identically.
|
||||||
|
public static class UnifiedDiffParser
|
||||||
|
{
|
||||||
|
public static List<DiffFileViewModel> Parse(string? raw)
|
||||||
|
{
|
||||||
|
var files = new List<DiffFileViewModel>();
|
||||||
|
if (string.IsNullOrWhiteSpace(raw)) return files;
|
||||||
|
|
||||||
|
DiffFileViewModel? current = null;
|
||||||
|
int oldLine = 0, newLine = 0;
|
||||||
|
|
||||||
|
foreach (var line in raw.Split('\n'))
|
||||||
|
{
|
||||||
|
if (line.StartsWith("diff --git ", StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
// e.g. "diff --git a/src/Foo.cs b/src/Foo.cs"
|
||||||
|
var parts = line.Split(' ');
|
||||||
|
var path = parts.Length >= 4 ? parts[3][2..] : line;
|
||||||
|
current = new DiffFileViewModel { Path = path };
|
||||||
|
files.Add(current);
|
||||||
|
oldLine = 0; newLine = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current == null) continue;
|
||||||
|
|
||||||
|
if (line.StartsWith("@@ ", StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
// e.g. "@@ -10,7 +10,9 @@"
|
||||||
|
ParseHunkHeader(line, out oldLine, out newLine);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip diff metadata lines
|
||||||
|
if (line.StartsWith("--- ", StringComparison.Ordinal) ||
|
||||||
|
line.StartsWith("+++ ", StringComparison.Ordinal) ||
|
||||||
|
line.StartsWith("index ", StringComparison.Ordinal) ||
|
||||||
|
line.StartsWith("new file", StringComparison.Ordinal) ||
|
||||||
|
line.StartsWith("deleted file", StringComparison.Ordinal) ||
|
||||||
|
line.StartsWith("Binary ", StringComparison.Ordinal))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (line.StartsWith('+'))
|
||||||
|
{
|
||||||
|
current.Lines.Add(new DiffLineViewModel
|
||||||
|
{
|
||||||
|
Kind = DiffLineKind.Add,
|
||||||
|
NewNo = newLine++,
|
||||||
|
Text = line.Length > 1 ? line[1..] : "",
|
||||||
|
});
|
||||||
|
current.Additions++;
|
||||||
|
}
|
||||||
|
else if (line.StartsWith('-'))
|
||||||
|
{
|
||||||
|
current.Lines.Add(new DiffLineViewModel
|
||||||
|
{
|
||||||
|
Kind = DiffLineKind.Del,
|
||||||
|
OldNo = oldLine++,
|
||||||
|
Text = line.Length > 1 ? line[1..] : "",
|
||||||
|
});
|
||||||
|
current.Deletions++;
|
||||||
|
}
|
||||||
|
else if (line.StartsWith(' '))
|
||||||
|
{
|
||||||
|
current.Lines.Add(new DiffLineViewModel
|
||||||
|
{
|
||||||
|
Kind = DiffLineKind.Ctx,
|
||||||
|
OldNo = oldLine++,
|
||||||
|
NewNo = newLine++,
|
||||||
|
Text = line.Length > 1 ? line[1..] : "",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Flattens multiple parsed files into a single line stream, inserting a
|
||||||
|
/// file-header row before each file so boundaries are visible in a
|
||||||
|
/// single-pane (combined) view.
|
||||||
|
public static List<DiffLineViewModel> Flatten(IEnumerable<DiffFileViewModel> files)
|
||||||
|
{
|
||||||
|
var lines = new List<DiffLineViewModel>();
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
lines.Add(new DiffLineViewModel { Kind = DiffLineKind.File, Text = file.Path });
|
||||||
|
foreach (var line in file.Lines)
|
||||||
|
lines.Add(line);
|
||||||
|
}
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ParseHunkHeader(string header, out int oldStart, out int newStart)
|
||||||
|
{
|
||||||
|
oldStart = 1; newStart = 1;
|
||||||
|
// Format: @@ -<old>,<count> +<new>,<count> @@
|
||||||
|
var at = header.IndexOf("@@", 3, StringComparison.Ordinal);
|
||||||
|
var inner = at > 0 ? header[3..at].Trim() : header;
|
||||||
|
var segs = inner.Split(' ');
|
||||||
|
foreach (var seg in segs)
|
||||||
|
{
|
||||||
|
if (seg.StartsWith('-') && int.TryParse(seg[1..].Split(',')[0], out var o))
|
||||||
|
oldStart = o;
|
||||||
|
else if (seg.StartsWith('+') && int.TryParse(seg[1..].Split(',')[0], out var n))
|
||||||
|
newStart = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
|||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using ClaudeDo.Ui.Localization;
|
using ClaudeDo.Ui.Localization;
|
||||||
using ClaudeDo.Ui.Services;
|
using ClaudeDo.Ui.Services;
|
||||||
|
using ClaudeDo.Ui.ViewModels.Modals;
|
||||||
|
|
||||||
namespace ClaudeDo.Ui.ViewModels.Planning;
|
namespace ClaudeDo.Ui.ViewModels.Planning;
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@ public sealed partial class PlanningDiffViewModel : ObservableObject
|
|||||||
private readonly string _targetBranch;
|
private readonly string _targetBranch;
|
||||||
|
|
||||||
public ObservableCollection<SubtaskDiffRow> Subtasks { get; } = new();
|
public ObservableCollection<SubtaskDiffRow> Subtasks { get; } = new();
|
||||||
|
public ObservableCollection<DiffLineViewModel> DiffLines { get; } = new();
|
||||||
|
|
||||||
[ObservableProperty] private SubtaskDiffRow? _selectedSubtask;
|
[ObservableProperty] private SubtaskDiffRow? _selectedSubtask;
|
||||||
[ObservableProperty] private string _displayedDiff = "";
|
[ObservableProperty] private string _displayedDiff = "";
|
||||||
@@ -87,6 +89,13 @@ public sealed partial class PlanningDiffViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
partial void OnIsCombinedModeChanged(bool value) => ToggleCombinedCommand.Execute(null);
|
partial void OnIsCombinedModeChanged(bool value) => ToggleCombinedCommand.Execute(null);
|
||||||
|
|
||||||
|
partial void OnDisplayedDiffChanged(string value)
|
||||||
|
{
|
||||||
|
DiffLines.Clear();
|
||||||
|
foreach (var line in UnifiedDiffParser.Flatten(UnifiedDiffParser.Parse(value)))
|
||||||
|
DiffLines.Add(line);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed record SubtaskDiffRow(string Id, string Title, string? DiffStat, string UnifiedDiff);
|
public sealed record SubtaskDiffRow(string Id, string Title, string? DiffStat, string UnifiedDiff);
|
||||||
|
|||||||
82
src/ClaudeDo.Ui/Views/Controls/DiffLinesView.axaml
Normal file
82
src/ClaudeDo.Ui/Views/Controls/DiffLinesView.axaml
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:vm="using:ClaudeDo.Ui.ViewModels.Modals"
|
||||||
|
x:Class="ClaudeDo.Ui.Views.Controls.DiffLinesView"
|
||||||
|
x:Name="Root">
|
||||||
|
|
||||||
|
<UserControl.Styles>
|
||||||
|
<!-- diff line row tints via Tag selector (compiled-binding-friendly) -->
|
||||||
|
<Style Selector="Border.diff-line[Tag=add]">
|
||||||
|
<Setter Property="Background" Value="{StaticResource RunningTintBrush}"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="Border.diff-line[Tag=del]">
|
||||||
|
<Setter Property="Background" Value="{StaticResource ErrorTintBrush}"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="Border.diff-line[Tag=ctx]">
|
||||||
|
<Setter Property="Background" Value="Transparent"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="Border.diff-line[Tag=file]">
|
||||||
|
<Setter Property="Background" Value="{StaticResource Surface3Brush}"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="Border.diff-line[Tag=add] TextBlock.diff-sign">
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource MossBrightBrush}"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="Border.diff-line[Tag=del] TextBlock.diff-sign">
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource BloodBrush}"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="Border.diff-line[Tag=ctx] TextBlock.diff-sign">
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextFaintBrush}"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="Border.diff-line[Tag=add] TextBlock.diff-text">
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource MossBrightBrush}"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="Border.diff-line[Tag=del] TextBlock.diff-text">
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource BloodBrush}"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="Border.diff-line[Tag=ctx] TextBlock.diff-text">
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextDimBrush}"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="Border.diff-line[Tag=file] TextBlock.diff-text">
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||||
|
</Style>
|
||||||
|
</UserControl.Styles>
|
||||||
|
|
||||||
|
<ItemsControl ItemsSource="{Binding #Root.Lines}">
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate x:DataType="vm:DiffLineViewModel">
|
||||||
|
<Border Classes="diff-line"
|
||||||
|
Tag="{Binding ClassName}"
|
||||||
|
Padding="4,1">
|
||||||
|
<Grid ColumnDefinitions="48,48,16,*">
|
||||||
|
<!-- Old line number -->
|
||||||
|
<TextBlock Grid.Column="0"
|
||||||
|
Text="{Binding OldNo}"
|
||||||
|
Classes="diff-lineno"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Margin="0,0,8,0"/>
|
||||||
|
<!-- New line number -->
|
||||||
|
<TextBlock Grid.Column="1"
|
||||||
|
Text="{Binding NewNo}"
|
||||||
|
Classes="diff-lineno"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Margin="0,0,8,0"/>
|
||||||
|
<!-- Sign -->
|
||||||
|
<TextBlock Grid.Column="2"
|
||||||
|
Classes="diff-sign"
|
||||||
|
Text="{Binding Sign}"
|
||||||
|
FontFamily="{DynamicResource MonoFont}"
|
||||||
|
FontSize="{StaticResource FontSizeMono}"/>
|
||||||
|
<!-- Line text -->
|
||||||
|
<TextBlock Grid.Column="3"
|
||||||
|
Classes="diff-text"
|
||||||
|
Text="{Binding Text}"
|
||||||
|
FontFamily="{DynamicResource MonoFont}"
|
||||||
|
FontSize="{StaticResource FontSizeMono}"
|
||||||
|
TextWrapping="NoWrap"/>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
</UserControl>
|
||||||
19
src/ClaudeDo.Ui/Views/Controls/DiffLinesView.axaml.cs
Normal file
19
src/ClaudeDo.Ui/Views/Controls/DiffLinesView.axaml.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
|
||||||
|
namespace ClaudeDo.Ui.Views.Controls;
|
||||||
|
|
||||||
|
public partial class DiffLinesView : UserControl
|
||||||
|
{
|
||||||
|
public static readonly StyledProperty<IEnumerable?> LinesProperty =
|
||||||
|
AvaloniaProperty.Register<DiffLinesView, IEnumerable?>(nameof(Lines));
|
||||||
|
|
||||||
|
public IEnumerable? Lines
|
||||||
|
{
|
||||||
|
get => GetValue(LinesProperty);
|
||||||
|
set => SetValue(LinesProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiffLinesView() => InitializeComponent();
|
||||||
|
}
|
||||||
@@ -18,37 +18,6 @@
|
|||||||
<KeyBinding Gesture="Escape" Command="{Binding CloseCommand}"/>
|
<KeyBinding Gesture="Escape" Command="{Binding CloseCommand}"/>
|
||||||
</Window.KeyBindings>
|
</Window.KeyBindings>
|
||||||
|
|
||||||
<Window.Styles>
|
|
||||||
<!-- diff line row tints via Tag selector (compiled-binding-friendly) -->
|
|
||||||
<Style Selector="Border.diff-line[Tag=add]">
|
|
||||||
<Setter Property="Background" Value="{StaticResource RunningTintBrush}"/>
|
|
||||||
</Style>
|
|
||||||
<Style Selector="Border.diff-line[Tag=del]">
|
|
||||||
<Setter Property="Background" Value="{StaticResource ErrorTintBrush}"/>
|
|
||||||
</Style>
|
|
||||||
<Style Selector="Border.diff-line[Tag=ctx]">
|
|
||||||
<Setter Property="Background" Value="Transparent"/>
|
|
||||||
</Style>
|
|
||||||
<Style Selector="Border.diff-line[Tag=add] TextBlock.diff-sign">
|
|
||||||
<Setter Property="Foreground" Value="{StaticResource MossBrightBrush}"/>
|
|
||||||
</Style>
|
|
||||||
<Style Selector="Border.diff-line[Tag=del] TextBlock.diff-sign">
|
|
||||||
<Setter Property="Foreground" Value="{StaticResource BloodBrush}"/>
|
|
||||||
</Style>
|
|
||||||
<Style Selector="Border.diff-line[Tag=ctx] TextBlock.diff-sign">
|
|
||||||
<Setter Property="Foreground" Value="{StaticResource TextFaintBrush}"/>
|
|
||||||
</Style>
|
|
||||||
<Style Selector="Border.diff-line[Tag=add] TextBlock.diff-text">
|
|
||||||
<Setter Property="Foreground" Value="{StaticResource MossBrightBrush}"/>
|
|
||||||
</Style>
|
|
||||||
<Style Selector="Border.diff-line[Tag=del] TextBlock.diff-text">
|
|
||||||
<Setter Property="Foreground" Value="{StaticResource BloodBrush}"/>
|
|
||||||
</Style>
|
|
||||||
<Style Selector="Border.diff-line[Tag=ctx] TextBlock.diff-text">
|
|
||||||
<Setter Property="Foreground" Value="{StaticResource TextDimBrush}"/>
|
|
||||||
</Style>
|
|
||||||
</Window.Styles>
|
|
||||||
|
|
||||||
<ctl:ModalShell Title="{loc:Tr modals.diff.title}" CloseCommand="{Binding CloseCommand}">
|
<ctl:ModalShell Title="{loc:Tr modals.diff.title}" CloseCommand="{Binding CloseCommand}">
|
||||||
<ctl:ModalShell.Footer>
|
<ctl:ModalShell.Footer>
|
||||||
<StackPanel Orientation="Horizontal" Spacing="8"
|
<StackPanel Orientation="Horizontal" Spacing="8"
|
||||||
@@ -99,43 +68,7 @@
|
|||||||
VerticalAlignment="Center"/>
|
VerticalAlignment="Center"/>
|
||||||
<ScrollViewer HorizontalScrollBarVisibility="Auto"
|
<ScrollViewer HorizontalScrollBarVisibility="Auto"
|
||||||
VerticalScrollBarVisibility="Auto">
|
VerticalScrollBarVisibility="Auto">
|
||||||
<ItemsControl ItemsSource="{Binding SelectedFile.Lines}">
|
<ctl:DiffLinesView Lines="{Binding SelectedFile.Lines}"/>
|
||||||
<ItemsControl.ItemTemplate>
|
|
||||||
<DataTemplate x:DataType="vm:DiffLineViewModel">
|
|
||||||
<Border Classes="diff-line"
|
|
||||||
Tag="{Binding ClassName}"
|
|
||||||
Padding="4,1">
|
|
||||||
<Grid ColumnDefinitions="48,48,16,*">
|
|
||||||
<!-- Old line number -->
|
|
||||||
<TextBlock Grid.Column="0"
|
|
||||||
Text="{Binding OldNo}"
|
|
||||||
Classes="diff-lineno"
|
|
||||||
HorizontalAlignment="Right"
|
|
||||||
Margin="0,0,8,0"/>
|
|
||||||
<!-- New line number -->
|
|
||||||
<TextBlock Grid.Column="1"
|
|
||||||
Text="{Binding NewNo}"
|
|
||||||
Classes="diff-lineno"
|
|
||||||
HorizontalAlignment="Right"
|
|
||||||
Margin="0,0,8,0"/>
|
|
||||||
<!-- Sign -->
|
|
||||||
<TextBlock Grid.Column="2"
|
|
||||||
Classes="diff-sign"
|
|
||||||
Text="{Binding Sign}"
|
|
||||||
FontFamily="{DynamicResource MonoFont}"
|
|
||||||
FontSize="{StaticResource FontSizeMono}"/>
|
|
||||||
<!-- Line text -->
|
|
||||||
<TextBlock Grid.Column="3"
|
|
||||||
Classes="diff-text"
|
|
||||||
Text="{Binding Text}"
|
|
||||||
FontFamily="{DynamicResource MonoFont}"
|
|
||||||
FontSize="{StaticResource FontSizeMono}"
|
|
||||||
TextWrapping="NoWrap"/>
|
|
||||||
</Grid>
|
|
||||||
</Border>
|
|
||||||
</DataTemplate>
|
|
||||||
</ItemsControl.ItemTemplate>
|
|
||||||
</ItemsControl>
|
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -66,14 +66,7 @@
|
|||||||
<Grid Grid.Column="1" Background="{DynamicResource VoidBrush}">
|
<Grid Grid.Column="1" Background="{DynamicResource VoidBrush}">
|
||||||
<ScrollViewer HorizontalScrollBarVisibility="Auto"
|
<ScrollViewer HorizontalScrollBarVisibility="Auto"
|
||||||
VerticalScrollBarVisibility="Auto">
|
VerticalScrollBarVisibility="Auto">
|
||||||
<TextBox Text="{Binding DisplayedDiff, Mode=OneWay}"
|
<ctl:DiffLinesView Lines="{Binding DiffLines}"/>
|
||||||
IsReadOnly="True"
|
|
||||||
AcceptsReturn="True"
|
|
||||||
FontFamily="{DynamicResource MonoFont}"
|
|
||||||
FontSize="{StaticResource FontSizeBody}"
|
|
||||||
Background="Transparent"
|
|
||||||
BorderThickness="0"
|
|
||||||
Padding="8"/>
|
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user