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
This commit is contained in:
goran-w 2024-11-01 20:45:06 +01:00
parent f7e37c4781
commit b5072360ed
4 changed files with 85 additions and 31 deletions

View file

@ -78,6 +78,12 @@ namespace SourceGit.ViewModels
LoadDiffContent(); LoadDiffContent();
} }
public void ToggleFullTextDiff()
{
Preference.Instance.UseFullTextDiff = !Preference.Instance.UseFullTextDiff;
LoadDiffContent();
}
public void IncrUnified() public void IncrUnified()
{ {
UnifiedLines = _unifiedLines + 1; UnifiedLines = _unifiedLines + 1;
@ -109,7 +115,12 @@ namespace SourceGit.ViewModels
Task.Run(() => Task.Run(() =>
{ {
var latest = new Commands.Diff(_repo, _option, _unifiedLines, _ignoreWhitespace).Result(); // NOTE: Here we override the UnifiedLines value (if UseFullTextDiff is on).
// There is no way to tell a git-diff to use "ALL lines of context",
// so instead we set a very high number for the "lines of context" parameter.
var numLines = Preference.Instance.UseFullTextDiff ? 999999999 : _unifiedLines;
var latest = new Commands.Diff(_repo, _option, numLines, _ignoreWhitespace).Result();
var rs = null as object; var rs = null as object;
if (latest.TextDiff != null) if (latest.TextDiff != null)

View file

@ -186,6 +186,12 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _showHiddenSymbolsInDiffView, value); set => SetProperty(ref _showHiddenSymbolsInDiffView, value);
} }
public bool UseFullTextDiff
{
get => _useFullTextDiff;
set => SetProperty(ref _useFullTextDiff, value);
}
public Models.ChangeViewMode UnstagedChangeViewMode public Models.ChangeViewMode UnstagedChangeViewMode
{ {
get => _unstagedChangeViewMode; get => _unstagedChangeViewMode;
@ -591,6 +597,7 @@ namespace SourceGit.ViewModels
private bool _useSyntaxHighlighting = false; private bool _useSyntaxHighlighting = false;
private bool _enableDiffViewWordWrap = false; private bool _enableDiffViewWordWrap = false;
private bool _showHiddenSymbolsInDiffView = false; private bool _showHiddenSymbolsInDiffView = false;
private bool _useFullTextDiff = false;
private Models.ChangeViewMode _unstagedChangeViewMode = Models.ChangeViewMode.List; private Models.ChangeViewMode _unstagedChangeViewMode = Models.ChangeViewMode.List;
private Models.ChangeViewMode _stagedChangeViewMode = Models.ChangeViewMode.List; private Models.ChangeViewMode _stagedChangeViewMode = Models.ChangeViewMode.List;

View file

@ -34,11 +34,24 @@
<!-- Toolbar Buttons --> <!-- Toolbar Buttons -->
<StackPanel Grid.Column="3" Margin="8,0,0,0" Orientation="Horizontal" VerticalAlignment="Center"> <StackPanel Grid.Column="3" Margin="8,0,0,0" Orientation="Horizontal" VerticalAlignment="Center">
<ToggleButton Classes="line_path"
Width="32" Height="18"
Background="Transparent"
Padding="9,6"
Command="{Binding ToggleFullTextDiff}"
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFullTextDiff, Mode=OneWay}"
IsVisible="{Binding IsTextDiff}"
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.All}">
<Path Width="13" Height="13" Data="{StaticResource Icons.Lines.All}" Margin="0,3,0,0"/>
</ToggleButton>
<Button Classes="icon_button" <Button Classes="icon_button"
Width="32" Width="32"
Command="{Binding IncrUnified}" Command="{Binding IncrUnified}"
IsVisible="{Binding IsTextDiff}" IsVisible="{Binding IsTextDiff}"
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Incr}"> ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Incr}">
<Button.IsEnabled>
<Binding Source="{x:Static vm:Preference.Instance}" Path="UseFullTextDiff" Mode="OneWay" Converter="{x:Static BoolConverters.Not}"/>
</Button.IsEnabled>
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Lines.Incr}"/> <Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Lines.Incr}"/>
</Button> </Button>
@ -46,8 +59,13 @@
Width="32" Width="32"
Command="{Binding DecrUnified}" Command="{Binding DecrUnified}"
IsVisible="{Binding IsTextDiff}" IsVisible="{Binding IsTextDiff}"
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Decr}" ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Decr}">
IsEnabled="{Binding UnifiedLines, Converter={x:Static c:IntConverters.IsGreaterThanFour}}"> <Button.IsEnabled>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="UnifiedLines" Mode="OneWay" Converter="{x:Static c:IntConverters.IsGreaterThanFour}"/>
<Binding Source="{x:Static vm:Preference.Instance}" Path="UseFullTextDiff" Mode="OneWay" Converter="{x:Static BoolConverters.Not}"/>
</MultiBinding>
</Button.IsEnabled>
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Lines.Decr}"/> <Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Lines.Decr}"/>
</Button> </Button>
@ -211,7 +229,9 @@
<!-- Text Diff --> <!-- Text Diff -->
<DataTemplate DataType="m:TextDiff"> <DataTemplate DataType="m:TextDiff">
<v:TextDiffView UseSideBySideDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"/> <v:TextDiffView
UseSideBySideDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"
UseFullTextDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFullTextDiff, Mode=OneWay}"/>
</DataTemplate> </DataTemplate>
<!-- Empty or only EOL changes --> <!-- Empty or only EOL changes -->

View file

@ -1205,6 +1205,15 @@ namespace SourceGit.Views
set => SetValue(UseSideBySideDiffProperty, value); set => SetValue(UseSideBySideDiffProperty, value);
} }
public static readonly StyledProperty<bool> UseFullTextDiffProperty =
AvaloniaProperty.Register<TextDiffView, bool>(nameof(UseFullTextDiff));
public bool UseFullTextDiff
{
get => GetValue(UseFullTextDiffProperty);
set => SetValue(UseFullTextDiffProperty, value);
}
public static readonly StyledProperty<TextDiffViewChunk> SelectedChunkProperty = public static readonly StyledProperty<TextDiffViewChunk> SelectedChunkProperty =
AvaloniaProperty.Register<TextDiffView, TextDiffViewChunk>(nameof(SelectedChunk)); AvaloniaProperty.Register<TextDiffView, TextDiffViewChunk>(nameof(SelectedChunk));
@ -1232,19 +1241,44 @@ namespace SourceGit.Views
set => SetValue(EnableChunkSelectionProperty, value); set => SetValue(EnableChunkSelectionProperty, value);
} }
private void RefreshContent(Models.TextDiff diff, bool keepScrollOffset = true)
{
if (SelectedChunk != null)
SetCurrentValue(SelectedChunkProperty, null);
if (diff == null)
{
Editor.Content = null;
GC.Collect();
return;
}
if (UseSideBySideDiff)
{
var previousContent = Editor.Content as ViewModels.TwoSideTextDiff;
Editor.Content = new ViewModels.TwoSideTextDiff(diff, keepScrollOffset ? previousContent : null);
}
else
{
if (!keepScrollOffset)
diff.ScrollOffset = Vector.Zero;
Editor.Content = diff;
}
IsUnstagedChange = diff.Option.IsUnstaged;
EnableChunkSelection = diff.Option.WorkingCopyChange != null;
}
static TextDiffView() static TextDiffView()
{ {
UseSideBySideDiffProperty.Changed.AddClassHandler<TextDiffView>((v, _) => UseSideBySideDiffProperty.Changed.AddClassHandler<TextDiffView>((v, _) =>
{ {
if (v.DataContext is Models.TextDiff diff) v.RefreshContent(v.DataContext as Models.TextDiff, false);
{ });
diff.ScrollOffset = Vector.Zero;
if (v.UseSideBySideDiff) UseFullTextDiffProperty.Changed.AddClassHandler<TextDiffView>((v, _) =>
v.Editor.Content = new ViewModels.TwoSideTextDiff(diff); {
else v.RefreshContent(v.DataContext as Models.TextDiff, false);
v.Editor.Content = diff;
}
}); });
SelectedChunkProperty.Changed.AddClassHandler<TextDiffView>((v, _) => SelectedChunkProperty.Changed.AddClassHandler<TextDiffView>((v, _) =>
@ -1271,25 +1305,7 @@ namespace SourceGit.Views
protected override void OnDataContextChanged(EventArgs e) protected override void OnDataContextChanged(EventArgs e)
{ {
base.OnDataContextChanged(e); base.OnDataContextChanged(e);
RefreshContent(DataContext as Models.TextDiff, true);
if (SelectedChunk != null)
SetCurrentValue(SelectedChunkProperty, null);
var diff = DataContext as Models.TextDiff;
if (diff == null)
{
Editor.Content = null;
GC.Collect();
return;
}
if (UseSideBySideDiff)
Editor.Content = new ViewModels.TwoSideTextDiff(diff, Editor.Content as ViewModels.TwoSideTextDiff);
else
Editor.Content = diff;
IsUnstagedChange = diff.Option.IsUnstaged;
EnableChunkSelection = diff.Option.WorkingCopyChange != null;
} }
protected override void OnPointerExited(PointerEventArgs e) protected override void OnPointerExited(PointerEventArgs e)