Skip to content

Commit fa4caa2

Browse files
authored
enhance: add first/last buttons for block-nav, no wrapping (#1015) (#1016)
Added 2 new buttons (only visible in block-nav mode), with new icons and new (en_US) strings (First/Last Difference). Implemented these new buttons, and disabled the automatic wrap-around for the prev/next buttons in block-nav mode.
1 parent 9ab6027 commit fa4caa2

File tree

6 files changed

+127
-3
lines changed

6 files changed

+127
-3
lines changed

src/Resources/Icons.axaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<StreamGeometry x:Key="Icons.Binary">M71 1024V0h661L953 219V1024H71zm808-731-220-219H145V951h735V293zM439 512h-220V219h220V512zm-74-219H292v146h74v-146zm0 512h74v73h-220v-73H292v-146H218V585h147v219zm294-366h74V512H512v-73h74v-146H512V219h147v219zm74 439H512V585h220v293zm-74-219h-74v146h74v-146z</StreamGeometry>
66
<StreamGeometry x:Key="Icons.Blame">M128 256h192a64 64 0 110 128H128a64 64 0 110-128zm576 192h192a64 64 0 010 128h-192a64 64 0 010-128zm-576 192h192a64 64 0 010 128H128a64 64 0 010-128zm576 0h192a64 64 0 010 128h-192a64 64 0 010-128zm0-384h192a64 64 0 010 128h-192a64 64 0 010-128zM128 448h192a64 64 0 110 128H128a64 64 0 110-128zm384-320a64 64 0 0164 64v640a64 64 0 01-128 0V192a64 64 0 0164-64z</StreamGeometry>
77
<StreamGeometry x:Key="Icons.Bookmark">M832 64H192c-18 0-32 14-32 32v832c0 18 14 32 32 32h640c18 0 32-14 32-32V96c0-18-14-32-32-32zM736 596 624 502 506 596V131h230v318z</StreamGeometry>
8+
<StreamGeometry x:Key="Icons.Bottom">M509 546 780 275 871 366 509 728 147 366 238 275zM509 728h-362v128h724v-128z</StreamGeometry>
89
<StreamGeometry x:Key="Icons.Branch">M757 226a143 143 0 00-55 276 96 96 0 01-88 59h-191a187 187 0 00-96 27V312a143 143 0 10-96 0v399a143 143 0 10103 2 96 96 0 0188-59h191a191 191 0 00187-151 143 143 0 00-43-279zM280 130a48 48 0 110 96 48 48 0 010-96zm0 764a48 48 0 110-96 48 48 0 010 96zM757 417a48 48 0 110-96 48 48 0 010 96z</StreamGeometry>
910
<StreamGeometry x:Key="Icons.Branch.Add">M896 128h-64V64c0-35-29-64-64-64s-64 29-64 64v64h-64c-35 0-64 29-64 64s29 64 64 64h64v64c0 35 29 64 64 64s64-29 64-64V256h64c35 0 64-29 64-64s-29-64-64-64zm-204 307C673 481 628 512 576 512H448c-47 0-90 13-128 35V372C394 346 448 275 448 192c0-106-86-192-192-192S64 86 64 192c0 83 54 154 128 180v280c-74 26-128 97-128 180c0 106 86 192 192 192s192-86 192-192c0-67-34-125-84-159c22-20 52-33 84-33h128c122 0 223-85 249-199c-19 4-37 7-57 7c-26 0-51-5-76-13zM256 128c35 0 64 29 64 64s-29 64-64 64s-64-29-64-64s29-64 64-64zm0 768c-35 0-64-29-64-64s29-64 64-64s64 29 64 64s-29 64-64 64z</StreamGeometry>
1011
<StreamGeometry x:Key="Icons.Check">M512 597m-1 0a1 1 0 103 0a1 1 0 10-3 0ZM810 393 732 315 448 600 293 444 214 522l156 156 78 78 362-362z</StreamGeometry>
@@ -119,6 +120,7 @@
119120
<StreamGeometry x:Key="Icons.Tags">M996 452 572 28A96 96 0 00504 0H96C43 0 0 43 0 96v408a96 96 0 0028 68l424 424c37 37 98 37 136 0l408-408c37-37 37-98 0-136zM224 320c-53 0-96-43-96-96s43-96 96-96 96 43 96 96-43 96-96 96zm1028 268L844 996c-37 37-98 37-136 0l-1-1L1055 647c34-34 53-79 53-127s-19-93-53-127L663 0h97a96 96 0 0168 28l424 424c37 37 37 98 0 136z</StreamGeometry>
120121
<StreamGeometry x:Key="Icons.Target">M765 118 629 239l-16 137-186 160 54 59 183-168 144 4 136-129 47-43-175-12L827 67zM489 404c-66 0-124 55-124 125s54 121 124 121c66 0 120-55 120-121H489l23-121c-8-4-16-4-23-4zM695 525c0 114-93 207-206 207s-206-94-206-207 93-207 206-207c16 0 27 0 43 4l43-207c-27-4-54-8-85-8-229 0-416 188-416 419s187 419 416 419c225 0 408-180 416-403v-12l-210-4z</StreamGeometry>
121122
<StreamGeometry x:Key="Icons.Terminal">M144 112h736c18 0 32 14 32 32v736c0 18-14 32-32 32H144c-18 0-32-14-32-32V144c0-18 14-32 32-32zm112 211v72a9 9 0 003 7L386 509 259 615a9 9 0 00-3 7v72a9 9 0 0015 7L493 516a9 9 0 000-14l-222-186a9 9 0 00-15 7zM522 624a10 10 0 00-10 10v60a10 10 0 0010 10h237a10 10 0 0010-10v-60a10 10 0 00-10-10H522z</StreamGeometry>
123+
<StreamGeometry x:Key="Icons.Top">M170 831 513 489 855 831 960 726 512 278 64 726 170 831zM512 278h448v-128h-896v128h448z</StreamGeometry>
122124
<StreamGeometry x:Key="Icons.Track">M897 673v13c0 51-42 93-93 93h-10c-1 0-2 0-2 0H220c-23 0-42 19-42 42v13c0 23 19 42 42 42h552c14 0 26 12 26 26 0 14-12 26-26 26H220c-51 0-93-42-93-93v-13c0-51 42-93 93-93h20c1-0 2-0 2-0h562c23 0 42-19 42-42v-13c0-11-5-22-13-29-8-7-17-11-28-10H660c-14 0-26-12-26-26 0-14 12-26 26-26h144c24-1 47 7 65 24 18 17 29 42 29 67zM479 98c-112 0-203 91-203 203 0 44 14 85 38 118l132 208c15 24 50 24 66 0l133-209c23-33 37-73 37-117 0-112-91-203-203-203zm0 327c-68 0-122-55-122-122s55-122 122-122 122 55 122 122-55 122-122 122z</StreamGeometry>
123125
<StreamGeometry x:Key="Icons.Tree">M912 800a48 48 0 1 1 0 96h-416a48 48 0 1 1 0-96h416z m-704-704A112 112 0 0 1 256 309.184V480h80a48 48 0 0 1 0 96H256v224h81.664a48 48 0 1 1 0 96H256a96 96 0 0 1-96-96V309.248A112 112 0 0 1 208 96z m704 384a48 48 0 1 1 0 96h-416a48 48 0 0 1 0-96h416z m0-320a48 48 0 1 1 0 96h-416a48 48 0 0 1 0-96h416z</StreamGeometry>
124126
<StreamGeometry x:Key="Icons.TriangleLeft">M30 0 30 30 0 15z</StreamGeometry>

src/Resources/Locales/en_US.axaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,11 @@
252252
<x:String x:Key="Text.Diff.FileModeChanged" xml:space="preserve">File Mode Changed</x:String>
253253
<x:String x:Key="Text.Diff.IgnoreWhitespace" xml:space="preserve">Ignore Whitespace Change</x:String>
254254
<x:String x:Key="Text.Diff.LFS" xml:space="preserve">LFS OBJECT CHANGE</x:String>
255+
<x:String x:Key="Text.Diff.First" xml:space="preserve">First Difference</x:String>
255256
<x:String x:Key="Text.Diff.Next" xml:space="preserve">Next Difference</x:String>
256257
<x:String x:Key="Text.Diff.NoChange" xml:space="preserve">NO CHANGES OR ONLY EOL CHANGES</x:String>
257258
<x:String x:Key="Text.Diff.Prev" xml:space="preserve">Previous Difference</x:String>
259+
<x:String x:Key="Text.Diff.Last" xml:space="preserve">Last Difference</x:String>
258260
<x:String x:Key="Text.Diff.SaveAsPatch" xml:space="preserve">Save as Patch</x:String>
259261
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">Show hidden symbols</x:String>
260262
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">Side-By-Side Diff</x:String>

src/ViewModels/BlockNavigation.cs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,12 @@ public Block GetCurrentBlock()
101101
return (_current >= 0 && _current < Blocks.Count) ? Blocks[_current] : null;
102102
}
103103

