Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 134c710

Browse files
feature: add buttons to go to prev/next change in text diff view (#616)
Signed-off-by: leo <longshuang@msn.cn>
1 parent cd137e2 commit 134c710

File tree

3 files changed

+161
-16
lines changed

3 files changed

+161
-16
lines changed

‎src/Views/DiffView.axaml

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,24 @@
3434

3535
<!-- Toolbar Buttons -->
3636
<StackPanel Grid.Column="3" Margin="8,0,0,0" Orientation="Horizontal" VerticalAlignment="Center">
37+
<Button Classes="icon_button"
38+
Width="28"
39+
Click="OnGotoPrevChange"
40+
IsVisible="{Binding IsTextDiff}"
41+
ToolTip.Tip="{DynamicResource Text.Diff.Prev}">
42+
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Up}"/>
43+
</Button>
44+
45+
<Button Classes="icon_button"
46+
Width="28"
47+
Click="OnGotoNextChange"
48+
IsVisible="{Binding IsTextDiff}"
49+
ToolTip.Tip="{DynamicResource Text.Diff.Next}">
50+
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Down}"/>
51+
</Button>
52+
3753
<Button Classes="icon_button"
38-
Width="32"
54+
Width="28"
3955
Command="{Binding IncrUnified}"
4056
IsVisible="{Binding IsTextDiff}"
4157
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Incr}">
@@ -46,7 +62,7 @@
4662
</Button>
4763

4864
<Button Classes="icon_button"
49-
Width="32"
65+
Width="28"
5066
Command="{Binding DecrUnified}"
5167
IsVisible="{Binding IsTextDiff}"
5268
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Decr}">
@@ -60,9 +76,7 @@
6076
</Button>
6177

6278
<ToggleButton Classes="line_path"
63-
Width="32" Height="18"
64-
Background="Transparent"
65-
Padding="9,6"
79+
Width="28"
6680
Command="{Binding ToggleFullTextDiff}"
6781
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFullTextDiff, Mode=OneWay}"
6882
IsVisible="{Binding IsTextDiff}"
@@ -71,19 +85,16 @@
7185
</ToggleButton>
7286

7387
<ToggleButton Classes="line_path"
74-
Width="32"Height="18"
88+
Width="28"
7589
Background="Transparent"
76-
Padding="9,6"
7790
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting, Mode=TwoWay}"
7891
IsVisible="{Binding IsTextDiff}"
7992
ToolTip.Tip="{DynamicResource Text.Diff.SyntaxHighlight}">
8093
<Path Width="13" Height="13" Data="{StaticResource Icons.SyntaxHighlight}" Margin="0,3,0,0"/>
8194
</ToggleButton>
8295

8396
<ToggleButton Classes="line_path"
84-
Width="32" Height="18"
85-
Background="Transparent"
86-
Padding="9,6"
97+
Width="28"
8798
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap, Mode=TwoWay}"
8899
ToolTip.Tip="{DynamicResource Text.Diff.ToggleWordWrap}">
89100
<ToggleButton.IsVisible>
@@ -97,31 +108,29 @@
97108
</ToggleButton>
98109

99110
<ToggleButton Classes="line_path"
100-
Width="32"
111+
Width="28"
101112
IsChecked="{Binding IgnoreWhitespace, Mode=TwoWay}"
102113
ToolTip.Tip="{DynamicResource Text.Diff.IgnoreWhitespace}">
103114
<Path Width="14" Height="14" Stretch="Uniform" Data="{StaticResource Icons.Whitespace}"/>
104115
</ToggleButton>
105116

106117
<ToggleButton Classes="line_path"
107-
Width="32"
118+
Width="28"
108119
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView, Mode=TwoWay}"
109120
IsVisible="{Binding IsTextDiff}"
110121
ToolTip.Tip="{DynamicResource Text.Diff.ShowHiddenSymbols}">
111122
<Path Width="11" Height="11" Stretch="Uniform" Data="{StaticResource Icons.HiddenSymbol}" Margin="0,1,0,0"/>
112123
</ToggleButton>
113124

114125
<ToggleButton Classes="line_path"
115-
Width="32" Height="18"
116-
Background="Transparent"
117-
Padding="9,6"
126+
Width="28" Height="18"
118127
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSideBySideDiff, Mode=TwoWay}"
119128
IsVisible="{Binding IsTextDiff}"
120129
ToolTip.Tip="{DynamicResource Text.Diff.SideBySide}">
121130
<Path Width="12" Height="12" Data="{StaticResource Icons.LayoutHorizontal}" Margin="0,2,0,0"/>
122131
</ToggleButton>
123132

124-
<Button Classes="icon_button" Width="32" Command="{Binding OpenExternalMergeTool}" ToolTip.Tip="{DynamicResource Text.Diff.UseMerger}">
133+
<Button Classes="icon_button" Width="28" Command="{Binding OpenExternalMergeTool}" ToolTip.Tip="{DynamicResource Text.Diff.UseMerger}">
125134
<Path Width="12" Height="12" Stretch="Uniform" Data="{StaticResource Icons.OpenWith}"/>
126135
</Button>
127136
</StackPanel>

‎src/Views/DiffView.axaml.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using Avalonia.Controls;
2+
using Avalonia.Interactivity;
3+
using Avalonia.VisualTree;
24

35
namespace SourceGit.Views
46
{
@@ -8,5 +10,31 @@ public DiffView()
810
{
911
InitializeComponent();
1012
}
13+
14+
private void OnGotoPrevChange(object _, RoutedEventArgs e)
15+
{
16+
var textDiff = this.FindDescendantOfType<ThemedTextDiffPresenter>();
17+
if (textDiff == null)
18+
return;
19+
20+
textDiff.GotoPrevChange();
21+
if (textDiff is SingleSideTextDiffPresenter presenter)
22+
presenter.ForceSyncScrollOffset();
23+
24+
e.Handled = true;
25+
}
26+
27+
private void OnGotoNextChange(object _, RoutedEventArgs e)
28+
{
29+
var textDiff = this.FindDescendantOfType<ThemedTextDiffPresenter>();
30+
if (textDiff == null)
31+
return;
32+
33+
textDiff.GotoNextChange();
34+
if (textDiff is SingleSideTextDiffPresenter presenter)
35+
presenter.ForceSyncScrollOffset();
36+
37+
e.Handled = true;
38+
}
1139
}
1240
}

‎src/Views/TextDiffView.axaml.cs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,108 @@ public virtual void UpdateSelectedChunk(double y)
498498
{
499499
}
500500

501+
public void GotoPrevChange()
502+
{
503+
var view = TextArea.TextView;
504+
var lines = GetLines();
505+
var firstLineIdx = lines.Count;
506+
foreach (var line in view.VisualLines)
507+
{
508+
if (line.IsDisposed || line.FirstDocumentLine == null || line.FirstDocumentLine.IsDeleted)
509+
continue;
510+
511+
var index = line.FirstDocumentLine.LineNumber - 1;
512+
if (index >= lines.Count)
513+
continue;
514+
515+
if (firstLineIdx > index)
516+
firstLineIdx = index;
517+
}
518+
519+
var firstLineType = lines[firstLineIdx].Type;
520+
var isChangeFirstLine = firstLineType != Models.TextDiffLineType.Normal && firstLineType != Models.TextDiffLineType.Indicator;
521+
if (isChangeFirstLine)
522+
{
523+
for (var i = firstLineIdx - 1; i >= 0; i--)
524+
{
525+
var prevType = lines[i].Type;
526+
if (prevType == Models.TextDiffLineType.Normal || prevType == Models.TextDiffLineType.Indicator)
527+
{
528+
ScrollToLine(i + 2);
529+
return;
530+
}
531+
}
532+
}
533+
else
534+
{
535+
var prevChangeEnd = -1;
536+
for (var i = firstLineIdx - 1; i >= 0; i--)
537+
{
538+
var prevType = lines[i].Type;
539+
if (prevType == Models.TextDiffLineType.None ||
540+
prevType == Models.TextDiffLineType.Added ||
541+
prevType == Models.TextDiffLineType.Deleted)
542+
{
543+
prevChangeEnd = i;
544+
break;
545+
}
546+
}
547+
548+
if (prevChangeEnd <= 0)
549+
return;
550+
551+
for (var i = prevChangeEnd - 1; i >= 0; i--)
552+
{
553+
var prevType = lines[i].Type;
554+
if (prevType == Models.TextDiffLineType.Normal || prevType == Models.TextDiffLineType.Indicator)
555+
{
556+
ScrollToLine(i + 2);
557+
return;
558+
}
559+
}
560+
}
561+
}
562+
563+
public void GotoNextChange()
564+
{
565+
var view = TextArea.TextView;
566+
var lines = GetLines();
567+
var lastLineIdx = -1;
568+
foreach (var line in view.VisualLines)
569+
{
570+
if (line.IsDisposed || line.FirstDocumentLine == null || line.FirstDocumentLine.IsDeleted)
571+
continue;
572+
573+
var index = line.FirstDocumentLine.LineNumber - 1;
574+
if (index >= lines.Count)
575+
continue;
576+
577+
if (lastLineIdx < index)
578+
lastLineIdx = index;
579+
}
580+
581+
var lastLineType = lines[lastLineIdx].Type;
582+
var findNormalLine = lastLineType == Models.TextDiffLineType.Normal || lastLineType == Models.TextDiffLineType.Indicator;
583+
for (var idx = lastLineIdx + 1; idx < lines.Count; idx++)
584+
{
585+
var nextType = lines[idx].Type;
586+
if (nextType == Models.TextDiffLineType.None ||
587+
nextType == Models.TextDiffLineType.Added ||
588+
nextType == Models.TextDiffLineType.Deleted)
589+
{
590+
if (findNormalLine)
591+
{
592+
ScrollToLine(idx + 1);
593+
return;
594+
}
595+
}
596+
else if (!findNormalLine)
597+
{
598+
findNormalLine = true;
599+
}
600+
}
601+
}
602+
501603
public override void Render(DrawingContext context)
502604
{
503605
base.Render(context);
@@ -968,6 +1070,12 @@ public class SingleSideTextDiffPresenter : ThemedTextDiffPresenter
9681070
TextArea.LeftMargins.Add(new LineModifyTypeMargin());
9691071
}
9701072

1073+
public void ForceSyncScrollOffset()
1074+
{
1075+
if (DataContext is ViewModels.TwoSideTextDiff diff)
1076+
diff.SyncScrollOffset = _scrollViewer.Offset;
1077+
}
1078+
9711079
public override List<Models.TextDiffLine> GetLines()
9721080
{
9731081
if (DataContext is ViewModels.TwoSideTextDiff diff)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /