diff --git a/Terminal.Gui/View/View.Drawing.cs b/Terminal.Gui/View/View.Drawing.cs
index d1a0f7734..3ec493b57 100644
--- a/Terminal.Gui/View/View.Drawing.cs
+++ b/Terminal.Gui/View/View.Drawing.cs
@@ -505,7 +505,7 @@ public partial class View // Drawing APIs
if (TabStop == TabBehavior.TabGroup && _subviews.Count(v => v.Arrangement.HasFlag (ViewArrangement.Overlapped)) > 0)
{
// TODO: This is a temporary hack to make overlapped non-Toplevels have a zorder. See also View.SetFocus
- subviewsNeedingDraw = _tabIndexes.Where (
+ subviewsNeedingDraw = _subviews.Where (
view => view.Visible
&& (view.NeedsDisplay || view.SubViewNeedsDisplay || view.LayoutNeeded)
).Reverse ();
diff --git a/Terminal.Gui/View/View.Hierarchy.cs b/Terminal.Gui/View/View.Hierarchy.cs
index e43ef7a9c..5e899e809 100644
--- a/Terminal.Gui/View/View.Hierarchy.cs
+++ b/Terminal.Gui/View/View.Hierarchy.cs
@@ -52,21 +52,10 @@ public partial class View // SuperView/SubView hierarchy management (SuperView,
_subviews = new ();
}
- if (_tabIndexes is null)
- {
- _tabIndexes = new ();
- }
-
Debug.WriteLineIf (_subviews.Contains (view), $"BUGBUG: {view} has already been added to {this}.");
_subviews.Add (view);
- _tabIndexes.Add (view);
view._superView = this;
- if (view.CanFocus)
- {
- view._tabIndex = _tabIndexes.IndexOf (view);
- }
-
if (view.Enabled && view.Visible && view.CanFocus)
{
// Add will cause the newly added subview to gain focus if it's focusable
@@ -179,16 +168,14 @@ public partial class View // SuperView/SubView hierarchy management (SuperView,
}
Rectangle touched = view.Frame;
- _subviews.Remove (view);
- _tabIndexes!.Remove (view);
- view._superView = null;
- //view._tabIndex = -1;
// If a view being removed is focused, it should lose focus.
if (view.HasFocus)
{
view.HasFocus = false;
}
+ _subviews.Remove (view);
+ view._superView = null; // Null this AFTER removing focus
SetNeedsLayout ();
SetNeedsDisplay ();
diff --git a/Terminal.Gui/View/View.Navigation.cs b/Terminal.Gui/View/View.Navigation.cs
index 255b5a307..315b53488 100644
--- a/Terminal.Gui/View/View.Navigation.cs
+++ b/Terminal.Gui/View/View.Navigation.cs
@@ -8,7 +8,7 @@ public partial class View // Focus and cross-view navigation management (TabStop
private bool _canFocus;
///
- /// Advances the focus to the next or previous view in , based on
+ /// Advances the focus to the next or previous view in the focus chain, based on
/// .
/// itself.
///
@@ -30,11 +30,6 @@ public partial class View // Focus and cross-view navigation management (TabStop
return false;
}
- if (TabIndexes is null || TabIndexes.Count == 0)
- {
- return false;
- }
-
View? focused = Focused;
if (focused is { } && focused.AdvanceFocus (direction, behavior))
@@ -42,14 +37,14 @@ public partial class View // Focus and cross-view navigation management (TabStop
return true;
}
- View [] index = GetScopedTabIndexes (direction, behavior);
+ View [] index = GetSubviewFocusChain (direction, behavior);
if (index.Length == 0)
{
return false;
}
- int focusedIndex = index.IndexOf (Focused);
+ int focusedIndex = index.IndexOf (Focused); // Will return -1 if Focused can't be found or is null
var next = 0;
if (focusedIndex < index.Length - 1)
@@ -69,7 +64,7 @@ public partial class View // Focus and cross-view navigation management (TabStop
//}
// - If we are TabStop and our SuperView has at least one other TabStop subview, move to the SuperView's chain
- if (TabStop == TabBehavior.TabStop && SuperView is { } && SuperView.GetScopedTabIndexes (direction, behavior).Length > 1)
+ if (TabStop == TabBehavior.TabStop && SuperView is { } && SuperView.GetSubviewFocusChain (direction, behavior).Length > 1)
{
return false;
}
@@ -81,7 +76,7 @@ public partial class View // Focus and cross-view navigation management (TabStop
{
// Wrap to first focusable views
// BUGBUG: This should do a Restore Focus instead
- index = GetScopedTabIndexes (direction, null);
+ index = GetSubviewFocusChain (direction, null);
}
}
}
@@ -110,10 +105,7 @@ public partial class View // Focus and cross-view navigation management (TabStop
/// the next focusable view.
///
///
- /// When set to , the will be set to -1.
- ///
- ///
- /// When set to , the values of and for all
+ /// When set to , the value of for all
/// subviews will be cached so that when is set back to , the subviews
/// will be restored to their previous values.
///
@@ -163,8 +155,7 @@ public partial class View // Focus and cross-view navigation management (TabStop
public event EventHandler CanFocusChanged;
///
- /// Focuses the deepest focusable view in if one exists. If there are no views in
- /// then the focus is set to the view itself.
+ /// Focuses the deepest focusable Subview if one exists. If there are no focusable Subviews then the focus is set to the view itself.
///
///
///
@@ -244,15 +235,10 @@ public partial class View // Focus and cross-view navigation management (TabStop
private View? FindDeepestFocusableView (NavigationDirection direction, TabBehavior? behavior)
{
- View [] indicies = GetScopedTabIndexes (direction, behavior);
+ View [] indicies = GetSubviewFocusChain (direction, behavior);
foreach (View v in indicies)
{
- if (v.TabIndexes.Count == 0)
- {
- return v;
- }
-
return v.FindDeepestFocusableView (direction, behavior);
}
@@ -580,6 +566,16 @@ public partial class View // Focus and cross-view navigation management (TabStop
View? focusedPeer = SuperView?.Focused;
_hasFocus = false;
+ if (Application.Navigation is { })
+ {
+ View? appFocused = Application.Navigation.GetFocused ();
+
+ if (appFocused is { } || appFocused == this)
+ {
+ Application.Navigation.SetFocused (SuperView);
+ }
+ }
+
NotifyFocusChanged (HasFocus, this, newFocusedVew);
if (_hasFocus)
@@ -643,14 +639,6 @@ public partial class View // Focus and cross-view navigation management (TabStop
#region Tab/Focus Handling
- private List? _tabIndexes;
-
- // TODO: This should be a get-only property?
- // BUGBUG: This returns an AsReadOnly list, but isn't declared as such.
- /// Gets a list of the subviews that are a .
- /// The tabIndexes.
- public IList TabIndexes => _tabIndexes?.AsReadOnly () ?? _empty;
-
///
/// Gets TabIndexes that are scoped to the specified behavior and direction. If behavior is null, all TabIndexes are
/// returned.
@@ -659,138 +647,25 @@ public partial class View // Focus and cross-view navigation management (TabStop
///
///
/// GetScopedTabIndexes
- private View [] GetScopedTabIndexes (NavigationDirection direction, TabBehavior? behavior)
+ private View [] GetSubviewFocusChain (NavigationDirection direction, TabBehavior? behavior)
{
- IEnumerable? indicies;
+ IEnumerable? fitleredSubviews;
if (behavior.HasValue)
{
- indicies = _tabIndexes?.Where (v => v.TabStop == behavior && v is { CanFocus: true, Visible: true, Enabled: true });
+ fitleredSubviews = _subviews?.Where (v => v.TabStop == behavior && v is { CanFocus: true, Visible: true, Enabled: true });
}
else
{
- indicies = _tabIndexes?.Where (v => v is { CanFocus: true, Visible: true, Enabled: true });
+ fitleredSubviews = _subviews?.Where (v => v is { CanFocus: true, Visible: true, Enabled: true });
}
if (direction == NavigationDirection.Backward)
{
- indicies = indicies?.Reverse ();
+ fitleredSubviews = fitleredSubviews?.Reverse ();
}
- return indicies?.ToArray () ?? Array.Empty ();
- }
-
- private int? _tabIndex; // null indicates the view has not yet been added to TabIndexes
-
- ///
- /// Indicates the order of the current in list.
- ///
- ///
- ///
- /// If , the view is not part of the tab order.
- ///
- ///
- /// On set, if is or has not TabStops, will
- /// be set to 0.
- ///
- ///
- /// On set, if has only one TabStop, will be set to 0.
- ///
- ///
- /// See also .
- ///
- ///
- public int? TabIndex
- {
- get => _tabIndex;
-
- // TOOD: This should be a get-only property. Introduce SetTabIndex (int value) (or similar).
- set
- {
- // Once a view is in the tab order, it should not be removed from the tab order; set TabStop to NoStop instead.
- Debug.Assert (value >= 0);
- Debug.Assert (value is { });
-
- if (SuperView?._tabIndexes is null || SuperView?._tabIndexes.Count == 1)
- {
- // BUGBUG: Property setters should set the property to the value passed in and not have side effects.
- _tabIndex = 0;
-
- return;
- }
-
- if (_tabIndex == value && TabIndexes.IndexOf (this) == value)
- {
- return;
- }
-
- _tabIndex = value > SuperView!.TabIndexes.Count - 1 ? SuperView._tabIndexes.Count - 1 :
- value < 0 ? 0 : value;
- _tabIndex = GetGreatestTabIndexInSuperView ((int)_tabIndex);
-
- if (SuperView._tabIndexes.IndexOf (this) != _tabIndex)
- {
- // BUGBUG: we have to use _tabIndexes and not TabIndexes because TabIndexes returns is a read-only version of _tabIndexes
- SuperView._tabIndexes.Remove (this);
- SuperView._tabIndexes.Insert ((int)_tabIndex, this);
- UpdatePeerTabIndexes ();
- }
-
- return;
-
- // Updates the s of the views in the 's to match their order in .
- void UpdatePeerTabIndexes ()
- {
- if (SuperView is null)
- {
- return;
- }
-
- var i = 0;
-
- foreach (View superViewTabStop in SuperView._tabIndexes)
- {
- if (superViewTabStop._tabIndex is null)
- {
- continue;
- }
-
- superViewTabStop._tabIndex = i;
- i++;
- }
- }
- }
- }
-
- ///
- /// Gets the greatest of the 's that is less
- /// than or equal to .
- ///
- ///
- /// The minimum of and the 's .
- private int GetGreatestTabIndexInSuperView (int idx)
- {
- if (SuperView is null)
- {
- return 0;
- }
-
- var i = 0;
-
- if (SuperView._tabIndexes is { })
- {
- foreach (View superViewTabStop in SuperView._tabIndexes)
- {
- if (superViewTabStop._tabIndex is null || superViewTabStop == this)
- {
- continue;
- }
-
- i++;
- }
- }
-
- return Math.Min (i, idx);
+ return fitleredSubviews?.ToArray () ?? Array.Empty ();
}
private TabBehavior? _tabStop;
@@ -828,17 +703,6 @@ public partial class View // Focus and cross-view navigation management (TabStop
return;
}
- Debug.Assert (value is { });
-
- if (_tabStop is null && TabIndex is null)
- {
- // This view has not yet been added to TabIndexes (TabStop has not been set previously).
- if (SuperView?._tabIndexes is { })
- {
- TabIndex = GetGreatestTabIndexInSuperView (SuperView is { } ? SuperView._tabIndexes.Count : 0);
- }
- }
-
_tabStop = value;
}
}
diff --git a/Terminal.Gui/Views/FileDialog.cs b/Terminal.Gui/Views/FileDialog.cs
index 655359135..a45243a89 100644
--- a/Terminal.Gui/Views/FileDialog.cs
+++ b/Terminal.Gui/Views/FileDialog.cs
@@ -463,12 +463,12 @@ public class FileDialog : Dialog
_btnCancel.X = Pos.Func (CalculateOkButtonPosX);
_btnOk.X = Pos.Right (_btnCancel) + 1;
- // Flip tab order too for consistency
- int? p1 = _btnOk.TabIndex;
- int? p2 = _btnCancel.TabIndex;
+ //// Flip tab order too for consistency
+ //int? p1 = _btnOk.TabIndex;
+ //int? p2 = _btnCancel.TabIndex;
- _btnOk.TabIndex = p2;
- _btnCancel.TabIndex = p1;
+ //_btnOk.TabIndex = p2;
+ //_btnCancel.TabIndex = p1;
}
_tbPath.Caption = Style.PathCaption;
diff --git a/UICatalog/Scenarios/Dialogs.cs b/UICatalog/Scenarios/Dialogs.cs
index ded47a5fa..5872cd093 100644
--- a/UICatalog/Scenarios/Dialogs.cs
+++ b/UICatalog/Scenarios/Dialogs.cs
@@ -311,10 +311,10 @@ public class Dialogs : Scenario
buttons.Add (button);
dialog.AddButton (button);
- if (buttons.Count > 1)
- {
- button.TabIndex = buttons [buttons.Count - 2].TabIndex + 1;
- }
+ //if (buttons.Count > 1)
+ //{
+ // button.TabIndex = buttons [buttons.Count - 2].TabIndex + 1;
+ //}
};
dialog.Add (add);
diff --git a/UICatalog/Scenarios/DynamicMenuBar.cs b/UICatalog/Scenarios/DynamicMenuBar.cs
index 25152ecd8..a65536cb1 100644
--- a/UICatalog/Scenarios/DynamicMenuBar.cs
+++ b/UICatalog/Scenarios/DynamicMenuBar.cs
@@ -640,10 +640,10 @@ public class DynamicMenuBar : Scenario
};
frmMenu.Add (_lstMenus);
- lblMenuBar.TabIndex = btnPrevious.TabIndex + 1;
- _lstMenus.TabIndex = lblMenuBar.TabIndex + 1;
- btnNext.TabIndex = _lstMenus.TabIndex + 1;
- btnAdd.TabIndex = btnNext.TabIndex + 1;
+ //lblMenuBar.TabIndex = btnPrevious.TabIndex + 1;
+ //_lstMenus.TabIndex = lblMenuBar.TabIndex + 1;
+ //btnNext.TabIndex = _lstMenus.TabIndex + 1;
+ //btnAdd.TabIndex = btnNext.TabIndex + 1;
var btnRemove = new Button { X = Pos.Left (btnAdd), Y = Pos.Top (btnAdd) + 1, Text = "Remove" };
frmMenu.Add (btnRemove);
diff --git a/UnitTests/Application/Application.NavigationTests.cs b/UnitTests/Application/Application.NavigationTests.cs
index 879eda872..d5d62383a 100644
--- a/UnitTests/Application/Application.NavigationTests.cs
+++ b/UnitTests/Application/Application.NavigationTests.cs
@@ -13,16 +13,16 @@ public class ApplicationNavigationTests (ITestOutputHelper output)
{
bool raised = false;
- Application.Navigation = new ApplicationNavigation();
+ Application.Navigation = new ApplicationNavigation ();
Application.Navigation.FocusedChanged += ApplicationNavigationOnFocusedChanged;
- Application.Navigation.SetFocused(new View ());
+ Application.Navigation.SetFocused (new View ());
Assert.True (raised);
- Application.Navigation.GetFocused().Dispose ();
- Application.Navigation.SetFocused(null);
+ Application.Navigation.GetFocused ().Dispose ();
+ Application.Navigation.SetFocused (null);
Application.Navigation.FocusedChanged -= ApplicationNavigationOnFocusedChanged;
@@ -30,10 +30,7 @@ public class ApplicationNavigationTests (ITestOutputHelper output)
return;
- void ApplicationNavigationOnFocusedChanged (object sender, EventArgs e)
- {
- raised = true;
- }
+ void ApplicationNavigationOnFocusedChanged (object sender, EventArgs e) { raised = true; }
}
[Fact]
@@ -50,7 +47,8 @@ public class ApplicationNavigationTests (ITestOutputHelper output)
public void GetDeepestFocusedSubview_ShouldReturnSameView_WhenNoSubviewsHaveFocus ()
{
// Arrange
- var view = new View () { Id = "view", CanFocus = true }; ;
+ var view = new View () { Id = "view", CanFocus = true };
+ ;
// Act
var result = ApplicationNavigation.GetDeepestFocusedSubview (view);
@@ -63,10 +61,14 @@ public class ApplicationNavigationTests (ITestOutputHelper output)
public void GetDeepestFocusedSubview_ShouldReturnFocusedSubview ()
{
// Arrange
- var parentView = new View () { Id = "parentView", CanFocus = true }; ;
- var childView1 = new View () { Id = "childView1", CanFocus = true }; ;
- var childView2 = new View () { Id = "childView2", CanFocus = true }; ;
- var grandChildView = new View () { Id = "grandChildView", CanFocus = true }; ;
+ var parentView = new View () { Id = "parentView", CanFocus = true };
+ ;
+ var childView1 = new View () { Id = "childView1", CanFocus = true };
+ ;
+ var childView2 = new View () { Id = "childView2", CanFocus = true };
+ ;
+ var grandChildView = new View () { Id = "grandChildView", CanFocus = true };
+ ;
parentView.Add (childView1, childView2);
childView2.Add (grandChildView);
@@ -84,11 +86,16 @@ public class ApplicationNavigationTests (ITestOutputHelper output)
public void GetDeepestFocusedSubview_ShouldReturnDeepestFocusedSubview ()
{
// Arrange
- var parentView = new View () { Id = "parentView", CanFocus = true }; ;
- var childView1 = new View () { Id = "childView1", CanFocus = true }; ;
- var childView2 = new View () { Id = "childView2", CanFocus = true }; ;
- var grandChildView = new View () { Id = "grandChildView", CanFocus = true }; ;
- var greatGrandChildView = new View () { Id = "greatGrandChildView", CanFocus = true }; ;
+ var parentView = new View () { Id = "parentView", CanFocus = true };
+ ;
+ var childView1 = new View () { Id = "childView1", CanFocus = true };
+ ;
+ var childView2 = new View () { Id = "childView2", CanFocus = true };
+ ;
+ var grandChildView = new View () { Id = "grandChildView", CanFocus = true };
+ ;
+ var greatGrandChildView = new View () { Id = "greatGrandChildView", CanFocus = true };
+ ;
parentView.Add (childView1, childView2);
childView2.Add (grandChildView);
@@ -113,48 +120,75 @@ public class ApplicationNavigationTests (ITestOutputHelper output)
Assert.Equal (grandChildView, result);
}
+ [Fact]
+ public void GetFocused_Returns_Null_If_No_Focused_View ()
+ {
+ Application.Navigation = new ();
- //[Fact]
- //public void MoveNextViewOrTop_ShouldMoveFocusToNextViewOrTop ()
- //{
- // // Arrange
- // var top = new Toplevel ();
- // var view1 = new View () { Id = "view1", CanFocus = true };
- // var view2 = new View () { Id = "view2", CanFocus = true };
- // top.Add (view1, view2);
- // Application.Top = top;
- // Application.Current = top;
- // view1.SetFocus ();
+ Application.Current = new Toplevel()
+ {
+ Id = "top",
+ CanFocus = true
+ };
- // // Act
- // ApplicationNavigation.MoveNextViewOrTop ();
+ View subView1 = new View ()
+ {
+ Id = "subView1",
+ CanFocus = true
+ };
- // // Assert
- // Assert.True (view2.HasFocus);
+ Application.Current.Add (subView1);
+ Assert.False (Application.Current.HasFocus);
- // top.Dispose ();
- //}
+ Application.Current.SetFocus ();
+ Assert.True (subView1.HasFocus);
+ Assert.Equal (subView1, Application.Navigation.GetFocused ());
+
+ subView1.HasFocus = false;
+ Assert.False (subView1.HasFocus);
+ Assert.True (Application.Current.HasFocus);
+ Assert.Equal (Application.Current, Application.Navigation.GetFocused ());
+
+ Application.Current.HasFocus = false;
+ Assert.False (Application.Current.HasFocus);
+ Assert.Null (Application.Navigation.GetFocused ());
+
+ Application.ResetState ();
+ }
+ [Fact]
+ public void GetFocused_Returns_Focused_View ()
+ {
+ Application.Navigation = new ();
- //[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 ();
+ Application.Current = new Toplevel ()
+ {
+ Id = "top",
+ CanFocus = true
+ };
- // // Act
- // ApplicationNavigation.MovePreviousViewOrTop ();
+ View subView1 = new View ()
+ {
+ Id = "subView1",
+ CanFocus = true
+ };
- // // Assert
- // Assert.True (view1.HasFocus);
+ View subView2 = new View ()
+ {
+ Id = "subView2",
+ CanFocus = true
+ };
+ Application.Current.Add (subView1, subView2);
+ Assert.False (Application.Current.HasFocus);
- // top.Dispose ();
- //}
+ Application.Current.SetFocus ();
+ Assert.True (subView1.HasFocus);
+ Assert.Equal(subView1, Application.Navigation.GetFocused());
+
+ Application.Current.AdvanceFocus (NavigationDirection.Forward, null);
+ Assert.Equal (subView2, Application.Navigation.GetFocused ());
+
+ Application.ResetState ();
+ }
}
diff --git a/UnitTests/View/Navigation/AddRemoveTests.cs b/UnitTests/View/Navigation/AddRemoveTests.cs
index e2182179f..cb1cd66fa 100644
--- a/UnitTests/View/Navigation/AddRemoveTests.cs
+++ b/UnitTests/View/Navigation/AddRemoveTests.cs
@@ -98,6 +98,83 @@ public class AddRemoveNavigationTests (ITestOutputHelper _output) : TestsAllView
Assert.True (subSubView.HasFocus);
}
+
+ [Fact]
+ public void Remove_Subview_Raises_HasFocusChanged ()
+ {
+ var top = new View
+ {
+ Id = "top",
+ CanFocus = true
+ };
+
+ var subView1 = new View
+ {
+ Id = "subView1",
+ CanFocus = true
+ };
+
+ var subView2 = new View
+ {
+ Id = "subView2",
+ CanFocus = true
+ };
+ top.Add (subView1, subView2);
+
+ var subView1HasFocusChangedTrueCount = 0;
+ var subView1HasFocusChangedFalseCount = 0;
+
+ subView1.HasFocusChanged += (s, e) =>
+ {
+ if (e.NewValue)
+ {
+ subView1HasFocusChangedTrueCount++;
+ }
+ else
+ {
+ subView1HasFocusChangedFalseCount++;
+ }
+ };
+
+ var subView2HasFocusChangedTrueCount = 0;
+ var subView2HasFocusChangedFalseCount = 0;
+
+ subView2.HasFocusChanged += (s, e) =>
+ {
+ if (e.NewValue)
+ {
+ subView2HasFocusChangedTrueCount++;
+ }
+ else
+ {
+ subView2HasFocusChangedFalseCount++;
+ }
+ };
+
+ top.SetFocus ();
+ Assert.True (top.HasFocus);
+ Assert.True (subView1.HasFocus);
+ Assert.False (subView2.HasFocus);
+
+ Assert.Equal (1, subView1HasFocusChangedTrueCount);
+ Assert.Equal (0, subView1HasFocusChangedFalseCount);
+
+ Assert.Equal (0, subView2HasFocusChangedTrueCount);
+ Assert.Equal (0, subView2HasFocusChangedFalseCount);
+
+ top.Remove (subView1); // this should have the same resuilt as top.AdvanceFocus (NavigationDirection.Forward, null);
+
+ Assert.False (subView1.HasFocus);
+ Assert.True (subView2.HasFocus);
+
+ Assert.Equal (1, subView1HasFocusChangedTrueCount);
+ Assert.Equal (1, subView1HasFocusChangedFalseCount);
+
+ Assert.Equal (1, subView2HasFocusChangedTrueCount);
+ Assert.Equal (0, subView2HasFocusChangedFalseCount);
+ }
+
+
[Fact]
public void Remove_Focused_Subview_Keeps_Focus_And_SubView_Looses_Focus ()
{
@@ -155,6 +232,7 @@ public class AddRemoveNavigationTests (ITestOutputHelper _output) : TestsAllView
Assert.False (subView2.HasFocus);
top.Remove (subView1);
+
Assert.True (top.HasFocus);
Assert.True (subView2.HasFocus);
Assert.Equal (subView2, top.Focused);
diff --git a/UnitTests/View/Navigation/AdvanceFocusTests.cs b/UnitTests/View/Navigation/AdvanceFocusTests.cs
index ffdea4c10..53f657d89 100644
--- a/UnitTests/View/Navigation/AdvanceFocusTests.cs
+++ b/UnitTests/View/Navigation/AdvanceFocusTests.cs
@@ -4,296 +4,6 @@ namespace Terminal.Gui.ViewTests;
public class AdvanceFocusTests (ITestOutputHelper _output)
{
- [Fact]
- public void Subviews_TabIndexes_AreEqual ()
- {
- var r = new View ();
- var v1 = new View { CanFocus = true };
- var v2 = new View { CanFocus = true };
- var v3 = new View { CanFocus = true };
-
- r.Add (v1, v2, v3);
-
- Assert.True (r.Subviews.IndexOf (v1) == 0);
- Assert.True (r.Subviews.IndexOf (v2) == 1);
- Assert.True (r.Subviews.IndexOf (v3) == 2);
-
- Assert.True (r.TabIndexes.IndexOf (v1) == 0);
- Assert.True (r.TabIndexes.IndexOf (v2) == 1);
- Assert.True (r.TabIndexes.IndexOf (v3) == 2);
-
- Assert.Equal (r.Subviews.IndexOf (v1), r.TabIndexes.IndexOf (v1));
- Assert.Equal (r.Subviews.IndexOf (v2), r.TabIndexes.IndexOf (v2));
- Assert.Equal (r.Subviews.IndexOf (v3), r.TabIndexes.IndexOf (v3));
- r.Dispose ();
- }
-
- [Fact]
- public void TabIndex_Invert_Order ()
- {
- var r = new View ();
- var v1 = new View { Id = "1", CanFocus = true };
- var v2 = new View { Id = "2", CanFocus = true };
- var v3 = new View { Id = "3", CanFocus = true };
-
- r.Add (v1, v2, v3);
-
- v1.TabIndex = 2;
- v2.TabIndex = 1;
- v3.TabIndex = 0;
- Assert.True (r.TabIndexes.IndexOf (v1) == 2);
- Assert.True (r.TabIndexes.IndexOf (v2) == 1);
- Assert.True (r.TabIndexes.IndexOf (v3) == 0);
-
- Assert.True (r.Subviews.IndexOf (v1) == 0);
- Assert.True (r.Subviews.IndexOf (v2) == 1);
- Assert.True (r.Subviews.IndexOf (v3) == 2);
- }
-
- [Fact]
- public void TabIndex_Invert_Order_Added_One_By_One_Does_Not_Do_What_Is_Expected ()
- {
- var r = new View ();
- var v1 = new View { Id = "1", CanFocus = true };
- r.Add (v1);
- v1.TabIndex = 2;
- var v2 = new View { Id = "2", CanFocus = true };
- r.Add (v2);
- v2.TabIndex = 1;
- var v3 = new View { Id = "3", CanFocus = true };
- r.Add (v3);
- v3.TabIndex = 0;
-
- Assert.False (r.TabIndexes.IndexOf (v1) == 2);
- Assert.True (r.TabIndexes.IndexOf (v1) == 1);
- Assert.False (r.TabIndexes.IndexOf (v2) == 1);
- Assert.True (r.TabIndexes.IndexOf (v2) == 2);
-
- // Only the last is in the expected index
- Assert.True (r.TabIndexes.IndexOf (v3) == 0);
-
- Assert.True (r.Subviews.IndexOf (v1) == 0);
- Assert.True (r.Subviews.IndexOf (v2) == 1);
- Assert.True (r.Subviews.IndexOf (v3) == 2);
- }
-
- [Fact]
- public void TabIndex_Invert_Order_Mixed ()
- {
- var r = new View ();
- var vl1 = new View { Id = "vl1" };
- var v1 = new View { Id = "v1", CanFocus = true };
- var vl2 = new View { Id = "vl2" };
- var v2 = new View { Id = "v2", CanFocus = true };
- var vl3 = new View { Id = "vl3" };
- var v3 = new View { Id = "v3", CanFocus = true };
-
- r.Add (vl1, v1, vl2, v2, vl3, v3);
-
- v1.TabIndex = 2;
- v2.TabIndex = 1;
- v3.TabIndex = 0;
- Assert.True (r.TabIndexes.IndexOf (v1) == 4);
- Assert.True (r.TabIndexes.IndexOf (v2) == 2);
- Assert.True (r.TabIndexes.IndexOf (v3) == 0);
-
- Assert.True (r.Subviews.IndexOf (v1) == 1);
- Assert.True (r.Subviews.IndexOf (v2) == 3);
- Assert.True (r.Subviews.IndexOf (v3) == 5);
- }
-
- [Fact]
- public void TabIndex_Set_CanFocus_False ()
- {
- var r = new View ();
- var v1 = new View { CanFocus = true };
- var v2 = new View { CanFocus = true };
- var v3 = new View { CanFocus = true };
-
- r.Add (v1, v2, v3);
-
- v1.CanFocus = false;
- v1.TabIndex = 0;
- Assert.True (r.Subviews.IndexOf (v1) == 0);
- Assert.True (r.TabIndexes.IndexOf (v1) == 0);
- Assert.NotEqual (-1, v1.TabIndex);
- r.Dispose ();
- }
-
- [Fact]
- public void TabIndex_Set_CanFocus_False_To_True ()
- {
- var r = new View ();
- var v1 = new View ();
- var v2 = new View { CanFocus = true };
- var v3 = new View { CanFocus = true };
-
- r.Add (v1, v2, v3);
-
- v1.CanFocus = true;
- v1.TabIndex = 1;
- Assert.True (r.Subviews.IndexOf (v1) == 0);
- Assert.True (r.TabIndexes.IndexOf (v1) == 1);
- r.Dispose ();
- }
-
- [Fact]
- public void TabIndex_Set_CanFocus_HigherValues ()
- {
- var r = new View ();
- var v1 = new View { CanFocus = true };
- var v2 = new View { CanFocus = true };
- var v3 = new View { CanFocus = true };
-
- r.Add (v1, v2, v3);
-
- v1.TabIndex = 3;
- Assert.True (r.Subviews.IndexOf (v1) == 0);
- Assert.True (r.TabIndexes.IndexOf (v1) == 2);
- r.Dispose ();
- }
-
- [Fact]
- public void TabIndex_Set_CanFocus_LowerValues ()
- {
- var r = new View ();
- var v1 = new View { CanFocus = true };
- var v2 = new View { CanFocus = true };
- var v3 = new View { CanFocus = true };
-
- r.Add (v1, v2, v3);
-
- //v1.TabIndex = -1;
- Assert.True (r.Subviews.IndexOf (v1) == 0);
- Assert.True (r.TabIndexes.IndexOf (v1) == 0);
- r.Dispose ();
- }
-
- [Fact]
- public void TabIndex_Set_CanFocus_ValidValues ()
- {
- var r = new View ();
- var v1 = new View { CanFocus = true };
- var v2 = new View { CanFocus = true };
- var v3 = new View { CanFocus = true };
-
- r.Add (v1, v2, v3);
-
- v1.TabIndex = 1;
- Assert.True (r.Subviews.IndexOf (v1) == 0);
- Assert.True (r.TabIndexes.IndexOf (v1) == 1);
-
- v1.TabIndex = 2;
- Assert.True (r.Subviews.IndexOf (v1) == 0);
- Assert.True (r.TabIndexes.IndexOf (v1) == 2);
- r.Dispose ();
- }
-
-
- [Theory]
- [CombinatorialData]
- public void TabStop_And_CanFocus_Are_Decoupled (bool canFocus, TabBehavior tabStop)
- {
- var view = new View { CanFocus = canFocus, TabStop = tabStop };
-
- Assert.Equal (canFocus, view.CanFocus);
- Assert.Equal (tabStop, view.TabStop);
- }
-
-
- [Fact]
- public void AdvanceFocus_Compound_Subview ()
- {
- var top = new View () { Id = "top", CanFocus = true };
-
- var compoundSubview = new View ()
- {
- CanFocus = true,
- Id = "compoundSubview",
- };
- var v1 = new View { Id = "v1", CanFocus = true };
- var v2 = new View { Id = "v2", CanFocus = true };
- var v3 = new View { Id = "v3", CanFocus = false };
-
- compoundSubview.Add (v1, v2, v3);
-
- top.Add (compoundSubview);
-
- // Cycle through v1 & v2
- top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
- Assert.True (v1.HasFocus);
- Assert.False (v2.HasFocus);
- Assert.False (v3.HasFocus);
- top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
- Assert.False (v1.HasFocus);
- Assert.True (v2.HasFocus);
- Assert.False (v3.HasFocus);
- top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
- Assert.True (v1.HasFocus);
- Assert.False (v2.HasFocus);
- Assert.False (v3.HasFocus);
-
- // Add another subview
- View otherSubview = new ()
- {
- CanFocus = true,
- Id = "otherSubview",
- };
-
- top.Add (otherSubview);
- // Adding a focusable subview causes advancefocus
- Assert.True (otherSubview.HasFocus);
- Assert.False (v1.HasFocus);
-
- // Cycle through v1 & v2
- top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
- Assert.True (v1.HasFocus);
- Assert.False (v2.HasFocus);
- Assert.False (v3.HasFocus);
- top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
- Assert.False (v1.HasFocus);
- Assert.True (v2.HasFocus);
- Assert.False (v3.HasFocus);
- top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
- Assert.False (v1.HasFocus);
- Assert.False (v2.HasFocus);
- Assert.False (v3.HasFocus);
-
- Assert.True (otherSubview.HasFocus);
- // v2 was previously focused down the compoundSubView focus chain
- top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
- Assert.False (v1.HasFocus);
- Assert.True (v2.HasFocus);
- Assert.False (v3.HasFocus);
-
- top.Dispose ();
- }
-
- [Fact]
- public void AdvanceFocus_With_CanFocus_Are_All_True ()
- {
- var top = new View () { Id = "top", CanFocus = true };
- var v1 = new View { Id = "v1", CanFocus = true };
- var v2 = new View { Id = "v2", CanFocus = true };
- var v3 = new View { Id = "v3", CanFocus = true };
-
- top.Add (v1, v2, v3);
-
- top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
- Assert.True (v1.HasFocus);
- Assert.False (v2.HasFocus);
- Assert.False (v3.HasFocus);
- top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
- Assert.False (v1.HasFocus);
- Assert.True (v2.HasFocus);
- Assert.False (v3.HasFocus);
- top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
- Assert.False (v1.HasFocus);
- Assert.False (v2.HasFocus);
- Assert.True (v3.HasFocus);
- top.Dispose ();
- }
-
[Fact]
public void AdvanceFocus_CanFocus_Mixed ()
{
@@ -323,7 +33,7 @@ public class AdvanceFocusTests (ITestOutputHelper _output)
[CombinatorialData]
public void AdvanceFocus_Change_CanFocus_Works ([CombinatorialValues (TabBehavior.NoStop, TabBehavior.TabStop, TabBehavior.TabGroup)] TabBehavior behavior)
{
- var r = new View () { CanFocus = true };
+ var r = new View { CanFocus = true };
var v1 = new View ();
var v2 = new View ();
var v3 = new View ();
@@ -362,6 +72,76 @@ public class AdvanceFocusTests (ITestOutputHelper _output)
r.Dispose ();
}
+ [Fact]
+ public void AdvanceFocus_Compound_Subview ()
+ {
+ var top = new View { Id = "top", CanFocus = true };
+
+ var compoundSubview = new View
+ {
+ CanFocus = true,
+ Id = "compoundSubview"
+ };
+ var v1 = new View { Id = "v1", CanFocus = true };
+ var v2 = new View { Id = "v2", CanFocus = true };
+ var v3 = new View { Id = "v3", CanFocus = false };
+
+ compoundSubview.Add (v1, v2, v3);
+
+ top.Add (compoundSubview);
+
+ // Cycle through v1 & v2
+ top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
+ Assert.True (v1.HasFocus);
+ Assert.False (v2.HasFocus);
+ Assert.False (v3.HasFocus);
+ top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
+ Assert.False (v1.HasFocus);
+ Assert.True (v2.HasFocus);
+ Assert.False (v3.HasFocus);
+ top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
+ Assert.True (v1.HasFocus);
+ Assert.False (v2.HasFocus);
+ Assert.False (v3.HasFocus);
+
+ // Add another subview
+ View otherSubview = new ()
+ {
+ CanFocus = true,
+ Id = "otherSubview"
+ };
+
+ top.Add (otherSubview);
+
+ // Adding a focusable subview causes advancefocus
+ Assert.True (otherSubview.HasFocus);
+ Assert.False (v1.HasFocus);
+
+ // Cycle through v1 & v2
+ top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
+ Assert.True (v1.HasFocus);
+ Assert.False (v2.HasFocus);
+ Assert.False (v3.HasFocus);
+ top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
+ Assert.False (v1.HasFocus);
+ Assert.True (v2.HasFocus);
+ Assert.False (v3.HasFocus);
+ top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
+ Assert.False (v1.HasFocus);
+ Assert.False (v2.HasFocus);
+ Assert.False (v3.HasFocus);
+
+ Assert.True (otherSubview.HasFocus);
+
+ // v2 was previously focused down the compoundSubView focus chain
+ top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
+ Assert.False (v1.HasFocus);
+ Assert.True (v2.HasFocus);
+ Assert.False (v3.HasFocus);
+
+ top.Dispose ();
+ }
+
[Fact]
public void AdvanceFocus_NoStop_And_CanFocus_True_No_Focus ()
{
@@ -459,4 +239,207 @@ public class AdvanceFocusTests (ITestOutputHelper _output)
Assert.False (v3.HasFocus);
r.Dispose ();
}
+
+ [Fact]
+ public void AdvanceFocus_Subviews_Raises_HasFocusChanged ()
+ {
+ var top = new View
+ {
+ Id = "top",
+ CanFocus = true
+ };
+
+ var subView1 = new View
+ {
+ Id = "subView1",
+ CanFocus = true
+ };
+
+ var subView2 = new View
+ {
+ Id = "subView2",
+ CanFocus = true
+ };
+ top.Add (subView1, subView2);
+
+ var subView1HasFocusChangedTrueCount = 0;
+ var subView1HasFocusChangedFalseCount = 0;
+
+ subView1.HasFocusChanged += (s, e) =>
+ {
+ if (e.NewValue)
+ {
+ subView1HasFocusChangedTrueCount++;
+ }
+ else
+ {
+ subView1HasFocusChangedFalseCount++;
+ }
+ };
+
+ var subView2HasFocusChangedTrueCount = 0;
+ var subView2HasFocusChangedFalseCount = 0;
+
+ subView2.HasFocusChanged += (s, e) =>
+ {
+ if (e.NewValue)
+ {
+ subView2HasFocusChangedTrueCount++;
+ }
+ else
+ {
+ subView2HasFocusChangedFalseCount++;
+ }
+ };
+
+ top.SetFocus ();
+ Assert.True (top.HasFocus);
+ Assert.True (subView1.HasFocus);
+ Assert.False (subView2.HasFocus);
+
+ Assert.Equal (1, subView1HasFocusChangedTrueCount);
+ Assert.Equal (0, subView1HasFocusChangedFalseCount);
+
+ Assert.Equal (0, subView2HasFocusChangedTrueCount);
+ Assert.Equal (0, subView2HasFocusChangedFalseCount);
+
+ top.AdvanceFocus (NavigationDirection.Forward, null);
+ Assert.False (subView1.HasFocus);
+ Assert.True (subView2.HasFocus);
+
+ Assert.Equal (1, subView1HasFocusChangedTrueCount);
+ Assert.Equal (1, subView1HasFocusChangedFalseCount);
+
+ Assert.Equal (1, subView2HasFocusChangedTrueCount);
+ Assert.Equal (0, subView2HasFocusChangedFalseCount);
+
+ top.AdvanceFocus (NavigationDirection.Forward, null);
+ Assert.True (subView1.HasFocus);
+ Assert.False (subView2.HasFocus);
+
+ Assert.Equal (2, subView1HasFocusChangedTrueCount);
+ Assert.Equal (1, subView1HasFocusChangedFalseCount);
+
+ Assert.Equal (1, subView2HasFocusChangedTrueCount);
+ Assert.Equal (1, subView2HasFocusChangedFalseCount);
+ }
+
+ [Fact]
+ public void AdvanceFocus_Subviews_Raises_HasFocusChanging ()
+ {
+ var top = new View
+ {
+ Id = "top",
+ CanFocus = true
+ };
+
+ var subView1 = new View
+ {
+ Id = "subView1",
+ CanFocus = true
+ };
+
+ var subView2 = new View
+ {
+ Id = "subView2",
+ CanFocus = true
+ };
+ top.Add (subView1, subView2);
+
+ var subView1HasFocusChangingTrueCount = 0;
+ var subView1HasFocusChangingFalseCount = 0;
+
+ subView1.HasFocusChanging += (s, e) =>
+ {
+ if (e.NewValue)
+ {
+ subView1HasFocusChangingTrueCount++;
+ }
+ else
+ {
+ subView1HasFocusChangingFalseCount++;
+ }
+ };
+
+ var subView2HasFocusChangingTrueCount = 0;
+ var subView2HasFocusChangingFalseCount = 0;
+
+ subView2.HasFocusChanging += (s, e) =>
+ {
+ if (e.NewValue)
+ {
+ subView2HasFocusChangingTrueCount++;
+ }
+ else
+ {
+ subView2HasFocusChangingFalseCount++;
+ }
+ };
+
+ top.SetFocus ();
+ Assert.True (top.HasFocus);
+ Assert.True (subView1.HasFocus);
+ Assert.False (subView2.HasFocus);
+
+ Assert.Equal (1, subView1HasFocusChangingTrueCount);
+ Assert.Equal (0, subView1HasFocusChangingFalseCount);
+
+ Assert.Equal (0, subView2HasFocusChangingTrueCount);
+ Assert.Equal (0, subView2HasFocusChangingFalseCount);
+
+ top.AdvanceFocus (NavigationDirection.Forward, null);
+ Assert.False (subView1.HasFocus);
+ Assert.True (subView2.HasFocus);
+
+ Assert.Equal (1, subView1HasFocusChangingTrueCount);
+ Assert.Equal (1, subView1HasFocusChangingFalseCount);
+
+ Assert.Equal (1, subView2HasFocusChangingTrueCount);
+ Assert.Equal (0, subView2HasFocusChangingFalseCount);
+
+ top.AdvanceFocus (NavigationDirection.Forward, null);
+ Assert.True (subView1.HasFocus);
+ Assert.False (subView2.HasFocus);
+
+ Assert.Equal (2, subView1HasFocusChangingTrueCount);
+ Assert.Equal (1, subView1HasFocusChangingFalseCount);
+
+ Assert.Equal (1, subView2HasFocusChangingTrueCount);
+ Assert.Equal (1, subView2HasFocusChangingFalseCount);
+ }
+
+ [Fact]
+ public void AdvanceFocus_With_CanFocus_Are_All_True ()
+ {
+ var top = new View { Id = "top", CanFocus = true };
+ var v1 = new View { Id = "v1", CanFocus = true };
+ var v2 = new View { Id = "v2", CanFocus = true };
+ var v3 = new View { Id = "v3", CanFocus = true };
+
+ top.Add (v1, v2, v3);
+
+ top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
+ Assert.True (v1.HasFocus);
+ Assert.False (v2.HasFocus);
+ Assert.False (v3.HasFocus);
+ top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
+ Assert.False (v1.HasFocus);
+ Assert.True (v2.HasFocus);
+ Assert.False (v3.HasFocus);
+ top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
+ Assert.False (v1.HasFocus);
+ Assert.False (v2.HasFocus);
+ Assert.True (v3.HasFocus);
+ top.Dispose ();
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void TabStop_And_CanFocus_Are_Decoupled (bool canFocus, TabBehavior tabStop)
+ {
+ var view = new View { CanFocus = canFocus, TabStop = tabStop };
+
+ Assert.Equal (canFocus, view.CanFocus);
+ Assert.Equal (tabStop, view.TabStop);
+ }
}
diff --git a/UnitTests/View/Navigation/CanFocusTests.cs b/UnitTests/View/Navigation/CanFocusTests.cs
index f275e710e..5d3bbc1e8 100644
--- a/UnitTests/View/Navigation/CanFocusTests.cs
+++ b/UnitTests/View/Navigation/CanFocusTests.cs
@@ -244,48 +244,48 @@ public class CanFocusTests (ITestOutputHelper _output) : TestsAllViews
Application.Shutdown ();
}
- [Fact]
- public void CanFocus_Set_Changes_TabIndex_And_TabStop ()
- {
- var r = new View ();
- var v1 = new View { Text = "1" };
- var v2 = new View { Text = "2" };
- var v3 = new View { Text = "3" };
+ //[Fact]
+ //public void CanFocus_Set_Changes_TabIndex_And_TabStop ()
+ //{
+ // var r = new View ();
+ // var v1 = new View { Text = "1" };
+ // var v2 = new View { Text = "2" };
+ // var v3 = new View { Text = "3" };
- r.Add (v1, v2, v3);
+ // r.Add (v1, v2, v3);
- v2.CanFocus = true;
- Assert.Equal (r.TabIndexes.IndexOf (v2), v2.TabIndex);
- Assert.Equal (0, v2.TabIndex);
- Assert.Equal (TabBehavior.TabStop, v2.TabStop);
+ // v2.CanFocus = true;
+ // Assert.Equal (r.TabIndexes.IndexOf (v2), v2.TabIndex);
+ // Assert.Equal (0, v2.TabIndex);
+ // Assert.Equal (TabBehavior.TabStop, v2.TabStop);
- v1.CanFocus = true;
- Assert.Equal (r.TabIndexes.IndexOf (v1), v1.TabIndex);
- Assert.Equal (1, v1.TabIndex);
- Assert.Equal (TabBehavior.TabStop, v1.TabStop);
+ // v1.CanFocus = true;
+ // Assert.Equal (r.TabIndexes.IndexOf (v1), v1.TabIndex);
+ // Assert.Equal (1, v1.TabIndex);
+ // Assert.Equal (TabBehavior.TabStop, v1.TabStop);
- v1.TabIndex = 2;
- Assert.Equal (r.TabIndexes.IndexOf (v1), v1.TabIndex);
- Assert.Equal (1, v1.TabIndex);
- v3.CanFocus = true;
- Assert.Equal (r.TabIndexes.IndexOf (v1), v1.TabIndex);
- Assert.Equal (1, v1.TabIndex);
- Assert.Equal (r.TabIndexes.IndexOf (v3), v3.TabIndex);
- Assert.Equal (2, v3.TabIndex);
- Assert.Equal (TabBehavior.TabStop, v3.TabStop);
+ // v1.TabIndex = 2;
+ // Assert.Equal (r.TabIndexes.IndexOf (v1), v1.TabIndex);
+ // Assert.Equal (1, v1.TabIndex);
+ // v3.CanFocus = true;
+ // Assert.Equal (r.TabIndexes.IndexOf (v1), v1.TabIndex);
+ // Assert.Equal (1, v1.TabIndex);
+ // Assert.Equal (r.TabIndexes.IndexOf (v3), v3.TabIndex);
+ // Assert.Equal (2, v3.TabIndex);
+ // Assert.Equal (TabBehavior.TabStop, v3.TabStop);
- v2.CanFocus = false;
- Assert.Equal (r.TabIndexes.IndexOf (v1), v1.TabIndex);
- Assert.Equal (1, v1.TabIndex);
- Assert.Equal (TabBehavior.TabStop, v1.TabStop);
- Assert.Equal (r.TabIndexes.IndexOf (v2), v2.TabIndex); // TabIndex is not changed
- Assert.NotEqual (-1, v2.TabIndex);
- Assert.Equal (TabBehavior.TabStop, v2.TabStop); // TabStop is not changed
- Assert.Equal (r.TabIndexes.IndexOf (v3), v3.TabIndex);
- Assert.Equal (2, v3.TabIndex);
- Assert.Equal (TabBehavior.TabStop, v3.TabStop);
- r.Dispose ();
- }
+ // v2.CanFocus = false;
+ // Assert.Equal (r.TabIndexes.IndexOf (v1), v1.TabIndex);
+ // Assert.Equal (1, v1.TabIndex);
+ // Assert.Equal (TabBehavior.TabStop, v1.TabStop);
+ // Assert.Equal (r.TabIndexes.IndexOf (v2), v2.TabIndex); // TabIndex is not changed
+ // Assert.NotEqual (-1, v2.TabIndex);
+ // Assert.Equal (TabBehavior.TabStop, v2.TabStop); // TabStop is not changed
+ // Assert.Equal (r.TabIndexes.IndexOf (v3), v3.TabIndex);
+ // Assert.Equal (2, v3.TabIndex);
+ // Assert.Equal (TabBehavior.TabStop, v3.TabStop);
+ // r.Dispose ();
+ //}
[Fact]
public void CanFocus_True_Focuses ()
diff --git a/UnitTests/View/Navigation/HasFocusChangeEventTests.cs b/UnitTests/View/Navigation/HasFocusChangeEventTests.cs
index 662021c55..86d11ddd1 100644
--- a/UnitTests/View/Navigation/HasFocusChangeEventTests.cs
+++ b/UnitTests/View/Navigation/HasFocusChangeEventTests.cs
@@ -5,6 +5,7 @@ namespace Terminal.Gui.ViewTests;
public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllViews
{
#region HasFocusChanging_NewValue_True
+
[Fact]
public void HasFocusChanging_SetFocus_Raises ()
{
@@ -16,6 +17,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "view",
CanFocus = true
};
+
view.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -49,6 +51,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "view",
CanFocus = true
};
+
view.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -69,17 +72,18 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subview",
CanFocus = true
};
+
subview.HasFocusChanging += (s, e) =>
- {
- if (e.NewValue)
- {
- subviewHasFocusTrueCount++;
- }
- else
- {
- subviewHasFocusFalseCount++;
- }
- };
+ {
+ if (e.NewValue)
+ {
+ subviewHasFocusTrueCount++;
+ }
+ else
+ {
+ subviewHasFocusFalseCount++;
+ }
+ };
view.Add (subview);
@@ -104,6 +108,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "view",
CanFocus = true
};
+
view.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -124,6 +129,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subview",
CanFocus = true
};
+
subview.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -158,6 +164,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "view",
CanFocus = true
};
+
view.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -178,6 +185,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subView",
CanFocus = true
};
+
subView.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -198,6 +206,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subViewSubView1",
CanFocus = false
};
+
subViewSubView1.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -218,6 +227,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subViewSubView2",
CanFocus = true
};
+
subViewSubView2.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -238,6 +248,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subViewSubView3",
CanFocus = false
};
+
subViewSubView3.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -288,6 +299,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "view",
CanFocus = true
};
+
view.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -309,6 +321,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subview",
CanFocus = true
};
+
subview.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -346,6 +359,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "view",
CanFocus = true
};
+
view.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -367,6 +381,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subview",
CanFocus = true
};
+
subview.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -404,6 +419,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "view",
CanFocus = true
};
+
view.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -424,6 +440,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subview",
CanFocus = true
};
+
subview.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -463,6 +480,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "view",
CanFocus = true
};
+
view.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -483,6 +501,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subview",
CanFocus = true
};
+
subview.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -537,6 +556,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "view",
CanFocus = true
};
+
view.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -575,6 +595,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "view",
CanFocus = true
};
+
view.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -595,6 +616,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subview",
CanFocus = true
};
+
subview.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -618,7 +640,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Assert.Equal (0, subviewHasFocusFalseCount);
view.HasFocus = false;
- Assert.False(view.HasFocus);
+ Assert.False (view.HasFocus);
Assert.False (subview.HasFocus);
Assert.Equal (1, hasFocusTrueCount);
Assert.Equal (1, hasFocusFalseCount);
@@ -640,6 +662,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "view",
CanFocus = true
};
+
view.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -660,6 +683,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subview",
CanFocus = true
};
+
subview.HasFocusChanging += (s, e) =>
{
if (e.NewValue)
@@ -691,6 +715,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Assert.Equal (1, subviewHasFocusFalseCount);
}
+
#endregion HasFocusChanging_NewValue_False
#region HasFocusChanged
@@ -706,6 +731,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "view",
CanFocus = true
};
+
view.HasFocusChanged += (s, e) =>
{
if (e.NewValue)
@@ -743,6 +769,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "view",
CanFocus = true
};
+
view.HasFocusChanged += (s, e) =>
{
if (e.NewValue)
@@ -763,6 +790,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subview",
CanFocus = true
};
+
subview.HasFocusChanged += (s, e) =>
{
if (e.NewValue)
@@ -821,6 +849,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "view",
CanFocus = true
};
+
view.HasFocusChanged += (s, e) =>
{
if (e.NewValue)
@@ -841,6 +870,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subView",
CanFocus = true
};
+
subView.HasFocusChanged += (s, e) =>
{
if (e.NewValue)
@@ -861,6 +891,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subViewSubView1",
CanFocus = false
};
+
subViewSubView1.HasFocusChanged += (s, e) =>
{
if (e.NewValue)
@@ -881,6 +912,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subViewSubView2",
CanFocus = true
};
+
subViewSubView2.HasFocusChanged += (s, e) =>
{
if (e.NewValue)
@@ -900,6 +932,7 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "subViewSubView3",
CanFocus = false
};
+
subViewSubView3.HasFocusChanged += (s, e) =>
{
if (e.NewValue)
@@ -967,32 +1000,33 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Id = "view",
CanFocus = true
};
+
view.HasFocusChanged += (s, e) =>
- {
- if (e.NewValue)
- {
- Assert.True (view.HasFocus);
- Assert.True (subView1.HasFocus);
- Assert.False (subView2.HasFocus);
+ {
+ if (e.NewValue)
+ {
+ Assert.True (view.HasFocus);
+ Assert.True (subView1.HasFocus);
+ Assert.False (subView2.HasFocus);
- subView1.Visible = true;
- subView2.Visible = false;
+ subView1.Visible = true;
+ subView2.Visible = false;
- Assert.True (view.HasFocus);
- Assert.True (subView1.HasFocus);
- Assert.False (subView2.HasFocus);
+ Assert.True (view.HasFocus);
+ Assert.True (subView1.HasFocus);
+ Assert.False (subView2.HasFocus);
- }
- else
- {
- Assert.False (view.HasFocus);
- Assert.False (subView1.HasFocus);
- Assert.False (subView2.HasFocus);
+ }
+ else
+ {
+ Assert.False (view.HasFocus);
+ Assert.False (subView1.HasFocus);
+ Assert.False (subView2.HasFocus);
- subView1.Visible = false;
- subView2.Visible = true;
- }
- };
+ subView1.Visible = false;
+ subView2.Visible = true;
+ }
+ };
view.Add (subView1, subView2);
@@ -1006,5 +1040,6 @@ public class HasFocusChangeEventTests (ITestOutputHelper _output) : TestsAllView
Assert.False (subView1.HasFocus);
Assert.False (subView2.HasFocus);
}
+
#endregion HasFocusChanged
}
diff --git a/UnitTests/View/Navigation/HasFocusTests.cs b/UnitTests/View/Navigation/HasFocusTests.cs
index fb6b1beef..b078f5501 100644
--- a/UnitTests/View/Navigation/HasFocusTests.cs
+++ b/UnitTests/View/Navigation/HasFocusTests.cs
@@ -155,4 +155,79 @@ public class HasFocusTests (ITestOutputHelper _output) : TestsAllViews
Assert.False (subViewSubView2.HasFocus);
Assert.False (subViewSubView3.HasFocus);
}
+
+ [Fact]
+ public void HasFocus_False_Subview_Raises_HasFocusChanged ()
+ {
+ var top = new View
+ {
+ Id = "top",
+ CanFocus = true
+ };
+
+ var subView1 = new View
+ {
+ Id = "subView1",
+ CanFocus = true
+ };
+
+ var subView2 = new View
+ {
+ Id = "subView2",
+ CanFocus = true
+ };
+ top.Add (subView1, subView2);
+
+ var subView1HasFocusChangedTrueCount = 0;
+ var subView1HasFocusChangedFalseCount = 0;
+
+ subView1.HasFocusChanged += (s, e) =>
+ {
+ if (e.NewValue)
+ {
+ subView1HasFocusChangedTrueCount++;
+ }
+ else
+ {
+ subView1HasFocusChangedFalseCount++;
+ }
+ };
+
+ var subView2HasFocusChangedTrueCount = 0;
+ var subView2HasFocusChangedFalseCount = 0;
+
+ subView2.HasFocusChanged += (s, e) =>
+ {
+ if (e.NewValue)
+ {
+ subView2HasFocusChangedTrueCount++;
+ }
+ else
+ {
+ subView2HasFocusChangedFalseCount++;
+ }
+ };
+
+ top.SetFocus ();
+ Assert.True (top.HasFocus);
+ Assert.True (subView1.HasFocus);
+ Assert.False (subView2.HasFocus);
+
+ Assert.Equal (1, subView1HasFocusChangedTrueCount);
+ Assert.Equal (0, subView1HasFocusChangedFalseCount);
+
+ Assert.Equal (0, subView2HasFocusChangedTrueCount);
+ Assert.Equal (0, subView2HasFocusChangedFalseCount);
+
+ subView1.HasFocus = false; // this should have the same resuilt as top.AdvanceFocus (NavigationDirection.Forward, null);
+
+ Assert.False (subView1.HasFocus);
+ Assert.True (subView2.HasFocus);
+
+ Assert.Equal (1, subView1HasFocusChangedTrueCount);
+ Assert.Equal (1, subView1HasFocusChangedFalseCount);
+
+ Assert.Equal (1, subView2HasFocusChangedTrueCount);
+ Assert.Equal (0, subView2HasFocusChangedFalseCount);
+ }
}
diff --git a/UnitTests/View/Navigation/NavigationTests.cs b/UnitTests/View/Navigation/NavigationTests.cs
index 5ddec1bef..27d343f30 100644
--- a/UnitTests/View/Navigation/NavigationTests.cs
+++ b/UnitTests/View/Navigation/NavigationTests.cs
@@ -313,48 +313,6 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
}
- [Fact]
- public void BringSubviewForward_Subviews_vs_TabIndexes ()
- {
- var r = new View ();
- var v1 = new View { CanFocus = true };
- var v2 = new View { CanFocus = true };
- var v3 = new View { CanFocus = true };
-
- r.Add (v1, v2, v3);
-
- r.BringSubviewForward (v1);
- Assert.True (r.Subviews.IndexOf (v1) == 1);
- Assert.True (r.Subviews.IndexOf (v2) == 0);
- Assert.True (r.Subviews.IndexOf (v3) == 2);
-
- Assert.True (r.TabIndexes.IndexOf (v1) == 0);
- Assert.True (r.TabIndexes.IndexOf (v2) == 1);
- Assert.True (r.TabIndexes.IndexOf (v3) == 2);
- r.Dispose ();
- }
-
- [Fact]
- public void BringSubviewToFront_Subviews_vs_TabIndexes ()
- {
- var r = new View ();
- var v1 = new View { CanFocus = true };
- var v2 = new View { CanFocus = true };
- var v3 = new View { CanFocus = true };
-
- r.Add (v1, v2, v3);
-
- r.BringSubviewToFront (v1);
- Assert.True (r.Subviews.IndexOf (v1) == 2);
- Assert.True (r.Subviews.IndexOf (v2) == 0);
- Assert.True (r.Subviews.IndexOf (v3) == 1);
-
- Assert.True (r.TabIndexes.IndexOf (v1) == 0);
- Assert.True (r.TabIndexes.IndexOf (v2) == 1);
- Assert.True (r.TabIndexes.IndexOf (v3) == 2);
- r.Dispose ();
- }
-
// View.Focused & View.MostFocused tests
// View.Focused - No subviews
diff --git a/UnitTests/View/ViewTests.cs b/UnitTests/View/ViewTests.cs
index a2b4af816..e4f0616ed 100644
--- a/UnitTests/View/ViewTests.cs
+++ b/UnitTests/View/ViewTests.cs
@@ -1064,7 +1064,6 @@ At 0,0
Assert.True (win.Visible);
Assert.True (win.CanFocus);
Assert.True (win.HasFocus);
- Assert.True (RunesCount () > 0);
win.Visible = false;
Assert.True (button.Visible);
@@ -1073,21 +1072,18 @@ At 0,0
Assert.False (win.Visible);
Assert.True (win.CanFocus);
Assert.False (win.HasFocus);
+
button.SetFocus ();
Assert.False (button.HasFocus);
Assert.False (win.HasFocus);
+
win.SetFocus ();
Assert.False (button.HasFocus);
Assert.False (win.HasFocus);
- top.Draw ();
- Assert.True (RunesCount () == 0);
win.Visible = true;
- win.FocusDeepest (NavigationDirection.Forward, null);
Assert.True (button.HasFocus);
Assert.True (win.HasFocus);
- top.Draw ();
- Assert.True (RunesCount () > 0);
Application.RequestStop ();
};
@@ -1095,25 +1091,6 @@ At 0,0
Application.Run (top);
top.Dispose ();
Assert.Equal (1, iterations);
-
- int RunesCount ()
- {
- Cell [,] contents = ((FakeDriver)Application.Driver).Contents;
- var runesCount = 0;
-
- for (var i = 0; i < Application.Driver!.Rows; i++)
- {
- for (var j = 0; j < Application.Driver!.Cols; j++)
- {
- if (contents [i, j].Rune != (Rune)' ')
- {
- runesCount++;
- }
- }
- }
-
- return runesCount;
- }
}
public class DerivedView : View
diff --git a/UnitTests/Views/ComboBoxTests.cs b/UnitTests/Views/ComboBoxTests.cs
index 293a739d1..366c9d42a 100644
--- a/UnitTests/Views/ComboBoxTests.cs
+++ b/UnitTests/Views/ComboBoxTests.cs
@@ -506,7 +506,7 @@ public class ComboBoxTests (ITestOutputHelper output)
top.Add (otherView, cb);
Application.Begin (top);
- Assert.False (cb.HasFocus);
+ Assert.True (cb.HasFocus);
Assert.True (cb.HideDropdownListOnClick);
Assert.False (cb.IsShow);
@@ -857,7 +857,7 @@ Three ",
Assert.True (Application.OnKeyDown (Key.CursorDown)); // losing focus
Assert.False (cb.IsShow);
Assert.False (cb.HasFocus);
- top.FocusDeepest (NavigationDirection.Forward, null); // Gets focus again
+ cb.SetFocus ();
Assert.False (cb.IsShow);
Assert.True (cb.HasFocus);
cb.Expand ();
@@ -969,7 +969,8 @@ Three
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("One", cb.Text);
- top.FocusDeepest (NavigationDirection.Forward, null); // Gets focus again
+
+ cb.SetFocus ();
Assert.True (cb.HasFocus);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
diff --git a/UnitTests/Views/OverlappedTests.cs b/UnitTests/Views/OverlappedTests.cs
index 0ce8c16b2..467718656 100644
--- a/UnitTests/Views/OverlappedTests.cs
+++ b/UnitTests/Views/OverlappedTests.cs
@@ -1232,7 +1232,7 @@ public class OverlappedTests
Assert.Equal (superView.MostFocused, current);
// Act
- ApplicationOverlapped.SetFocusToNextViewWithWrap (Application.Current.SuperView.TabIndexes, NavigationDirection.Forward);
+ ApplicationOverlapped.SetFocusToNextViewWithWrap (Application.Current.SuperView.Subviews, NavigationDirection.Forward);
// Assert
Assert.True (view1.HasFocus);