Skip to content

Commit 1a8acbf

Browse files
authored
feature: diff - toggle show all lines (#615) (#652)
* Renamed 1 of 2 SyncScrollOffset props, for clarity The property "SyncScrollOffset" in TextDiff is distinct from the one with the same name in TwoSideTextDiff. These two properties are used in separate (though slightly related) ways and are not really connected. The one in TwoSideTextDiff is mainly used to keep the scroll-pos of the two SingleSideTextDiffPresenter views in sync (aligned), while the one in TextDiff is used only to preserve/reset the scroll-pos in the single CombinedTextDiffPresenter view when (re)loading Diff Content (so not really syncing anything). To clarify this and to make the two properties more distinguishable, I renamed the one in TextDiff to simply "ScrollOffset". * Added icon and string for "Show All Lines" New StreamGeometry "Icons.Lines.All" using SVG path from "text_line_spacing_regular" at https://avaloniaui.github.io/icons.html. New String "Text.Diff.VisualLines.All" for en_US locale (no translations yet). * Implemented new TextDiff feature "Show All Lines" (toggle) * Added new ToggleButton in DiffView toolbar, visible when IsTextDiff, disabling the buttons "Increase/Decrease Number of Visible Lines" when on. * Added new Preference property "UseFullTextDiff". * Added StyledProperty "UseFullTextDiffProperty" in TextDiffView, with a DataTemplate binding to the corresponding preference property. * When changed, UseFullTextDiffProperty is handled identically as UseSideBySideDiffProperty (via new helper method RefreshContent(), for unification with OnDataContextChanged()). * Added new method DiffContext.ToggleFullTextDiff() for changing the preference property and reloading the diff content. * Implemented the new feature by overriding the "unified" (number of context lines) for Commands.Diff() with a very high number. NOTE: The number used (~1 billion) is supposed to be the highest one working on Mac, according to this forum comment: https://stackoverflow.com/questions/28727424/for-git-diff-is-there-a-uinfinity-option-to-show-the-whole-file#comment135202820_28846576
1 parent 779b38b commit 1a8acbf

File tree

7 files changed

+90
-34
lines changed

7 files changed

+90
-34
lines changed

src/Models/DiffResult.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public partial class TextDiff
6363
{
6464
public string File { get; set; } = string.Empty;
6565
public List<TextDiffLine> Lines { get; set; } = new List<TextDiffLine>();
66-
public Vector SyncScrollOffset { get; set; } = Vector.Zero;
66+
public Vector ScrollOffset { get; set; } = Vector.Zero;
6767
public int MaxLineNumber = 0;
6868

6969
public string Repo { get; set; } = null;

src/Resources/Icons.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
<StreamGeometry x:Key="Icons.LayoutHorizontal">M875 117H149C109 117 75 151 75 192v640c0 41 34 75 75 75h725c41 0 75-34 75-75V192c0-41-34-75-75-75zM139 832V192c0-6 4-11 11-11h331v661H149c-6 0-11-4-11-11zm747 0c0 6-4 11-11 11H544v-661H875c6 0 11 4 11 11v640z</StreamGeometry>
6666
<StreamGeometry x:Key="Icons.LayoutVertical">M875 117H149C109 117 75 151 75 192v640c0 41 34 75 75 75h725c41 0 75-34 75-75V192c0-41-34-75-75-75zm-725 64h725c6 0 11 4 11 11v288h-747V192c0-6 4-11 11-11zm725 661H149c-6 0-11-4-11-11V544h747V832c0 6-4 11-11 11z</StreamGeometry>
6767
<StreamGeometry x:Key="Icons.LFS">M40 9 15 23 15 31 9 28 9 20 34 5 24 0 0 14 0 34 25 48 25 28 49 14zM26 29 26 48 49 34 49 15z</StreamGeometry>
68+
<StreamGeometry x:Key="Icons.Lines.All">M19,13 C19.4142,13 19.75,13.3358 19.75,13.75 L19.75,18.4393 L20.4697,17.7197 C20.7626,17.4268 21.2374,17.4268 21.5303,17.7197 C21.8232,18.0126 21.8232,18.4874 21.5303,18.7803 L19.5303,20.7803 C19.4584,20.8522 19.3755,20.9065 19.2871,20.9431 C19.2099,20.9751 19.1262,20.9946 19.0386,20.999 L19,21 L19,21 C18.8983,21 18.8013,20.9798 18.7129,20.9431 C18.6245,20.9065 18.5416,20.8522 18.4697,20.7803 L16.4697,18.7803 C16.1768,18.4874 16.1768,18.0126 16.4697,17.7197 C16.7626,17.4268 17.2374,17.4268 17.5303,17.7197 L18.25,18.4393 L18.25,13.75 C18.25,13.3358 18.5858,13 19,13 Z M11.25,18 C11.6642,18 12,18.3358 12,18.75 C12,19.1296833 11.7178347,19.4434889 11.3517677,19.4931531 L11.25,19.5 L2.75,19.5 C2.33579,19.5 2,19.1642 2,18.75 C2,18.3703167 2.28215688,18.0565111 2.64823019,18.0068469 L2.75,18 L11.25,18 Z M14.25,11.5 C14.6642,11.5 15,11.8358 15,12.25 C15,12.6642 14.6642,13 14.25,13 L2.75,13 C2.33579,13 2,12.6642 2,12.25 C2,11.8358 2.33579,11.5 2.75,11.5 L14.25,11.5 Z M19.0022,3 C19.1031,3.0003 19.1993,3.02051 19.2871,3.05691 C19.3755,3.09351 19.4584,3.14776 19.5303,3.21967 L21.5303,5.21967 C21.8232,5.51256 21.8232,5.98744 21.5303,6.28033 C21.2374,6.57322 20.7626,6.57322 20.4697,6.28033 L19.75,5.56066 L19.75,10.25 C19.75,10.6642 19.4142,11 19,11 C18.5858,11 18.25,10.6642 18.25,10.25 L18.25,5.56066 L17.5303,6.28033 C17.2374,6.57322 16.7626,6.57322 16.4697,6.28033 C16.1768,5.98744 16.1768,5.51256 16.4697,5.21967 L18.4697,3.21967 C18.58634,3.102974 18.731972,3.0327676 18.8834536,3.00906104 L19.0022,3 Z M11.25,5 C11.6642,5 12,5.33579 12,5.75 C12,6.16421 11.6642,6.5 11.25,6.5 L2.75,6.5 C2.33579,6.5 2,6.16421 2,5.75 C2,5.33579 2.33579,5 2.75,5 L11.25,5 Z</StreamGeometry>
6869
<StreamGeometry x:Key="Icons.Lines.Incr">M408 232C408 210 426 192 448 192h416a40 40 0 110 80H448a40 40 0 01-40-40zM408 512c0-22 18-40 40-40h416a40 40 0 110 80H448A40 40 0 01408 512zM448 752A40 40 0 00448 832h416a40 40 0 100-80H448zM32 480l132 0 0-128 64 0 0 128 132 0 0 64-132 0 0 128-64 0 0-128-132 0Z</StreamGeometry>
6970
<StreamGeometry x:Key="Icons.Lines.Decr">M408 232C408 210 426 192 448 192h416a40 40 0 110 80H448a40 40 0 01-40-40zM408 512c0-22 18-40 40-40h416a40 40 0 110 80H448A40 40 0 01408 512zM448 752A40 40 0 00448 832h416a40 40 0 100-80H448zM32 480l328 0 0 64-328 0Z</StreamGeometry>
7071
<StreamGeometry x:Key="Icons.Link">M 968 418 l -95 94 c -59 59 -146 71 -218 37 L 874 331 a 64 64 0 0 0 0 -90 L 783 150 a 64 64 0 0 0 -90 0 L 475 368 c -34 -71 -22 -159 37 -218 l 94 -94 c 75 -75 196 -75 271 0 l 90 90 c 75 75 75 196 0 271 z M 332 693 a 64 64 0 0 1 0 -90 l 271 -271 c 25 -25 65 -25 90 0 s 25 65 0 90 L 422 693 a 64 64 0 0 1 -90 0 z M 151 783 l 90 90 a 64 64 0 0 0 90 0 l 218 -218 c 34 71 22 159 -37 218 l -86 94 a 192 192 0 0 1 -271 0 l -98 -98 a 192 192 0 0 1 0 -271 l 94 -86 c 59 -59 146 -71 218 -37 L 151 693 a 64 64 0 0 0 0 90 z</StreamGeometry>

src/Resources/Locales/en_US.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@
246246
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Syntax Highlighting</x:String>
247247
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">Line Word Wrap</x:String>
248248
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">Open in Merge Tool</x:String>
249+
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">Show All Lines</x:String>
249250
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">Decrease Number of Visible Lines</x:String>
250251
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">Increase Number of Visible Lines</x:String>
251252
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">SELECT FILE TO VIEW CHANGES</x:String>

src/ViewModels/DiffContext.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ public DiffContext(string repo, Models.DiffOption option, DiffContext previous =
7878
LoadDiffContent();
7979
}
8080

81+
public void ToggleFullTextDiff()
82+
{
83+
Preference.Instance.UseFullTextDiff = !Preference.Instance.UseFullTextDiff;
84+
LoadDiffContent();
85+
}
86+
8187
public void IncrUnified()
8288
{
8389
UnifiedLines = _unifiedLines + 1;
@@ -109,7 +115,12 @@ private void LoadDiffContent()
109115

110116
Task.Run(() =>
111117
{
112-
var latest = new Commands.Diff(_repo, _option, _unifiedLines, _ignoreWhitespace).Result();
118+
// NOTE: Here we override the UnifiedLines value (if UseFullTextDiff is on).
119+
// There is no way to tell a git-diff to use "ALL lines of context",
120+
// so instead we set a very high number for the "lines of context" parameter.
121+
var numLines = Preference.Instance.UseFullTextDiff ? 999999999 : _unifiedLines;
122+
123+
var latest = new Commands.Diff(_repo, _option, numLines, _ignoreWhitespace).Result();
113124
var rs = null as object;
114125

115126
if (latest.TextDiff != null)
@@ -203,7 +214,7 @@ private void LoadDiffContent()
203214
Dispatcher.UIThread.Post(() =>
204215
{
205216
if (_content is Models.TextDiff old && rs is Models.TextDiff cur && old.File == cur.File)
206-
cur.SyncScrollOffset = old.SyncScrollOffset;
217+
cur.ScrollOffset = old.ScrollOffset;
207218

208219
FileModeChange = latest.FileModeChange;
209220
Content = rs;

src/ViewModels/Preference.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,12 @@ public bool ShowHiddenSymbolsInDiffView
186186
set => SetProperty(ref _showHiddenSymbolsInDiffView, value);
187187
}
188188

189+
public bool UseFullTextDiff
190+
{
191+
get => _useFullTextDiff;
192+
set => SetProperty(ref _useFullTextDiff, value);
193+
}
194+
189195
public Models.ChangeViewMode UnstagedChangeViewMode
190196
{
191197
get => _unstagedChangeViewMode;
@@ -591,6 +597,7 @@ private bool RemoveInvalidRepositoriesRecursive(List<RepositoryNode> collection)
591597
private bool _useSyntaxHighlighting = false;
592598
private bool _enableDiffViewWordWrap = false;
593599
private bool _showHiddenSymbolsInDiffView = false;
600+
private bool _useFullTextDiff = false;
594601

595602
private Models.ChangeViewMode _unstagedChangeViewMode = Models.ChangeViewMode.List;
596603
private Models.ChangeViewMode _stagedChangeViewMode = Models.ChangeViewMode.List;

src/Views/DiffView.axaml

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,38 @@
3434

3535
<!-- Toolbar Buttons -->
3636
<StackPanel Grid.Column="3" Margin="8,0,0,0" Orientation="Horizontal" VerticalAlignment="Center">
37+
<ToggleButton Classes="line_path"
38+
Width="32" Height="18"
39+
Background="Transparent"
40+
Padding="9,6"
41+
Command="{Binding ToggleFullTextDiff}"
42+
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFullTextDiff, Mode=OneWay}"
43+
IsVisible="{Binding IsTextDiff}"
44+
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.All}">
45+
<Path Width="13" Height="13" Data="{StaticResource Icons.Lines.All}" Margin="0,3,0,0"/>
46+
</ToggleButton>
3747
<Button Classes="icon_button"
3848
Width="32"
3949
Command="{Binding IncrUnified}"
4050
IsVisible="{Binding IsTextDiff}"
4151
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Incr}">
52+
<Button.IsEnabled>
53+
<Binding Source="{x:Static vm:Preference.Instance}" Path="UseFullTextDiff" Mode="OneWay" Converter="{x:Static BoolConverters.Not}"/>
54+
</Button.IsEnabled>
4255
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Lines.Incr}"/>
4356
</Button>
4457

4558
<Button Classes="icon_button"
4659
Width="32"
4760
Command="{Binding DecrUnified}"
4861
IsVisible="{Binding IsTextDiff}"
49-
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Decr}"
50-
IsEnabled="{Binding UnifiedLines, Converter={x:Static c:IntConverters.IsGreaterThanFour}}">
62+
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Decr}">
63+
<Button.IsEnabled>
64+
<MultiBinding Converter="{x:Static BoolConverters.And}">
65+
<Binding Path="UnifiedLines" Mode="OneWay" Converter="{x:Static c:IntConverters.IsGreaterThanFour}"/>
66+
<Binding Source="{x:Static vm:Preference.Instance}" Path="UseFullTextDiff" Mode="OneWay" Converter="{x:Static BoolConverters.Not}"/>
67+
</MultiBinding>
68+
</Button.IsEnabled>
5169
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Lines.Decr}"/>
5270
</Button>
5371