104-
public Block GotoNext()
104+
public Block GotoFirst()
105105
{
106106
if (Blocks.Count == 0)
107107
return null;
108108

109-
Current = (_current + 1) % Blocks.Count;
109+
Current = 0;
110110
return Blocks[_current];
111111
}
112112

@@ -115,7 +115,29 @@ public Block GotoPrev()
115115
if (Blocks.Count == 0)
116116
return null;
117117

118-
Current = _current == -1 ? Blocks.Count - 1 : (_current - 1 + Blocks.Count) % Blocks.Count;
118+
if (_current == -1)
119+
Current = 0;
120+
else if (_current > 0)
121+
Current = _current - 1;
122+
return Blocks[_current];
123+
}
124+
125+
public Block GotoNext()
126+
{
127+
if (Blocks.Count == 0)
128+
return null;
129+
130+
if (_current < Blocks.Count - 1)
131+
Current = _current + 1;
132+
return Blocks[_current];
133+
}
134+
135+
public Block GotoLast()
136+
{
137+
if (Blocks.Count == 0)
138+
return null;
139+
140+
Current = Blocks.Count - 1;
119141
return Blocks[_current];
120142
}
121143

src/Views/DiffView.axaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,20 @@
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="OnGotoFirstChange"
40+
IsVisible="{Binding IsTextDiff}"
41+
ToolTip.Tip="{DynamicResource Text.Diff.First}">
42+
<Button.IsVisible>
43+
<MultiBinding Converter="{x:Static BoolConverters.And}">
44+
<Binding Path="IsTextDiff"/>
45+
<Binding Source="{x:Static vm:Preferences.Instance}" Path="UseBlockNavigationInDiffView" Mode="OneWay"/>
46+
</MultiBinding>
47+
</Button.IsVisible>
48+
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Top}"/>
49+
</Button>
50+
3751
<Button Classes="icon_button"
3852
Width="28"
3953
Click="OnGotoPrevChange"
@@ -61,6 +75,20 @@
6175
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Down}"/>
6276
</Button>
6377

78+
<Button Classes="icon_button"
79+
Width="28"
80+
Click="OnGotoLastChange"
81+
IsVisible="{Binding IsTextDiff}"
82+
ToolTip.Tip="{DynamicResource Text.Diff.Last}">
83+
<Button.IsVisible>
84+
<MultiBinding Converter="{x:Static BoolConverters.And}">
85+
<Binding Path="IsTextDiff"/>
86+
<Binding Source="{x:Static vm:Preferences.Instance}" Path="UseBlockNavigationInDiffView" Mode="OneWay"/>
87+
</MultiBinding>
88+
</Button.IsVisible>
89+
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Bottom}"/>
90+
</Button>
91+
6492
<ToggleButton Classes="line_path"
6593
Width="28"
6694
IsChecked="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseBlockNavigationInDiffView, Mode=TwoWay}"

src/Views/DiffView.axaml.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ public DiffView()
1111
InitializeComponent();
1212
}
1313

14+
private void OnGotoFirstChange(object _, RoutedEventArgs e)
15+
{
16+
var textDiff = this.FindDescendantOfType<TextDiffView>();
17+
textDiff?.GotoFirstChange();
18+
e.Handled = true;
19+
}
20+
1421
private void OnGotoPrevChange(object _, RoutedEventArgs e)
1522
{
1623
var textDiff = this.FindDescendantOfType<TextDiffView>();
@@ -24,5 +31,12 @@ private void OnGotoNextChange(object _, RoutedEventArgs e)
2431
textDiff?.GotoNextChange();
2532
e.Handled = true;
2633
}
34+
35+
private void OnGotoLastChange(object _, RoutedEventArgs e)
36+
{
37+
var textDiff = this.FindDescendantOfType<TextDiffView>();
38+
textDiff?.GotoLastChange();
39+
e.Handled = true;
40+
}
2741
}
2842
}

src/Views/TextDiffView.axaml.cs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,21 @@ public virtual void UpdateSelectedChunk(double y)
543543
{
544544
}
545545

546+
public void GotoFirstChange()
547+
{
548+
var blockNavigation = BlockNavigation;
549+
if (blockNavigation != null)
550+
{
551+
var prev = blockNavigation.GotoFirst();
552+
if (prev != null)
553+
{
554+
TextArea.Caret.Line = prev.Start;
555+
ScrollToLine(prev.Start);
556+
}
557+
}
558+
// NOTE: Not implemented (button hidden) for non-block navigation.
559+
}
560+
546561
public void GotoPrevChange()
547562
{
548563
var blockNavigation = BlockNavigation;
@@ -641,6 +656,21 @@ public void GotoNextChange()
641656
}
642657
}
643658

659+
public void GotoLastChange()
660+
{
661+
var blockNavigation = BlockNavigation;
662+
if (blockNavigation != null)
663+
{
664+
var next = blockNavigation.GotoLast();
665+
if (next != null)
666+
{
667+
TextArea.Caret.Line = next.Start;
668+
ScrollToLine(next.Start);
669+
}
670+
}
671+
// NOTE: Not implemented (button hidden) for non-block navigation.
672+
}
673+
644674
public override void Render(DrawingContext context)
645675
{
646676
base.Render(context);
@@ -1682,6 +1712,19 @@ public TextDiffView()
16821712
InitializeComponent();
16831713
}
16841714

1715+
public void GotoFirstChange()
1716+
{
1717+
var presenter = this.FindDescendantOfType<ThemedTextDiffPresenter>();
1718+
if (presenter == null)
1719+
return;
1720+
1721+
presenter.GotoFirstChange();
1722+
if (presenter is SingleSideTextDiffPresenter singleSide)
1723+
singleSide.ForceSyncScrollOffset();
1724+
1725+
BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty;
1726+
}
1727+
16851728
public void GotoPrevChange()
16861729
{
16871730
var presenter = this.FindDescendantOfType<ThemedTextDiffPresenter>();
@@ -1708,6 +1751,19 @@ public void GotoNextChange()
17081751
BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty;
17091752
}
17101753

1754+
public void GotoLastChange()
1755+
{
1756+
var presenter = this.FindDescendantOfType<ThemedTextDiffPresenter>();
1757+
if (presenter == null)
1758+
return;
1759+
1760+
presenter.GotoLastChange();
1761+
if (presenter is SingleSideTextDiffPresenter singleSide)
1762+
singleSide.ForceSyncScrollOffset();
1763+
1764+
BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty;
1765+
}
1766+
17111767
protected override void OnDataContextChanged(EventArgs e)
17121768
{
17131769
base.OnDataContextChanged(e);

0 commit comments

Comments
 (0)