Skip to content

Commit 37e983a

Browse files
committed
Added AdvancingFocus events. Fixed hexview bugs
1 parent 11f2f30 commit 37e983a

File tree

6 files changed

+171
-67
lines changed

6 files changed

+171
-67
lines changed

Terminal.Gui/View/CancelEventArgs.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public CancelEventArgs (ref readonly T currentValue, ref T newValue, bool cancel
2727
NewValue = newValue;
2828
}
2929

30+
protected CancelEventArgs () { }
31+
3032
/// <summary>The current value of the property.</summary>
3133
public T CurrentValue { get; }
3234

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
namespace Terminal.Gui;
2+
3+
/// <summary>The event arguments for <see cref="View.AdvanceFocus"/> events.</summary>
4+
public class AdvanceFocusEventArgs : CancelEventArgs<bool>
5+
{
6+
/// <summary>Initializes a new instance.</summary>
7+
public AdvanceFocusEventArgs (NavigationDirection direction, TabBehavior? behavior)
8+
{
9+
Direction = direction;
10+
Behavior = behavior;
11+
}
12+
13+
/// <summary>Gets or sets the view that is losing focus.</summary>
14+
public NavigationDirection Direction { get; set; }
15+
16+
/// <summary>Gets or sets the view that is gaining focus.</summary>
17+
public TabBehavior? Behavior { get; set; }
18+
19+
}

Terminal.Gui/View/Navigation/FocusEventArgs.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ public HasFocusEventArgs (bool currentHasFocus, bool newHasFocus, View currentFo
2020
/// <summary>Gets or sets the view that is gaining focus.</summary>
2121
public View NewFocused { get; set; }
2222

23-
}
23+
}

Terminal.Gui/View/View.Navigation.cs

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ public bool AdvanceFocus (NavigationDirection direction, TabBehavior? behavior)
3434
return false;
3535
}
3636

37+
if (RaiseAdvancingFocus (direction, behavior))
38+
{
39+
return true;
40+
}
41+
3742
View? focused = Focused;
3843

3944
if (focused is { } && focused.AdvanceFocus (direction, behavior))
@@ -128,6 +133,11 @@ public bool AdvanceFocus (NavigationDirection direction, TabBehavior? behavior)
128133
if (view.HasFocus)
129134
{
130135
// We could not advance
136+
if (view != this)
137+
{
138+
// Tell it to try the other way.
139+
return view.RaiseAdvancingFocus (direction == NavigationDirection.Forward ? NavigationDirection.Backward : NavigationDirection.Forward, behavior);
140+
}
131141
return view == this;
132142
}
133143

@@ -137,6 +147,52 @@ public bool AdvanceFocus (NavigationDirection direction, TabBehavior? behavior)
137147
return focusSet;
138148
}
139149

150+
private bool RaiseAdvancingFocus (NavigationDirection direction, TabBehavior? behavior)
151+
{
152+
// Call the virtual method
153+
if (OnAdvancingFocus (direction, behavior))
154+
{
155+
// The event was cancelled
156+
return true;
157+
}
158+
159+
var args = new AdvanceFocusEventArgs (direction, behavior);
160+
AdvancingFocus?.Invoke (this, args);
161+
162+
if (args.Cancel)
163+
{
164+
// The event was cancelled
165+
return true;
166+
}
167+
168+
return false;
169+
}
170+
171+
/// <summary>
172+
/// Called when <see cref="View.AdvanceFocus"/> is about to advance focus.
173+
/// </summary>
174+
/// <remarks>
175+
/// </remarks>
176+
/// <returns>
177+
/// <see langword="true"/>, if the focus advance is to be cancelled, <see langword="false"/>
178+
/// otherwise.
179+
/// </returns>
180+
protected virtual bool OnAdvancingFocus (NavigationDirection direction, TabBehavior? behavior) { return false; }
181+
182+
/// <summary>
183+
/// Raised when <see cref="View.AdvanceFocus"/> is about to advance focus.
184+
/// </summary>
185+
/// <remarks>
186+
/// <para>
187+
/// Cancel the event to prevent the focus from advancing.
188+
/// </para>
189+
/// <para>
190+
/// Use <see cref="HasFocusChanged"/> to be notified after the focus has changed.
191+
/// </para>
192+
/// </remarks>
193+
public event EventHandler<AdvanceFocusEventArgs>? AdvancingFocus;
194+
195+
140196
/// <summary>Gets or sets a value indicating whether this <see cref="View"/> can be focused.</summary>
141197
/// <remarks>
142198
/// <para>
@@ -467,7 +523,7 @@ public bool SetFocus ()
467523

468524
bool previousValue = HasFocus;
469525

470-
bool cancelled = NotifyFocusChanging (false, true, currentFocusedView, this);
526+
bool cancelled = RaiseFocusChanging (false, true, currentFocusedView, this);
471527

472528
if (cancelled)
473529
{
@@ -529,7 +585,7 @@ public bool SetFocus ()
529585
}
530586

531587
// Focus work is done. Notify.
532-
NotifyFocusChanged (HasFocus, currentFocusedView, this);
588+
RaiseFocusChanged (HasFocus, currentFocusedView, this);
533589

534590
SetNeedsDisplay ();
535591