@@ -211,7 +229,9 @@
211229

212230
<!-- Text Diff -->
213231
<DataTemplate DataType="m:TextDiff">
214-
<v:TextDiffView UseSideBySideDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"/>
232+
<v:TextDiffView
233+
UseSideBySideDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"
234+
UseFullTextDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFullTextDiff, Mode=OneWay}"/>
215235
</DataTemplate>
216236

217237
<!-- Empty or only EOL changes -->

src/Views/TextDiffView.axaml.cs

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,7 @@ protected override void OnLoaded(RoutedEventArgs e)
902902
var scroller = this.FindDescendantOfType<ScrollViewer>();
903903
if (scroller != null)
904904
{
905-
scroller.Bind(ScrollViewer.OffsetProperty, new Binding("SyncScrollOffset", BindingMode.TwoWay));
905+
scroller.Bind(ScrollViewer.OffsetProperty, new Binding("ScrollOffset", BindingMode.TwoWay));
906906
scroller.GotFocus += OnTextViewScrollGotFocus;
907907
}
908908
}
@@ -1205,6 +1205,15 @@ public bool UseSideBySideDiff
12051205
set => SetValue(UseSideBySideDiffProperty, value);
12061206
}
12071207

1208+
public static readonly StyledProperty<bool> UseFullTextDiffProperty =
1209+
AvaloniaProperty.Register<TextDiffView, bool>(nameof(UseFullTextDiff));
1210+
1211+
public bool UseFullTextDiff
1212+
{
1213+
get => GetValue(UseFullTextDiffProperty);
1214+
set => SetValue(UseFullTextDiffProperty, value);
1215+
}
1216+
12081217
public static readonly StyledProperty<TextDiffViewChunk> SelectedChunkProperty =
12091218
AvaloniaProperty.Register<TextDiffView, TextDiffViewChunk>(nameof(SelectedChunk));
12101219

