浏览代码

Merged with v2_develop.
Code cleanup

Tig 1 年之前
父节点
当前提交
9865f72801

+ 73 - 79
Terminal.Gui/Application/Application.cs

@@ -26,6 +26,79 @@ public static partial class Application
     /// <summary>Gets all cultures supported by the application without the invariant language.</summary>
     public static List<CultureInfo>? SupportedCultures { get; private set; }
 
+    /// <summary>
+    ///     Gets a string representation of the Application as rendered by <see cref="Driver"/>.
+    /// </summary>
+    /// <returns>A string representation of the Application </returns>
+    public new static string ToString ()
+    {
+        ConsoleDriver driver = Driver;
+
+        if (driver is null)
+        {
+            return string.Empty;
+        }
+
+        return ToString (driver);
+    }
+
+    /// <summary>
+    ///     Gets a string representation of the Application rendered by the provided <see cref="ConsoleDriver"/>.
+    /// </summary>
+    /// <param name="driver">The driver to use to render the contents.</param>
+    /// <returns>A string representation of the Application </returns>
+    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<CultureInfo> 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<CultureInfo> GetSupportedCultures ()
     {
         CultureInfo [] cultures = CultureInfo.GetCultures (CultureTypes.AllCultures);
@@ -54,20 +127,6 @@ public static partial class Application
         return GetAvailableCulturesFromEmbeddedResources ();
     }
 
-    internal static List<CultureInfo> 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
-
-    /// <summary>
-    ///     Gets a string representation of the Application as rendered by <see cref="Driver"/>.
-    /// </summary>
-    /// <returns>A string representation of the Application </returns>
-    public new static string ToString ()
-    {
-        ConsoleDriver driver = Driver;
-
-        if (driver is null)
-        {
-            return string.Empty;
-        }
-
-        return ToString (driver);
-    }
-
-    /// <summary>
-    ///     Gets a string representation of the Application rendered by the provided <see cref="ConsoleDriver"/>.
-    /// </summary>
-    /// <param name="driver">The driver to use to render the contents.</param>
-    /// <returns>A string representation of the Application </returns>
-    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 ();
-    }
 }

+ 63 - 65
Terminal.Gui/Input/KeyBindings.cs

@@ -1,12 +1,9 @@
 #nullable enable
 
-using System.Diagnostics;
-using Microsoft.CodeAnalysis;
-
 namespace Terminal.Gui;
 
 /// <summary>
-/// Provides a collection of <see cref="KeyBinding"/> objects bound to a <see cref="Key"/>.
+///     Provides a collection of <see cref="KeyBinding"/> objects bound to a <see cref="Key"/>.
 /// </summary>
 public class KeyBindings
 {
@@ -19,19 +16,6 @@ public class KeyBindings
     /// <summary>Initializes a new instance bound to <paramref name="boundView"/>.</summary>
     public KeyBindings (View boundView) { BoundView = boundView; }
 
-    /// <summary>
-    ///     The view that the <see cref="KeyBindings"/> are bound to.
-    /// </summary>
-    /// <remarks>
-    ///     If <see langword="null"/>, the <see cref="KeyBindings"/> are not bound to a <see cref="View"/>. This is used for Application.KeyBindings.
-    /// </remarks>
-    public View? BoundView { get; }
-
-    // TODO: Add a dictionary comparer that ignores Scope
-    // TODO: This should not be public!
-    /// <summary>The collection of <see cref="KeyBinding"/> objects.</summary>
-    public Dictionary<Key, KeyBinding> Bindings { get; } = new ();
-
     /// <summary>Adds a <see cref="KeyBinding"/> to the collection.</summary>
     /// <param name="key"></param>
     /// <param name="binding"></param>
@@ -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);
     }
 
     /// <summary>
@@ -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);
+    }
 
     /// <summary>
     ///     <para>Adds a new key combination that will trigger the commands in <paramref name="commands"/>.</para>
@@ -129,7 +111,7 @@ public class KeyBindings
     ///     multiple commands are provided,they will be applied in sequence. The bound <paramref name="key"/> strike will be
     ///     consumed if any took effect.
     /// </param>
