From 89f4fcd4bb7049ae2eb6f85a86aeecfa379b8e7e Mon Sep 17 00:00:00 2001 From: BDisp Date: Wed, 10 Nov 2021 22:15:59 +0000 Subject: [PATCH 1/2] Allows ListView trigger the Enter and Leave events. --- Terminal.Gui/Views/ListView.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Terminal.Gui/Views/ListView.cs b/Terminal.Gui/Views/ListView.cs index fad92f4e27..b988cfb9d6 100644 --- a/Terminal.Gui/Views/ListView.cs +++ b/Terminal.Gui/Views/ListView.cs @@ -673,7 +673,6 @@ public override bool OnEnter (View view) if (lastSelectedItem == -1) { EnsuresVisibilitySelectedItem (); OnSelectedChanged (); - return true; } return base.OnEnter (view); @@ -684,10 +683,9 @@ public override bool OnLeave (View view) { if (lastSelectedItem > -1) { lastSelectedItem = -1; - return true; } - return false; + return base.OnLeave (view); } void EnsuresVisibilitySelectedItem () From b7fb31f2d50b195a1231b2c6d730bb001fb7acc7 Mon Sep 17 00:00:00 2001 From: BDisp Date: Thu, 11 Nov 2021 18:45:38 +0000 Subject: [PATCH 2/2] Added unit test for Enter and Leave events to all views. --- Terminal.Gui/Views/Button.cs | 2 +- Terminal.Gui/Views/ComboBox.cs | 4 +- Terminal.Gui/Views/TabView.cs | 2 +- Terminal.Gui/Views/TextValidateField.cs | 4 +- UnitTests/AllViewsTests.cs | 134 ++++++++++++++++++------ 5 files changed, 109 insertions(+), 37 deletions(-) diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs index 4cd600f3f4..a4a6080938 100644 --- a/Terminal.Gui/Views/Button.cs +++ b/Terminal.Gui/Views/Button.cs @@ -256,7 +256,7 @@ public override bool MouseEvent (MouseEvent me) /// public override void PositionCursor () { - if (HotKey == Key.Unknown) { + if (HotKey == Key.Unknown && text != "") { for (int i = 0; i < base.Text.RuneCount; i++) { if (base.Text [i] == text [0]) { Move (i, 0); diff --git a/Terminal.Gui/Views/ComboBox.cs b/Terminal.Gui/Views/ComboBox.cs index edda3950b7..8a2d430a8e 100644 --- a/Terminal.Gui/Views/ComboBox.cs +++ b/Terminal.Gui/Views/ComboBox.cs @@ -238,7 +238,7 @@ public override bool OnEnter (View view) search.CursorPosition = search.Text.RuneCount; - return true; + return base.OnEnter (view); } /// @@ -251,7 +251,7 @@ public override bool OnLeave (View view) listview.TabStop = false; } - return true; + return base.OnLeave (view); } /// diff --git a/Terminal.Gui/Views/TabView.cs b/Terminal.Gui/Views/TabView.cs index 193751e4cb..2b925d0101 100644 --- a/Terminal.Gui/Views/TabView.cs +++ b/Terminal.Gui/Views/TabView.cs @@ -174,7 +174,7 @@ public override void Redraw (Rect bounds) int startAtY = Math.Max (0, GetTabHeight (true) - 1); DrawFrame (new Rect (0, startAtY, bounds.Width, - bounds.Height - spaceAtBottom - startAtY), 0, true); + Math.Max (bounds.Height - spaceAtBottom - startAtY, 0)), 0, true); } if (Tabs.Any ()) { diff --git a/Terminal.Gui/Views/TextValidateField.cs b/Terminal.Gui/Views/TextValidateField.cs index 940480b57d..2c5314979b 100644 --- a/Terminal.Gui/Views/TextValidateField.cs +++ b/Terminal.Gui/Views/TextValidateField.cs @@ -454,7 +454,7 @@ public override void PositionCursor () // Fixed = true, is for inputs thar have fixed width, like masked ones. // Fixed = false, is for normal input. // When it's right-aligned and it's a normal input, the cursor behaves differently. - if (provider.Fixed == false && TextAlignment == TextAlignment.Right) { + if (provider?.Fixed == false && TextAlignment == TextAlignment.Right) { Move (cursorPosition + left - 1, 0); } else { Move (cursorPosition + left, 0); @@ -591,7 +591,7 @@ bool EndKeyHandler () public override bool ProcessKey (KeyEvent kb) { if (provider == null) { - return true; + return false; } switch (kb.Key) { diff --git a/UnitTests/AllViewsTests.cs b/UnitTests/AllViewsTests.cs index 913090e7aa..5b62591f77 100644 --- a/UnitTests/AllViewsTests.cs +++ b/UnitTests/AllViewsTests.cs @@ -22,51 +22,65 @@ public void AllViews_Tests_All_Constructors () public bool Constructors_FullTest (Type type) { foreach (var ctor in type.GetConstructors ()) { - if (type.IsGenericType && type.IsTypeDefinition) { - List gTypes = new List (); + var view = GetTypeInitializer (type, ctor); + if (view != null) { + Assert.True (type.FullName == view.GetType ().FullName); + } + } - foreach (var args in type.GetGenericArguments ()) { - gTypes.Add (typeof (object)); - } - type = type.MakeGenericType (gTypes.ToArray ()); + return true; + } - Assert.IsType (type, (View)Activator.CreateInstance (type)); + private static View GetTypeInitializer (Type type, ConstructorInfo ctor) + { + View viewType = null; - } else { - ParameterInfo [] paramsInfo = ctor.GetParameters (); - Type paramType; - List pTypes = new List (); - - if (type.IsGenericType) { - foreach (var args in type.GetGenericArguments ()) { - paramType = args.GetType (); - if (args.Name == "T") { - pTypes.Add (typeof (object)); - } else { - AddArguments (paramType, pTypes); - } - } - } + if (type.IsGenericType && type.IsTypeDefinition) { + List gTypes = new List (); - foreach (var p in paramsInfo) { - paramType = p.ParameterType; - if (p.HasDefaultValue) { - pTypes.Add (p.DefaultValue); + foreach (var args in type.GetGenericArguments ()) { + gTypes.Add (typeof (object)); + } + type = type.MakeGenericType (gTypes.ToArray ()); + + Assert.IsType (type, (View)Activator.CreateInstance (type)); + + } else { + ParameterInfo [] paramsInfo = ctor.GetParameters (); + Type paramType; + List pTypes = new List (); + + if (type.IsGenericType) { + foreach (var args in type.GetGenericArguments ()) { + paramType = args.GetType (); + if (args.Name == "T") { + pTypes.Add (typeof (object)); } else { AddArguments (paramType, pTypes); } - } + } - if (type.IsGenericType && !type.IsTypeDefinition) { - Assert.IsType (type, (View)Activator.CreateInstance (type)); + foreach (var p in paramsInfo) { + paramType = p.ParameterType; + if (p.HasDefaultValue) { + pTypes.Add (p.DefaultValue); } else { - Assert.IsType (type, ctor.Invoke (pTypes.ToArray ())); + AddArguments (paramType, pTypes); } + + } + + if (type.IsGenericType && !type.IsTypeDefinition) { + viewType = (View)Activator.CreateInstance (type); + Assert.IsType (type, viewType); + } else { + viewType = (View)ctor.Invoke (pTypes.ToArray ()); + Assert.IsType (type, viewType); } } - return true; + return viewType; } private static void AddArguments (Type paramType, List pTypes) @@ -108,5 +122,63 @@ List GetAllViewClassesCollection () } return types; } + + [Fact] + public void AllViews_Enter_Leave_Events () + { + foreach (var type in GetAllViewClassesCollection ()) { + Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true))); + + var top = Application.Top; + var vType = GetTypeInitializer (type, type.GetConstructor (Array.Empty ())); + if (vType == null) { + Application.Shutdown (); + continue; + } + vType.X = 0; + vType.Y = 0; + vType.Width = 10; + vType.Height = 1; + + var view = new View () { + X = 0, + Y = 1, + Width = 10, + Height = 1, + CanFocus = true + }; + var vTypeEnter = 0; + var vTypeLeave = 0; + var viewEnter = 0; + var viewLeave = 0; + + vType.Enter += _ => vTypeEnter++; + vType.Leave += _ => vTypeLeave++; + view.Enter += _ => viewEnter++; + view.Leave += _ => viewLeave++; + + top.Add (vType, view); + Application.Begin (top); + + if (!vType.CanFocus || (vType is Toplevel && ((Toplevel)vType).Modal)) { + Application.Shutdown (); + continue; + } + + if (vType is TextView) { + top.ProcessKey (new KeyEvent (Key.Tab | Key.CtrlMask, new KeyModifiers ())); + } else { + top.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ())); + } + top.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ())); + + Assert.Equal (2, vTypeEnter); + Assert.Equal (1, vTypeLeave); + Assert.Equal (1, viewEnter); + Assert.Equal (1, viewLeave); + + Application.Shutdown (); + } + } } }