@@ -1232,19 +1241,44 @@ public bool EnableChunkSelection
12321241
set => SetValue(EnableChunkSelectionProperty, value);
12331242
}
12341243

1244+
private void RefreshContent(Models.TextDiff diff, bool keepScrollOffset = true)
1245+
{
1246+
if (SelectedChunk != null)
1247+
SetCurrentValue(SelectedChunkProperty, null);
1248+
1249+
if (diff == null)
1250+
{
1251+
Editor.Content = null;
1252+
GC.Collect();
1253+
return;
1254+
}
1255+
1256+
if (UseSideBySideDiff)
1257+
{
1258+
var previousContent = Editor.Content as ViewModels.TwoSideTextDiff;
1259+
Editor.Content = new ViewModels.TwoSideTextDiff(diff, keepScrollOffset ? previousContent : null);
1260+
}
1261+
else
1262+
{
1263+
if (!keepScrollOffset)
1264+
diff.ScrollOffset = Vector.Zero;
1265+
Editor.Content = diff;
1266+
}
1267+
1268+
IsUnstagedChange = diff.Option.IsUnstaged;
1269+
EnableChunkSelection = diff.Option.WorkingCopyChange != null;
1270+
}
1271+
12351272
static TextDiffView()
12361273
{
12371274
UseSideBySideDiffProperty.Changed.AddClassHandler<TextDiffView>((v, _) =>
12381275
{
1239-
if (v.DataContext is Models.TextDiff diff)
1240-
{
1241-
diff.SyncScrollOffset = Vector.Zero;
1276+
v.RefreshContent(v.DataContext as Models.TextDiff, false);
1277+
});
12421278

1243-
if (v.UseSideBySideDiff)
1244-
v.Editor.Content = new ViewModels.TwoSideTextDiff(diff);
1245-
else
1246-
v.Editor.Content = diff;
1247-
}
1279+
UseFullTextDiffProperty.Changed.AddClassHandler<TextDiffView>((v, _) =>
1280+
{
1281+
v.RefreshContent(v.DataContext as Models.TextDiff, false);
12481282
});
12491283

12501284
SelectedChunkProperty.Changed.AddClassHandler<TextDiffView>((v, _) =>
@@ -1271,25 +1305,7 @@ public TextDiffView()
12711305
protected override void OnDataContextChanged(EventArgs e)
12721306
{
12731307
base.OnDataContextChanged(e);
1274-
1275-
if (SelectedChunk != null)
1276-
SetCurrentValue(SelectedChunkProperty, null);
1277-
1278-
var diff = DataContext as Models.TextDiff;
1279-
if (diff == null)
1280-
{
1281-
Editor.Content = null;
1282-
GC.Collect();
1283-
return;
1284-
}
1285-
1286-
if (UseSideBySideDiff)
1287-
Editor.Content = new ViewModels.TwoSideTextDiff(diff, Editor.Content as ViewModels.TwoSideTextDiff);
1288-
else
1289-
Editor.Content = diff;
1290-
1291-
IsUnstagedChange = diff.Option.IsUnstaged;
1292-
EnableChunkSelection = diff.Option.WorkingCopyChange != null;
1308+
RefreshContent(DataContext as Models.TextDiff, true);
12931309
}
12941310

12951311
protected override void OnPointerExited(PointerEventArgs e)

0 commit comments

Comments
 (0)