Done with refactor. Nav unit tests all pass. Fixing View unit tests...

This commit is contained in:
Tig
2024-08-20 13:11:55 -06:00
parent 794ad0bad7
commit d1d7ab5fa8
17 changed files with 561 additions and 486 deletions

View File

@@ -333,7 +333,7 @@ public static partial class Application // Keyboard handling
() =>
{
View? current = Application.Current;
if (current is {})
if (current is { })
{
return current.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
}
@@ -363,7 +363,7 @@ public static partial class Application // Keyboard handling
View? current = Application.Current;
if (current is { })
{
return current.AdvanceFocus (NavigationDirection.Backward, TabBehavior.TabGroup);
return current.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabGroup);
}
}
else
@@ -381,9 +381,22 @@ public static partial class Application // Keyboard handling
Command.PreviousViewOrTop,
() =>
{
ApplicationNavigation.MovePreviousViewOrTop ();
if (ApplicationOverlapped.OverlappedTop is null)
{
View? current = Application.Current;
if (current is { })
{
return current.AdvanceFocus (NavigationDirection.Backward, TabBehavior.TabGroup);
}
}
else
{
ApplicationOverlapped.OverlappedMovePrevious();
return true;
return true;
}
return false;
}
);

View File

@@ -186,7 +186,12 @@ public static partial class Application // Run (Begin, Run, End, Stop)
toplevel.LayoutSubviews ();
toplevel.PositionToplevels ();
toplevel.AdvanceFocus (NavigationDirection.Forward, null);//.FocusDeepest (null, NavigationDirection.Forward);
// Try to set initial focus to any TabGroup
if (!toplevel.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabGroup))
{
// That didn't work. Try TabStop.
toplevel.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
}
ApplicationOverlapped.BringOverlappedTopToFront ();
if (refreshDriver)

View File

@@ -107,27 +107,4 @@ public class ApplicationNavigation
return view;
}
internal static void MovePreviousViewOrTop ()
{
if (ApplicationOverlapped.OverlappedTop is null)
{
Toplevel? top = Application.Current!.Modal ? Application.Current : Application.Top;
top!.AdvanceFocus (NavigationDirection.Backward, TabBehavior.TabGroup);
if (top.Focused is null)
{
top.AdvanceFocus (NavigationDirection.Backward, null);
}
top.SetNeedsDisplay ();
ApplicationOverlapped.BringOverlappedTopToFront ();
}
else
{
ApplicationOverlapped.OverlappedMovePrevious ();
}
}
}

View File

@@ -46,7 +46,8 @@ public partial class View // Focus and cross-view navigation management (TabStop
if (value)
{
// NOTE: If Application.Navigation is null, we pass null to FocusChanging. For unit tests.
if (SetHasFocusTrue (Application.Navigation?.GetFocused ()))
(bool focusSet, bool _) = SetHasFocusTrue (Application.Navigation?.GetFocused ());
if (focusSet)
{
// The change happened
// HasFocus is now true
@@ -67,7 +68,8 @@ public partial class View // Focus and cross-view navigation management (TabStop
/// </summary>
public bool SetFocus ()
{
return SetHasFocusTrue (Application.Navigation?.GetFocused ());
(bool focusSet, bool _) = SetHasFocusTrue (Application.Navigation?.GetFocused ());
return focusSet;
}
/// <summary>
@@ -78,82 +80,58 @@ public partial class View // Focus and cross-view navigation management (TabStop
/// <param name="traversingUp"></param>
/// <returns><see langword="true"/> if <see cref="HasFocus"/> was changed to <see langword="true"/>.</returns>
/// <exception cref="InvalidOperationException"></exception>
private bool SetHasFocusTrue ([CanBeNull] View previousFocusedView, bool traversingUp = false)
private (bool focusSet, bool cancelled) SetHasFocusTrue ([CanBeNull] View previousFocusedView, bool traversingUp = false)
{
Debug.Assert (ApplicationNavigation.IsInHierarchy (SuperView, this));
// Pre-conditions
if (_hasFocus)
{
return false;
return (false, false);
}
if (CanFocus && SuperView is { CanFocus: false })
{
Debug.WriteLine ($@"WARNING: Attempt to FocusChanging where SuperView.CanFocus == false. {this}");
return false;
return (false, false);
}
if (!CanBeVisible (this) || !Enabled)
{
return false;
return (false, false);
}
if (!CanFocus)
{
return false;
return (false, false);
}
bool previousValue = HasFocus;
if (!traversingUp)
bool cancelled = NotifyFocusChanging (false, true, previousFocusedView, this);
if (cancelled)
{
// If we're here, we can be focused. But we may have subviews.
// Restore focus to the previously most focused subview in the subview-hierarchy
if (RestoreFocus (TabStop))
{
// A subview was focused. We're done because the subview has focus and it recursed up the superview hierarchy.
return true;
}
// Couldn't restore focus, so use Advance to navigate to the next focusable subview
if (AdvanceFocus (NavigationDirection.Forward, null))
{
// A subview was focused. We're done because the subview has focus and it recursed up the superview hierarchy.
return true;
}
return (false, true);
}
if (NotifyFocusChanging (false, true, previousFocusedView, this))
{
return false;
}
//// If we previously had a subview with focus (`Focused = subview`), we need to make sure that all subviews down the `subview`-hierarchy LeaveFocus.
//// LeaveFocus will recurse down the subview hierarchy and will also set PreviouslyMostFocused
//View focused = Focused;
//focused?.SetHasFocusFalse (this, true);
// If we're here, we're the most-focusable view in the application OR we're traversing up the superview hierarchy.
// If we previously had a subview with focus (`Focused = subview`), we need to make sure that all subviews down the `subview`-hierarchy LeaveFocus.
// LeaveFocus will recurse down the subview hierarchy and will also set PreviouslyMostFocused
View focused = Focused;
focused?.SetHasFocusFalse (this, true);
// We need to ensure all superviews up the superview hierarchy have focus.
// Make sure superviews up the superview hierarchy have focus.
// Any of them may cancel gaining focus. In which case we need to back out.
if (SuperView is { HasFocus: false } sv)
{
// Tell SetHasFocusTrue that we're traversing up the superview hierarchy
if (!sv.SetHasFocusTrue (previousFocusedView, true))
(bool focusSet, bool svCancelled) = sv.SetHasFocusTrue (previousFocusedView, true);
if (!focusSet)
{
// The change didn't happen.
return false;
return (false, svCancelled);
}
}
// If we're here:
// - we're the most-focusable view in the application
// - all superviews up the superview hierarchy have focus.
// - By setting _hasFocus to true we definitively change HasFocus for this view.
// By setting _hasFocus to true we definitively change HasFocus for this view.
// Get whatever peer has focus, if any
View focusedPeer = SuperView?.Focused;
@@ -163,11 +141,23 @@ public partial class View // Focus and cross-view navigation management (TabStop
// Ensure that the peer loses focus
focusedPeer?.SetHasFocusFalse (this, true);
// We're the most focused view in the application, we need to set the focused view to this view.
Application.Navigation?.SetFocused (this);
if (!traversingUp)
{
// Restore focus to the previously most focused subview in the subview-hierarchy
if (!RestoreFocus (TabStop))
{
// Couldn't restore focus, so use Advance to navigate to the next focusable subview
if (!AdvanceFocus (NavigationDirection.Forward, null))
{
// Couldn't advance, so we're the most focused view in the application
_previouslyMostFocused = null;
Application.Navigation?.SetFocused (this);
//NotifyFocusChanged (HasFocus, previousFocusedView, this);
}
}
}
NotifyFocusChanged (HasFocus, previousFocusedView, this);
SetNeedsDisplay ();
// Post-conditions - prove correctness
@@ -176,7 +166,7 @@ public partial class View // Focus and cross-view navigation management (TabStop
throw new InvalidOperationException ($"NotifyFocusChanging was not cancelled and the HasFocus value did not change.");
}
return true;
return (true, false);
}
@@ -204,8 +194,13 @@ public partial class View // Focus and cross-view navigation management (TabStop
/// <summary>
/// Invoked when <see cref="View.HasFocus"/> is about to change. This method is called before the <see cref="HasFocusChanging"/> event is raised.
/// </summary>
/// <remarks>
/// <para>
/// Use <see cref="OnHasFocusChanged"/> to be notified after the focus has changed.
/// </para>
/// </remarks>
/// <param name="currentHasFocus">The current value of <see cref="View.HasFocus"/>.</param>
/// <param name="newHasFocus">The value <see cref="View.HasFocus"/> will have if the event is not cancelled.</param>
/// <param name="newHasFocus">The value <see cref="View.HasFocus"/> will have if the focus change happens.</param>
/// <param name="currentFocused">The view that is currently Focused. May be <see langword="null"/>.</param>
/// <param name="newFocused">The view that will be focused. May be <see langword="null"/>.</param>
/// <returns> <see langword="true"/>, if the change to <see cref="View.HasFocus"/> is to be cancelled, <see langword="false"/> otherwise.</returns>
@@ -214,57 +209,70 @@ public partial class View // Focus and cross-view navigation management (TabStop
return false;
}
/// <summary>Raised when the view is gaining (entering) focus. Can be cancelled.</summary>
/// <summary>
/// Raised when <see cref="View.HasFocus"/> is about to change.
/// </summary>
/// <remarks>
/// <para>
/// Cancel the event to prevent the focus from changing.
/// </para>
/// <para>
/// Use <see cref="HasFocusChanged"/> to be notified after the focus has changed.
/// </para>
/// </remarks>
public event EventHandler<HasFocusEventArgs> HasFocusChanging;
/// <summary>
/// Called when focus has changed to another view.
/// Called when this view should stop being focused.
/// </summary>
/// <param name="focusedVew">The view that now has focus. If <see langword="null"/> there is no view that has focus.</param>
/// <param name="newFocusedVew">The new focused view. If <see langword="null"/> it is not known which view will be focused.</param>
/// <exception cref="InvalidOperationException"></exception>
private void SetHasFocusFalse ([CanBeNull] View focusedVew, bool traversingDown = false)
private void SetHasFocusFalse ([CanBeNull] View newFocusedVew, bool traversingDown = false)
{
// Pre-conditions
if (!_hasFocus)
{
throw new InvalidOperationException ($"FocusChanged should not be called if the view does not have focus.");
throw new InvalidOperationException ($"SetHasFocusFalse should not be called if the view does not have focus.");
}
// If enteringView is null, we need to find the view that should get focus, and SetFocus on it.
if (!traversingDown && focusedVew is null)
// If newFocusedVew is null, we need to find the view that should get focus, and SetFocus on it.
if (!traversingDown && newFocusedVew is null)
{
if (SuperView?._previouslyMostFocused is { } && SuperView?._previouslyMostFocused != this)
{
SuperView?._previouslyMostFocused?.SetFocus ();
// The above will cause FocusChanged, so we can return
// The above will cause SetHasFocusFalse, so we can return
return;
}
if (SuperView is { } && SuperView.AdvanceFocus (NavigationDirection.Forward, TabStop))
{
// The above will cause FocusChanged, so we can return
// The above will cause SetHasFocusFalse, so we can return
return;
}
//if (Application.Navigation is { })
//{
// // Temporarily ensure this view can't get focus
// bool prevCanFocus = _canFocus;
// _canFocus = false;
// Application.Navigation.;
// _canFocus = prevCanFocus;
if (Application.Navigation is { })
{
// Temporarily ensure this view can't get focus
bool prevCanFocus = _canFocus;
_canFocus = false;
bool restoredFocus = Application.Current!.RestoreFocus (null);
_canFocus = prevCanFocus;
// // The above will cause LeaveFocus, so we can return
// return;
//}
if (restoredFocus)
{
// The above caused SetHasFocusFalse, so we can return
return;
}
}
// No other focusable view to be found. Just "leave" us...
}
// Before we can leave focus, we need to make sure that all views down the subview-hierarchy have left focus.
View mostFocused = MostFocused;
if (mostFocused is { } && (focusedVew is null || mostFocused != focusedVew))
if (mostFocused is { } && (newFocusedVew is null || mostFocused != newFocusedVew))
{
// Start at the bottom and work our way up to us
View bottom = mostFocused;
@@ -273,7 +281,7 @@ public partial class View // Focus and cross-view navigation management (TabStop
{
if (bottom.HasFocus)
{
bottom.SetHasFocusFalse (focusedVew, true);
bottom.SetHasFocusFalse (newFocusedVew, true);
}
bottom = bottom.SuperView;
}
@@ -283,26 +291,17 @@ public partial class View // Focus and cross-view navigation management (TabStop
bool previousValue = HasFocus;
// Note, can't be cancelled.
NotifyFocusChanging (HasFocus, !HasFocus, focusedVew, this);
NotifyFocusChanging (HasFocus, !HasFocus, newFocusedVew, this);
// Get whatever peer has focus, if any
View focusedPeer = SuperView?.Focused;
_hasFocus = false;
NotifyFocusChanged (HasFocus, this, focusedVew);
if (!traversingDown && CanFocus && Visible && Enabled)
{
// Now ensure all views up the superview-hierarchy are unfocused
if (SuperView is { HasFocus: true } && focusedPeer == this)
{
SuperView.SetHasFocusFalse (focusedVew);
}
}
NotifyFocusChanged (HasFocus, this, newFocusedVew);
if (SuperView is { })
{
SuperView._previouslyMostFocused = this;
SuperView._previouslyMostFocused = focusedPeer;
}
// Post-conditions - prove correctness
@@ -428,7 +427,9 @@ public partial class View // Focus and cross-view navigation management (TabStop
}
// The subview does not have focus, but at least one other that can. Can this one be focused?
return view.SetHasFocusTrue (Focused);
(bool focusSet, bool _) = view.SetHasFocusTrue (Focused);
return focusSet;
}