-    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));
     }
 
     /// <summary>
@@ -162,7 +142,8 @@ public class KeyBindings
     ///         View - see <see cref="View.GetSupportedCommands"/>).
     ///     </para>
     ///     <para>
-    ///         This is a helper function for <see cref="Add(Key,KeyBinding,View?)"/>. If used for a View (<see cref="BoundView"/> is set), the scope will be set to <see cref="KeyBindingScope.Focused"/>.
+    ///         This is a helper function for <see cref="Add(Key,KeyBinding,View?)"/>. If used for a View (
+    ///         <see cref="BoundView"/> is set), the scope will be set to <see cref="KeyBindingScope.Focused"/>.
     ///         Otherwise, it will be set to <see cref="KeyBindingScope.Application"/>.
     ///     </para>
     ///     <para>
@@ -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 <see cref="View.GetSupportedCommands"/>).
     ///     </para>
     ///     <para>
-    ///         This is a helper function for <see cref="Add(Key,KeyBinding,View?)"/>. If used for a View (<see cref="BoundView"/> is set), the scope will be set to <see cref="KeyBindingScope.Focused"/>.
+    ///         This is a helper function for <see cref="Add(Key,KeyBinding,View?)"/>. If used for a View (
+    ///         <see cref="BoundView"/> is set), the scope will be set to <see cref="KeyBindingScope.Focused"/>.
     ///         Otherwise, it will be set to <see cref="KeyBindingScope.Application"/>.
     ///     </para>
     ///     <para>
@@ -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!
+    /// <summary>The collection of <see cref="KeyBinding"/> objects.</summary>
+    public Dictionary<Key, KeyBinding> Bindings { get; } = new ();
+
+    /// <summary>
+    ///     The view that the <see cref="KeyBindings"/> are bound to.
+    /// </summary>
+    /// <remarks>
+    ///     If <see langword="null"/>, the <see cref="KeyBindings"/> are not bound to a <see cref="View"/>. This is used for
+    ///     Application.KeyBindings.
+    /// </remarks>
+    public View? BoundView { get; }
+
     /// <summary>Removes all <see cref="KeyBinding"/> objects from the collection.</summary>
-    public void Clear ()
-    {
-        Bindings.Clear ();
-    }
+    public void Clear () { Bindings.Clear (); }
 
     /// <summary>
     ///     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
     /// <param name="boundViewForAppScope">Optional View for <see cref="KeyBindingScope.Application"/> bindings.</param>
     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);
     }
 
+    /// <summary>Replaces the commands already bound to a key.</summary>
+    /// <remarks>
+    ///     <para>
+    ///         If the key is not already bound, it will be added.
+    ///     </para>
+    /// </remarks>
+    /// <param name="key">The key bound to the command to be replaced.</param>
+    /// <param name="commands">The set of commands to replace the old ones with.</param>
+    public void ReplaceCommands (Key key, params Command [] commands)
+    {
+        if (TryGet (key, out KeyBinding binding))
+        {
+            binding.Commands = commands;
+        }
+        else
+        {
+            Add (key, commands);
+        }
+    }
+
     /// <summary>Replaces a key combination already bound to a set of <see cref="Command"/>s.</summary>
     /// <remarks></remarks>
     /// <param name="oldKey">The key to be replaced.</param>
@@ -329,26 +345,6 @@ public class KeyBindings
         Add (newKey, value);
     }
 
-    /// <summary>Replaces the commands already bound to a key.</summary>
-    /// <remarks>
-    ///     <para>
-    ///         If the key is not already bound, it will be added.
-    ///     </para>
-    /// </remarks>
-    /// <param name="key">The key bound to the command to be replaced.</param>
-    /// <param name="commands">The set of commands to replace the old ones with.</param>
-    public void ReplaceCommands (Key key, params Command [] commands)
-    {
-        if (TryGet (key, out KeyBinding binding))
-        {
-            binding.Commands = commands;
-        }
-        else
-        {
-            Add (key, commands);
-        }
-    }
-
     /// <summary>Gets the commands bound with the specified Key.</summary>
     /// <remarks></remarks>
     /// <param name="key">The key to check.</param>
@@ -360,6 +356,7 @@ public class KeyBindings
     public bool TryGet (Key key, out KeyBinding binding)
     {
         binding = new (Array.Empty<Command> (), 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<Command> (), KeyBindingScope.Disabled, null);
+
         if (key.IsValid && Bindings.TryGetValue (key, out binding))
         {
             if (scope.HasFlag (binding.Scope))

+ 3 - 2
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": [
           {

+ 3 - 3
Terminal.Gui/Views/Dialog.cs

@@ -20,7 +20,7 @@ public class Dialog : Window
     /// <remarks>This property can be set in a Theme.</remarks>
     [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
     [JsonConverter (typeof (JsonStringEnumConverter<Alignment>))]
-    public static Alignment DefaultButtonAlignment { get; set; } = Alignment.End;
+    public static Alignment DefaultButtonAlignment { get; set; } = Alignment.End; // Default is set in config.json
 
     /// <summary>The default <see cref="Alignment"/> for <see cref="Dialog"/>.</summary>
     /// <remarks>This property can be set in a Theme.</remarks>
@@ -48,7 +48,7 @@ public class Dialog : Window
     /// </summary>
     [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
     [JsonConverter (typeof (JsonStringEnumConverter<ShadowStyle>))]
-    public new static ShadowStyle DefaultShadow { get; set; } = ShadowStyle.None;
+    public new static ShadowStyle DefaultShadow { get; set; } = ShadowStyle.None; // Default is set in config.json
 
     /// <summary>
     ///     Defines the default border styling for <see cref="Dialog"/>. Can be configured via
@@ -57,7 +57,7 @@ public class Dialog : Window
 
     [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
     [JsonConverter (typeof (JsonStringEnumConverter<LineStyle>))]
-    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<Button> _buttons = new ();
 

+ 9 - 3
Terminal.Gui/Views/MessageBox.cs

@@ -33,7 +33,13 @@ public static class MessageBox
     /// </summary>
     [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
     [JsonConverter (typeof (JsonStringEnumConverter<LineStyle>))]
-    public static LineStyle DefaultBorderStyle { get; set; } = LineStyle.Single;
+    public static LineStyle DefaultBorderStyle { get; set; } = LineStyle.Single; // Default is set in config.json
+
+    /// <summary>The default <see cref="Alignment"/> for <see cref="Dialog"/>.</summary>
+    /// <remarks>This property can be set in a Theme.</remarks>
+    [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
+    [JsonConverter (typeof (JsonStringEnumConverter<Alignment>))]
+    public static Alignment DefaultButtonAlignment { get; set; } = Alignment.Center; // Default is set in config.json
 
     /// <summary>
     ///     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,

+ 1 - 1
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";

+ 76 - 78
UICatalog/Scenarios/AdornmentsEditor.cs

@@ -9,23 +9,10 @@ namespace UICatalog.Scenarios;
 /// </summary>
 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)
+    private readonly ViewDiagnosticFlags _savedDiagnosticFlags = Diagnostics;
+    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;
+
+    /// <summary>
+    ///     Gets or sets whether the AdornmentsEditor should automatically select the View to edit when the mouse is clicked
+    ///     anywhere outside the editor.
+    /// </summary>
+    public bool AutoSelectViewToEdit { get; set; }
+
+    public View ViewToEdit
     {
-        if (ApplicationNavigation.IsInHierarchy (this, Application.Navigation!.GetFocused ()))
+        get => _viewToEdit;
+        set
         {
-            return;
-        }
+            if (_viewToEdit == value)
+            {
+                return;
+            }
 
-        if (Application.Navigation!.GetFocused () is Adornment adornment)
-        {
-            ViewToEdit = adornment.Parent;
-        }
-        else
-        {
-            ViewToEdit = Application.Navigation.GetFocused ();
+            _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;
         }
     }
 
-    /// <summary>
-    /// Gets or sets whether the AdornmentsEditor should automatically select the View to edit when the mouse is clicked
-    /// anywhere outside the editor.
-    /// </summary>
-    public bool AutoSelectViewToEdit { get; set; }
+    /// <inheritdoc/>
+    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
         }
     }
 
-    /// <inheritdoc />
-    protected override void Dispose (bool disposing)
-    {
-        View.Diagnostics = _savedDiagnosticFlags;
-        base.Dispose (disposing);
-    }
-
-    public View ViewToEdit
+    private void ApplicationNavigationOnFocusedChanged (object sender, EventArgs e)
     {
-        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 ();
+        }
     }
-}
+}

+ 155 - 155
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<Toplevel> ().Dispose ()..");
+        Application.Run<Toplevel> ().Dispose ();
+        _output.WriteLine ("Back from Application.Run<Toplevel> ().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<bool> 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<Toplevel> ().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<Toplevel> ().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<InvalidOperationException> (() => 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<Toplevel> ().Dispose ()..");
-        Application.Run<Toplevel> ().Dispose ();
-        _output.WriteLine ("Back from Application.Run<Toplevel> ().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<bool> 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 ();
-            }
-        }
-    }
 }

+ 30 - 1
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,

+ 12 - 0
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++;

+ 14 - 0
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<string, MockFileData> (), "/");
         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<string, MockFileData> (), @"c:\");
         fileSystem.MockTime (() => new (2010, 01, 01, 11, 12, 43));

+ 62 - 67
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<Command> commands = new ();
-        Assert.Throws<ArgumentException> (() => 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<Command> commands = new ();
+        Assert.Throws<ArgumentException> (() => 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<InvalidOperationException> (() => 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<InvalidOperationException> (() => 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<InvalidOperationException> (() => 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<InvalidOperationException> (() => 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<InvalidOperationException> (() => keyBindings.GetKeyFromCommands (Command.Accept));
     }
 
+    [Fact]
+    public void Get_Binding_Not_Found_Throws ()
+    {
+        var keyBindings = new KeyBindings ();
+        Assert.Throws<InvalidOperationException> (() => keyBindings.Get (Key.A));
+        Assert.Throws<InvalidOperationException> (() => 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<InvalidOperationException> (() => 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<InvalidOperationException> (() => 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<InvalidOperationException> (() => 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<InvalidOperationException> (() => 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 ()
     {
@@ -228,34 +235,32 @@ public class KeyBindingTests
     }
 
     [Fact]
-    public void ReplaceKey_Throws_If_DoesNotContain_Old ()
+    public void ReplaceKey_Replaces_Leaves_Old_Binding ()
     {
         var keyBindings = new KeyBindings ();
-        Assert.Throws<InvalidOperationException> (() => keyBindings.ReplaceKey (Key.A, Key.B));
+        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_New_Is_Empty ()
+    public void ReplaceKey_Throws_If_DoesNotContain_Old ()
     {
         var keyBindings = new KeyBindings ();
-        keyBindings.Add (Key.A, KeyBindingScope.Application, Command.HotKey);
-        Assert.Throws<InvalidOperationException> (() => keyBindings.ReplaceKey (Key.A, Key.Empty));
+        Assert.Throws<InvalidOperationException> (() => keyBindings.ReplaceKey (Key.A, Key.B));
     }
 
     [Fact]
-    public void ReplaceKey_Replaces_Leaves_Old_Binding ()
+    public void ReplaceKey_Throws_If_New_Is_Empty ()
     {
         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));
-
+        keyBindings.Add (Key.A, KeyBindingScope.Application, Command.HotKey);
+        Assert.Throws<InvalidOperationException> (() => keyBindings.ReplaceKey (Key.A, Key.Empty));
     }
 
-
     // 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<InvalidOperationException> (() => keyBindings.Get (Key.A));
-        Assert.Throws<InvalidOperationException> (() => 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);
     }
-
-
 }

文件差异内容过多而无法显示
+ 1187 - 1191
UnitTests/View/NavigationTests.cs


+ 11 - 1
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);

部分文件因为文件数量过多而无法显示