@@ -542,7 +598,7 @@ public bool SetFocus ()
542598
return (true, false);
543599
}
544600

545-
private bool NotifyFocusChanging (bool currentHasFocus, bool newHasFocus, View? currentFocused, View? newFocused)
601+
private bool RaiseFocusChanging (bool currentHasFocus, bool newHasFocus, View? currentFocused, View? newFocused)
546602
{
547603
Debug.Assert (currentFocused is null || currentFocused is { HasFocus: true });
548604
Debug.Assert (newFocused is null || newFocused is { CanFocus: true });
@@ -750,7 +806,7 @@ private void SetHasFocusFalse (View? newFocusedView, bool traversingDown = false
750806
Debug.Assert (_hasFocus);
751807

752808
// Note, can't be cancelled.
753-
NotifyFocusChanging (HasFocus, !HasFocus, this, newFocusedView);
809+
RaiseFocusChanging (HasFocus, !HasFocus, this, newFocusedView);
754810

755811
// Even though the change can't be cancelled, some listener may have changed the focus to another view.
756812
if (!_hasFocus)
@@ -765,7 +821,7 @@ private void SetHasFocusFalse (View? newFocusedView, bool traversingDown = false
765821
// Set HasFocus false
766822
_hasFocus = false;
767823

768-
NotifyFocusChanged (HasFocus, this, newFocusedView);
824+
RaiseFocusChanged (HasFocus, this, newFocusedView);
769825

770826
if (_hasFocus)
771827
{
@@ -782,7 +838,7 @@ private void SetHasFocusFalse (View? newFocusedView, bool traversingDown = false
782838
SetNeedsDisplay ();
783839
}
784840

785-
private void NotifyFocusChanged (bool newHasFocus, View? previousFocusedView, View? focusedVew)
841+
private void RaiseFocusChanged (bool newHasFocus, View? previousFocusedView, View? focusedVew)
786842
{
787843
if (newHasFocus && focusedVew?.Focused is null)
788844
{

Terminal.Gui/Views/HexView.cs

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,6 @@ public HexView (Stream? source)
6666
AddCommand (Command.Right, () => MoveRight ());
6767
AddCommand (Command.Down, () => MoveDown (BytesPerLine));
6868
AddCommand (Command.Up, () => MoveUp (BytesPerLine));
69-
AddCommand (Command.Tab, () => Navigate (NavigationDirection.Forward));
70-
AddCommand (Command.BackTab, () => Navigate (NavigationDirection.Backward));
7169
AddCommand (Command.PageUp, () => MoveUp (BytesPerLine * Viewport.Height));
7270
AddCommand (Command.PageDown, () => MoveDown (BytesPerLine * Viewport.Height));
7371
AddCommand (Command.Start, () => MoveHome ());
@@ -99,9 +97,6 @@ public HexView (Stream? source)
9997
KeyBindings.Add (Key.CursorUp.WithCtrl, Command.StartOfPage);
10098
KeyBindings.Add (Key.CursorDown.WithCtrl, Command.EndOfPage);
10199

102-
KeyBindings.Add (Key.Tab, Command.Tab);
103-
KeyBindings.Add (Key.Tab.WithShift, Command.BackTab);
104-
105100
KeyBindings.Add (Key.Backspace, Command.DeleteCharLeft);
106101
KeyBindings.Add (Key.Delete, Command.DeleteCharRight);
107102
KeyBindings.Add (Key.InsertChar, Command.Insert);
@@ -606,7 +601,7 @@ public override bool OnProcessKeyDown (Key keyEvent)
606601
int value;
607602
var k = (char)keyEvent.KeyCode;
608603

609-
if (!char.IsAsciiDigit ((char)keyEvent.KeyCode))
604+
if (!char.IsAsciiHexDigit ((char)keyEvent.KeyCode))
610605
{
611606
return false;
612607
}
@@ -949,23 +944,25 @@ private void RedisplayLine (long pos)
949944
SetNeedsDisplay (new (0, line, Viewport.Width, 1));
950945
}
951946

952-
private bool Navigate (NavigationDirection direction)
947+
/// <inheritdoc />
948+
protected override bool OnAdvancingFocus (NavigationDirection direction, TabBehavior? behavior)
953949
{
954-
switch (direction)
950+
if (direction == NavigationDirection.Forward && _leftSideHasFocus)
955951
{
956-
case NavigationDirection.Forward:
957-
_leftSideHasFocus = !_leftSideHasFocus;
958-
RedisplayLine (Address);
959-
_firstNibble = true;
952+
_leftSideHasFocus = !_leftSideHasFocus;
953+
RedisplayLine (Address);
954+
_firstNibble = true;
960955

961-
return true;
956+
return true;
957+
}
962958

963-
case NavigationDirection.Backward:
964-
_leftSideHasFocus = !_leftSideHasFocus;
965-
RedisplayLine (Address);
966-
_firstNibble = true;
959+
if (direction == NavigationDirection.Backward && !_leftSideHasFocus)
960+
{
961+
_leftSideHasFocus = !_leftSideHasFocus;
962+
RedisplayLine (Address);
963+
_firstNibble = true;
967964

968-
return true;
965+
return true;
969966
}
970967

971968
return false;

0 commit comments

Comments
 (0)