View File

@@ -8,6 +8,7 @@
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading.Channels;
namespace Terminal.Gui;
@@ -31,7 +32,7 @@ public class ComboBox : View, IDesignable
CanFocus = true;
_search = new TextField () { CanFocus = true, TabStop = TabBehavior.NoStop };
_listview = new ComboListView (this, HideDropdownListOnClick) { CanFocus = true, TabStop = TabBehavior.NoStop};
_listview = new ComboListView (this, HideDropdownListOnClick) { CanFocus = true, TabStop = TabBehavior.NoStop };
_search.TextChanged += Search_Changed;
_search.Accept += Search_Accept;
@@ -299,19 +300,6 @@ public class ComboBox : View, IDesignable
Driver.AddRune (Glyphs.DownArrow);
}
/// <inheritdoc/>
protected override bool OnHasFocusChanging (bool currentHasFocus, bool newHasFocus, [CanBeNull] View currentFocused, [CanBeNull] View newFocused)
{
bool cancel = false;
if (!_search.HasFocus && !_listview.HasFocus)
{
cancel = _search.SetFocus ();
}
_search.CursorPosition = _search.Text.GetRuneCount ();
return cancel;
}
/// <summary>Virtual method which invokes the <see cref="Expanded"/> event.</summary>
public virtual void OnExpanded () { Expanded?.Invoke (this, EventArgs.Empty); }
@@ -319,25 +307,34 @@ public class ComboBox : View, IDesignable
/// <inheritdoc/>
protected override void OnHasFocusChanged (bool newHasFocus, View previousFocusedView, View view)
{
if (_source?.Count > 0
&& _selectedItem > -1
&& _selectedItem < _source.Count - 1
&& _text != _source.ToList () [_selectedItem].ToString ())
if (newHasFocus)
{
SetValue (_source.ToList () [_selectedItem].ToString ());
if (!_search.HasFocus && !_listview.HasFocus)
{
_search.SetFocus ();
}
_search.CursorPosition = _search.Text.GetRuneCount ();
}
else
{
if (_source?.Count > 0
&& _selectedItem > -1
&& _selectedItem < _source.Count - 1
&& _text != _source.ToList () [_selectedItem].ToString ())
{
SetValue (_source.ToList () [_selectedItem].ToString ());
}
if (_autoHide && IsShow && view != this && view != _search && view != _listview)
{
IsShow = false;
HideList ();
if (_autoHide && IsShow && view != this && view != _search && view != _listview)
{
IsShow = false;
HideList ();
}
else if (_listview.TabStop?.HasFlag (TabBehavior.TabStop) ?? false)
{
_listview.TabStop = TabBehavior.NoStop;
}
}
else if (_listview.TabStop?.HasFlag (TabBehavior.TabStop) ?? false)
{
_listview.TabStop = TabBehavior.NoStop;
}
return;
}
/// <summary>Invokes the OnOpenSelectedItem event if it is defined.</summary>
@@ -565,7 +562,7 @@ public class ComboBox : View, IDesignable
{
if (HasItems ())
{
return _listview.MoveUp ();
return _listview.MoveUp ();
}
return false;

View File

@@ -518,7 +518,10 @@ public class FileDialog : Dialog
};
AllowedTypeMenuClicked (0);
_allowedTypeMenuBar.HasFocusChanging += (s, e) => { _allowedTypeMenuBar.OpenMenu (0); };
_allowedTypeMenuBar.HasFocusChanging += (s, e) =>
{
_allowedTypeMenuBar.OpenMenu (0);
};
_allowedTypeMenuBar.DrawContentComplete += (s, e) =>
{

View File

@@ -760,6 +760,10 @@ public class HexView : View
private void RedisplayLine (long pos)
{
if (bytesPerLine == 0)
{
return;
}
var delta = (int)(pos - DisplayStart);
int line = delta / bytesPerLine;

View File

@@ -739,14 +739,12 @@ public class ListView : View, IDesignable
}
/// <inheritdoc/>
protected override bool OnHasFocusChanging (bool currentHasFocus, bool newHasFocus, [CanBeNull] View currentFocused, [CanBeNull] View newFocused)
protected override void OnHasFocusChanged (bool newHasFocus, [CanBeNull] View currentFocused, [CanBeNull] View newFocused)
{
if (_lastSelectedItem != _selected)
if (newHasFocus && _lastSelectedItem != _selected)
{
EnsureSelectedItemVisible ();
}
return false; // Don't cancel the focus switch
}
// TODO: This should be cancelable

View File

@@ -86,45 +86,10 @@ public class MenuBar : View, IDesignable
Added += MenuBar_Added;
// Things this view knows how to do
AddCommand (
Command.Left,
() =>
{
MoveLeft ();
return true;
}
);
AddCommand (
Command.Right,
() =>
{
MoveRight ();
return true;
}
);
AddCommand (
Command.Cancel,
() =>
{
CloseMenuBar ();
return true;
}
);
AddCommand (
Command.Accept,
() =>
{
ProcessMenu (_selected, Menus [_selected]);
return true;
}
);
AddCommand (Command.Left, () => MoveLeft ());
AddCommand (Command.Right, () => MoveRight ());
AddCommand (Command.Cancel, () => CloseMenuBar ());
AddCommand (Command.Accept, () => _selected >= 0 && ProcessMenu (_selected, Menus [_selected]));
AddCommand (Command.ToggleExpandCollapse, ctx => Select (Menus.IndexOf (ctx.KeyBinding?.Context)));
AddCommand (Command.Select, ctx => Run ((ctx.KeyBinding?.Context as MenuItem)?.Action));
@@ -225,7 +190,6 @@ public class MenuBar : View, IDesignable
if (value && UseKeysUpDownAsKeysLeftRight)
{
_useKeysUpDownAsKeysLeftRight = false;
SetNeedsDisplay ();
}
}
}
@@ -375,7 +339,7 @@ public class MenuBar : View, IDesignable
}
/// <summary>Opens the Menu programatically, as though the F9 key were pressed.</summary>
public void OpenMenu ()
public bool OpenMenu ()
{
MenuBar mbar = GetMouseGrabViewInstance (this);
@@ -386,11 +350,10 @@ public class MenuBar : View, IDesignable
if (!Enabled || _openMenu is { })
{
return;
return false;
}
_selected = 0;
SetNeedsDisplay ();
_previousFocused = null;//SuperView is null ? Application.Current?.Focused : SuperView.Focused;
OpenMenu (_selected);
@@ -402,15 +365,17 @@ public class MenuBar : View, IDesignable
)
&& !CloseMenu (false))
{
return;
return IsMenuOpen;
}
if (!OpenCurrentMenu.CheckSubMenu ())
{
return;
return IsMenuOpen;
}
Application.GrabMouse (this);
return IsMenuOpen;
}
/// <inheritdoc/>
@@ -446,7 +411,7 @@ public class MenuBar : View, IDesignable
// Activates the menu, handles either first focus, or activating an entry when it was already active
// For mouse events.
internal void Activate (int idx, int sIdx = -1, MenuBarItem subMenu = null)
internal bool Activate (int idx, int sIdx = -1, MenuBarItem subMenu = null)
{
_selected = idx;
_selectedSub = sIdx;
@@ -456,8 +421,7 @@ public class MenuBar : View, IDesignable
_previousFocused = null;//SuperView is null ? Application.Current?.Focused ?? null : SuperView.Focused;
}
OpenMenu (idx, sIdx, subMenu);
SetNeedsDisplay ();
return OpenMenu (idx, sIdx, subMenu);
}
internal void CleanUp ()
@@ -479,7 +443,6 @@ public class MenuBar : View, IDesignable
_lastFocused.SetFocus ();
}
SetNeedsDisplay ();
Application.UngrabMouse ();
_isCleaning = false;
}
@@ -550,8 +513,6 @@ public class MenuBar : View, IDesignable
Application.Current?.Remove (_openMenu);
}
SetNeedsDisplay ();
if (_previousFocused is Menu && _openMenu is { } && _previousFocused.ToString () != OpenCurrentMenu.ToString ())
{
_previousFocused.SetFocus ();
@@ -603,7 +564,6 @@ public class MenuBar : View, IDesignable
case true:
_selectedSub = -1;
SetNeedsDisplay ();
RemoveAllOpensSubMenus ();
OpenCurrentMenu?._previousSubFocused.SetFocus ();
_openSubMenu = null;
@@ -644,7 +604,7 @@ public class MenuBar : View, IDesignable
);
}
internal void NextMenu (bool isSubMenu = false, bool ignoreUseSubMenusSingleFrame = false)
internal bool NextMenu (bool isSubMenu = false, bool ignoreUseSubMenusSingleFrame = false)
{
switch (isSubMenu)
{
@@ -664,7 +624,7 @@ public class MenuBar : View, IDesignable
if (_selected > -1 && !CloseMenu (true, ignoreUseSubMenusSingleFrame))
{
return;
return false;
}
OpenMenu (_selected);
@@ -696,7 +656,7 @@ public class MenuBar : View, IDesignable
{
if (_openSubMenu is { } && !CloseMenu (false, true))
{
return;
return IsMenuOpen;
}
NextMenu (false, ignoreUseSubMenusSingleFrame);
@@ -714,14 +674,12 @@ public class MenuBar : View, IDesignable
{
if (CloseMenu (false, true, ignoreUseSubMenusSingleFrame))
{
NextMenu (false, ignoreUseSubMenusSingleFrame);
return NextMenu (false, ignoreUseSubMenusSingleFrame);
}
return;
return IsMenuOpen;
}
SetNeedsDisplay ();
if (UseKeysUpDownAsKeysLeftRight)
{
OpenCurrentMenu.CheckSubMenu ();
@@ -730,9 +688,11 @@ public class MenuBar : View, IDesignable
break;
}
return IsMenuOpen;
}
internal void OpenMenu (int index, int sIndex = -1, MenuBarItem subMenu = null)
internal bool OpenMenu (int index, int sIndex = -1, MenuBarItem subMenu = null)
{
_isMenuOpening = true;
MenuOpeningEventArgs newMenu = OnMenuOpening (Menus [index]);
@@ -741,7 +701,7 @@ public class MenuBar : View, IDesignable
{
_isMenuOpening = false;
return;
return false;
}
if (newMenu.NewMenuBarItem is { })
@@ -759,7 +719,7 @@ public class MenuBar : View, IDesignable
if (_openSubMenu is { } && !CloseMenu (false, true))
{
return;
return IsMenuOpen;
}
if (_openMenu is { })
@@ -895,9 +855,11 @@ public class MenuBar : View, IDesignable
_isMenuOpening = false;
IsMenuOpen = true;
return true;
}
internal void PreviousMenu (bool isSubMenu = false, bool ignoreUseSubMenusSingleFrame = false)
internal bool PreviousMenu (bool isSubMenu = false, bool ignoreUseSubMenusSingleFrame = false)
{
switch (isSubMenu)
{
@@ -913,10 +875,10 @@ public class MenuBar : View, IDesignable
if (_selected > -1 && !CloseMenu (true, false, ignoreUseSubMenusSingleFrame))
{
return;
return true;
}
OpenMenu (_selected);
bool opened = OpenMenu (_selected);
if (!SelectEnabledItem (
OpenCurrentMenu.BarItems.Children,
@@ -928,21 +890,23 @@ public class MenuBar : View, IDesignable
OpenCurrentMenu._currentChild = 0;
}
break;
return opened;
case true:
if (_selectedSub > -1)
{
_selectedSub--;
RemoveSubMenu (_selectedSub, ignoreUseSubMenusSingleFrame);
SetNeedsDisplay ();
}
else
{
PreviousMenu ();
return PreviousMenu ();
}
break;
}
return true;
}
internal void RemoveAllOpensSubMenus ()
@@ -1063,11 +1027,11 @@ public class MenuBar : View, IDesignable
return Run (item?.Action);
}
private void CloseMenuBar ()
private bool CloseMenuBar ()
{
if (!CloseMenu (false))
{
return;
return false;
}
if (_openedByAltKey)
@@ -1076,7 +1040,7 @@ public class MenuBar : View, IDesignable
LastFocused?.SetFocus ();
}
SetNeedsDisplay ();
return true;
}
private Point GetLocationOffset ()
@@ -1095,7 +1059,7 @@ public class MenuBar : View, IDesignable
Added -= MenuBar_Added;
}
private void MoveLeft ()
private bool MoveLeft ()
{
_selected--;
@@ -1104,22 +1068,30 @@ public class MenuBar : View, IDesignable
_selected = Menus.Length - 1;
}
OpenMenu (_selected);
SetNeedsDisplay ();
if (_selected < 0)
{
return false;
}
return OpenMenu (_selected);
}
private void MoveRight ()
private bool MoveRight ()
{
if (Menus.Length == 0)
{
return false;
}
_selected = (_selected + 1) % Menus.Length;
OpenMenu (_selected);
SetNeedsDisplay ();
return OpenMenu (_selected);
}
private void ProcessMenu (int i, MenuBarItem mi)
private bool ProcessMenu (int i, MenuBarItem mi)
{
if (_selected < 0 && IsMenuOpen)
{
return;
return false;
}
if (mi.IsTopLevel)
@@ -1133,7 +1105,7 @@ public class MenuBar : View, IDesignable
{
Application.GrabMouse (this);
_selected = i;
OpenMenu (i);
bool opened = OpenMenu (i);
if (!SelectEnabledItem (
OpenCurrentMenu.BarItems.Children,
@@ -1142,16 +1114,17 @@ public class MenuBar : View, IDesignable
)
&& !CloseMenu (false))
{
return;
return false;
}
if (!OpenCurrentMenu.CheckSubMenu ())
{
return;
return true;
}
return opened;
}
SetNeedsDisplay ();
return true;
}
private void RemoveSubMenu (int index, bool ignoreUseSubMenusSingleFrame = false)
@@ -1256,7 +1229,6 @@ public class MenuBar : View, IDesignable
if (value && UseSubMenusSingleFrame)
{
UseSubMenusSingleFrame = false;
SetNeedsDisplay ();
}
}
}

View File

@@ -137,24 +137,24 @@ public class ApplicationNavigationTests (ITestOutputHelper output)
[Fact]
public void MovePreviousViewOrTop_ShouldMoveFocusToPreviousViewOrTop ()
{
// Arrange
var top = new Toplevel ();
var view1 = new View () { Id = "view1", CanFocus = true, TabStop = TabBehavior.TabGroup };
var view2 = new View () { Id = "view2", CanFocus = true, TabStop = TabBehavior.TabGroup };
top.Add (view1, view2);
Application.Top = top;
Application.Current = top;
view2.SetFocus ();
//[Fact]
//public void MovePreviousViewOrTop_ShouldMoveFocusToPreviousViewOrTop ()
//{
// // Arrange
// var top = new Toplevel ();
// var view1 = new View () { Id = "view1", CanFocus = true, TabStop = TabBehavior.TabGroup };
// var view2 = new View () { Id = "view2", CanFocus = true, TabStop = TabBehavior.TabGroup };
// top.Add (view1, view2);
// Application.Top = top;
// Application.Current = top;
// view2.SetFocus ();
// Act
ApplicationNavigation.MovePreviousViewOrTop ();
// // Act
// ApplicationNavigation.MovePreviousViewOrTop ();
// Assert
Assert.True (view1.HasFocus);
// // Assert
// Assert.True (view1.HasFocus);
top.Dispose ();
}
// top.Dispose ();
//}
}

View File

@@ -75,14 +75,11 @@ public class AddRemoveNavigationTests (ITestOutputHelper _output) : TestsAllView
CanFocus = true
};
int nLeave = 0;
View subView = new View ()
{
Id = "subView",
CanFocus = true
};
subView.HasFocusChanged += (s, e) => nLeave++;
top.Add (subView);
@@ -95,7 +92,6 @@ public class AddRemoveNavigationTests (ITestOutputHelper _output) : TestsAllView
Assert.True (top.HasFocus);
Assert.Equal (null, top.Focused);
Assert.False (subView.HasFocus);
Assert.Equal (1, nLeave);
}
[Fact]
@@ -107,14 +103,11 @@ public class AddRemoveNavigationTests (ITestOutputHelper _output) : TestsAllView
CanFocus = true
};
int nLeave1 = 0;
View subView1 = new View ()
{
Id = "subView1",
CanFocus = true
};
subView1.HasFocusChanged += (s, e) => nLeave1++;
View subView2 = new View ()
{
@@ -134,7 +127,5 @@ public class AddRemoveNavigationTests (ITestOutputHelper _output) : TestsAllView
Assert.True (subView2.HasFocus);
Assert.Equal (subView2, top.Focused);
Assert.False (subView1.HasFocus);
Assert.Equal (1, nLeave1);
}
}

View File

@@ -4,6 +4,7 @@ namespace Terminal.Gui.ViewTests;
public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllViews
{
#region HasFocusChanging_NewValue_True
[Fact]
public void HasFocusChanging_SetFocus_Raises ()
{
@@ -452,7 +453,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
[Fact]
public void HasFocusChanging_SetFocus_On_Subview_SubView_Can_Cancel ()
public void HasFocusChanging_SetFocus_On_Subview_If_SubView_Cancels ()
{
var hasFocusTrueCount = 0;
var hasFocusFalseCount = 0;
@@ -499,100 +500,318 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
subview.SetFocus ();
Assert.False (view.HasFocus);
Assert.False (subview.HasFocus);
Assert.False (view.HasFocus); // Never had focus
Assert.False (subview.HasFocus); // Cancelled
Assert.Equal (0, hasFocusTrueCount);
Assert.Equal (0, hasFocusFalseCount);
Assert.Equal (1, subviewHasFocusTrueCount);
Assert.Equal (0, subviewHasFocusFalseCount);
// Now set focus on the view
view.SetFocus ();
Assert.True (view.HasFocus);
Assert.False (subview.HasFocus); // Cancelled
Assert.Equal (1, hasFocusTrueCount);
Assert.Equal (0, hasFocusFalseCount);
Assert.Equal (2, subviewHasFocusTrueCount);
Assert.Equal (0, subviewHasFocusFalseCount);
}
#endregion HasFocusChanging_NewValue_True
#region HasFocusChanging_NewValue_False
[Fact]
public void RemoveFocus_Raises_HasFocusChanged ()
public void HasFocusChanging_RemoveFocus_Raises ()
{
var nEnter = 0;
var nLeave = 0;
var hasFocusTrueCount = 0;
var hasFocusFalseCount = 0;
var view = new View
{
Id = "view",
CanFocus = true
};
view.HasFocusChanging += (s, e) => nEnter++;
view.HasFocusChanged += (s, e) => nLeave++;
view.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
{
hasFocusTrueCount++;
}
else
{
hasFocusFalseCount++;
}
};
Assert.True (view.CanFocus);
Assert.False (view.HasFocus);
view.SetFocus ();
Assert.True (view.HasFocus);
Assert.Equal (1, nEnter);
Assert.Equal (0, nLeave);
Assert.Equal (1, hasFocusTrueCount);
Assert.Equal (0, hasFocusFalseCount);
view.HasFocus = false;
Assert.Equal (1, nEnter);
Assert.Equal (1, nLeave);
Assert.False (view.HasFocus);
Assert.Equal (1, hasFocusTrueCount);
Assert.Equal (1, hasFocusFalseCount);
}
[Fact]
public void RemoveFocus_SubView_Raises_HasFocusChanged ()
public void HasFocusChanging_RemoveFocus_SubView_SetFocus_Raises ()
{
var viewEnterCount = 0;
var viewLeaveCount = 0;
var hasFocusTrueCount = 0;
var hasFocusFalseCount = 0;
var view = new View
{
Id = "view",
CanFocus = true
};
view.HasFocusChanging += (s, e) => viewEnterCount++;
view.HasFocusChanged += (s, e) => viewLeaveCount++;
view.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
{
hasFocusTrueCount++;
}
else
{
hasFocusFalseCount++;
}
};
var subviewEnterCount = 0;
var subviewLeaveCount = 0;
var subviewHasFocusTrueCount = 0;
var subviewHasFocusFalseCount = 0;
var subview = new View
{
Id = "subview",
CanFocus = true
};
subview.HasFocusChanging += (s, e) => subviewEnterCount++;
subview.HasFocusChanged += (s, e) => subviewLeaveCount++;
subview.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
{
subviewHasFocusTrueCount++;
}
else
{
subviewHasFocusFalseCount++;
}
};
view.Add (subview);
view.SetFocus ();
Assert.Equal (1, hasFocusTrueCount);
Assert.Equal (0, hasFocusFalseCount);
Assert.Equal (1, subviewHasFocusTrueCount);
Assert.Equal (0, subviewHasFocusFalseCount);
view.HasFocus = false;
Assert.False(view.HasFocus);
Assert.False (subview.HasFocus);
Assert.Equal (1, hasFocusTrueCount);
Assert.Equal (1, hasFocusFalseCount);
Assert.Equal (1, subviewHasFocusTrueCount);
Assert.Equal (1, subviewHasFocusFalseCount);
}
[Fact]
public void HasFocusChanging_RemoveFocus_On_SubView_SubView_SetFocus_Raises ()
{
var hasFocusTrueCount = 0;
var hasFocusFalseCount = 0;
var view = new View
{
Id = "view",
CanFocus = true
};
view.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
{
hasFocusTrueCount++;
}
else
{
hasFocusFalseCount++;
}
};
var subviewHasFocusTrueCount = 0;
var subviewHasFocusFalseCount = 0;
var subview = new View
{
Id = "subview",
CanFocus = true
};
subview.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
{
subviewHasFocusTrueCount++;
}
else
{
subviewHasFocusFalseCount++;
}
};
view.Add (subview);
subview.SetFocus ();
Assert.Equal (1, hasFocusTrueCount);
Assert.Equal (0, hasFocusFalseCount);
Assert.Equal (1, subviewHasFocusTrueCount);
Assert.Equal (0, subviewHasFocusFalseCount);
subview.HasFocus = false;
Assert.False (subview.HasFocus);
Assert.Equal (1, hasFocusTrueCount);
Assert.Equal (0, hasFocusFalseCount);
Assert.Equal (1, subviewHasFocusTrueCount);
Assert.Equal (1, subviewHasFocusFalseCount);
}
#endregion HasFocusChanging_NewValue_False
#region HasFocusChanged
[Fact]
public void HasFocusChanged_RemoveFocus_Raises ()
{
var newValueTrueCount = 0;
var newValueFalseCount = 0;
var view = new View
{
Id = "view",
CanFocus = true
};
view.HasFocusChanged += (s, e) =>
{
if (e.NewValue)
{
newValueTrueCount++;
}
else
{
newValueFalseCount++;
}
};
Assert.True (view.CanFocus);
Assert.False (view.HasFocus);
view.SetFocus ();
Assert.True (view.HasFocus);
Assert.Equal (1, newValueTrueCount);
Assert.Equal (0, newValueFalseCount);
view.HasFocus = false;
Assert.Equal (1, newValueTrueCount);
Assert.Equal (1, newValueFalseCount);
}
[Fact]
public void HasFocusChanged_With_SubView_Raises ()
{
var newValueTrueCount = 0;
var newValueFalseCount = 0;
var view = new View
{
Id = "view",
CanFocus = true
};
view.HasFocusChanged += (s, e) =>
{
if (e.NewValue)
{
newValueTrueCount++;
}
else
{
newValueFalseCount++;
}
};
var subviewNewValueTrueCount = 0;
var subviewNewValueFalseCount = 0;
var subview = new View
{
Id = "subview",
CanFocus = true
};
subview.HasFocusChanged += (s, e) =>
{
if (e.NewValue)
{
subviewNewValueTrueCount++;
}
else
{
subviewNewValueFalseCount++;
}
};
view.Add (subview);
view.SetFocus ();
Assert.Equal (1, newValueTrueCount);
Assert.Equal (0, newValueFalseCount);
Assert.Equal (1, subviewNewValueTrueCount);
Assert.Equal (0, subviewNewValueFalseCount);
view.HasFocus = false;
Assert.Equal (1, viewEnterCount);
Assert.Equal (1, viewLeaveCount);
Assert.Equal (1, newValueTrueCount);
Assert.Equal (1, newValueFalseCount);
Assert.Equal (1, subviewEnterCount);
Assert.Equal (1, subviewLeaveCount);
Assert.Equal (1, subviewNewValueTrueCount);
Assert.Equal (1, subviewNewValueFalseCount);
view.SetFocus ();
Assert.Equal (2, viewEnterCount);
Assert.Equal (1, viewLeaveCount);
Assert.Equal (2, newValueTrueCount);
Assert.Equal (1, newValueFalseCount);
Assert.Equal (2, subviewEnterCount);
Assert.Equal (1, subviewLeaveCount);
Assert.Equal (2, subviewNewValueTrueCount);
Assert.Equal (1, subviewNewValueFalseCount);
subview.HasFocus = false;
Assert.Equal (2, viewEnterCount);
Assert.Equal (2, viewLeaveCount);
Assert.Equal (2, newValueTrueCount);
Assert.Equal (1, newValueFalseCount);
Assert.Equal (2, subviewEnterCount);
Assert.Equal (2, subviewLeaveCount);
Assert.Equal (2, subviewNewValueTrueCount);
Assert.Equal (2, subviewNewValueFalseCount);
}
[Fact]
public void RemoveFocus_CompoundSubView_Raises_HasFocusChanged ()
public void HasFocusChanged_CompoundSubView_Raises ()
{
var viewEnterCount = 0;
var viewLeaveCount = 0;
@@ -602,8 +821,17 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "view",
CanFocus = true
};
view.HasFocusChanging += (s, e) => viewEnterCount++;
view.HasFocusChanged += (s, e) => viewLeaveCount++;
view.HasFocusChanged += (s, e) =>
{
if (e.NewValue)
{
viewEnterCount++;
}
else
{
viewLeaveCount++;
}
};
var subViewEnterCount = 0;
var subViewLeaveCount = 0;
@@ -613,8 +841,17 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subView",
CanFocus = true
};
subView.HasFocusChanging += (s, e) => subViewEnterCount++;
subView.HasFocusChanged += (s, e) => subViewLeaveCount++;
subView.HasFocusChanged += (s, e) =>
{
if (e.NewValue)
{
subViewEnterCount++;
}
else
{
subViewLeaveCount++;
}
};
var subviewSubView1EnterCount = 0;
var subviewSubView1LeaveCount = 0;
@@ -624,8 +861,17 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subViewSubView1",
CanFocus = false
};
subViewSubView1.HasFocusChanging += (s, e) => subviewSubView1EnterCount++;
subViewSubView1.HasFocusChanged += (s, e) => subviewSubView1LeaveCount++;
subViewSubView1.HasFocusChanged += (s, e) =>
{
if (e.NewValue)
{
subviewSubView1EnterCount++;
}
else
{
subviewSubView1LeaveCount++;
}
};
var subviewSubView2EnterCount = 0;
var subviewSubView2LeaveCount = 0;
@@ -635,9 +881,17 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subViewSubView2",
CanFocus = true
};
subViewSubView2.HasFocusChanging += (s, e) => subviewSubView2EnterCount++;
subViewSubView2.HasFocusChanged += (s, e) => subviewSubView2LeaveCount++;
subViewSubView2.HasFocusChanged += (s, e) =>
{
if (e.NewValue)
{
subviewSubView2EnterCount++;
}
else
{
subviewSubView2LeaveCount++;
}
};
var subviewSubView3EnterCount = 0;
var subviewSubView3LeaveCount = 0;
@@ -646,8 +900,17 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subViewSubView3",
CanFocus = false
};
subViewSubView3.HasFocusChanging += (s, e) => subviewSubView3EnterCount++;
subViewSubView3.HasFocusChanged += (s, e) => subviewSubView3LeaveCount++;
subViewSubView3.HasFocusChanged += (s, e) =>
{
if (e.NewValue)
{
subviewSubView3EnterCount++;
}
else
{
subviewSubView3LeaveCount++;
}
};
subView.Add (subViewSubView1, subViewSubView2, subViewSubView3);
@@ -682,59 +945,5 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Assert.Equal (0, subviewSubView3EnterCount);
Assert.Equal (0, subviewSubView3LeaveCount);
}
[Fact]
public void HasFocus_False_Leave_Raised ()
{
var view = new View
{
Id = "view",
CanFocus = true
};
Assert.True (view.CanFocus);
Assert.False (view.HasFocus);
var leaveInvoked = 0;
view.HasFocusChanged += (s, e) => leaveInvoked++;
view.SetFocus ();
Assert.True (view.HasFocus);
Assert.Equal (0, leaveInvoked);
view.HasFocus = false;
Assert.False (view.HasFocus);
Assert.Equal (1, leaveInvoked);
}
[Fact]
public void HasFocus_False_Leave_Raised_ForAllSubViews ()
{
var view = new View
{
Id = "view",
CanFocus = true
};
var subview = new View
{
Id = "subview",
CanFocus = true
};
view.Add (subview);
var leaveInvoked = 0;
view.HasFocusChanged += (s, e) => leaveInvoked++;
subview.HasFocusChanged += (s, e) => leaveInvoked++;
view.SetFocus ();
Assert.True (view.HasFocus);
Assert.Equal (0, leaveInvoked);
view.HasFocus = false;
Assert.False (view.HasFocus);
Assert.False (subview.HasFocus);
Assert.Equal (2, leaveInvoked);
}
#endregion HasFocusChanged
}

View File

@@ -6,7 +6,7 @@ public class HasFocusTests (ITestOutputHelper _output) : TestsAllViews
{
[Fact]
public void HasFocus_False_Leaves ()
public void HasFocus_False ()
{
var view = new View ()
{
@@ -22,7 +22,7 @@ public class HasFocusTests (ITestOutputHelper _output) : TestsAllViews
}
[Fact]
public void HasFocus_False_WithSuperView_Leaves_All ()
public void HasFocus_False_WithSuperView_Does_Not_Change_SuperView ()
{
var view = new View ()
{
@@ -42,8 +42,8 @@ public class HasFocusTests (ITestOutputHelper _output) : TestsAllViews
Assert.True (subview.HasFocus);
subview.HasFocus = false;
Assert.False (view.HasFocus);
Assert.False (subview.HasFocus);
Assert.True (view.HasFocus);
}
[Fact]

View File

@@ -8,7 +8,8 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
{
[Theory]
[MemberData (nameof (AllViewTypes))]
public void AllViews_AtLeastOneNavKey_Leaves (Type viewType)
[SetupFakeDriver] // SetupFakeDriver resets app state; helps to avoid test pollution
public void AllViews_AtLeastOneNavKey_Advances (Type viewType)
{
View view = CreateInstanceIfNotGeneric (viewType);
@@ -26,9 +27,10 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
return;
}
Application.Init (new FakeDriver ());
Toplevel top = new ();
Application.Current = top;
Application.Navigation = new ApplicationNavigation ();
View otherView = new ()
{
@@ -38,12 +40,11 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
};
top.Add (view, otherView);
Application.Begin (top);
// Start with the focus on our test view
view.SetFocus ();
Key [] navKeys = { Key.Tab, Key.Tab.WithShift, Key.CursorUp, Key.CursorDown, Key.CursorLeft, Key.CursorRight };
Key [] navKeys = [Key.Tab, Key.Tab.WithShift, Key.CursorUp, Key.CursorDown, Key.CursorLeft, Key.CursorRight];
if (view.TabStop == TabBehavior.TabGroup)
{
@@ -81,14 +82,14 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
}
top.Dispose ();
Application.Shutdown ();
Application.ResetState ();
Assert.True (left);
}
[Theory]
[MemberData (nameof (AllViewTypes))]
[SetupFakeDriver]
[SetupFakeDriver] // SetupFakeDriver resets app state; helps to avoid test pollution
public void AllViews_HasFocus_Changed_Event (Type viewType)
{
View view = CreateInstanceIfNotGeneric (viewType);
@@ -114,29 +115,17 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
return;
}
Toplevel top = new ()
{
Height = 10,
Width = 10
};
Toplevel top = new ();
Application.Current = top;
Application.Navigation = new ApplicationNavigation();
Application.Navigation = new ApplicationNavigation ();
View otherView = new ()
{
Id = "otherView",
X = 0, Y = 0,
Height = 1,
Width = 1,
CanFocus = true,
TabStop = view.TabStop == TabBehavior.NoStop ? TabBehavior.TabStop : view.TabStop
};
view.X = Pos.Right (otherView);
view.Y = 0;
view.Width = 10;
view.Height = 1;
var hasFocusTrue = 0;
var hasFocusFalse = 0;
@@ -256,7 +245,8 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
[Theory]
[MemberData (nameof (AllViewTypes))]
public void AllViews_Enter_Leave_Events_Visible_False (Type viewType)
[SetupFakeDriver] // SetupFakeDriver resets app state; helps to avoid test pollution
public void AllViews_Visible_False_No_HasFocus_Events (Type viewType)
{
View view = CreateInstanceIfNotGeneric (viewType);
@@ -281,70 +271,46 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
return;
}
Application.Init (new FakeDriver ());
Toplevel top = new ();
Toplevel top = new ()
{
Height = 10,
Width = 10
};
Application.Current = top;
Application.Navigation = new ApplicationNavigation ();
View otherView = new ()
{
X = 0, Y = 0,
Height = 1,
Width = 1,
CanFocus = true
};
view.Visible = false;
view.X = Pos.Right (otherView);
view.Y = 0;
view.Width = 10;
view.Height = 1;
var nEnter = 0;
var nLeave = 0;
var hasFocusChangingCount = 0;
var hasFocusChangedCount = 0;
view.HasFocusChanging += (s, e) => nEnter++;
view.HasFocusChanged += (s, e) => nLeave++;
view.HasFocusChanging += (s, e) => hasFocusChangingCount++;
view.HasFocusChanged += (s, e) => hasFocusChangedCount++;
top.Add (view, otherView);
Application.Begin (top);
// Start with the focus on our test view
view.SetFocus ();
Assert.Equal (0, nEnter);
Assert.Equal (0, nLeave);
Assert.Equal (0, hasFocusChangingCount);
Assert.Equal (0, hasFocusChangedCount);
// Use keyboard to navigate to next view (otherView).
if (view is TextView)
{
Application.OnKeyDown (Key.F6);
}
else if (view is DatePicker)
{
for (var i = 0; i < 4; i++)
{
Application.OnKeyDown (Key.F6);
}
}
else
{
Application.OnKeyDown (Key.Tab);
}
Application.OnKeyDown (Key.Tab);
Assert.Equal (0, nEnter);
Assert.Equal (0, nLeave);
Assert.Equal (0, hasFocusChangingCount);
Assert.Equal (0, hasFocusChangedCount);
top.NewKeyDownEvent (Key.Tab);
Application.OnKeyDown (Key.F6);
Assert.Equal (0, nEnter);
Assert.Equal (0, nLeave);
Assert.Equal (0, hasFocusChangingCount);
Assert.Equal (0, hasFocusChangedCount);
top.Dispose ();
Application.Shutdown ();
Application.ResetState ();
}
[Fact]
@@ -444,67 +410,6 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
Application.Current.Dispose ();
}
[Fact]
[AutoInitShutdown]
public void FocusNext_Does_Not_Throws_If_A_View_Was_Removed_From_The_Collection ()
{
Toplevel top1 = new ();
var view1 = new View { Id = "view1", Width = 10, Height = 5, CanFocus = true };
var top2 = new Toplevel { Id = "top2", Y = 1, Width = 10, Height = 5 };
var view2 = new View
{
Id = "view2",
Y = 1,
Width = 10,
Height = 5,
CanFocus = true
};
View view3 = null;
var removed = false;
view2.HasFocusChanging += (s, e) =>
{
if (!removed)
{
removed = true;
view3 = new () { Id = "view3", Y = 1, Width = 10, Height = 5 };
Application.Current.Add (view3);
Application.Current.BringSubviewToFront (view3);
Assert.False (view3.HasFocus);
}
};
view2.HasFocusChanged += (s, e) =>
{
Application.Current.Remove (view3);
view3.Dispose ();
view3 = null;
};
top2.Add (view2);
top1.Add (view1, top2);
Application.Begin (top1);
Assert.True (top1.HasFocus);
Assert.True (view1.HasFocus);
Assert.False (view2.HasFocus);
Assert.False (removed);
Assert.Null (view3);
Assert.True (Application.OnKeyDown (Key.F6));
Assert.True (top1.HasFocus);
Assert.False (view1.HasFocus);
Assert.True (view2.HasFocus);
Assert.True (removed);
Assert.NotNull (view3);
Exception exception = Record.Exception (() => Application.OnKeyDown (Key.F6));
Assert.Null (exception);
Assert.True (removed);
//Assert.Null (view3);
top1.Dispose ();
}
[Fact]
public void GetMostFocused_NoSubviews_Returns_Null ()
{

View File

@@ -224,7 +224,7 @@ public class SetFocusTests (ITestOutputHelper _output) : TestsAllViews
}
[Fact]
public void SetFocus_Peer_LeavesOthers_Subviews ()
public void SetFocus_On_Peer_Moves_Focus_To_Peer ()
{
var top = new View
{

View File

@@ -2560,7 +2560,7 @@ Edit
top.Draw ();
TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (0), output);
Assert.True (menu.NewKeyDownEvent (menu.Key));
Assert.True (Application.OnKeyDown(menu.Key));
Assert.False (menu.IsMenuOpen);
Assert.True (tf.HasFocus);
top.Draw ();

View File

@@ -611,7 +611,7 @@ public class ShortcutTests
shortcut.HasFocus = true;
Assert.Null (shortcut.ColorScheme);
Assert.NotNull (shortcut.ColorScheme);
Application.Current.Dispose ();
Application.ResetState ();