mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-12-25 21:07:20 -08:00
feature: add buttons to go to prev/next change in text diff view (#616)
Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
parent
cd137e222c
commit
134c71064e
3 changed files with 161 additions and 16 deletions
|
@ -35,7 +35,23 @@
|
||||||
<!-- 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">
|
||||||
<Button Classes="icon_button"
|
<Button Classes="icon_button"
|
||||||
Width="32"
|
Width="28"
|
||||||
|
Click="OnGotoPrevChange"
|
||||||
|
IsVisible="{Binding IsTextDiff}"
|
||||||
|
ToolTip.Tip="{DynamicResource Text.Diff.Prev}">
|
||||||
|
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Up}"/>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button Classes="icon_button"
|
||||||
|
Width="28"
|
||||||
|
Click="OnGotoNextChange"
|
||||||
|
IsVisible="{Binding IsTextDiff}"
|
||||||
|
ToolTip.Tip="{DynamicResource Text.Diff.Next}">
|
||||||
|
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Down}"/>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button Classes="icon_button"
|
||||||
|
Width="28"
|
||||||
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}">
|
||||||
|
@ -46,7 +62,7 @@
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button Classes="icon_button"
|
<Button Classes="icon_button"
|
||||||
Width="32"
|
Width="28"
|
||||||
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}">
|
||||||
|
@ -60,9 +76,7 @@
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<ToggleButton Classes="line_path"
|
<ToggleButton Classes="line_path"
|
||||||
Width="32" Height="18"
|
Width="28"
|
||||||
Background="Transparent"
|
|
||||||
Padding="9,6"
|
|
||||||
Command="{Binding ToggleFullTextDiff}"
|
Command="{Binding ToggleFullTextDiff}"
|
||||||
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFullTextDiff, Mode=OneWay}"
|
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFullTextDiff, Mode=OneWay}"
|
||||||
IsVisible="{Binding IsTextDiff}"
|
IsVisible="{Binding IsTextDiff}"
|
||||||
|
@ -71,9 +85,8 @@
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
|
|
||||||
<ToggleButton Classes="line_path"
|
<ToggleButton Classes="line_path"
|
||||||
Width="32" Height="18"
|
Width="28"
|
||||||
Background="Transparent"
|
Background="Transparent"
|
||||||
Padding="9,6"
|
|
||||||
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting, Mode=TwoWay}"
|
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting, Mode=TwoWay}"
|
||||||
IsVisible="{Binding IsTextDiff}"
|
IsVisible="{Binding IsTextDiff}"
|
||||||
ToolTip.Tip="{DynamicResource Text.Diff.SyntaxHighlight}">
|
ToolTip.Tip="{DynamicResource Text.Diff.SyntaxHighlight}">
|
||||||
|
@ -81,9 +94,7 @@
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
|
|
||||||
<ToggleButton Classes="line_path"
|
<ToggleButton Classes="line_path"
|
||||||
Width="32" Height="18"
|
Width="28"
|
||||||
Background="Transparent"
|
|
||||||
Padding="9,6"
|
|
||||||
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap, Mode=TwoWay}"
|
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap, Mode=TwoWay}"
|
||||||
ToolTip.Tip="{DynamicResource Text.Diff.ToggleWordWrap}">
|
ToolTip.Tip="{DynamicResource Text.Diff.ToggleWordWrap}">
|
||||||
<ToggleButton.IsVisible>
|
<ToggleButton.IsVisible>
|
||||||
|
@ -97,14 +108,14 @@
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
|
|
||||||
<ToggleButton Classes="line_path"
|
<ToggleButton Classes="line_path"
|
||||||
Width="32"
|
Width="28"
|
||||||
IsChecked="{Binding IgnoreWhitespace, Mode=TwoWay}"
|
IsChecked="{Binding IgnoreWhitespace, Mode=TwoWay}"
|
||||||
ToolTip.Tip="{DynamicResource Text.Diff.IgnoreWhitespace}">
|
ToolTip.Tip="{DynamicResource Text.Diff.IgnoreWhitespace}">
|
||||||
<Path Width="14" Height="14" Stretch="Uniform" Data="{StaticResource Icons.Whitespace}"/>
|
<Path Width="14" Height="14" Stretch="Uniform" Data="{StaticResource Icons.Whitespace}"/>
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
|
|
||||||
<ToggleButton Classes="line_path"
|
<ToggleButton Classes="line_path"
|
||||||
Width="32"
|
Width="28"
|
||||||
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView, Mode=TwoWay}"
|
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView, Mode=TwoWay}"
|
||||||
IsVisible="{Binding IsTextDiff}"
|
IsVisible="{Binding IsTextDiff}"
|
||||||
ToolTip.Tip="{DynamicResource Text.Diff.ShowHiddenSymbols}">
|
ToolTip.Tip="{DynamicResource Text.Diff.ShowHiddenSymbols}">
|
||||||
|
@ -112,16 +123,14 @@
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
|
|
||||||
<ToggleButton Classes="line_path"
|
<ToggleButton Classes="line_path"
|
||||||
Width="32" Height="18"
|
Width="28" Height="18"
|
||||||
Background="Transparent"
|
|
||||||
Padding="9,6"
|
|
||||||
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSideBySideDiff, Mode=TwoWay}"
|
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSideBySideDiff, Mode=TwoWay}"
|
||||||
IsVisible="{Binding IsTextDiff}"
|
IsVisible="{Binding IsTextDiff}"
|
||||||
ToolTip.Tip="{DynamicResource Text.Diff.SideBySide}">
|
ToolTip.Tip="{DynamicResource Text.Diff.SideBySide}">
|
||||||
<Path Width="12" Height="12" Data="{StaticResource Icons.LayoutHorizontal}" Margin="0,2,0,0"/>
|
<Path Width="12" Height="12" Data="{StaticResource Icons.LayoutHorizontal}" Margin="0,2,0,0"/>
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
|
|
||||||
<Button Classes="icon_button" Width="32" Command="{Binding OpenExternalMergeTool}" ToolTip.Tip="{DynamicResource Text.Diff.UseMerger}">
|
<Button Classes="icon_button" Width="28" Command="{Binding OpenExternalMergeTool}" ToolTip.Tip="{DynamicResource Text.Diff.UseMerger}">
|
||||||
<Path Width="12" Height="12" Stretch="Uniform" Data="{StaticResource Icons.OpenWith}"/>
|
<Path Width="12" Height="12" Stretch="Uniform" Data="{StaticResource Icons.OpenWith}"/>
|
||||||
</Button>
|
</Button>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Interactivity;
|
||||||
|
using Avalonia.VisualTree;
|
||||||
|
|
||||||
namespace SourceGit.Views
|
namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
|
@ -8,5 +10,31 @@ namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnGotoPrevChange(object _, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var textDiff = this.FindDescendantOfType<ThemedTextDiffPresenter>();
|
||||||
|
if (textDiff == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
textDiff.GotoPrevChange();
|
||||||
|
if (textDiff is SingleSideTextDiffPresenter presenter)
|
||||||
|
presenter.ForceSyncScrollOffset();
|
||||||
|
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGotoNextChange(object _, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var textDiff = this.FindDescendantOfType<ThemedTextDiffPresenter>();
|
||||||
|
if (textDiff == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
textDiff.GotoNextChange();
|
||||||
|
if (textDiff is SingleSideTextDiffPresenter presenter)
|
||||||
|
presenter.ForceSyncScrollOffset();
|
||||||
|
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -498,6 +498,108 @@ namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void GotoPrevChange()
|
||||||
|
{
|
||||||
|
var view = TextArea.TextView;
|
||||||
|
var lines = GetLines();
|
||||||
|
var firstLineIdx = lines.Count;
|
||||||
|
foreach (var line in view.VisualLines)
|
||||||
|
{
|
||||||
|
if (line.IsDisposed || line.FirstDocumentLine == null || line.FirstDocumentLine.IsDeleted)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var index = line.FirstDocumentLine.LineNumber - 1;
|
||||||
|
if (index >= lines.Count)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (firstLineIdx > index)
|
||||||
|
firstLineIdx = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
var firstLineType = lines[firstLineIdx].Type;
|
||||||
|
var isChangeFirstLine = firstLineType != Models.TextDiffLineType.Normal && firstLineType != Models.TextDiffLineType.Indicator;
|
||||||
|
if (isChangeFirstLine)
|
||||||
|
{
|
||||||
|
for (var i = firstLineIdx - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var prevType = lines[i].Type;
|
||||||
|
if (prevType == Models.TextDiffLineType.Normal || prevType == Models.TextDiffLineType.Indicator)
|
||||||
|
{
|
||||||
|
ScrollToLine(i + 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var prevChangeEnd = -1;
|
||||||
|
for (var i = firstLineIdx - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var prevType = lines[i].Type;
|
||||||
|
if (prevType == Models.TextDiffLineType.None ||
|
||||||
|
prevType == Models.TextDiffLineType.Added ||
|
||||||
|
prevType == Models.TextDiffLineType.Deleted)
|
||||||
|
{
|
||||||
|
prevChangeEnd = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevChangeEnd <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (var i = prevChangeEnd - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var prevType = lines[i].Type;
|
||||||
|
if (prevType == Models.TextDiffLineType.Normal || prevType == Models.TextDiffLineType.Indicator)
|
||||||
|
{
|
||||||
|
ScrollToLine(i + 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GotoNextChange()
|
||||||
|
{
|
||||||
|
var view = TextArea.TextView;
|
||||||
|
var lines = GetLines();
|
||||||
|
var lastLineIdx = -1;
|
||||||
|
foreach (var line in view.VisualLines)
|
||||||
|
{
|
||||||
|
if (line.IsDisposed || line.FirstDocumentLine == null || line.FirstDocumentLine.IsDeleted)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var index = line.FirstDocumentLine.LineNumber - 1;
|
||||||
|
if (index >= lines.Count)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (lastLineIdx < index)
|
||||||
|
lastLineIdx = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastLineType = lines[lastLineIdx].Type;
|
||||||
|
var findNormalLine = lastLineType == Models.TextDiffLineType.Normal || lastLineType == Models.TextDiffLineType.Indicator;
|
||||||
|
for (var idx = lastLineIdx + 1; idx < lines.Count; idx++)
|
||||||
|
{
|
||||||
|
var nextType = lines[idx].Type;
|
||||||
|
if (nextType == Models.TextDiffLineType.None ||
|
||||||
|
nextType == Models.TextDiffLineType.Added ||
|
||||||
|
nextType == Models.TextDiffLineType.Deleted)
|
||||||
|
{
|
||||||
|
if (findNormalLine)
|
||||||
|
{
|
||||||
|
ScrollToLine(idx + 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!findNormalLine)
|
||||||
|
{
|
||||||
|
findNormalLine = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void Render(DrawingContext context)
|
public override void Render(DrawingContext context)
|
||||||
{
|
{
|
||||||
base.Render(context);
|
base.Render(context);
|
||||||
|
@ -968,6 +1070,12 @@ namespace SourceGit.Views
|
||||||
TextArea.LeftMargins.Add(new LineModifyTypeMargin());
|
TextArea.LeftMargins.Add(new LineModifyTypeMargin());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ForceSyncScrollOffset()
|
||||||
|
{
|
||||||
|
if (DataContext is ViewModels.TwoSideTextDiff diff)
|
||||||
|
diff.SyncScrollOffset = _scrollViewer.Offset;
|
||||||
|
}
|
||||||
|
|
||||||
public override List<Models.TextDiffLine> GetLines()
|
public override List<Models.TextDiffLine> GetLines()
|
||||||
{
|
{
|
||||||
if (DataContext is ViewModels.TwoSideTextDiff diff)
|
if (DataContext is ViewModels.TwoSideTextDiff diff)
|
||||||
|
|
Loading…
Reference in a new issue