diff --git a/Terminal.Gui/Application/Application.cs b/Terminal.Gui/Application/Application.cs
index e3912475f..fe1a5cd55 100644
--- a/Terminal.Gui/Application/Application.cs
+++ b/Terminal.Gui/Application/Application.cs
@@ -26,6 +26,79 @@ public static partial class Application
/// Gets all cultures supported by the application without the invariant language.
public static List? SupportedCultures { get; private set; }
+ ///
+ /// Gets a string representation of the Application as rendered by .
+ ///
+ /// A string representation of the Application
+ public new static string ToString ()
+ {
+ ConsoleDriver driver = Driver;
+
+ if (driver is null)
+ {
+ return string.Empty;
+ }
+
+ return ToString (driver);
+ }
+
+ ///
+ /// Gets a string representation of the Application rendered by the provided .
+ ///
+ /// The driver to use to render the contents.
+ /// A string representation of the Application
+ public static string ToString (ConsoleDriver driver)
+ {
+ var sb = new StringBuilder ();
+
+ Cell [,] contents = driver.Contents;
+
+ for (var r = 0; r < driver.Rows; r++)
+ {
+ for (var c = 0; c < driver.Cols; c++)
+ {
+ Rune rune = contents [r, c].Rune;
+
+ if (rune.DecodeSurrogatePair (out char [] sp))
+ {
+ sb.Append (sp);
+ }
+ else
+ {
+ sb.Append ((char)rune.Value);
+ }
+
+ if (rune.GetColumns () > 1)
+ {
+ c++;
+ }
+
+ // See Issue #2616
+ //foreach (var combMark in contents [r, c].CombiningMarks) {
+ // sb.Append ((char)combMark.Value);
+ //}
+ }
+
+ sb.AppendLine ();
+ }
+
+ return sb.ToString ();
+ }
+
+ internal static List GetAvailableCulturesFromEmbeddedResources ()
+ {
+ ResourceManager rm = new (typeof (Strings));
+
+ CultureInfo [] cultures = CultureInfo.GetCultures (CultureTypes.AllCultures);
+
+ return cultures.Where (
+ cultureInfo =>
+ !cultureInfo.Equals (CultureInfo.InvariantCulture)
+ && rm.GetResourceSet (cultureInfo, true, false) is { }
+ )
+ .ToList ();
+ }
+
internal static List GetSupportedCultures ()
{
CultureInfo [] cultures = CultureInfo.GetCultures (CultureTypes.AllCultures);
@@ -54,20 +127,6 @@ public static partial class Application
return GetAvailableCulturesFromEmbeddedResources ();
}
- internal static List GetAvailableCulturesFromEmbeddedResources ()
- {
- ResourceManager rm = new (typeof (Strings));
-
- CultureInfo [] cultures = CultureInfo.GetCultures (CultureTypes.AllCultures);
-
- return cultures.Where (
- cultureInfo =>
- !cultureInfo.Equals (CultureInfo.InvariantCulture)
- && rm.GetResourceSet (cultureInfo, true, false) is { }
- )
- .ToList ();
- }
-
// IMPORTANT: Ensure all property/fields are reset here. See Init_ResetState_Resets_Properties unit test.
// Encapsulate all setting of initial state for Application; Having
// this in a function like this ensures we don't make mistakes in
@@ -159,70 +218,5 @@ public static partial class Application
SynchronizationContext.SetSynchronizationContext (null);
}
-#nullable enable
-#nullable restore
-
-#nullable enable
-
// Only return true if the Current has changed.
-#nullable restore
-
- ///
- /// Gets a string representation of the Application as rendered by .
- ///
- /// A string representation of the Application
- public new static string ToString ()
- {
- ConsoleDriver driver = Driver;
-
- if (driver is null)
- {
- return string.Empty;
- }
-
- return ToString (driver);
- }
-
- ///
- /// Gets a string representation of the Application rendered by the provided .
- ///
- /// The driver to use to render the contents.
- /// A string representation of the Application
- public static string ToString (ConsoleDriver driver)
- {
- var sb = new StringBuilder ();
-
- Cell [,] contents = driver.Contents;
-
- for (var r = 0; r < driver.Rows; r++)
- {
- for (var c = 0; c < driver.Cols; c++)
- {
- Rune rune = contents [r, c].Rune;
-
- if (rune.DecodeSurrogatePair (out char [] sp))
- {
- sb.Append (sp);
- }
- else
- {
- sb.Append ((char)rune.Value);
- }
-
- if (rune.GetColumns () > 1)
- {
- c++;
- }
-
- // See Issue #2616
- //foreach (var combMark in contents [r, c].CombiningMarks) {
- // sb.Append ((char)combMark.Value);
- //}
- }
-
- sb.AppendLine ();
- }
-
- return sb.ToString ();
- }
}
diff --git a/Terminal.Gui/Input/KeyBindings.cs b/Terminal.Gui/Input/KeyBindings.cs
index 5dd69a260..4df4b6e32 100644
--- a/Terminal.Gui/Input/KeyBindings.cs
+++ b/Terminal.Gui/Input/KeyBindings.cs
@@ -1,12 +1,9 @@
#nullable enable
-using System.Diagnostics;
-using Microsoft.CodeAnalysis;
-
namespace Terminal.Gui;
///
-/// Provides a collection of objects bound to a .
+/// Provides a collection of objects bound to a .
///
public class KeyBindings
{
@@ -19,19 +16,6 @@ public class KeyBindings
/// Initializes a new instance bound to .
public KeyBindings (View boundView) { BoundView = boundView; }
- ///
- /// The view that the are bound to.
- ///
- ///
- /// If , the are not bound to a . This is used for Application.KeyBindings.
- ///
- public View? BoundView { get; }
-
- // TODO: Add a dictionary comparer that ignores Scope
- // TODO: This should not be public!
- /// The collection of objects.
- public Dictionary Bindings { get; } = new ();
-
/// Adds a to the collection.
///
///
@@ -45,21 +29,21 @@ public class KeyBindings
if (TryGet (key, out KeyBinding _))
{
- throw new InvalidOperationException(@$"A key binding for {key} exists ({binding}).");
+ throw new InvalidOperationException (@$"A key binding for {key} exists ({binding}).");
+
//Bindings [key] = binding;
}
+
+ if (BoundView is { })
+ {
+ binding.BoundView = BoundView;
+ }
else
{
- if (BoundView is { })
- {
- binding.BoundView = BoundView;
- }
- else
- {
- binding.BoundView = boundViewForAppScope;
- }
- Bindings.Add (key, binding);
+ binding.BoundView = boundViewForAppScope;
}
+
+ Bindings.Add (key, binding);
}
///
@@ -102,14 +86,12 @@ public class KeyBindings
if (TryGet (key, out KeyBinding binding))
{
throw new InvalidOperationException (@$"A key binding for {key} exists ({binding}).");
+
//Bindings [key] = new (commands, scope, BoundView);
}
- else
- {
- Add (key, new KeyBinding (commands, scope, BoundView), boundViewForAppScope);
- }
- }
+ Add (key, new KeyBinding (commands, scope, BoundView), boundViewForAppScope);
+ }
///
/// Adds a new key combination that will trigger the commands in .
@@ -129,7 +111,7 @@ public class KeyBindings
/// multiple commands are provided,they will be applied in sequence. The bound strike will be
/// consumed if any took effect.
///
- public void Add (Key key, KeyBindingScope scope, params Command [] commands)
+ public void Add (Key key, KeyBindingScope scope, params Command [] commands)
{
if (BoundView is { } && scope.FastHasFlags (KeyBindingScope.Application))
{
@@ -150,10 +132,8 @@ public class KeyBindings
{
throw new InvalidOperationException (@$"A key binding for {key} exists ({binding}).");
}
- else
- {
- Add (key, new KeyBinding (commands, scope, BoundView), null);
- }
+
+ Add (key, new KeyBinding (commands, scope, BoundView));
}
///
@@ -162,7 +142,8 @@ public class KeyBindings
/// View - see ).
///
///
- /// This is a helper function for . If used for a View ( is set), the scope will be set to .
+ /// This is a helper function for . If used for a View (
+ /// is set), the scope will be set to .
/// Otherwise, it will be set to .
///
///
@@ -185,8 +166,9 @@ public class KeyBindings
{
if (BoundView is null && boundViewForAppScope is null)
{
- throw new ArgumentException (@"Application scoped KeyBindings must provide a bound view to Add.", nameof(boundViewForAppScope));
+ throw new ArgumentException (@"Application scoped KeyBindings must provide a bound view to Add.", nameof (boundViewForAppScope));
}
+
Add (key, BoundView is { } ? KeyBindingScope.Focused : KeyBindingScope.Application, boundViewForAppScope, commands);
}
@@ -196,7 +178,8 @@ public class KeyBindings
/// View - see ).
///
///
- /// This is a helper function for . If used for a View ( is set), the scope will be set to .
+ /// This is a helper function for . If used for a View (
+ /// is set), the scope will be set to .
/// Otherwise, it will be set to .
///
///
@@ -220,14 +203,26 @@ public class KeyBindings
{
throw new ArgumentException (@"Application scoped KeyBindings must provide a boundViewForAppScope to Add.");
}
+
Add (key, BoundView is { } ? KeyBindingScope.Focused : KeyBindingScope.Application, null, commands);
}
+ // TODO: Add a dictionary comparer that ignores Scope
+ // TODO: This should not be public!
+ /// The collection of objects.
+ public Dictionary Bindings { get; } = new ();
+
+ ///
+ /// The view that the are bound to.
+ ///
+ ///
+ /// If , the are not bound to a . This is used for
+ /// Application.KeyBindings.
+ ///
+ public View? BoundView { get; }
+
/// Removes all objects from the collection.
- public void Clear ()
- {
- Bindings.Clear ();
- }
+ public void Clear () { Bindings.Clear (); }
///
/// Removes all key bindings that trigger the given command set. Views can have multiple different keys bound to
@@ -255,6 +250,7 @@ public class KeyBindings
{
return binding;
}
+
throw new InvalidOperationException ($"Key {key} is not bound.");
}
@@ -268,6 +264,7 @@ public class KeyBindings
{
return binding;
}
+
throw new InvalidOperationException ($"Key {key}/{scope} is not bound.");
}
@@ -299,7 +296,6 @@ public class KeyBindings
/// Optional View for bindings.
public void Remove (Key key, View? boundViewForAppScope = null)
{
-
if (!TryGet (key, out KeyBinding binding))
{
return;
@@ -308,6 +304,26 @@ public class KeyBindings
Bindings.Remove (key);
}
+ /// Replaces the commands already bound to a key.
+ ///
+ ///
+ /// If the key is not already bound, it will be added.
+ ///
+ ///
+ /// The key bound to the command to be replaced.
+ /// The set of commands to replace the old ones with.
+ public void ReplaceCommands (Key key, params Command [] commands)
+ {
+ if (TryGet (key, out KeyBinding binding))
+ {
+ binding.Commands = commands;
+ }
+ else
+ {
+ Add (key, commands);
+ }
+ }
+
/// Replaces a key combination already bound to a set of s.
///
/// The key to be replaced.
@@ -329,26 +345,6 @@ public class KeyBindings
Add (newKey, value);
}
- /// Replaces the commands already bound to a key.
- ///
- ///
- /// If the key is not already bound, it will be added.
- ///
- ///
- /// The key bound to the command to be replaced.
- /// The set of commands to replace the old ones with.
- public void ReplaceCommands (Key key, params Command [] commands)
- {
- if (TryGet (key, out KeyBinding binding))
- {
- binding.Commands = commands;
- }
- else
- {
- Add (key, commands);
- }
- }
-
/// Gets the commands bound with the specified Key.
///
/// The key to check.
@@ -360,6 +356,7 @@ public class KeyBindings
public bool TryGet (Key key, out KeyBinding binding)
{
binding = new (Array.Empty (), KeyBindingScope.Disabled, null);
+
if (key.IsValid)
{
return Bindings.TryGetValue (key, out binding);
@@ -380,6 +377,7 @@ public class KeyBindings
public bool TryGet (Key key, KeyBindingScope scope, out KeyBinding binding)
{
binding = new (Array.Empty (), KeyBindingScope.Disabled, null);
+
if (key.IsValid && Bindings.TryGetValue (key, out binding))
{
if (scope.HasFlag (binding.Scope))
diff --git a/Terminal.Gui/Resources/config.json b/Terminal.Gui/Resources/config.json
index a80d8334e..d001326a0 100644
--- a/Terminal.Gui/Resources/config.json
+++ b/Terminal.Gui/Resources/config.json
@@ -31,8 +31,9 @@
"Dialog.DefaultButtonAlignmentModes": "AddSpaceBetweenItems",
"FrameView.DefaultBorderStyle": "Single",
"Window.DefaultBorderStyle": "Single",
- "Dialog.DefaultBorderStyle": "Single",
- "MessageBox.DefaultBorderStyle": "Double",
+ "Dialog.DefaultBorderStyle": "Heavy",
+ "MessageBox.DefaultButtonAlignment": "Center",
+ "MessageBox.DefaultBorderStyle": "Heavy",
"Button.DefaultShadow": "None",
"ColorSchemes": [
{
diff --git a/Terminal.Gui/Views/Dialog.cs b/Terminal.Gui/Views/Dialog.cs
index 7b4da9355..c1f18e8fb 100644
--- a/Terminal.Gui/Views/Dialog.cs
+++ b/Terminal.Gui/Views/Dialog.cs
@@ -20,7 +20,7 @@ public class Dialog : Window
/// This property can be set in a Theme.
[SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
[JsonConverter (typeof (JsonStringEnumConverter))]
- public static Alignment DefaultButtonAlignment { get; set; } = Alignment.End;
+ public static Alignment DefaultButtonAlignment { get; set; } = Alignment.End; // Default is set in config.json
/// The default for .
/// This property can be set in a Theme.
@@ -48,7 +48,7 @@ public class Dialog : Window
///
[SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
[JsonConverter (typeof (JsonStringEnumConverter))]
- public new static ShadowStyle DefaultShadow { get; set; } = ShadowStyle.None;
+ public new static ShadowStyle DefaultShadow { get; set; } = ShadowStyle.None; // Default is set in config.json
///
/// Defines the default border styling for . Can be configured via
@@ -57,7 +57,7 @@ public class Dialog : Window
[SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
[JsonConverter (typeof (JsonStringEnumConverter))]
- public new static LineStyle DefaultBorderStyle { get; set; } = LineStyle.Single;
+ public new static LineStyle DefaultBorderStyle { get; set; } = LineStyle.Single; // Default is set in config.json
private readonly List
[SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
[JsonConverter (typeof (JsonStringEnumConverter))]
- public static LineStyle DefaultBorderStyle { get; set; } = LineStyle.Single;
+ public static LineStyle DefaultBorderStyle { get; set; } = LineStyle.Single; // Default is set in config.json
+
+ /// The default for .
+ /// This property can be set in a Theme.
+ [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
+ [JsonConverter (typeof (JsonStringEnumConverter))]
+ public static Alignment DefaultButtonAlignment { get; set; } = Alignment.Center; // Default is set in config.json
///
/// Defines the default minimum MessageBox width, as a percentage of the screen width. Can be configured via
@@ -365,10 +371,10 @@ public static class MessageBox
var d = new Dialog
{
Title = title,
- Buttons = buttonList.ToArray (),
- ButtonAlignment = Alignment.Center,
+ ButtonAlignment = MessageBox.DefaultButtonAlignment,
ButtonAlignmentModes = AlignmentModes.StartToEnd | AlignmentModes.AddSpaceBetweenItems,
BorderStyle = MessageBox.DefaultBorderStyle,
+ Buttons = buttonList.ToArray (),
};
d.Width = Dim.Auto (DimAutoStyle.Auto,
diff --git a/Terminal.Gui/Views/Shortcut.cs b/Terminal.Gui/Views/Shortcut.cs
index 6530d71bc..ff1d4b21f 100644
--- a/Terminal.Gui/Views/Shortcut.cs
+++ b/Terminal.Gui/Views/Shortcut.cs
@@ -74,7 +74,7 @@ public class Shortcut : View, IOrientation, IDesignable
CommandView = new ()
{
Width = Dim.Auto (),
- Height = Dim.Auto (DimAutoStyle.Auto, minimumContentDim: 1)
+ Height = Dim.Auto (1)
};
HelpView.Id = "_helpView";
diff --git a/UICatalog/Scenarios/AdornmentsEditor.cs b/UICatalog/Scenarios/AdornmentsEditor.cs
index 472ed4897..2f389552a 100644
--- a/UICatalog/Scenarios/AdornmentsEditor.cs
+++ b/UICatalog/Scenarios/AdornmentsEditor.cs
@@ -9,23 +9,10 @@ namespace UICatalog.Scenarios;
///
public class AdornmentsEditor : View
{
- private View _viewToEdit;
-
- private Label _lblView; // Text describing the vi
-
- private MarginEditor _marginEditor;
- private BorderEditor _borderEditor;
- private PaddingEditor _paddingEditor;
-
- // TODO: Move Diagnostics to a separate Editor class (DiagnosticsEditor?).
- private CheckBox _diagPaddingCheckBox;
- private CheckBox _diagRulerCheckBox;
- private readonly ViewDiagnosticFlags _savedDiagnosticFlags = Diagnostics;
-
public AdornmentsEditor ()
{
//ColorScheme = Colors.ColorSchemes ["Dialog"];
- Title = $"AdornmentsEditor";
+ Title = "AdornmentsEditor";
Width = Dim.Auto (DimAutoStyle.Content);
Height = Dim.Auto (DimAutoStyle.Content);
@@ -39,34 +26,57 @@ public class AdornmentsEditor : View
Initialized += AdornmentsEditor_Initialized;
}
- private void ApplicationNavigationOnFocusedChanged (object sender, EventArgs e)
- {
- if (ApplicationNavigation.IsInHierarchy (this, Application.Navigation!.GetFocused ()))
- {
- return;
- }
+ private readonly ViewDiagnosticFlags _savedDiagnosticFlags = Diagnostics;
+ private View _viewToEdit;
- if (Application.Navigation!.GetFocused () is Adornment adornment)
+ private Label _lblView; // Text describing the vi
+
+ private MarginEditor _marginEditor;
+ private BorderEditor _borderEditor;
+ private PaddingEditor _paddingEditor;
+
+ // TODO: Move Diagnostics to a separate Editor class (DiagnosticsEditor?).
+ private CheckBox _diagPaddingCheckBox;
+ private CheckBox _diagRulerCheckBox;
+
+ ///
+ /// Gets or sets whether the AdornmentsEditor should automatically select the View to edit when the mouse is clicked
+ /// anywhere outside the editor.
+ ///
+ public bool AutoSelectViewToEdit { get; set; }
+
+ public View ViewToEdit
+ {
+ get => _viewToEdit;
+ set
{
- ViewToEdit = adornment.Parent;
- }
- else
- {
- ViewToEdit = Application.Navigation.GetFocused ();
+ if (_viewToEdit == value)
+ {
+ return;
+ }
+
+ _viewToEdit = value;
+
+ _marginEditor.AdornmentToEdit = _viewToEdit?.Margin ?? null;
+ _borderEditor.AdornmentToEdit = _viewToEdit?.Border ?? null;
+ _paddingEditor.AdornmentToEdit = _viewToEdit?.Padding ?? null;
+
+ _lblView.Text = $"{_viewToEdit?.GetType ().Name}: {_viewToEdit?.Id}" ?? string.Empty;
}
}
- ///
- /// Gets or sets whether the AdornmentsEditor should automatically select the View to edit when the mouse is clicked
- /// anywhere outside the editor.
- ///
- public bool AutoSelectViewToEdit { get; set; }
+ ///
+ protected override void Dispose (bool disposing)
+ {
+ Diagnostics = _savedDiagnosticFlags;
+ base.Dispose (disposing);
+ }
private void AdornmentsEditor_Initialized (object sender, EventArgs e)
{
BorderStyle = LineStyle.Dotted;
- ExpanderButton expandButton = new ExpanderButton ()
+ var expandButton = new ExpanderButton
{
Orientation = Orientation.Horizontal
};
@@ -76,7 +86,7 @@ public class AdornmentsEditor : View
{
X = 0,
Y = 0,
- Height = 2,
+ Height = 2
};
_lblView.TextFormatter.WordWrap = true;
_lblView.TextFormatter.MultiLine = true;
@@ -113,16 +123,16 @@ public class AdornmentsEditor : View
_diagPaddingCheckBox.State = Diagnostics.FastHasFlags (ViewDiagnosticFlags.Padding) ? CheckState.Checked : CheckState.UnChecked;
_diagPaddingCheckBox.Toggle += (s, e) =>
- {
- if (e.NewValue == CheckState.Checked)
- {
- Diagnostics |= ViewDiagnosticFlags.Padding;
- }
- else
- {
- Diagnostics &= ~ViewDiagnosticFlags.Padding;
- }
- };
+ {
+ if (e.NewValue == CheckState.Checked)
+ {
+ Diagnostics |= ViewDiagnosticFlags.Padding;
+ }
+ else
+ {
+ Diagnostics &= ~ViewDiagnosticFlags.Padding;
+ }
+ };
Add (_diagPaddingCheckBox);
_diagPaddingCheckBox.Y = Pos.Bottom (_paddingEditor);
@@ -131,16 +141,16 @@ public class AdornmentsEditor : View
_diagRulerCheckBox.State = Diagnostics.FastHasFlags (ViewDiagnosticFlags.Ruler) ? CheckState.Checked : CheckState.UnChecked;
_diagRulerCheckBox.Toggle += (s, e) =>
- {
- if (e.NewValue == CheckState.Checked)
- {
- Diagnostics |= ViewDiagnosticFlags.Ruler;
- }
- else
- {
- Diagnostics &= ~ViewDiagnosticFlags.Ruler;
- }
- };
+ {
+ if (e.NewValue == CheckState.Checked)
+ {
+ Diagnostics |= ViewDiagnosticFlags.Ruler;
+ }
+ else
+ {
+ Diagnostics &= ~ViewDiagnosticFlags.Ruler;
+ }
+ };
Add (_diagRulerCheckBox);
_diagRulerCheckBox.Y = Pos.Bottom (_diagPaddingCheckBox);
@@ -154,7 +164,8 @@ public class AdornmentsEditor : View
}
// TODO: Add a setting (property) so only subviews of a specified view are considered.
- var view = e.View;
+ View view = e.View;
+
if (view is { } && e.Flags == MouseFlags.Button1Clicked)
{
if (view is Adornment adornment)
@@ -168,33 +179,20 @@ public class AdornmentsEditor : View
}
}
- ///
- protected override void Dispose (bool disposing)
+ private void ApplicationNavigationOnFocusedChanged (object sender, EventArgs e)
{
- View.Diagnostics = _savedDiagnosticFlags;
- base.Dispose (disposing);
- }
-
- public View ViewToEdit
- {
- get => _viewToEdit;
- set
+ if (ApplicationNavigation.IsInHierarchy (this, Application.Navigation!.GetFocused ()))
{
- if (_viewToEdit == value)
- {
- return;
- }
-
- _viewToEdit = value;
-
-
- _marginEditor.AdornmentToEdit = _viewToEdit?.Margin ?? null;
- _borderEditor.AdornmentToEdit = _viewToEdit?.Border ?? null;
- _paddingEditor.AdornmentToEdit = _viewToEdit?.Padding ?? null;
-
- _lblView.Text = $"{_viewToEdit?.GetType ().Name}: {_viewToEdit?.Id}" ?? string.Empty;
-
return;
}
+
+ if (Application.Navigation!.GetFocused () is Adornment adornment)
+ {
+ ViewToEdit = adornment.Parent;
+ }
+ else
+ {
+ ViewToEdit = Application.Navigation.GetFocused ();
+ }
}
-}
\ No newline at end of file
+}
diff --git a/UnitTests/Application/ApplicationTests.cs b/UnitTests/Application/ApplicationTests.cs
index b84dc8ae8..b0383e986 100644
--- a/UnitTests/Application/ApplicationTests.cs
+++ b/UnitTests/Application/ApplicationTests.cs
@@ -6,8 +6,6 @@ namespace Terminal.Gui.ApplicationTests;
public class ApplicationTests
{
- private readonly ITestOutputHelper _output;
-
public ApplicationTests (ITestOutputHelper output)
{
_output = output;
@@ -19,6 +17,127 @@ public class ApplicationTests
#endif
}
+ private readonly ITestOutputHelper _output;
+
+ private object _timeoutLock;
+
+ [Fact]
+ public void AddTimeout_Fires ()
+ {
+ Assert.Null (_timeoutLock);
+ _timeoutLock = new ();
+
+ uint timeoutTime = 250;
+ var initialized = false;
+ var iteration = 0;
+ var shutdown = false;
+ object timeout = null;
+ var timeoutCount = 0;
+
+ Application.InitializedChanged += OnApplicationOnInitializedChanged;
+
+ Application.Init (new FakeDriver ());
+ Assert.True (initialized);
+ Assert.False (shutdown);
+
+ _output.WriteLine ("Application.Run ().Dispose ()..");
+ Application.Run ().Dispose ();
+ _output.WriteLine ("Back from Application.Run ().Dispose ()");
+
+ Assert.True (initialized);
+ Assert.False (shutdown);
+
+ Assert.Equal (1, timeoutCount);
+ Application.Shutdown ();
+
+ Application.InitializedChanged -= OnApplicationOnInitializedChanged;
+
+ lock (_timeoutLock)
+ {
+ if (timeout is { })
+ {
+ Application.RemoveTimeout (timeout);
+ timeout = null;
+ }
+ }
+
+ Assert.True (initialized);
+ Assert.True (shutdown);
+
+#if DEBUG_IDISPOSABLE
+ Assert.Empty (Responder.Instances);
+#endif
+ lock (_timeoutLock)
+ {
+ _timeoutLock = null;
+ }
+
+ return;
+
+ void OnApplicationOnInitializedChanged (object s, EventArgs a)
+ {
+ if (a.CurrentValue)
+ {
+ Application.Iteration += OnApplicationOnIteration;
+ initialized = true;
+
+ lock (_timeoutLock)
+ {
+ _output.WriteLine ($"Setting timeout for {timeoutTime}ms");
+ timeout = Application.AddTimeout (TimeSpan.FromMilliseconds (timeoutTime), TimeoutCallback);
+ }
+ }
+ else
+ {
+ Application.Iteration -= OnApplicationOnIteration;
+ shutdown = true;
+ }
+ }
+
+ bool TimeoutCallback ()
+ {
+ lock (_timeoutLock)
+ {
+ _output.WriteLine ($"TimeoutCallback. Count: {++timeoutCount}. Application Iteration: {iteration}");
+
+ if (timeout is { })
+ {
+ _output.WriteLine (" Nulling timeout.");
+ timeout = null;
+ }
+ }
+
+ // False means "don't re-do timer and remove it"
+ return false;
+ }
+
+ void OnApplicationOnIteration (object s, IterationEventArgs a)
+ {
+ lock (_timeoutLock)
+ {
+ if (timeoutCount > 0)
+ {
+ _output.WriteLine ($"Iteration #{iteration} - Timeout fired. Calling Application.RequestStop.");
+ Application.RequestStop ();
+
+ return;
+ }
+ }
+
+ iteration++;
+
+ // Simulate a delay
+ Thread.Sleep ((int)timeoutTime / 10);
+
+ // Worst case scenario - something went wrong
+ if (Application.IsInitialized && iteration > 25)
+ {
+ _output.WriteLine ($"Too many iterations ({iteration}): Calling Application.RequestStop.");
+ Application.RequestStop ();
+ }
+ }
+ }
+
[Fact]
public void Begin_Null_Toplevel_Throws ()
{
@@ -194,7 +313,7 @@ public class ApplicationTests
// Internal properties
Assert.False (Application.IsInitialized);
Assert.Equal (Application.GetSupportedCultures (), Application.SupportedCultures);
- Assert.Equal (Application.GetAvailableCulturesFromEmbeddedResources(), Application.SupportedCultures);
+ Assert.Equal (Application.GetAvailableCulturesFromEmbeddedResources (), Application.SupportedCultures);
Assert.False (Application._forceFakeConsole);
Assert.Equal (-1, Application.MainThreadId);
Assert.Empty (Application.TopLevels);
@@ -285,8 +404,8 @@ public class ApplicationTests
[InlineData (typeof (CursesDriver))]
public void Init_Shutdown_Fire_InitializedChanged (Type driverType)
{
- bool initialized = false;
- bool shutdown = false;
+ var initialized = false;
+ var shutdown = false;
Application.InitializedChanged += OnApplicationOnInitializedChanged;
@@ -315,34 +434,6 @@ public class ApplicationTests
}
}
-
- [Fact]
- public void Run_Iteration_Fires ()
- {
- int iteration = 0;
-
- Application.Init (new FakeDriver ());
-
- Application.Iteration += Application_Iteration;
- Application.Run ().Dispose ();
-
- Assert.Equal (1, iteration);
- Application.Shutdown ();
-
- return;
-
- void Application_Iteration (object sender, IterationEventArgs e)
- {
- if (iteration > 0)
- {
- Assert.Fail ();
- }
- iteration++;
- Application.RequestStop ();
- }
- }
-
-
[Fact]
public void Init_Unbalanced_Throws ()
{
@@ -449,6 +540,33 @@ public class ApplicationTests
Application.Shutdown ();
}
+ [Fact]
+ public void Run_Iteration_Fires ()
+ {
+ var iteration = 0;
+
+ Application.Init (new FakeDriver ());
+
+ Application.Iteration += Application_Iteration;
+ Application.Run ().Dispose ();
+
+ Assert.Equal (1, iteration);
+ Application.Shutdown ();
+
+ return;
+
+ void Application_Iteration (object sender, IterationEventArgs e)
+ {
+ if (iteration > 0)
+ {
+ Assert.Fail ();
+ }
+
+ iteration++;
+ Application.RequestStop ();
+ }
+ }
+
[Fact]
[AutoInitShutdown]
public void SetCurrentAsTop_Run_A_Not_Modal_Toplevel_Make_It_The_Current_Application_Top ()
@@ -899,15 +1017,15 @@ public class ApplicationTests
RunState rs = Application.Begin (w);
// Don't use visuals to test as style of border can change over time.
- Assert.Equal (new Point (0, 0), w.Frame.Location);
+ Assert.Equal (new (0, 0), w.Frame.Location);
Application.OnMouseEvent (new () { Flags = MouseFlags.Button1Pressed });
Assert.Equal (w.Border, Application.MouseGrabView);
- Assert.Equal (new Point (0, 0), w.Frame.Location);
+ Assert.Equal (new (0, 0), w.Frame.Location);
// Move down and to the right.
Application.OnMouseEvent (new () { Position = new (1, 1), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition });
- Assert.Equal (new Point (1, 1), w.Frame.Location);
+ Assert.Equal (new (1, 1), w.Frame.Location);
Application.End (rs);
w.Dispose ();
@@ -1042,6 +1160,7 @@ public class ApplicationTests
Assert.Throws (() => Application.Run (new Toplevel ()));
Application.Init (driver);
+
Application.Iteration += (s, e) =>
{
Assert.NotNull (Application.Top);
@@ -1101,123 +1220,4 @@ public class ApplicationTests
}
#endregion
-
-
- private object _timeoutLock;
-
- [Fact]
- public void AddTimeout_Fires ()
- {
- Assert.Null (_timeoutLock);
- _timeoutLock = new object ();
-
- uint timeoutTime = 250;
- bool initialized = false;
- int iteration = 0;
- bool shutdown = false;
- object timeout = null;
- int timeoutCount = 0;
-
- Application.InitializedChanged += OnApplicationOnInitializedChanged;
-
- Application.Init (new FakeDriver ());
- Assert.True (initialized);
- Assert.False (shutdown);
-
- _output.WriteLine ("Application.Run ().Dispose ()..");
- Application.Run ().Dispose ();
- _output.WriteLine ("Back from Application.Run ().Dispose ()");
-
- Assert.True (initialized);
- Assert.False (shutdown);
-
- Assert.Equal (1, timeoutCount);
- Application.Shutdown ();
-
- Application.InitializedChanged -= OnApplicationOnInitializedChanged;
-
- lock (_timeoutLock)
- {
- if (timeout is { })
- {
- Application.RemoveTimeout (timeout);
- timeout = null;
- }
- }
-
- Assert.True (initialized);
- Assert.True (shutdown);
-
-#if DEBUG_IDISPOSABLE
- Assert.Empty (Responder.Instances);
-#endif
- lock (_timeoutLock)
- {
- _timeoutLock = null;
- }
-
- return;
-
- void OnApplicationOnInitializedChanged (object s, EventArgs a)
- {
- if (a.CurrentValue)
- {
- Application.Iteration += OnApplicationOnIteration;
- initialized = true;
-
- lock (_timeoutLock)
- {
- _output.WriteLine ($"Setting timeout for {timeoutTime}ms");
- timeout = Application.AddTimeout (TimeSpan.FromMilliseconds (timeoutTime), TimeoutCallback);
- }
-
- }
- else
- {
- Application.Iteration -= OnApplicationOnIteration;
- shutdown = true;
- }
- }
-
- bool TimeoutCallback ()
- {
- lock (_timeoutLock)
- {
- _output.WriteLine ($"TimeoutCallback. Count: {++timeoutCount}. Application Iteration: {iteration}");
- if (timeout is { })
- {
- _output.WriteLine ($" Nulling timeout.");
- timeout = null;
- }
- }
-
- // False means "don't re-do timer and remove it"
- return false;
- }
-
- void OnApplicationOnIteration (object s, IterationEventArgs a)
- {
- lock (_timeoutLock)
- {
- if (timeoutCount > 0)
- {
- _output.WriteLine ($"Iteration #{iteration} - Timeout fired. Calling Application.RequestStop.");
- Application.RequestStop ();
-
- return;
- }
- }
- iteration++;
-
- // Simulate a delay
- Thread.Sleep ((int)timeoutTime / 10);
-
- // Worst case scenario - something went wrong
- if (Application.IsInitialized && iteration > 25)
- {
- _output.WriteLine ($"Too many iterations ({iteration}): Calling Application.RequestStop.");
- Application.RequestStop ();
- }
- }
- }
}
diff --git a/UnitTests/Dialogs/DialogTests.cs b/UnitTests/Dialogs/DialogTests.cs
index d07b627ee..582cf659a 100644
--- a/UnitTests/Dialogs/DialogTests.cs
+++ b/UnitTests/Dialogs/DialogTests.cs
@@ -26,6 +26,10 @@ public class DialogTests
int width = $@"{CM.Glyphs.VLine} {btn1} {btn2} {CM.Glyphs.VLine}".Length;
d.SetBufferSize (width, 1);
+ // Override CM
+ Dialog.DefaultButtonAlignment = Alignment.Center;
+ Dialog.DefaultBorderStyle = LineStyle.Single;
+
// Default (center)
var dlg = new Dialog
{
@@ -151,6 +155,7 @@ public class DialogTests
int width = buttonRow.Length;
d.SetBufferSize (buttonRow.Length, 3);
+
// Default - Center
(runstate, Dialog dlg) = RunButtonTestDialog (
title,
@@ -874,6 +879,11 @@ public class DialogTests
{
((FakeDriver)Driver).SetBufferSize (20, 5);
+ // Override CM
+ Window.DefaultBorderStyle = LineStyle.Single;
+ Dialog.DefaultButtonAlignment = Alignment.Center;
+ Dialog.DefaultBorderStyle = LineStyle.Single;
+
var win = new Window ();
var iterations = 0;
@@ -889,7 +899,6 @@ public class DialogTests
win.Loaded += (s, a) =>
{
- Dialog.DefaultButtonAlignment = Alignment.Center;
var dlg = new Dialog { Width = 18, Height = 3, Buttons = [new () { Text = "Ok" }] };
dlg.Loaded += (s, a) =>
@@ -975,7 +984,10 @@ public class DialogTests
var win = new Window ();
int iterations = -1;
+
+ // Override CM
Dialog.DefaultButtonAlignment = Alignment.Center;
+ Dialog.DefaultBorderStyle = LineStyle.Single;
Iteration += (s, a) =>
{
@@ -1012,7 +1024,10 @@ public class DialogTests
public void Dialog_Opened_From_Another_Dialog ()
{
((FakeDriver)Driver).SetBufferSize (30, 10);
+
+ // Override CM
Dialog.DefaultButtonAlignment = Alignment.Center;
+ Dialog.DefaultBorderStyle = LineStyle.Single;
var btn1 = new Button { Text = "press me 1" };
Button btn2 = null;
@@ -1159,6 +1174,11 @@ public class DialogTests
[AutoInitShutdown]
public void Location_When_Application_Top_Not_Default ()
{
+ // Override CM
+ Window.DefaultBorderStyle = LineStyle.Single;
+ Dialog.DefaultButtonAlignment = Alignment.Center;
+ Dialog.DefaultBorderStyle = LineStyle.Single;
+
var expected = 5;
var d = new Dialog { X = expected, Y = expected, Height = 5, Width = 5 };
Begin (d);
@@ -1188,6 +1208,11 @@ public class DialogTests
int iterations = -1;
+ // Override CM
+ Window.DefaultBorderStyle = LineStyle.Single;
+ Dialog.DefaultButtonAlignment = Alignment.Center;
+ Dialog.DefaultBorderStyle = LineStyle.Single;
+
Iteration += (s, a) =>
{
iterations++;
@@ -1361,6 +1386,10 @@ public class DialogTests
params Button [] btns
)
{
+ // Override CM
+ Dialog.DefaultButtonAlignment = Alignment.Center;
+ Dialog.DefaultBorderStyle = LineStyle.Single;
+
var dlg = new Dialog
{
Title = title,
diff --git a/UnitTests/Dialogs/MessageBoxTests.cs b/UnitTests/Dialogs/MessageBoxTests.cs
index de94732ad..c4e501f80 100644
--- a/UnitTests/Dialogs/MessageBoxTests.cs
+++ b/UnitTests/Dialogs/MessageBoxTests.cs
@@ -174,6 +174,10 @@ public class MessageBoxTests
var btn =
$"{CM.Glyphs.LeftBracket}{CM.Glyphs.LeftDefaultIndicator} btn {CM.Glyphs.RightDefaultIndicator}{CM.Glyphs.RightBracket}";
+ // Override CM
+ MessageBox.DefaultButtonAlignment = Alignment.End;
+ MessageBox.DefaultBorderStyle = LineStyle.Double;
+
Application.Iteration += (s, a) =>
{
iterations++;
@@ -239,6 +243,10 @@ public class MessageBoxTests
var btn =
$"{CM.Glyphs.LeftBracket}{CM.Glyphs.LeftDefaultIndicator} btn {CM.Glyphs.RightDefaultIndicator}{CM.Glyphs.RightBracket}";
+ // Override CM
+ MessageBox.DefaultButtonAlignment = Alignment.End;
+ MessageBox.DefaultBorderStyle = LineStyle.Double;
+
Application.Iteration += (s, a) =>
{
iterations++;
@@ -415,6 +423,10 @@ public class MessageBoxTests
int iterations = -1;
((FakeDriver)Application.Driver).SetBufferSize (70, 15);
+ // Override CM
+ MessageBox.DefaultButtonAlignment = Alignment.End;
+ MessageBox.DefaultBorderStyle = LineStyle.Double;
+
Application.Iteration += (s, a) =>
{
iterations++;
diff --git a/UnitTests/FileServices/FileDialogTests.cs b/UnitTests/FileServices/FileDialogTests.cs
index 86cb50481..1c0954168 100644
--- a/UnitTests/FileServices/FileDialogTests.cs
+++ b/UnitTests/FileServices/FileDialogTests.cs
@@ -572,6 +572,11 @@ public class FileDialogTests (ITestOutputHelper output)
private FileDialog GetInitializedFileDialog ()
{
+
+ Window.DefaultBorderStyle = LineStyle.Single;
+ Dialog.DefaultButtonAlignment = Alignment.Center;
+ Dialog.DefaultBorderStyle = LineStyle.Single;
+
var dlg = new FileDialog ();
Begin (dlg);
@@ -580,6 +585,10 @@ public class FileDialogTests (ITestOutputHelper output)
private FileDialog GetLinuxDialog ()
{
+ Window.DefaultBorderStyle = LineStyle.Single;
+ Dialog.DefaultButtonAlignment = Alignment.Center;
+ Dialog.DefaultBorderStyle = LineStyle.Single;
+
// Arrange
var fileSystem = new MockFileSystem (new Dictionary (), "/");
fileSystem.MockTime (() => new (2010, 01, 01, 11, 12, 43));
@@ -623,6 +632,11 @@ public class FileDialogTests (ITestOutputHelper output)
private FileDialog GetWindowsDialog ()
{
+ // Override CM
+ Window.DefaultBorderStyle = LineStyle.Single;
+ Dialog.DefaultButtonAlignment = Alignment.Center;
+ Dialog.DefaultBorderStyle = LineStyle.Single;
+
// Arrange
var fileSystem = new MockFileSystem (new Dictionary (), @"c:\");
fileSystem.MockTime (() => new (2010, 01, 01, 11, 12, 43));
diff --git a/UnitTests/Input/KeyBindingTests.cs b/UnitTests/Input/KeyBindingTests.cs
index e78ec5730..9ef3da07e 100644
--- a/UnitTests/Input/KeyBindingTests.cs
+++ b/UnitTests/Input/KeyBindingTests.cs
@@ -4,17 +4,8 @@ namespace Terminal.Gui.InputTests;
public class KeyBindingTests
{
- private readonly ITestOutputHelper _output;
public KeyBindingTests (ITestOutputHelper output) { _output = output; }
-
- [Fact]
- public void Add_No_Commands_Throws ()
- {
- var keyBindings = new KeyBindings ();
- List commands = new ();
- Assert.Throws (() => keyBindings.Add (Key.A, commands.ToArray ()));
-
- }
+ private readonly ITestOutputHelper _output;
[Fact]
public void Add_Invalid_Key_Throws ()
@@ -41,6 +32,14 @@ public class KeyBindingTests
Assert.Contains (Command.Left, resultCommands);
}
+ [Fact]
+ public void Add_No_Commands_Throws ()
+ {
+ var keyBindings = new KeyBindings ();
+ List commands = new ();
+ Assert.Throws (() => keyBindings.Add (Key.A, commands.ToArray ()));
+ }
+
[Fact]
public void Add_Single_Adds ()
{
@@ -54,6 +53,39 @@ public class KeyBindingTests
Assert.Contains (Command.HotKey, resultCommands);
}
+ // Add should not allow duplicates
+ [Fact]
+ public void Add_Throws_If_Exists ()
+ {
+ var keyBindings = new KeyBindings ();
+ keyBindings.Add (Key.A, KeyBindingScope.Application, Command.HotKey);
+ Assert.Throws (() => keyBindings.Add (Key.A, KeyBindingScope.Application, Command.Accept));
+
+ Command [] resultCommands = keyBindings.GetCommands (Key.A);
+ Assert.Contains (Command.HotKey, resultCommands);
+
+ keyBindings = new ();
+ keyBindings.Add (Key.A, KeyBindingScope.Focused, Command.HotKey);
+ Assert.Throws (() => keyBindings.Add (Key.A, KeyBindingScope.Focused, Command.Accept));
+
+ resultCommands = keyBindings.GetCommands (Key.A);
+ Assert.Contains (Command.HotKey, resultCommands);
+
+ keyBindings = new ();
+ keyBindings.Add (Key.A, KeyBindingScope.HotKey, Command.HotKey);
+ Assert.Throws (() => keyBindings.Add (Key.A, KeyBindingScope.Focused, Command.Accept));
+
+ resultCommands = keyBindings.GetCommands (Key.A);
+ Assert.Contains (Command.HotKey, resultCommands);
+
+ keyBindings = new ();
+ keyBindings.Add (Key.A, new KeyBinding (new [] { Command.HotKey }, KeyBindingScope.HotKey));
+ Assert.Throws (() => keyBindings.Add (Key.A, new KeyBinding (new [] { Command.Accept }, KeyBindingScope.HotKey)));
+
+ resultCommands = keyBindings.GetCommands (Key.A);
+ Assert.Contains (Command.HotKey, resultCommands);
+ }
+
// Clear
[Fact]
public void Clear_Clears ()
@@ -74,6 +106,14 @@ public class KeyBindingTests
Assert.Throws (() => keyBindings.GetKeyFromCommands (Command.Accept));
}
+ [Fact]
+ public void Get_Binding_Not_Found_Throws ()
+ {
+ var keyBindings = new KeyBindings ();
+ Assert.Throws (() => keyBindings.Get (Key.A));
+ Assert.Throws (() => keyBindings.Get (Key.B, KeyBindingScope.Application));
+ }
+
// GetCommands
[Fact]
public void GetCommands_Unknown_ReturnsEmpty ()
@@ -168,39 +208,6 @@ public class KeyBindingTests
Assert.Equal (Key.A, resultKey);
}
- // Add should not allow duplicates
- [Fact]
- public void Add_Throws_If_Exists ()
- {
- var keyBindings = new KeyBindings ();
- keyBindings.Add (Key.A, KeyBindingScope.Application, Command.HotKey);
- Assert.Throws (() => keyBindings.Add (Key.A, KeyBindingScope.Application, Command.Accept));
-
- Command [] resultCommands = keyBindings.GetCommands (Key.A);
- Assert.Contains (Command.HotKey, resultCommands);
-
- keyBindings = new ();
- keyBindings.Add (Key.A, KeyBindingScope.Focused, Command.HotKey);
- Assert.Throws (() => keyBindings.Add (Key.A, KeyBindingScope.Focused, Command.Accept));
-
- resultCommands = keyBindings.GetCommands (Key.A);
- Assert.Contains (Command.HotKey, resultCommands);
-
- keyBindings = new ();
- keyBindings.Add (Key.A, KeyBindingScope.HotKey, Command.HotKey);
- Assert.Throws (() => keyBindings.Add (Key.A, KeyBindingScope.Focused, Command.Accept));
-
- resultCommands = keyBindings.GetCommands (Key.A);
- Assert.Contains (Command.HotKey, resultCommands);
-
- keyBindings = new ();
- keyBindings.Add (Key.A, new KeyBinding (new [] { Command.HotKey }, KeyBindingScope.HotKey));
- Assert.Throws (() => keyBindings.Add (Key.A, new KeyBinding (new [] { Command.Accept }, KeyBindingScope.HotKey)));
-
- resultCommands = keyBindings.GetCommands (Key.A);
- Assert.Contains (Command.HotKey, resultCommands);
- }
-
[Fact]
public void ReplaceKey_Replaces ()
{
@@ -227,6 +234,18 @@ public class KeyBindingTests
Assert.Contains (Command.HotKey, keyBindings.GetCommands (Key.H));
}
+ [Fact]
+ public void ReplaceKey_Replaces_Leaves_Old_Binding ()
+ {
+ var keyBindings = new KeyBindings ();
+ keyBindings.Add (Key.A, KeyBindingScope.Application, Command.Accept);
+ keyBindings.Add (Key.B, KeyBindingScope.Application, Command.HotKey);
+
+ keyBindings.ReplaceKey (keyBindings.GetKeyFromCommands (Command.Accept), Key.C);
+ Assert.Empty (keyBindings.GetCommands (Key.A));
+ Assert.Contains (Command.Accept, keyBindings.GetCommands (Key.C));
+ }
+
[Fact]
public void ReplaceKey_Throws_If_DoesNotContain_Old ()
{
@@ -242,20 +261,6 @@ public class KeyBindingTests
Assert.Throws (() => keyBindings.ReplaceKey (Key.A, Key.Empty));
}
- [Fact]
- public void ReplaceKey_Replaces_Leaves_Old_Binding ()
- {
- var keyBindings = new KeyBindings ();
- keyBindings.Add (Key.A, KeyBindingScope.Application, Command.Accept);
- keyBindings.Add (Key.B, KeyBindingScope.Application, Command.HotKey);
-
- keyBindings.ReplaceKey (keyBindings.GetKeyFromCommands(Command.Accept), Key.C);
- Assert.Empty (keyBindings.GetCommands (Key.A));
- Assert.Contains (Command.Accept, keyBindings.GetCommands (Key.C));
-
- }
-
-
// Add with scope does the right things
[Theory]
[InlineData (KeyBindingScope.Focused)]
@@ -301,14 +306,6 @@ public class KeyBindingTests
Assert.Contains (Command.Left, binding.Commands);
}
- [Fact]
- public void Get_Binding_Not_Found_Throws ()
- {
- var keyBindings = new KeyBindings ();
- Assert.Throws (() => keyBindings.Get (Key.A));
- Assert.Throws (() => keyBindings.Get (Key.B, KeyBindingScope.Application));
- }
-
[Theory]
[InlineData (KeyBindingScope.Focused)]
[InlineData (KeyBindingScope.HotKey)]
@@ -355,6 +352,4 @@ public class KeyBindingTests
Assert.True (result);
Assert.Contains (Command.HotKey, bindings.Commands);
}
-
-
}
diff --git a/UnitTests/View/NavigationTests.cs b/UnitTests/View/NavigationTests.cs
index 59245d3c8..488bed57f 100644
--- a/UnitTests/View/NavigationTests.cs
+++ b/UnitTests/View/NavigationTests.cs
@@ -4,6 +4,331 @@ namespace Terminal.Gui.ViewTests;
public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
{
+ [Theory]
+ [MemberData (nameof (AllViewTypes))]
+ public void AllViews_AtLeastOneNavKey_Leaves (Type viewType)
+ {
+ View view = CreateInstanceIfNotGeneric (viewType);
+
+ if (view == null)
+ {
+ _output.WriteLine ($"Ignoring {viewType} - It's a Generic");
+
+ return;
+ }
+
+ if (!view.CanFocus)
+ {
+ _output.WriteLine ($"Ignoring {viewType} - It can't focus.");
+
+ return;
+ }
+
+ Application.Init (new FakeDriver ());
+
+ Toplevel top = new ();
+
+ View otherView = new ()
+ {
+ Id = "otherView",
+ CanFocus = true,
+ TabStop = view.TabStop
+ };
+
+ 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 };
+
+ if (view.TabStop == TabBehavior.TabGroup)
+ {
+ navKeys = new [] { Key.F6, Key.F6.WithShift };
+ }
+
+ var left = false;
+
+ foreach (Key key in navKeys)
+ {
+ switch (view.TabStop)
+ {
+ case TabBehavior.TabStop:
+ case TabBehavior.NoStop:
+ case TabBehavior.TabGroup:
+ Application.OnKeyDown (key);
+
+ break;
+ default:
+ Application.OnKeyDown (Key.Tab);
+
+ break;
+ }
+
+ if (!view.HasFocus)
+ {
+ left = true;
+ _output.WriteLine ($"{view.GetType ().Name} - {key} Left.");
+ view.SetFocus ();
+ }
+ else
+ {
+ _output.WriteLine ($"{view.GetType ().Name} - {key} did not Leave.");
+ }
+ }
+
+ top.Dispose ();
+ Application.Shutdown ();
+
+ Assert.True (left);
+ }
+
+ [Theory]
+ [MemberData (nameof (AllViewTypes))]
+ public void AllViews_Enter_Leave_Events (Type viewType)
+ {
+ View view = CreateInstanceIfNotGeneric (viewType);
+
+ if (view == null)
+ {
+ _output.WriteLine ($"Ignoring {viewType} - It's a Generic");
+
+ return;
+ }
+
+ if (!view.CanFocus)
+ {
+ _output.WriteLine ($"Ignoring {viewType} - It can't focus.");
+
+ return;
+ }
+
+ if (view is Toplevel && ((Toplevel)view).Modal)
+ {
+ _output.WriteLine ($"Ignoring {viewType} - It's a Modal Toplevel");
+
+ return;
+ }
+
+ Application.Init (new FakeDriver ());
+
+ Toplevel top = new ()
+ {
+ Height = 10,
+ Width = 10
+ };
+
+ View otherView = new ()
+ {
+ Id = "otherView",
+ X = 0, Y = 0,
+ Height = 1,
+ Width = 1,
+ CanFocus = true,
+ TabStop = view.TabStop
+ };
+
+ view.X = Pos.Right (otherView);
+ view.Y = 0;
+ view.Width = 10;
+ view.Height = 1;
+
+ var nEnter = 0;
+ var nLeave = 0;
+
+ view.Enter += (s, e) => nEnter++;
+ view.Leave += (s, e) => nLeave++;
+
+ top.Add (view, otherView);
+ Application.Begin (top);
+
+ // Start with the focus on our test view
+ view.SetFocus ();
+
+ //Assert.Equal (1, nEnter);
+ //Assert.Equal (0, nLeave);
+
+ // Use keyboard to navigate to next view (otherView).
+ if (view is TextView)
+ {
+ Application.OnKeyDown (Key.F6);
+ }
+ else
+ {
+ var tries = 0;
+
+ while (view.HasFocus)
+ {
+ if (++tries > 10)
+ {
+ Assert.Fail ($"{view} is not leaving.");
+ }
+
+ switch (view.TabStop)
+ {
+ case TabBehavior.NoStop:
+ Application.OnKeyDown (Key.Tab);
+
+ break;
+ case TabBehavior.TabStop:
+ Application.OnKeyDown (Key.Tab);
+
+ break;
+ case TabBehavior.TabGroup:
+ Application.OnKeyDown (Key.F6);
+
+ break;
+ case null:
+ Application.OnKeyDown (Key.Tab);
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
+ }
+ }
+
+ //Assert.Equal (1, nEnter);
+ //Assert.Equal (1, nLeave);
+
+ //Assert.False (view.HasFocus);
+ //Assert.True (otherView.HasFocus);
+
+ // Now navigate back to our test view
+ switch (view.TabStop)
+ {
+ case TabBehavior.NoStop:
+ view.SetFocus ();
+
+ break;
+ case TabBehavior.TabStop:
+ Application.OnKeyDown (Key.Tab);
+
+ break;
+ case TabBehavior.TabGroup:
+ Application.OnKeyDown (Key.F6);
+
+ break;
+ case null:
+ Application.OnKeyDown (Key.Tab);
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
+
+ // Cache state because Shutdown has side effects.
+ // Also ensures other tests can continue running if there's a fail
+ bool otherViewHasFocus = otherView.HasFocus;
+ bool viewHasFocus = view.HasFocus;
+
+ int enterCount = nEnter;
+ int leaveCount = nLeave;
+
+ top.Dispose ();
+ Application.Shutdown ();
+
+ Assert.False (otherViewHasFocus);
+ Assert.True (viewHasFocus);
+
+ Assert.Equal (2, enterCount);
+ Assert.Equal (1, leaveCount);
+ }
+
+ [Theory]
+ [MemberData (nameof (AllViewTypes))]
+ public void AllViews_Enter_Leave_Events_Visible_False (Type viewType)
+ {
+ View view = CreateInstanceIfNotGeneric (viewType);
+
+ if (view == null)
+ {
+ _output.WriteLine ($"Ignoring {viewType} - It's a Generic");
+
+ return;
+ }
+
+ if (!view.CanFocus)
+ {
+ _output.WriteLine ($"Ignoring {viewType} - It can't focus.");
+
+ return;
+ }
+
+ if (view is Toplevel && ((Toplevel)view).Modal)
+ {
+ _output.WriteLine ($"Ignoring {viewType} - It's a Modal Toplevel");
+
+ return;
+ }
+
+ Application.Init (new FakeDriver ());
+
+ Toplevel top = new ()
+ {
+ Height = 10,
+ Width = 10
+ };
+
+ 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;
+
+ view.Enter += (s, e) => nEnter++;
+ view.Leave += (s, e) => nLeave++;
+
+ 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);
+
+ // 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);
+ }
+
+ Assert.Equal (0, nEnter);
+ Assert.Equal (0, nLeave);
+
+ top.NewKeyDownEvent (Key.Tab);
+
+ Assert.Equal (0, nEnter);
+ Assert.Equal (0, nLeave);
+
+ top.Dispose ();
+ Application.Shutdown ();
+ }
+
[Fact]
public void BringSubviewForward_Subviews_vs_TabIndexes ()
{
@@ -240,6 +565,23 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
Application.Shutdown ();
}
+ [Fact]
+ public void CanFocus_False_Set_HasFocus_To_False ()
+ {
+ var view = new View { CanFocus = true };
+ var view2 = new View { CanFocus = true };
+ view2.Add (view);
+
+ Assert.True (view.CanFocus);
+
+ view.SetFocus ();
+ Assert.True (view.HasFocus);
+
+ view.CanFocus = false;
+ Assert.False (view.CanFocus);
+ Assert.False (view.HasFocus);
+ }
+
[Fact]
public void CanFocus_Set_Changes_TabIndex_And_TabStop ()
{
@@ -283,23 +625,6 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
r.Dispose ();
}
- [Fact]
- public void CanFocus_False_Set_HasFocus_To_False ()
- {
- var view = new View { CanFocus = true };
- var view2 = new View { CanFocus = true };
- view2.Add (view);
-
- Assert.True (view.CanFocus);
-
- view.SetFocus ();
- Assert.True (view.HasFocus);
-
- view.CanFocus = false;
- Assert.False (view.CanFocus);
- Assert.False (view.HasFocus);
- }
-
[Fact]
[AutoInitShutdown]
public void CanFocus_Sets_To_False_On_Single_View_Focus_View_On_Another_Toplevel ()
@@ -443,7 +768,7 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
view.NewKeyDownEvent (Key.Space);
Assert.True (wasClicked);
- view.NewMouseEvent (new MouseEvent { Flags = MouseFlags.Button1Clicked });
+ view.NewMouseEvent (new() { Flags = MouseFlags.Button1Clicked });
Assert.False (wasClicked);
Assert.True (view.Enabled);
Assert.True (view.CanFocus);
@@ -452,7 +777,7 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
view.Enabled = false;
view.NewKeyDownEvent (Key.Space);
Assert.False (wasClicked);
- view.NewMouseEvent (new MouseEvent { Flags = MouseFlags.Button1Clicked });
+ view.NewMouseEvent (new() { Flags = MouseFlags.Button1Clicked });
Assert.False (wasClicked);
Assert.False (view.Enabled);
Assert.True (view.CanFocus);
@@ -482,7 +807,7 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
win.NewKeyDownEvent (Key.Enter);
Assert.True (wasClicked);
- button.NewMouseEvent (new MouseEvent { Flags = MouseFlags.Button1Clicked });
+ button.NewMouseEvent (new() { Flags = MouseFlags.Button1Clicked });
Assert.False (wasClicked);
Assert.True (button.Enabled);
Assert.True (button.CanFocus);
@@ -494,7 +819,7 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
win.Enabled = false;
button.NewKeyDownEvent (Key.Enter);
Assert.False (wasClicked);
- button.NewMouseEvent (new MouseEvent { Flags = MouseFlags.Button1Clicked });
+ button.NewMouseEvent (new() { Flags = MouseFlags.Button1Clicked });
Assert.False (wasClicked);
Assert.False (button.Enabled);
Assert.True (button.CanFocus);
@@ -523,6 +848,22 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
top.Dispose ();
}
+ // View.Focused & View.MostFocused tests
+
+ // View.Focused - No subviews
+ [Fact]
+ [Trait ("BUGBUG", "Fix in Issue #3444")]
+ public void Focused_NoSubviews ()
+ {
+ var view = new View ();
+ Assert.Null (view.Focused);
+
+ view.CanFocus = true;
+ view.SetFocus ();
+ Assert.True (view.HasFocus);
+ Assert.Null (view.Focused); // BUGBUG: Should be view
+ }
+
[Fact]
[AutoInitShutdown]
public void FocusNearestView_Ensure_Focus_Ordered ()
@@ -586,7 +927,7 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
if (!removed)
{
removed = true;
- view3 = new View { Id = "view3", Y = 1, Width = 10, Height = 5 };
+ view3 = new() { Id = "view3", Y = 1, Width = 10, Height = 5 };
Application.Current.Add (view3);
Application.Current.BringSubviewToFront (view3);
Assert.False (view3.HasFocus);
@@ -623,6 +964,20 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
top1.Dispose ();
}
+ // View.MostFocused - No subviews
+ [Fact]
+ [Trait ("BUGBUG", "Fix in Issue #3444")]
+ public void Most_Focused_NoSubviews ()
+ {
+ var view = new View ();
+ Assert.Null (view.Focused);
+
+ view.CanFocus = true;
+ view.SetFocus ();
+ Assert.True (view.HasFocus);
+ Assert.Null (view.MostFocused); // BUGBUG: Should be view
+ }
+
// [Fact]
// [AutoInitShutdown]
// public void HotKey_Will_Invoke_KeyPressed_Only_For_The_MostFocused_With_Top_KeyPress_Event ()
@@ -763,7 +1118,7 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
top.Ready += (s, e) => { Assert.Null (top.Focused); };
// Keyboard navigation with tab
- FakeConsole.MockKeyPresses.Push (new ConsoleKeyInfo ('\t', ConsoleKey.Tab, false, false, false));
+ FakeConsole.MockKeyPresses.Push (new ('\t', ConsoleKey.Tab, false, false, false));
Application.Iteration += (s, a) => Application.RequestStop ();
@@ -833,13 +1188,13 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
Application.Begin (top);
Assert.Equal (Application.Current, top);
- Assert.Equal (new Rectangle (0, 0, 80, 25), new Rectangle (0, 0, View.Driver.Cols, View.Driver.Rows));
- Assert.Equal (new Rectangle (0, 0, View.Driver.Cols, View.Driver.Rows), top.Frame);
- Assert.Equal (new Rectangle (0, 0, 80, 25), top.Frame);
+ Assert.Equal (new (0, 0, 80, 25), new Rectangle (0, 0, View.Driver.Cols, View.Driver.Rows));
+ Assert.Equal (new (0, 0, View.Driver.Cols, View.Driver.Rows), top.Frame);
+ Assert.Equal (new (0, 0, 80, 25), top.Frame);
((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
- Assert.Equal (new Rectangle (0, 0, View.Driver.Cols, View.Driver.Rows), top.Frame);
- Assert.Equal (new Rectangle (0, 0, 20, 10), top.Frame);
+ Assert.Equal (new (0, 0, View.Driver.Cols, View.Driver.Rows), top.Frame);
+ Assert.Equal (new (0, 0, 20, 10), top.Frame);
_ = TestHelpers.AssertDriverContentsWithFrameAre (
@"
@@ -858,7 +1213,7 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
// top
Assert.Equal (Point.Empty, top.ScreenToFrame (new (0, 0)));
- var screen = top.Margin.ViewportToScreen (new Point (0, 0));
+ Point screen = top.Margin.ViewportToScreen (new Point (0, 0));
Assert.Equal (0, screen.X);
Assert.Equal (0, screen.Y);
screen = top.Border.ViewportToScreen (new Point (0, 0));
@@ -878,24 +1233,27 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
Assert.Equal (0, found.Frame.X);
Assert.Equal (0, found.Frame.Y);
- Assert.Equal (new Point (3, 2), top.ScreenToFrame (new (3, 2)));
+ Assert.Equal (new (3, 2), top.ScreenToFrame (new (3, 2)));
screen = top.ViewportToScreen (new Point (3, 2));
Assert.Equal (4, screen.X);
Assert.Equal (3, screen.Y);
found = View.FindDeepestView (top, new (screen.X, screen.Y));
Assert.Equal (view, found);
+
//Assert.Equal (0, found.FrameToScreen ().X);
//Assert.Equal (0, found.FrameToScreen ().Y);
found = View.FindDeepestView (top, new (3, 2));
Assert.Equal (top, found);
+
//Assert.Equal (3, found.FrameToScreen ().X);
//Assert.Equal (2, found.FrameToScreen ().Y);
- Assert.Equal (new Point (13, 2), top.ScreenToFrame (new (13, 2)));
+ Assert.Equal (new (13, 2), top.ScreenToFrame (new (13, 2)));
screen = top.ViewportToScreen (new Point (12, 2));
Assert.Equal (13, screen.X);
Assert.Equal (3, screen.Y);
found = View.FindDeepestView (top, new (screen.X, screen.Y));
Assert.Equal (view, found);
+
//Assert.Equal (9, found.FrameToScreen ().X);
//Assert.Equal (0, found.FrameToScreen ().Y);
screen = top.ViewportToScreen (new Point (13, 2));
@@ -903,19 +1261,21 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
Assert.Equal (3, screen.Y);
found = View.FindDeepestView (top, new (13, 2));
Assert.Equal (top, found);
+
//Assert.Equal (13, found.FrameToScreen ().X);
//Assert.Equal (2, found.FrameToScreen ().Y);
- Assert.Equal (new Point (14, 3), top.ScreenToFrame (new (14, 3)));
+ Assert.Equal (new (14, 3), top.ScreenToFrame (new (14, 3)));
screen = top.ViewportToScreen (new Point (14, 3));
Assert.Equal (15, screen.X);
Assert.Equal (4, screen.Y);
found = View.FindDeepestView (top, new (14, 3));
Assert.Equal (top, found);
+
//Assert.Equal (14, found.FrameToScreen ().X);
//Assert.Equal (3, found.FrameToScreen ().Y);
// view
- Assert.Equal (new Point (-4, -3), view.ScreenToFrame (new (0, 0)));
+ Assert.Equal (new (-4, -3), view.ScreenToFrame (new (0, 0)));
screen = view.Margin.ViewportToScreen (new Point (-3, -2));
Assert.Equal (1, screen.X);
Assert.Equal (1, screen.Y);
@@ -934,21 +1294,21 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
found = View.FindDeepestView (top, new (0, 0));
Assert.Equal (top.Border, found);
- Assert.Equal (new Point (-1, -1), view.ScreenToFrame (new (3, 2)));
+ Assert.Equal (new (-1, -1), view.ScreenToFrame (new (3, 2)));
screen = view.ViewportToScreen (new Point (0, 0));
Assert.Equal (4, screen.X);
Assert.Equal (3, screen.Y);
found = View.FindDeepestView (top, new (4, 3));
Assert.Equal (view, found);
- Assert.Equal (new Point (9, -1), view.ScreenToFrame (new (13, 2)));
+ Assert.Equal (new (9, -1), view.ScreenToFrame (new (13, 2)));
screen = view.ViewportToScreen (new Point (10, 0));
Assert.Equal (14, screen.X);
Assert.Equal (3, screen.Y);
found = View.FindDeepestView (top, new (14, 3));
Assert.Equal (top, found);
- Assert.Equal (new Point (10, 0), view.ScreenToFrame (new (14, 3)));
+ Assert.Equal (new (10, 0), view.ScreenToFrame (new (14, 3)));
screen = view.ViewportToScreen (new Point (11, 1));
Assert.Equal (15, screen.X);
Assert.Equal (4, screen.Y);
@@ -983,17 +1343,17 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
Application.Begin (top);
Assert.Equal (Application.Current, top);
- Assert.Equal (new Rectangle (0, 0, 80, 25), new Rectangle (0, 0, View.Driver.Cols, View.Driver.Rows));
- Assert.NotEqual (new Rectangle (0, 0, View.Driver.Cols, View.Driver.Rows), top.Frame);
- Assert.Equal (new Rectangle (3, 2, 20, 10), top.Frame);
+ Assert.Equal (new (0, 0, 80, 25), new Rectangle (0, 0, View.Driver.Cols, View.Driver.Rows));
+ Assert.NotEqual (new (0, 0, View.Driver.Cols, View.Driver.Rows), top.Frame);
+ Assert.Equal (new (3, 2, 20, 10), top.Frame);
((FakeDriver)Application.Driver!).SetBufferSize (30, 20);
- Assert.Equal (new Rectangle (0, 0, 30, 20), new Rectangle (0, 0, View.Driver.Cols, View.Driver.Rows));
- Assert.NotEqual (new Rectangle (0, 0, View.Driver.Cols, View.Driver.Rows), top.Frame);
- Assert.Equal (new Rectangle (3, 2, 20, 10), top.Frame);
+ Assert.Equal (new (0, 0, 30, 20), new Rectangle (0, 0, View.Driver.Cols, View.Driver.Rows));
+ Assert.NotEqual (new (0, 0, View.Driver.Cols, View.Driver.Rows), top.Frame);
+ Assert.Equal (new (3, 2, 20, 10), top.Frame);
Rectangle frame = TestHelpers.AssertDriverContentsWithFrameAre (
- @"
+ @"
┌──────────────────┐
│ │
│ │
@@ -1004,16 +1364,16 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
│ │
│ │
└──────────────────┘",
- _output
- );
+ _output
+ );
// mean the output started at col 3 and line 2
// which result with a width of 23 and a height of 10 on the output
- Assert.Equal (new Rectangle (3, 2, 23, 10), frame);
+ Assert.Equal (new (3, 2, 23, 10), frame);
// top
- Assert.Equal (new Point (-3, -2), top.ScreenToFrame (new (0, 0)));
- var screen = top.Margin.ViewportToScreen (new Point (-3, -2));
+ Assert.Equal (new (-3, -2), top.ScreenToFrame (new (0, 0)));
+ Point screen = top.Margin.ViewportToScreen (new Point (-3, -2));
Assert.Equal (0, screen.X);
Assert.Equal (0, screen.Y);
screen = top.Border.ViewportToScreen (new Point (-3, -2));
@@ -1035,23 +1395,25 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
Assert.Equal (4, screen.X);
Assert.Equal (3, screen.Y);
Assert.Equal (top.Border, View.FindDeepestView (top, new (3, 2)));
+
//Assert.Equal (0, found.FrameToScreen ().X);
//Assert.Equal (0, found.FrameToScreen ().Y);
- Assert.Equal (new Point (10, 0), top.ScreenToFrame (new (13, 2)));
+ Assert.Equal (new (10, 0), top.ScreenToFrame (new (13, 2)));
screen = top.ViewportToScreen (new Point (10, 0));
Assert.Equal (14, screen.X);
Assert.Equal (3, screen.Y);
Assert.Equal (top.Border, View.FindDeepestView (top, new (13, 2)));
+
//Assert.Equal (10, found.FrameToScreen ().X);
//Assert.Equal (0, found.FrameToScreen ().Y);
- Assert.Equal (new Point (11, 1), top.ScreenToFrame (new (14, 3)));
+ Assert.Equal (new (11, 1), top.ScreenToFrame (new (14, 3)));
screen = top.ViewportToScreen (new Point (11, 1));
Assert.Equal (15, screen.X);
Assert.Equal (4, screen.Y);
Assert.Equal (top, View.FindDeepestView (top, new (14, 3)));
// view
- Assert.Equal (new Point (-7, -5), view.ScreenToFrame (new (0, 0)));
+ Assert.Equal (new (-7, -5), view.ScreenToFrame (new (0, 0)));
screen = view.Margin.ViewportToScreen (new Point (-6, -4));
Assert.Equal (1, screen.X);
Assert.Equal (1, screen.Y);
@@ -1065,27 +1427,27 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
Assert.Equal (1, screen.X);
Assert.Equal (1, screen.Y);
Assert.Null (View.FindDeepestView (top, new (1, 1)));
- Assert.Equal (new Point (-4, -3), view.ScreenToFrame (new (3, 2)));
+ Assert.Equal (new (-4, -3), view.ScreenToFrame (new (3, 2)));
screen = view.ViewportToScreen (new Point (-3, -2));
Assert.Equal (4, screen.X);
Assert.Equal (3, screen.Y);
Assert.Equal (top, View.FindDeepestView (top, new (4, 3)));
- Assert.Equal (new Point (-1, -1), view.ScreenToFrame (new (6, 4)));
+ Assert.Equal (new (-1, -1), view.ScreenToFrame (new (6, 4)));
screen = view.ViewportToScreen (new Point (0, 0));
Assert.Equal (7, screen.X);
Assert.Equal (5, screen.Y);
Assert.Equal (view, View.FindDeepestView (top, new (7, 5)));
- Assert.Equal (new Point (6, -1), view.ScreenToFrame (new (13, 4)));
+ Assert.Equal (new (6, -1), view.ScreenToFrame (new (13, 4)));
screen = view.ViewportToScreen (new Point (7, 0));
Assert.Equal (14, screen.X);
Assert.Equal (5, screen.Y);
Assert.Equal (view, View.FindDeepestView (top, new (14, 5)));
- Assert.Equal (new Point (7, -2), view.ScreenToFrame (new (14, 3)));
+ Assert.Equal (new (7, -2), view.ScreenToFrame (new (14, 3)));
screen = view.ViewportToScreen (new Point (8, -1));
Assert.Equal (15, screen.X);
Assert.Equal (4, screen.Y);
Assert.Equal (top, View.FindDeepestView (top, new (15, 4)));
- Assert.Equal (new Point (16, -2), view.ScreenToFrame (new (23, 3)));
+ Assert.Equal (new (16, -2), view.ScreenToFrame (new (23, 3)));
screen = view.ViewportToScreen (new Point (17, -1));
Assert.Equal (24, screen.X);
Assert.Equal (4, screen.Y);
@@ -1211,6 +1573,80 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
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 ()
{
@@ -1299,117 +1735,23 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
}
[Fact]
- public void TabIndex_Invert_Order ()
+ public void TabStop_And_CanFocus_Are_All_True ()
{
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 };
+ 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 = 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 TabStop_NoStop_Prevents_Stop ()
- {
- var r = new View ();
- var v1 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
- var v2 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
- var v3 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
-
- r.Add (v1, v2, v3);
-
- r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
- Assert.False (v1.HasFocus);
- Assert.False (v2.HasFocus);
- Assert.False (v3.HasFocus);
- }
-
- [Fact]
- public void TabStop_NoStop_Change_Enables_Stop ()
- {
- var r = new View ();
- var v1 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
- var v2 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
- var v3 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
-
- r.Add (v1, v2, v3);
-
- v1.TabStop = TabBehavior.TabStop;
r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
Assert.True (v1.HasFocus);
Assert.False (v2.HasFocus);
Assert.False (v3.HasFocus);
-
- v2.TabStop = TabBehavior.TabStop;
r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
Assert.False (v1.HasFocus);
Assert.True (v2.HasFocus);
Assert.False (v3.HasFocus);
-
- v3.TabStop = TabBehavior.TabStop;
r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
Assert.False (v1.HasFocus);
Assert.False (v2.HasFocus);
@@ -1417,6 +1759,41 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
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 TabStop_And_CanFocus_Mixed ()
+ {
+ var r = new View ();
+ var v1 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
+ var v2 = new View { CanFocus = false, TabStop = TabBehavior.TabStop };
+ var v3 = new View { CanFocus = false, TabStop = TabBehavior.NoStop };
+
+ r.Add (v1, v2, v3);
+
+ r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
+ Assert.False (v1.HasFocus);
+ Assert.False (v2.HasFocus);
+ Assert.False (v3.HasFocus);
+ r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
+ Assert.False (v1.HasFocus);
+ Assert.False (v2.HasFocus);
+ Assert.False (v3.HasFocus);
+ r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
+ Assert.False (v1.HasFocus);
+ Assert.False (v2.HasFocus);
+ Assert.False (v3.HasFocus);
+ r.Dispose ();
+ }
+
[Theory]
[CombinatorialData]
public void TabStop_Change_CanFocus_Works ([CombinatorialValues (TabBehavior.NoStop, TabBehavior.TabStop, TabBehavior.TabGroup)] TabBehavior behavior)
@@ -1459,56 +1836,6 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
r.Dispose ();
}
- [Fact]
- public void TabStop_And_CanFocus_Are_All_True ()
- {
- 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.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
- Assert.True (v1.HasFocus);
- Assert.False (v2.HasFocus);
- Assert.False (v3.HasFocus);
- r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
- Assert.False (v1.HasFocus);
- Assert.True (v2.HasFocus);
- Assert.False (v3.HasFocus);
- r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
- Assert.False (v1.HasFocus);
- Assert.False (v2.HasFocus);
- Assert.True (v3.HasFocus);
- r.Dispose ();
- }
-
- [Fact]
- public void TabStop_And_CanFocus_Mixed ()
- {
- var r = new View ();
- var v1 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
- var v2 = new View { CanFocus = false, TabStop = TabBehavior.TabStop };
- var v3 = new View { CanFocus = false, TabStop = TabBehavior.NoStop };
-
- r.Add (v1, v2, v3);
-
- r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
- Assert.False (v1.HasFocus);
- Assert.False (v2.HasFocus);
- Assert.False (v3.HasFocus);
- r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
- Assert.False (v1.HasFocus);
- Assert.False (v2.HasFocus);
- Assert.False (v3.HasFocus);
- r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
- Assert.False (v1.HasFocus);
- Assert.False (v2.HasFocus);
- Assert.False (v3.HasFocus);
- r.Dispose ();
- }
-
[Fact]
public void TabStop_NoStop_And_CanFocus_True_No_Focus ()
{
@@ -1534,6 +1861,52 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
r.Dispose ();
}
+ [Fact]
+ public void TabStop_NoStop_Change_Enables_Stop ()
+ {
+ var r = new View ();
+ var v1 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
+ var v2 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
+ var v3 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
+
+ r.Add (v1, v2, v3);
+
+ v1.TabStop = TabBehavior.TabStop;
+ r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
+ Assert.True (v1.HasFocus);
+ Assert.False (v2.HasFocus);
+ Assert.False (v3.HasFocus);
+
+ v2.TabStop = TabBehavior.TabStop;
+ r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
+ Assert.False (v1.HasFocus);
+ Assert.True (v2.HasFocus);
+ Assert.False (v3.HasFocus);
+
+ v3.TabStop = TabBehavior.TabStop;
+ r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
+ Assert.False (v1.HasFocus);
+ Assert.False (v2.HasFocus);
+ Assert.True (v3.HasFocus);
+ r.Dispose ();
+ }
+
+ [Fact]
+ public void TabStop_NoStop_Prevents_Stop ()
+ {
+ var r = new View ();
+ var v1 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
+ var v2 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
+ var v3 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
+
+ r.Add (v1, v2, v3);
+
+ r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
+ Assert.False (v1.HasFocus);
+ Assert.False (v2.HasFocus);
+ Assert.False (v3.HasFocus);
+ }
+
[Fact]
public void TabStop_Null_And_CanFocus_False_No_Advance ()
{
@@ -1561,16 +1934,6 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
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 (Skip = "Causes crash on Ubuntu in Github Action. Bogus test anyway.")]
public void WindowDispose_CanFocusProblem ()
{
@@ -1591,348 +1954,4 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews
// Assert does Not throw NullReferenceException
top.SetFocus ();
}
-
- // View.Focused & View.MostFocused tests
-
- // View.Focused - No subviews
- [Fact, Trait ("BUGBUG", "Fix in Issue #3444")]
- public void Focused_NoSubviews ()
- {
- var view = new View ();
- Assert.Null (view.Focused);
-
- view.CanFocus = true;
- view.SetFocus ();
- Assert.True (view.HasFocus);
- Assert.Null (view.Focused); // BUGBUG: Should be view
- }
-
- // View.MostFocused - No subviews
- [Fact, Trait ("BUGBUG", "Fix in Issue #3444")]
- public void Most_Focused_NoSubviews ()
- {
- var view = new View ();
- Assert.Null (view.Focused);
-
- view.CanFocus = true;
- view.SetFocus ();
- Assert.True (view.HasFocus);
- Assert.Null (view.MostFocused); // BUGBUG: Should be view
- }
-
-
- [Theory]
- [MemberData (nameof (AllViewTypes))]
-
- public void AllViews_Enter_Leave_Events (Type viewType)
- {
- var view = CreateInstanceIfNotGeneric (viewType);
-
- if (view == null)
- {
- _output.WriteLine ($"Ignoring {viewType} - It's a Generic");
- return;
- }
-
- if (!view.CanFocus)
- {
- _output.WriteLine ($"Ignoring {viewType} - It can't focus.");
-
- return;
- }
-
- if (view is Toplevel && ((Toplevel)view).Modal)
- {
- _output.WriteLine ($"Ignoring {viewType} - It's a Modal Toplevel");
-
- return;
- }
-
- Application.Init (new FakeDriver ());
-
- Toplevel top = new ()
- {
- Height = 10,
- Width = 10
- };
-
- View otherView = new ()
- {
- Id = "otherView",
- X = 0, Y = 0,
- Height = 1,
- Width = 1,
- CanFocus = true,
- TabStop = view.TabStop
- };
-
- view.X = Pos.Right (otherView);
- view.Y = 0;
- view.Width = 10;
- view.Height = 1;
-
- var nEnter = 0;
- var nLeave = 0;
-
- view.Enter += (s, e) => nEnter++;
- view.Leave += (s, e) => nLeave++;
-
- top.Add (view, otherView);
- Application.Begin (top);
-
- // Start with the focus on our test view
- view.SetFocus ();
-
- //Assert.Equal (1, nEnter);
- //Assert.Equal (0, nLeave);
-
- // Use keyboard to navigate to next view (otherView).
- if (view is TextView)
- {
- Application.OnKeyDown (Key.F6);
- }
- else
- {
- int tries = 0;
- while (view.HasFocus)
- {
- if (++tries > 10)
- {
- Assert.Fail ($"{view} is not leaving.");
- }
-
- switch (view.TabStop)
- {
- case TabBehavior.NoStop:
- Application.OnKeyDown (Key.Tab);
- break;
- case TabBehavior.TabStop:
- Application.OnKeyDown (Key.Tab);
- break;
- case TabBehavior.TabGroup:
- Application.OnKeyDown (Key.F6);
- break;
- case null:
- Application.OnKeyDown (Key.Tab);
- break;
- default:
- throw new ArgumentOutOfRangeException ();
- }
- }
- }
-
- //Assert.Equal (1, nEnter);
- //Assert.Equal (1, nLeave);
-
- //Assert.False (view.HasFocus);
- //Assert.True (otherView.HasFocus);
-
- // Now navigate back to our test view
- switch (view.TabStop)
- {
- case TabBehavior.NoStop:
- view.SetFocus ();
- break;
- case TabBehavior.TabStop:
- Application.OnKeyDown (Key.Tab);
- break;
- case TabBehavior.TabGroup:
- Application.OnKeyDown (Key.F6);
- break;
- case null:
- Application.OnKeyDown (Key.Tab);
- break;
- default:
- throw new ArgumentOutOfRangeException ();
- }
-
- // Cache state because Shutdown has side effects.
- // Also ensures other tests can continue running if there's a fail
- bool otherViewHasFocus = otherView.HasFocus;
- bool viewHasFocus = view.HasFocus;
-
- int enterCount = nEnter;
- int leaveCount = nLeave;
-
- top.Dispose ();
- Application.Shutdown ();
-
- Assert.False (otherViewHasFocus);
- Assert.True (viewHasFocus);
-
- Assert.Equal (2, enterCount);
- Assert.Equal (1, leaveCount);
- }
-
-
- [Theory]
- [MemberData (nameof (AllViewTypes))]
-
- public void AllViews_Enter_Leave_Events_Visible_False (Type viewType)
- {
- var view = CreateInstanceIfNotGeneric (viewType);
-
- if (view == null)
- {
- _output.WriteLine ($"Ignoring {viewType} - It's a Generic");
- return;
- }
-
- if (!view.CanFocus)
- {
- _output.WriteLine ($"Ignoring {viewType} - It can't focus.");
-
- return;
- }
-
- if (view is Toplevel && ((Toplevel)view).Modal)
- {
- _output.WriteLine ($"Ignoring {viewType} - It's a Modal Toplevel");
-
- return;
- }
-
- Application.Init (new FakeDriver ());
-
- Toplevel top = new ()
- {
- Height = 10,
- Width = 10
- };
-
- 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;
-
- view.Enter += (s, e) => nEnter++;
- view.Leave += (s, e) => nLeave++;
-
- 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);
-
- // 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);
- }
-
- Assert.Equal (0, nEnter);
- Assert.Equal (0, nLeave);
-
- top.NewKeyDownEvent (Key.Tab);
-
- Assert.Equal (0, nEnter);
- Assert.Equal (0, nLeave);
-
- top.Dispose ();
- Application.Shutdown ();
- }
-
-
- [Theory]
- [MemberData (nameof (AllViewTypes))]
- public void AllViews_AtLeastOneNavKey_Leaves (Type viewType)
- {
- var view = CreateInstanceIfNotGeneric (viewType);
-
- if (view == null)
- {
- _output.WriteLine ($"Ignoring {viewType} - It's a Generic");
- return;
- }
-
- if (!view.CanFocus)
- {
- _output.WriteLine ($"Ignoring {viewType} - It can't focus.");
-
- return;
- }
-
- Application.Init (new FakeDriver ());
-
- Toplevel top = new ();
-
- View otherView = new ()
- {
- Id = "otherView",
- CanFocus = true,
- TabStop = view.TabStop
- };
-
- top.Add (view, otherView);
- Application.Begin (top);
-
- // Start with the focus on our test view
- view.SetFocus ();
-
- Key [] navKeys = new Key [] { Key.Tab, Key.Tab.WithShift, Key.CursorUp, Key.CursorDown, Key.CursorLeft, Key.CursorRight };
-
- if (view.TabStop == TabBehavior.TabGroup)
- {
- navKeys = new Key [] { Key.F6, Key.F6.WithShift };
- }
-
- bool left = false;
-
- foreach (Key key in navKeys)
- {
- switch (view.TabStop)
- {
- case TabBehavior.TabStop:
- case TabBehavior.NoStop:
- case TabBehavior.TabGroup:
- Application.OnKeyDown (key);
- break;
- default:
- Application.OnKeyDown (Key.Tab);
-
- break;
- }
-
- if (!view.HasFocus)
- {
- left = true;
- _output.WriteLine ($"{view.GetType ().Name} - {key} Left.");
- view.SetFocus();
- }
- else
- {
- _output.WriteLine ($"{view.GetType ().Name} - {key} did not Leave.");
- }
- }
- top.Dispose ();
- Application.Shutdown ();
-
- Assert.True (left);
- }
}
diff --git a/UnitTests/Views/MenuBarTests.cs b/UnitTests/Views/MenuBarTests.cs
index 76598902c..e8d5ad3dc 100644
--- a/UnitTests/Views/MenuBarTests.cs
+++ b/UnitTests/Views/MenuBarTests.cs
@@ -358,6 +358,11 @@ public class MenuBarTests (ITestOutputHelper output)
[AutoInitShutdown]
public void Draw_A_Menu_Over_A_Dialog ()
{
+ // Override CM
+ Window.DefaultBorderStyle = LineStyle.Single;
+ Dialog.DefaultButtonAlignment = Alignment.Center;
+ Dialog.DefaultBorderStyle = LineStyle.Single;
+
Toplevel top = new ();
var win = new Window ();
top.Add (win);
@@ -586,7 +591,12 @@ public class MenuBarTests (ITestOutputHelper output)
[AutoInitShutdown]
public void Draw_A_Menu_Over_A_Top_Dialog ()
{
- ((FakeDriver)Application.Driver!).SetBufferSize (40, 15);
+ // Override CM
+ Window.DefaultBorderStyle = LineStyle.Single;
+ Dialog.DefaultButtonAlignment = Alignment.Center;
+ Dialog.DefaultBorderStyle = LineStyle.Single;
+
+ ((FakeDriver)Application.Driver).SetBufferSize (40, 15);
Assert.Equal (new (0, 0, 40, 15), Application.Driver?.Clip);
TestHelpers.AssertDriverContentsWithFrameAre (@"", output);