From 6d86e7f294cb770053d064ae415f5b6d159fc2d8 Mon Sep 17 00:00:00 2001 From: BDisp Date: Wed, 6 Jan 2021 11:27:05 +0000 Subject: [PATCH 1/7] Fixes #1071. Toplevel.GetTopLevelSubviews (). Changed from HashSet to IList. --- Terminal.Gui/Core/Toplevel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Terminal.Gui/Core/Toplevel.cs b/Terminal.Gui/Core/Toplevel.cs index 19b133ef9..a779accc6 100644 --- a/Terminal.Gui/Core/Toplevel.cs +++ b/Terminal.Gui/Core/Toplevel.cs @@ -278,7 +278,7 @@ namespace Terminal.Gui { return null; } - HashSet views = new HashSet (); + IList views = new List (); foreach (var v in SuperView.Subviews) { views.Add (v); From 950c7dd19ab198a3872548c847a37d04d9398759 Mon Sep 17 00:00:00 2001 From: BDisp Date: Thu, 7 Jan 2021 17:37:54 +0000 Subject: [PATCH 2/7] Adding unit test. --- UnitTests/ViewTests.cs | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/UnitTests/ViewTests.cs b/UnitTests/ViewTests.cs index dfb45df8b..35712be12 100644 --- a/UnitTests/ViewTests.cs +++ b/UnitTests/ViewTests.cs @@ -6,7 +6,7 @@ using System.Linq; using Terminal.Gui; using Xunit; -// Alais Console to MockConsole so we don't accidentally use Console +// Alias Console to MockConsole so we don't accidentally use Console using Console = Terminal.Gui.FakeConsole; namespace Terminal.Gui { @@ -27,9 +27,9 @@ namespace Terminal.Gui { Assert.Null (r.ColorScheme); Assert.Equal (Dim.Sized (0), r.Width); Assert.Equal (Dim.Sized (0), r.Height); - // BUGBUG: Pos needs eqality implemented - //Assert.Equal (Pos.At (0), r.X); - //Assert.Equal (Pos.At (0), r.Y); + // FIXED: Pos needs equality implemented + Assert.Equal (Pos.At (0), r.X); + Assert.Equal (Pos.At (0), r.Y); Assert.False (r.IsCurrentTop); Assert.Empty (r.Id); Assert.Empty (r.Subviews); @@ -1077,5 +1077,32 @@ namespace Terminal.Gui { Assert.True (view.Frame.IsEmpty); Assert.True (view.Bounds.IsEmpty); } + + [Fact] + public void GetToplevelSubviews_Ensure_Order_List () + { + var top = new Toplevel (); + + for (int i = 0; i < 6; i++) { + var view = new View ($"View{i}"); + top.Add (view); + } + + IList views = new List (); + + var idx = 0; + foreach (var v in top.Subviews) { + views.Add (v); + Assert.Equal ($"View{idx}", v.Text); + idx++; + } + + idx = top.Subviews.Count - 1; + foreach (var v in top.Subviews.Reverse ()) { + views.Add (v); + Assert.Equal ($"View{idx}", v.Text); + idx--; + } + } } } From ea8d84f185c6ba341dd41c259215d16c661df10c Mon Sep 17 00:00:00 2001 From: BDisp Date: Fri, 8 Jan 2021 19:53:04 +0000 Subject: [PATCH 3/7] Fixing the FocusNearestView method. --- Terminal.Gui/Core/Toplevel.cs | 37 ++++++++----------- UICatalog/Scenarios/WindowsAndFrameViews.cs | 2 +- UnitTests/ViewTests.cs | 41 ++++++++++++--------- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/Terminal.Gui/Core/Toplevel.cs b/Terminal.Gui/Core/Toplevel.cs index a779accc6..1699cd9d7 100644 --- a/Terminal.Gui/Core/Toplevel.cs +++ b/Terminal.Gui/Core/Toplevel.cs @@ -217,11 +217,11 @@ namespace Terminal.Gui { var old = GetDeepestFocusedSubview (Focused); if (!FocusNext ()) FocusNext (); - if (old != Focused) { + if (old != Focused && old != Focused?.Focused) { old?.SetNeedsDisplay (); Focused?.SetNeedsDisplay (); } else { - FocusNearestView (GetToplevelSubviews (true)); + FocusNearestView (SuperView?.Subviews, Direction.Forward); } return true; case Key.CursorLeft: @@ -230,11 +230,11 @@ namespace Terminal.Gui { old = GetDeepestFocusedSubview (Focused); if (!FocusPrev ()) FocusPrev (); - if (old != Focused) { + if (old != Focused && old != Focused?.Focused) { old?.SetNeedsDisplay (); Focused?.SetNeedsDisplay (); } else { - FocusNearestView (GetToplevelSubviews (false)); + FocusNearestView (SuperView?.Subviews?.Reverse(), Direction.Backward); } return true; @@ -272,39 +272,34 @@ namespace Terminal.Gui { return view; } - IEnumerable GetToplevelSubviews (bool isForward) - { - if (SuperView == null) { - return null; - } - - IList views = new List (); - - foreach (var v in SuperView.Subviews) { - views.Add (v); - } - - return isForward ? views : views.Reverse (); - } - - void FocusNearestView (IEnumerable views) + void FocusNearestView (IEnumerable views, Direction direction) { if (views == null) { return; } bool found = false; + bool focusProcessed = false; + int idx = 0; foreach (var v in views) { if (v == this) { found = true; } if (found && v != this) { - v.EnsureFocus (); + if (direction == Direction.Forward) { + SuperView?.FocusNext (); + } else { + SuperView?.FocusPrev (); + } + focusProcessed = true; if (SuperView.Focused != null && SuperView.Focused != this) { return; } + } else if (found && !focusProcessed && idx == views.Count () - 1) { + views.ToList () [0].SetFocus (); } + idx++; } } diff --git a/UICatalog/Scenarios/WindowsAndFrameViews.cs b/UICatalog/Scenarios/WindowsAndFrameViews.cs index 0d7f108c3..df590328c 100644 --- a/UICatalog/Scenarios/WindowsAndFrameViews.cs +++ b/UICatalog/Scenarios/WindowsAndFrameViews.cs @@ -108,7 +108,7 @@ namespace UICatalog { var frameView = new FrameView ("This is a Sub-FrameView") { X = Pos.Percent (50), Y = 1, - Width = Dim.Percent (100), + Width = Dim.Percent (100, true), // Or Dim.Percent (50) Height = 5, ColorScheme = Colors.Base, Text = "The Text in the FrameView", diff --git a/UnitTests/ViewTests.cs b/UnitTests/ViewTests.cs index 35712be12..b8cc950bd 100644 --- a/UnitTests/ViewTests.cs +++ b/UnitTests/ViewTests.cs @@ -1079,30 +1079,35 @@ namespace Terminal.Gui { } [Fact] - public void GetToplevelSubviews_Ensure_Order_List () + public void FocusNearestView_Ensure_Focus_Ordered () { var top = new Toplevel (); - for (int i = 0; i < 6; i++) { - var view = new View ($"View{i}"); - top.Add (view); - } + var win = new Window (); + var winSubview = new View ("WindowSubview") { + CanFocus = true + }; + win.Add (winSubview); + top.Add (win); - IList views = new List (); + var frm = new FrameView (); + var frmSubview = new View ("FrameSubview") { + CanFocus = true + }; + frm.Add (frmSubview); + top.Add (frm); - var idx = 0; - foreach (var v in top.Subviews) { - views.Add (v); - Assert.Equal ($"View{idx}", v.Text); - idx++; - } + top.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ())); + Assert.Equal ($"WindowSubview", top.MostFocused.Text); + top.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ())); + Assert.Equal ("FrameSubview", top.MostFocused.Text); + top.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ())); + Assert.Equal ($"WindowSubview", top.MostFocused.Text); - idx = top.Subviews.Count - 1; - foreach (var v in top.Subviews.Reverse ()) { - views.Add (v); - Assert.Equal ($"View{idx}", v.Text); - idx--; - } + top.ProcessKey (new KeyEvent (Key.BackTab, new KeyModifiers ())); + Assert.Equal ("FrameSubview", top.MostFocused.Text); + top.ProcessKey (new KeyEvent (Key.BackTab, new KeyModifiers ())); + Assert.Equal ($"WindowSubview", top.MostFocused.Text); } } } From 3dd17bd82cf78cb607867bbca8a562abaef89561 Mon Sep 17 00:00:00 2001 From: BDisp Date: Fri, 8 Jan 2021 20:35:47 +0000 Subject: [PATCH 4/7] Added feature to navigate through all Application.Top's subviews. --- Terminal.Gui/Core/Toplevel.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Terminal.Gui/Core/Toplevel.cs b/Terminal.Gui/Core/Toplevel.cs index 1699cd9d7..c83eee343 100644 --- a/Terminal.Gui/Core/Toplevel.cs +++ b/Terminal.Gui/Core/Toplevel.cs @@ -195,7 +195,7 @@ namespace Terminal.Gui { if (base.ProcessKey (keyEvent)) return true; - switch (keyEvent.Key) { + switch (ShortcutHelper.GetModifiersKey (keyEvent)) { case Key.Q | Key.CtrlMask: // FIXED: stop current execution of this container Application.RequestStop (); @@ -224,9 +224,9 @@ namespace Terminal.Gui { FocusNearestView (SuperView?.Subviews, Direction.Forward); } return true; + case Key.BackTab | Key.ShiftMask: case Key.CursorLeft: case Key.CursorUp: - case Key.BackTab: old = GetDeepestFocusedSubview (Focused); if (!FocusPrev ()) FocusPrev (); @@ -237,7 +237,12 @@ namespace Terminal.Gui { FocusNearestView (SuperView?.Subviews?.Reverse(), Direction.Backward); } return true; - + case Key.Tab | Key.CtrlMask: + Application.Top.FocusNext (); + return true; + case Key.Tab | Key.ShiftMask | Key.CtrlMask: + Application.Top.FocusPrev (); + return true; case Key.L | Key.CtrlMask: Application.Refresh (); return true; From b3850f7f61e40e43a005a90382ad1895685dabd8 Mon Sep 17 00:00:00 2001 From: BDisp Date: Fri, 8 Jan 2021 21:33:07 +0000 Subject: [PATCH 5/7] Fixing FakeDriver and unit test. --- Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs | 1 + UnitTests/ViewTests.cs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs index 8a443133e..d79f5007b 100644 --- a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs @@ -391,6 +391,7 @@ namespace Terminal.Gui { keyHandler (new KeyEvent (map, keyModifiers)); keyUpHandler (new KeyEvent (map, keyModifiers)); + keyModifiers = new KeyModifiers (); }; } diff --git a/UnitTests/ViewTests.cs b/UnitTests/ViewTests.cs index b8cc950bd..990e3f9c9 100644 --- a/UnitTests/ViewTests.cs +++ b/UnitTests/ViewTests.cs @@ -1104,9 +1104,9 @@ namespace Terminal.Gui { top.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ())); Assert.Equal ($"WindowSubview", top.MostFocused.Text); - top.ProcessKey (new KeyEvent (Key.BackTab, new KeyModifiers ())); + top.ProcessKey (new KeyEvent (Key.BackTab | Key.ShiftMask, new KeyModifiers ())); Assert.Equal ("FrameSubview", top.MostFocused.Text); - top.ProcessKey (new KeyEvent (Key.BackTab, new KeyModifiers ())); + top.ProcessKey (new KeyEvent (Key.BackTab | Key.ShiftMask, new KeyModifiers ())); Assert.Equal ($"WindowSubview", top.MostFocused.Text); } } From 845b9400788819781144088905639e339c3389c1 Mon Sep 17 00:00:00 2001 From: BDisp Date: Fri, 8 Jan 2021 22:44:03 +0000 Subject: [PATCH 6/7] Fixes shift on Unix. --- Terminal.Gui/Core/Event.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Terminal.Gui/Core/Event.cs b/Terminal.Gui/Core/Event.cs index 04ae3b961..83ccffe61 100644 --- a/Terminal.Gui/Core/Event.cs +++ b/Terminal.Gui/Core/Event.cs @@ -392,7 +392,7 @@ namespace Terminal.Gui { /// Gets a value indicating whether the Shift key was pressed. /// /// true if is shift; otherwise, false. - public bool IsShift => keyModifiers.Shift; + public bool IsShift => keyModifiers.Shift || Key == Key.BackTab; /// /// Gets a value indicating whether the Alt key was pressed (real or synthesized) From f7a8cf63d74aba7faefb93bcd58d9d528d06c81d Mon Sep 17 00:00:00 2001 From: BDisp Date: Tue, 12 Jan 2021 00:18:16 +0000 Subject: [PATCH 7/7] Since FocusNearestView method deals with navigation and focus is better use TabIndexes instead. --- Terminal.Gui/Core/Toplevel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Terminal.Gui/Core/Toplevel.cs b/Terminal.Gui/Core/Toplevel.cs index c83eee343..69f75e3a3 100644 --- a/Terminal.Gui/Core/Toplevel.cs +++ b/Terminal.Gui/Core/Toplevel.cs @@ -221,7 +221,7 @@ namespace Terminal.Gui { old?.SetNeedsDisplay (); Focused?.SetNeedsDisplay (); } else { - FocusNearestView (SuperView?.Subviews, Direction.Forward); + FocusNearestView (SuperView?.TabIndexes, Direction.Forward); } return true; case Key.BackTab | Key.ShiftMask: @@ -234,7 +234,7 @@ namespace Terminal.Gui { old?.SetNeedsDisplay (); Focused?.SetNeedsDisplay (); } else { - FocusNearestView (SuperView?.Subviews?.Reverse(), Direction.Backward); + FocusNearestView (SuperView?.TabIndexes?.Reverse(), Direction.Backward); } return true; case Key.Tab | Key.CtrlMask: