Pārlūkot izejas kodu

Partially Fixes #2975 - Replaces old `ContextMenu` with new `Bar/Shortcut` based implementation (#4008)

* touching publish.yml

* Nuked ContextMenuv2 - use PopverMenu instead

* WIP context menu stuff

* More robust dispose

* Removed ConextMenu; use PopoverMenu instead

* Code cleanup

* Code cleanup2
Tig 5 mēneši atpakaļ
vecāks
revīzija
ac5c7e5d9e
40 mainītis faili ar 710 papildinājumiem un 3728 dzēšanām
  1. 3 0
      Terminal.Gui/Application/Application.Initialization.cs
  2. 1 1
      Terminal.Gui/Application/Application.Run.cs
  3. 1 0
      Terminal.Gui/Application/Application.cs
  4. 49 19
      Terminal.Gui/Application/ApplicationPopover.cs
  5. 10 22
      Terminal.Gui/Application/PopoverBaseImpl.cs
  6. 4 0
      Terminal.Gui/ConsoleDrivers/V2/ApplicationV2.cs
  7. 1 1
      Terminal.Gui/Drawing/Color/ColorScheme.Colors.cs
  8. 1 1
      Terminal.Gui/Resources/config.json
  9. 1 1
      Terminal.Gui/Terminal.Gui.csproj
  10. 14 28
      Terminal.Gui/Views/CharMap/CharMap.cs
  11. 99 96
      Terminal.Gui/Views/FileDialog.cs
  12. 0 283
      Terminal.Gui/Views/Menu/ContextMenu.cs
  13. 0 104
      Terminal.Gui/Views/Menu/ContextMenuv2.cs
  14. 1 1
      Terminal.Gui/Views/Menu/MenuBarItemv2.cs
  15. 2 172
      Terminal.Gui/Views/Menu/MenuBarv2.cs
  16. 16 5
      Terminal.Gui/Views/Menu/MenuItemv2.cs
  17. 26 32
      Terminal.Gui/Views/Menu/Menuv2.cs
  18. 99 73
      Terminal.Gui/Views/Menu/PopoverMenu.cs
  19. 1 2
      Terminal.Gui/Views/Menuv1/Menu.cs
  20. 0 1
      Terminal.Gui/Views/Menuv1/MenuBar.cs
  21. 0 0
      Terminal.Gui/Views/Menuv1/MenuBarItem.cs
  22. 0 0
      Terminal.Gui/Views/Menuv1/MenuClosingEventArgs.cs
  23. 1 1
      Terminal.Gui/Views/Menuv1/MenuItem.cs
  24. 0 0
      Terminal.Gui/Views/Menuv1/MenuItemCheckStyle.cs
  25. 0 0
      Terminal.Gui/Views/Menuv1/MenuOpenedEventArgs.cs
  26. 0 0
      Terminal.Gui/Views/Menuv1/MenuOpeningEventArgs.cs
  27. 5 5
      Terminal.Gui/Views/TextField.cs
  28. 11 11
      Terminal.Gui/Views/TextView.cs
  29. 22 20
      TerminalGuiFluentTesting/GuiTestContext.cs
  30. 21 35
      Tests/IntegrationTests/FluentTests/BasicFluentAssertionTests.cs
  31. 80 342
      Tests/UnitTests/Application/ApplicationPopoverTests.cs
  32. 0 2218
      Tests/UnitTests/Views/ContextMenuTests.cs
  33. 1 1
      Tests/UnitTests/Views/TextViewTests.cs
  34. 9 9
      Tests/UnitTestsParallelizable/Application/ApplicationPopoverTests.cs
  35. 2 2
      UICatalog/Scenarios/ContextMenus.cs
  36. 0 18
      UICatalog/Scenarios/MenusV2.cs
  37. 21 23
      UICatalog/Scenarios/Notepad.cs
  38. 28 37
      UICatalog/Scenarios/TableEditor.cs
  39. 162 164
      UICatalog/Scenarios/TreeViewFileSystem.cs
  40. 18 0
      docfx/docs/migratingfromv1.md

+ 3 - 0
Terminal.Gui/Application/Application.Initialization.cs

@@ -82,7 +82,10 @@ public static partial class Application // Initialization (Init/Shutdown)
             ResetState (ignoreDisposed: true);
         }
 
+        Debug.Assert (Navigation is null);
         Navigation = new ();
+
+        Debug.Assert(Popover is null);
         Popover = new ();
 
         // For UnitTests

+ 1 - 1
Terminal.Gui/Application/Application.Run.cs

@@ -564,7 +564,7 @@ public static partial class Application // Run (Begin, Run, End, Stop)
     {
         ArgumentNullException.ThrowIfNull (runState);
 
-        Popover?.HidePopover (Popover?.GetActivePopover ());
+        Popover?.Hide (Popover?.GetActivePopover ());
 
         runState.Toplevel.OnUnloaded ();
 

+ 1 - 0
Terminal.Gui/Application/Application.cs

@@ -153,6 +153,7 @@ public static partial class Application
         {
             popover.Visible = false;
         }
+        Popover?.Dispose ();
         Popover = null;
 
         TopLevels.Clear ();

+ 49 - 19
Terminal.Gui/Application/ApplicationPopover.cs

@@ -1,13 +1,12 @@
 #nullable enable
 
-using System.Diagnostics;
-
 namespace Terminal.Gui;
 
 /// <summary>
-///     Helper class for support of <see cref="IPopover"/> views for <see cref="Application"/>. Held by <see cref="Application.Popover"/>
+///     Helper class for support of <see cref="IPopover"/> views for <see cref="Application"/>. Held by
+///     <see cref="Application.Popover"/>
 /// </summary>
-public class ApplicationPopover
+public sealed class ApplicationPopover : IDisposable
 {
     /// <summary>
     ///     Initializes a new instance of the <see cref="ApplicationPopover"/> class.
@@ -16,27 +15,41 @@ public class ApplicationPopover
 
     private readonly List<IPopover> _popovers = [];
 
-    /// <summary></summary>
+    /// <summary>
+    ///     Gets the list of popovers registered with the application.
+    /// </summary>
     public IReadOnlyCollection<IPopover> Popovers => _popovers.AsReadOnly ();
 
     /// <summary>
     ///     Registers <paramref name="popover"/> with the application.
-    ///     This enables the popover to receive keyboard events even when when it is not active.
+    ///     This enables the popover to receive keyboard events even when it is not active.
     /// </summary>
+    /// <remarks>
+    ///     When a popover is registered, the View instance lifetime is managed by the application. Call
+    ///     <see cref="DeRegister"/>
+    ///     to manage the lifetime of the popover directly.
+    /// </remarks>
     /// <param name="popover"></param>
-    public void Register (IPopover? popover)
+    /// <returns><paramref name="popover"/>, after it has been registered.</returns>
+    public IPopover? Register (IPopover? popover)
     {
         if (popover is { } && !_popovers.Contains (popover))
         {
             _popovers.Add (popover);
-
         }
+
+        return popover;
     }
 
     /// <summary>
     ///     De-registers <paramref name="popover"/> with the application. Use this to remove the popover and it's
     ///     keyboard bindings from the application.
     /// </summary>
+    /// <remarks>
+    ///     When a popover is registered, the View instance lifetime is managed by the application. Call
+    ///     <see cref="DeRegister"/>
+    ///     to manage the lifetime of the popover directly.
+    /// </remarks>
     /// <param name="popover"></param>
     /// <returns></returns>
     public bool DeRegister (IPopover? popover)
@@ -61,22 +74,25 @@ public class ApplicationPopover
     /// <summary>
     ///     Gets the active popover, if any.
     /// </summary>
+    /// <remarks>
+    ///     Note, the active pop over does not necessarily to be registered with the application.
+    /// </remarks>
     /// <returns></returns>
     public IPopover? GetActivePopover () { return _activePopover; }
 
     /// <summary>
-    ///     Shows <paramref name="popover"/>. IPopover implementations should use OnVisibleChnaged/VisibleChanged to be
+    ///     Shows <paramref name="popover"/>. IPopover implementations should use OnVisibleChanaged/VisibleChanged to be
     ///     notified when the user has done something to cause the popover to be hidden.
     /// </summary>
     /// <remarks>
     ///     <para>
-    ///         Note, this API calls <see cref="Register"/>. To disable the popover from processing keyboard events,
+    ///         This API calls <see cref="Register"/>. To disable the popover from processing keyboard events,
     ///         either call <see cref="DeRegister"/> to
     ///         remove the popover from the application or set <see cref="View.Enabled"/> to <see langword="false"/>.
     ///     </para>
     /// </remarks>
     /// <param name="popover"></param>
-    public void ShowPopover (IPopover? popover)
+    public void Show (IPopover? popover)
     {
         // If there's an existing popover, hide it.
         if (_activePopover is View popoverView)
@@ -87,8 +103,6 @@ public class ApplicationPopover
 
         if (popover is View newPopover)
         {
-            Register (popover);
-
             if (!newPopover.IsInitialized)
             {
                 newPopover.BeginInit ();
@@ -103,10 +117,11 @@ public class ApplicationPopover
 
     /// <summary>
     ///     Causes the specified popover to be hidden.
-    ///     If the popover is dervied from <see cref="PopoverBaseImpl"/>, this is the same as setting <see cref="View.Visible"/> to <see langword="false"/>.
+    ///     If the popover is dervied from <see cref="PopoverBaseImpl"/>, this is the same as setting
+    ///     <see cref="View.Visible"/> to <see langword="false"/>.
     /// </summary>
     /// <param name="popover"></param>
-    public void HidePopover (IPopover? popover)
+    public void Hide (IPopover? popover)
     {
         // If there's an existing popover, hide it.
         if (_activePopover is View popoverView && popoverView == popover)
@@ -117,7 +132,6 @@ public class ApplicationPopover
         }
     }
 
-
     /// <summary>
     ///     Called when the user presses a key. Dispatches the key to the active popover, if any,
     ///     otherwise to the popovers in the order they were registered. Inactive popovers only get hotkeys.
@@ -127,9 +141,11 @@ public class ApplicationPopover
     internal bool DispatchKeyDown (Key key)
     {
         // Do active first - Active gets all key down events.
-        if (GetActivePopover () as View is { Visible: true } visiblePopover)
+        var activePopover = GetActivePopover () as View;
+
+        if (activePopover is { Visible: true })
         {
-            if (visiblePopover.NewKeyDownEvent (key))
+            if (activePopover.NewKeyDownEvent (key))
             {
                 return true;
             }
@@ -141,7 +157,7 @@ public class ApplicationPopover
 
         foreach (IPopover popover in _popovers)
         {
-            if (GetActivePopover () == popover || popover is not View popoverView)
+            if (popover == activePopover || popover is not View popoverView)
             {
                 continue;
             }
@@ -157,4 +173,18 @@ public class ApplicationPopover
 
         return hotKeyHandled is true;
     }
+
+    /// <inheritdoc/>
+    public void Dispose ()
+    {
+        foreach (IPopover popover in _popovers)
+        {
+            if (popover is View view)
+            {
+                view.Dispose ();
+            }
+        }
+
+        _popovers.Clear ();
+    }
 }

+ 10 - 22
Terminal.Gui/Application/PopoverBaseImpl.cs

@@ -6,19 +6,18 @@ namespace Terminal.Gui;
 /// </summary>
 /// <remarks>
 ///     <para>
-///         To show a Popover, use <see cref="ApplicationPopover.ShowPopover"/>. To hide a popover,
-///         call <see cref="ApplicationPopover.ShowPopover"/> with <see langword="null"/> set <see cref="View.Visible"/> to <see langword="false"/>.
+///         To show a Popover, use <see cref="ApplicationPopover.Show"/>. To hide a popover,
+///         call <see cref="ApplicationPopover.Show"/> with <see langword="null"/> set <see cref="View.Visible"/> to <see langword="false"/>.
 ///     </para>
 ///     <para>
-///         If the user clicks anywhere not occulded by a SubView of the Popover, presses <see cref="Application.QuitKey"/>,
+///         If the user clicks anywhere not occluded by a SubView of the Popover, presses <see cref="Application.QuitKey"/>,
 ///         or causes another popover to show, the Popover will be hidden.
 ///     </para>
 /// </remarks>
-
 public abstract class PopoverBaseImpl : View, IPopover
 {
     /// <summary>
-    /// 
+    ///     Creates a new PopoverBaseImpl.
     /// </summary>
     protected PopoverBaseImpl ()
     {
@@ -28,10 +27,10 @@ public abstract class PopoverBaseImpl : View, IPopover
         Height = Dim.Fill ();
         ViewportSettings = ViewportSettings.Transparent | ViewportSettings.TransparentMouse;
 
-        //// TODO: Add a diagnostic setting for this?
-        TextFormatter.VerticalAlignment = Alignment.End;
-        TextFormatter.Alignment = Alignment.End;
-        base.Text = "popover";
+        // TODO: Add a diagnostic setting for this?
+        //TextFormatter.VerticalAlignment = Alignment.End;
+        //TextFormatter.Alignment = Alignment.End;
+        //base.Text = "popover";
 
         AddCommand (Command.Quit, Quit);
         KeyBindings.Add (Application.QuitKey, Command.Quit);
@@ -55,24 +54,13 @@ public abstract class PopoverBaseImpl : View, IPopover
     protected override bool OnVisibleChanging ()
     {
         bool ret = base.OnVisibleChanging ();
-        if (!ret & !Visible)
+        if (!ret && !Visible)
         {
-            // Whenvver visible is changing to true, we need to resize;
+            // Whenever visible is changing to true, we need to resize;
             // it's our only chance because we don't get laid out until we're visible
             Layout (Application.Screen.Size);
         }
 
         return ret;
     }
-
-    // TODO: Pretty sure this is not needed. set_Visible SetFocus already
-    ///// <inheritdoc />
-    //protected override void OnVisibleChanged ()
-    //{
-    //    base.OnVisibleChanged ();
-    //    if (Visible)
-    //    {
-    //        //SetFocus ();
-    //    }
-    //}
 }

+ 4 - 0
Terminal.Gui/ConsoleDrivers/V2/ApplicationV2.cs

@@ -1,5 +1,6 @@
 #nullable enable
 using System.Collections.Concurrent;
+using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 using Microsoft.Extensions.Logging;
 
@@ -63,7 +64,10 @@ public class ApplicationV2 : ApplicationImpl
             _driverName = driverName;
         }
 
+        Debug.Assert(Application.Navigation is null);
         Application.Navigation = new ();
+
+        Debug.Assert (Application.Popover is null);
         Application.Popover = new ();
 
         Application.AddKeyBindings ();

+ 1 - 1
Terminal.Gui/Drawing/Color/ColorScheme.Colors.cs

@@ -44,7 +44,7 @@ public sealed class Colors : INotifyCollectionChanged, IDictionary<string, Color
     ///             <item>
     ///                 <term>Menu</term>
     ///                 <description>
-    ///                     The menu color scheme; used for <see cref="MenuBar"/>, <see cref="ContextMenu"/>, and
+    ///                     The menu color scheme; used for <see cref="Menu"/>, <see cref="MenuBar"/>, and
     ///                     <see cref="StatusBar"/>.
     ///                 </description>
     ///             </item>

+ 1 - 1
Terminal.Gui/Resources/config.json

@@ -33,7 +33,7 @@
 
 
   // --------------- View Specific Settings ---------------
-  "ContextMenu.DefaultKey": "Shift+F10",
+  "PopoverMenu.DefaultKey": "Shift+F10",
   "FileDialog.MaxSearchResults": 10000,
   "FileDialogStyle.DefaultUseColors": false,
   "FileDialogStyle.DefaultUseUnicodeCharacters": false,

+ 1 - 1
Terminal.Gui/Terminal.Gui.csproj

@@ -81,7 +81,7 @@
     <!-- Assembly names for which internal items are visible -->
     <!-- =================================================================== -->
     <ItemGroup>
-        <InternalsVisibleTo Include="Benchmarks"/>
+        <InternalsVisibleTo Include="Benchmarks" />
         <InternalsVisibleTo Include="UnitTests" />
         <InternalsVisibleTo Include="UnitTests.Parallelizable" />
         <InternalsVisibleTo Include="StressTests" />

+ 14 - 28
Terminal.Gui/Views/CharMap/CharMap.cs

@@ -18,8 +18,6 @@ public class CharMap : View, IDesignable
     private const int HEADER_HEIGHT = 1; // Height of the header
     private int _rowHeight = 1; // Height of each row of 16 glyphs - changing this is not tested
 
-    private ContextMenu _contextMenu = new ();
-
     /// <summary>
     ///     Initializes a new instance.
     /// </summary>
@@ -58,7 +56,7 @@ public class CharMap : View, IDesignable
         KeyBindings.Add (Key.PageDown, Command.PageDown);
         KeyBindings.Add (Key.Home, Command.Start);
         KeyBindings.Add (Key.End, Command.End);
-        KeyBindings.Add (ContextMenu.DefaultKey, Command.Context);
+        KeyBindings.Add (PopoverMenu.DefaultKey, Command.Context);
 
         MouseBindings.Add (MouseFlags.Button1DoubleClicked, Command.Accept);
         MouseBindings.ReplaceCommands (MouseFlags.Button3Clicked, Command.Context);
@@ -505,32 +503,20 @@ public class CharMap : View, IDesignable
 
         SelectedCodePoint = newCodePoint;
 
-        _contextMenu = new ()
-        {
-            Position = ViewportToScreen (GetCursor (SelectedCodePoint))
-        };
+        // This demonstrates how to create an ephemeral Popover; one that exists
+        // ony as long as the popover is visible.
+        // Note, for ephemeral Popovers, hotkeys are not supported.
+        PopoverMenu? contextMenu = new (
+                                        [
+                                            new (Strings.charMapCopyGlyph, string.Empty, CopyGlyph),
+                                            new (Strings.charMapCopyCP, string.Empty, CopyCodePoint)
+                                        ]);
+
+        // Registering with the PopoverManager will ensure that the context menu is closed when the view is no longer focused
+        // and the context menu is disposed when it is closed.
+        Application.Popover?.Register (contextMenu);
 
-        MenuBarItem menuItems = new (
-                                     [
-                                         new (
-                                              Strings.charMapCopyGlyph,
-                                              "",
-                                              CopyGlyph,
-                                              null,
-                                              null,
-                                              (KeyCode)Key.G.WithCtrl
-                                             ),
-                                         new (
-                                              Strings.charMapCopyCP,
-                                              "",
-                                              CopyCodePoint,
-                                              null,
-                                              null,
-                                              (KeyCode)Key.P.WithCtrl
-                                             )
-                                     ]
-                                    );
-        _contextMenu.Show (menuItems);
+        contextMenu?.MakeVisible (ViewportToScreen (GetCursor (SelectedCodePoint)));
 
         return true;
     }

+ 99 - 96
Terminal.Gui/Views/FileDialog.cs

@@ -70,14 +70,15 @@ public class FileDialog : Dialog, IDesignable
         Canceled = true;
 
         _fileSystem = fileSystem;
-        Style = new FileDialogStyle (fileSystem);
+        Style = new (fileSystem);
 
-        _btnOk = new Button
+        _btnOk = new()
         {
             X = Pos.Align (Alignment.End, AlignmentModes.AddSpaceBetweenItems, alignmentGroupComplete),
             Y = Pos.AnchorEnd (),
             IsDefault = true, Text = Style.OkButtonText
         };
+
         _btnOk.Accepting += (s, e) =>
                             {
                                 if (e.Cancel)
@@ -88,8 +89,7 @@ public class FileDialog : Dialog, IDesignable
                                 Accept (true);
                             };
 
-
-        _btnCancel = new Button
+        _btnCancel = new()
         {
             X = Pos.Align (Alignment.End, AlignmentModes.AddSpaceBetweenItems, alignmentGroupComplete),
             Y = Pos.AnchorEnd (),
@@ -97,30 +97,31 @@ public class FileDialog : Dialog, IDesignable
         };
 
         _btnCancel.Accepting += (s, e) =>
-        {
-            if (e.Cancel)
-            {
-                return;
-            }
-            if (Modal)
-            {
-                Application.RequestStop ();
-            }
-        };
-
-        _btnUp = new Button { X = 0, Y = 1, NoPadding = true };
+                                {
+                                    if (e.Cancel)
+                                    {
+                                        return;
+                                    }
+
+                                    if (Modal)
+                                    {
+                                        Application.RequestStop ();
+                                    }
+                                };
+
+        _btnUp = new() { X = 0, Y = 1, NoPadding = true };
         _btnUp.Text = GetUpButtonText ();
         _btnUp.Accepting += (s, e) => _history.Up ();
 
-        _btnBack = new Button { X = Pos.Right (_btnUp) + 1, Y = 1, NoPadding = true };
+        _btnBack = new() { X = Pos.Right (_btnUp) + 1, Y = 1, NoPadding = true };
         _btnBack.Text = GetBackButtonText ();
         _btnBack.Accepting += (s, e) => _history.Back ();
 
-        _btnForward = new Button { X = Pos.Right (_btnBack) + 1, Y = 1, NoPadding = true };
+        _btnForward = new() { X = Pos.Right (_btnBack) + 1, Y = 1, NoPadding = true };
         _btnForward.Text = GetForwardButtonText ();
         _btnForward.Accepting += (s, e) => _history.Forward ();
 
-        _tbPath = new TextField { Width = Dim.Fill (), CaptionColor = new Color (Color.Black) };
+        _tbPath = new() { Width = Dim.Fill (), CaptionColor = new (Color.Black) };
 
         _tbPath.KeyDown += (s, k) =>
                            {
@@ -134,12 +135,12 @@ public class FileDialog : Dialog, IDesignable
         _tbPath.Autocomplete = new AppendAutocomplete (_tbPath);
         _tbPath.Autocomplete.SuggestionGenerator = new FilepathSuggestionGenerator ();
 
-        _splitContainer = new TileView
+        _splitContainer = new()
         {
             X = 0,
             Y = Pos.Bottom (_btnBack),
             Width = Dim.Fill (),
-            Height = Dim.Fill (Dim.Func (() => IsInitialized ? _btnOk.Frame.Height : 1)),
+            Height = Dim.Fill (Dim.Func (() => IsInitialized ? _btnOk.Frame.Height : 1))
         };
 
         Initialized += (s, e) =>
@@ -150,7 +151,7 @@ public class FileDialog : Dialog, IDesignable
 
         // this.splitContainer.Border.BorderStyle = BorderStyle.None;
 
-        _tableView = new TableView
+        _tableView = new()
         {
             Width = Dim.Fill (),
             Height = Dim.Fill (),
@@ -178,7 +179,7 @@ public class FileDialog : Dialog, IDesignable
         typeStyle.MinWidth = 6;
         typeStyle.ColorGetter = ColorGetter;
 
-        _treeView = new TreeView<IFileSystemInfo> { Width = Dim.Fill (), Height = Dim.Fill () };
+        _treeView = new() { Width = Dim.Fill (), Height = Dim.Fill () };
 
         var fileDialogTreeBuilder = new FileSystemTreeBuilder ();
         _treeView.TreeBuilder = fileDialogTreeBuilder;
@@ -190,31 +191,33 @@ public class FileDialog : Dialog, IDesignable
         _splitContainer.Tiles.ElementAt (0).ContentView.Add (_treeView);
         _splitContainer.Tiles.ElementAt (1).ContentView.Add (_tableView);
 
-        _btnToggleSplitterCollapse = new Button
+        _btnToggleSplitterCollapse = new()
         {
             X = Pos.Align (Alignment.Start, AlignmentModes.AddSpaceBetweenItems, alignmentGroupInput),
             Y = Pos.AnchorEnd (), Text = GetToggleSplitterText (false)
         };
 
         _btnToggleSplitterCollapse.Accepting += (s, e) =>
-                                              {
-                                                  Tile tile = _splitContainer.Tiles.ElementAt (0);
+                                                {
+                                                    Tile tile = _splitContainer.Tiles.ElementAt (0);
 
-                                                  bool newState = !tile.ContentView.Visible;
-                                                  tile.ContentView.Visible = newState;
-                                                  _btnToggleSplitterCollapse.Text = GetToggleSplitterText (newState);
-                                                  SetNeedsLayout ();
-                                              };
+                                                    bool newState = !tile.ContentView.Visible;
+                                                    tile.ContentView.Visible = newState;
+                                                    _btnToggleSplitterCollapse.Text = GetToggleSplitterText (newState);
+                                                    SetNeedsLayout ();
+                                                };
 
-        _tbFind = new TextField
+        _tbFind = new()
         {
             X = Pos.Align (Alignment.Start, AlignmentModes.AddSpaceBetweenItems, alignmentGroupInput),
-            CaptionColor = new Color (Color.Black),
+            CaptionColor = new (Color.Black),
             Width = 30,
             Y = Pos.Top (_btnToggleSplitterCollapse),
             HotKey = Key.F.WithAlt
         };
-        _spinnerView = new SpinnerView { X = Pos.Align (Alignment.Start, AlignmentModes.AddSpaceBetweenItems, alignmentGroupInput), Y = Pos.AnchorEnd (1), Visible = false };
+
+        _spinnerView = new()
+            { X = Pos.Align (Alignment.Start, AlignmentModes.AddSpaceBetweenItems, alignmentGroupInput), Y = Pos.AnchorEnd (1), Visible = false };
 
         _tbFind.TextChanged += (s, o) => RestartSearch ();
 
@@ -242,7 +245,7 @@ public class FileDialog : Dialog, IDesignable
         _tableView.Style.ShowHorizontalHeaderUnderline = true;
         _tableView.Style.ShowHorizontalScrollIndicators = true;
 
-        _history = new FileDialogHistory (this);
+        _history = new (this);
 
         _tbPath.TextChanged += (s, e) => PathChanged ();
 
@@ -398,10 +401,10 @@ public class FileDialog : Dialog, IDesignable
 
             Move (0, Viewport.Height / 2);
 
-            SetAttribute (new Attribute (Color.Red, ColorScheme.Normal.Background));
-            Driver.AddStr (new string (' ', feedbackPadLeft));
+            SetAttribute (new (Color.Red, ColorScheme.Normal.Background));
+            Driver.AddStr (new (' ', feedbackPadLeft));
             Driver.AddStr (_feedback);
-            Driver.AddStr (new string (' ', feedbackPadRight));
+            Driver.AddStr (new (' ', feedbackPadRight));
         }
 
         return true;
@@ -430,9 +433,9 @@ public class FileDialog : Dialog, IDesignable
         _tbPath.Caption = Style.PathCaption;
         _tbFind.Caption = Style.SearchCaption;
 
-        _tbPath.Autocomplete.ColorScheme = new ColorScheme (_tbPath.ColorScheme)
+        _tbPath.Autocomplete.ColorScheme = new (_tbPath.ColorScheme)
         {
-            Normal = new Attribute (Color.Black, _tbPath.ColorScheme.Normal.Background)
+            Normal = new (Color.Black, _tbPath.ColorScheme.Normal.Background)
         };
 
         _treeRoots = Style.TreeRootGetter ();
@@ -449,18 +452,18 @@ public class FileDialog : Dialog, IDesignable
             // Fiddle factor
             int width = AllowedTypes.Max (a => a.ToString ().Length) + 6;
 
-            _allowedTypeMenu = new MenuBarItem (
-                                                "<placeholder>",
-                                                _allowedTypeMenuItems = AllowedTypes.Select (
-                                                                                             (a, i) => new MenuItem (
-                                                                                              a.ToString (),
-                                                                                              null,
-                                                                                              () => { AllowedTypeMenuClicked (i); })
-                                                                                            )
-                                                                                    .ToArray ()
-                                               );
-
-            _allowedTypeMenuBar = new MenuBar
+            _allowedTypeMenu = new (
+                                    "<placeholder>",
+                                    _allowedTypeMenuItems = AllowedTypes.Select (
+                                                                                 (a, i) => new MenuItem (
+                                                                                                         a.ToString (),
+                                                                                                         null,
+                                                                                                         () => { AllowedTypeMenuClicked (i); })
+                                                                                )
+                                                                        .ToArray ()
+                                   );
+
+            _allowedTypeMenuBar = new()
             {
                 Width = width,
                 Y = 1,
@@ -476,10 +479,10 @@ public class FileDialog : Dialog, IDesignable
 
             // TODO: Using v1's menu bar here is a hack. Need to upgrade this.
             _allowedTypeMenuBar.DrawingContent += (s, e) =>
-                                                       {
-                                                           _allowedTypeMenuBar.Move (e.NewViewport.Width - 1, 0);
-                                                           Driver.AddRune (Glyphs.DownArrow);
-                                                       };
+                                                  {
+                                                      _allowedTypeMenuBar.Move (e.NewViewport.Width - 1, 0);
+                                                      Driver.AddRune (Glyphs.DownArrow);
+                                                  };
 
             Add (_allowedTypeMenuBar);
         }
@@ -803,12 +806,12 @@ public class FileDialog : Dialog, IDesignable
         var black = new Color (Color.Black);
 
         // TODO: Add some kind of cache for this
-        return new ColorScheme
+        return new()
         {
-            Normal = new Attribute (color, black),
-            HotNormal = new Attribute (color, black),
-            Focus = new Attribute (black, color),
-            HotFocus = new Attribute (black, color)
+            Normal = new (color, black),
+            HotNormal = new (color, black),
+            Focus = new (black, color),
+            HotFocus = new (black, color)
         };
     }
 
@@ -895,7 +898,7 @@ public class FileDialog : Dialog, IDesignable
     private string GetToggleSplitterText (bool isExpanded)
     {
         return isExpanded
-                   ? new string ((char)Glyphs.LeftArrow.Value, 2)
+                   ? new ((char)Glyphs.LeftArrow.Value, 2)
                    : new string ((char)Glyphs.RightArrow.Value, 2);
     }
 
@@ -1225,49 +1228,48 @@ public class FileDialog : Dialog, IDesignable
             return;
         }
 
-        var contextMenu = new ContextMenu
-        {
-            Position = new Point (e.Position.X + 1, e.Position.Y + 1)
-        };
+        PopoverMenu? contextMenu = new (
+                                        [
+                                            new (Strings.fdCtxNew, string.Empty, New),
+                                            new (Strings.fdCtxRename, string.Empty, Rename),
+                                            new (Strings.fdCtxDelete, string.Empty, Delete)
+                                        ]);
 
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new MenuItem (Strings.fdCtxNew, string.Empty, New),
-                                             new MenuItem (Strings.fdCtxRename, string.Empty, Rename),
-                                             new MenuItem (Strings.fdCtxDelete, string.Empty, Delete)
-                                         ]
-                                        );
         _tableView.SetSelection (clickedCell.Value.X, clickedCell.Value.Y, false);
 
-        contextMenu.Show (menuItems);
+        // Registering with the PopoverManager will ensure that the context menu is closed when the view is no longer focused
+        // and the context menu is disposed when it is closed.
+        Application.Popover?.Register (contextMenu);
+
+        contextMenu?.MakeVisible (e.ScreenPosition);
     }
 
     private void ShowHeaderContextMenu (int clickedCol, MouseEventArgs e)
     {
         string sort = GetProposedNewSortOrder (clickedCol, out bool isAsc);
 
-        var contextMenu = new ContextMenu
-        {
-            Position = new Point (e.Position.X + 1, e.Position.Y + 1)
-        };
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new MenuItem (
-                                                           string.Format (
-                                                                          Strings.fdCtxHide,
-                                                                          StripArrows (_tableView.Table.ColumnNames [clickedCol])
-                                                                         ),
-                                                           string.Empty,
-                                                           () => HideColumn (clickedCol)
-                                                          ),
-                                             new MenuItem (
-                                                           StripArrows (sort),
-                                                           string.Empty,
-                                                           () => SortColumn (clickedCol, isAsc))
-                                         ]
-                                        );
-        contextMenu.Show (menuItems);
+        PopoverMenu? contextMenu = new (
+                                        [
+                                            new (
+                                                 string.Format (
+                                                                Strings.fdCtxHide,
+                                                                StripArrows (_tableView.Table.ColumnNames [clickedCol])
+                                                               ),
+                                                 string.Empty,
+                                                 () => HideColumn (clickedCol)
+                                                ),
+                                            new (
+                                                 StripArrows (sort),
+                                                 string.Empty,
+                                                 () => SortColumn (clickedCol, isAsc))
+                                        ]
+                                       );
+
+        // Registering with the PopoverManager will ensure that the context menu is closed when the view is no longer focused
+        // and the context menu is disposed when it is closed.
+        Application.Popover?.Register (contextMenu);
+
+        contextMenu?.MakeVisible (e.ScreenPosition);
     }
 
     private void SortColumn (int clickedCol)
@@ -1618,6 +1620,7 @@ public class FileDialog : Dialog, IDesignable
     {
         Modal = false;
         OnLoaded ();
+
         return true;
     }
 }

+ 0 - 283
Terminal.Gui/Views/Menu/ContextMenu.cs

@@ -1,283 +0,0 @@
-#nullable enable
-
-namespace Terminal.Gui;
-
-/// <summary>
-///     ContextMenu provides a pop-up menu that can be positioned anywhere within a <see cref="View"/>. ContextMenu is
-///     analogous to <see cref="MenuBar"/> and, once activated, works like a sub-menu of a <see cref="MenuBarItem"/> (but
-///     can be positioned anywhere).
-///     <para>
-///         By default, a ContextMenu with sub-menus is displayed in a cascading manner, where each sub-menu pops out of
-///         the ContextMenu frame (either to the right or left, depending on where the ContextMenu is relative to the edge
-///         of the screen). By setting <see cref="UseSubMenusSingleFrame"/> to <see langword="true"/>, this behavior can be
-///         changed such that all sub-menus are drawn within the ContextMenu frame.
-///     </para>
-///     <para>
-///         ContextMenus can be activated using the Shift-F10 key (by default; use the <see cref="Key"/> to change to
-///         another key).
-///     </para>
-///     <para>
-///         Callers can cause the ContextMenu to be activated on a right-mouse click (or other interaction) by calling
-///         <see cref="Show"/>.
-///     </para>
-///     <para>ContextMenus are located using screen coordinates and appear above all other Views.</para>
-/// </summary>
-public sealed class ContextMenu : IDisposable
-{
-    private static MenuBar? _menuBar;
-
-    private Toplevel? _container;
-    private Key _key = DefaultKey;
-    private MouseFlags _mouseFlags = MouseFlags.Button3Clicked;
-
-    /// <summary>Initializes a context menu with no menu items.</summary>
-    public ContextMenu ()
-    {
-        if (IsShow)
-        {
-            Hide ();
-            IsShow = false;
-        }
-    }
-
-    /// <summary>The default shortcut key for activating the context menu.</summary>
-    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
-    public static Key DefaultKey { get; set; } = Key.F10.WithShift;
-
-    /// <summary>
-    ///     Sets or gets whether the context menu be forced to the right, ensuring it is not clipped, if the x position is
-    ///     less than zero. The default is <see langword="true"/> which means the context menu will be forced to the right. If
-    ///     set to <see langword="false"/>, the context menu will be clipped on the left if x is less than zero.
-    /// </summary>
-    public bool ForceMinimumPosToZero { get; set; } = true;
-
-    /// <summary>The host <see cref="View "/> which position will be used, otherwise if it's null the container will be used.</summary>
-    public View? Host { get; set; }
-
-    /// <summary>Gets whether the ContextMenu is showing or not.</summary>
-    public static bool IsShow { get; private set; }
-
-    /// <summary>Specifies the key that will activate the context menu.</summary>
-    public Key Key
-    {
-        get => _key;
-        set
-        {
-            Key oldKey = _key;
-            _key = value;
-            KeyChanged?.Invoke (this, new KeyChangedEventArgs (oldKey, _key));
-        }
-    }
-
-    /// <summary>Gets the <see cref="MenuBar"/> that is hosting this context menu.</summary>
-    public MenuBar? MenuBar => _menuBar;
-
-    /// <summary>Gets or sets the menu items for this context menu.</summary>
-    public MenuBarItem? MenuItems { get; private set; }
-
-    /// <summary><see cref="Gui.MouseFlags"/> specifies the mouse action used to activate the context menu by mouse.</summary>
-    public MouseFlags MouseFlags
-    {
-        get => _mouseFlags;
-        set
-        {
-            MouseFlags oldFlags = _mouseFlags;
-            _mouseFlags = value;
-            MouseFlagsChanged?.Invoke (this, new MouseFlagsChangedEventArgs (oldFlags, value));
-        }
-    }
-
-    /// <summary>Gets or sets the menu position.</summary>
-    public Point Position { get; set; }
-
-    /// <summary>
-    ///     Gets or sets if sub-menus will be displayed using a "single frame" menu style. If <see langword="true"/>, the
-    ///     ContextMenu and any sub-menus that would normally cascade will be displayed within a single frame. If
-    ///     <see langword="false"/> (the default), sub-menus will cascade using separate frames for each level of the menu
-    ///     hierarchy.
-    /// </summary>
-    public bool UseSubMenusSingleFrame { get; set; }
-
-    /// <summary>Disposes the context menu object.</summary>
-    public void Dispose ()
-    {
-        if (_menuBar is { })
-        {
-            _menuBar.MenuAllClosed -= MenuBar_MenuAllClosed;
-            _container?.Remove (_menuBar);
-        }
-        Application.UngrabMouse ();
-        _menuBar?.Dispose ();
-        _menuBar = null;
-        IsShow = false;
-
-        if (_container is { })
-        {
-            _container.Closing -= Container_Closing;
-            _container.Deactivate -= Container_Deactivate;
-            _container.Disposing -= Container_Disposing;
-        }
-    }
-
-    /// <summary>Hides (closes) the ContextMenu.</summary>
-    public void Hide ()
-    {
-        RemoveKeyBindings (MenuItems);
-        _menuBar?.CleanUp ();
-        IsShow = false;
-    }
-
-    private void RemoveKeyBindings (MenuBarItem? menuBarItem)
-    {
-        if (menuBarItem is null)
-        {
-            return;
-        }
-
-        foreach (MenuItem? menuItem in menuBarItem.Children!)
-        {
-            // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
-            if (menuItem is null)
-            {
-                continue;
-            }
-
-            if (menuItem is MenuBarItem barItem)
-            {
-                RemoveKeyBindings (barItem);
-            }
-            else
-            {
-                if (menuItem.ShortcutKey != Key.Empty)
-                {
-                    // Remove an existent ShortcutKey
-                    _menuBar?.HotKeyBindings.Remove (menuItem.ShortcutKey!);
-                }
-            }
-        }
-    }
-
-    /// <summary>Event invoked when the <see cref="ContextMenu.Key"/> is changed.</summary>
-    public event EventHandler<KeyChangedEventArgs>? KeyChanged;
-
-    /// <summary>Event invoked when the <see cref="ContextMenu.MouseFlags"/> is changed.</summary>
-    public event EventHandler<MouseFlagsChangedEventArgs>? MouseFlagsChanged;
-
-    /// <summary>Shows (opens) the ContextMenu, displaying the <see cref="MenuItem"/>s it contains.</summary>
-    public void Show (MenuBarItem? menuItems)
-    {
-        if (_menuBar is { })
-        {
-            Hide ();
-            Dispose ();
-        }
-
-        if (menuItems is null || menuItems.Children!.Length == 0)
-        {
-            return;
-        }
-
-        MenuItems = menuItems;
-        _container = GetTopSuperView (Host);
-        _container!.Closing += Container_Closing;
-        _container.Deactivate += Container_Deactivate;
-        _container.Disposing += Container_Disposing;
-        Rectangle viewport = _container.Viewport;
-        Point position = Position;
-
-        if (Host is { })
-        {
-            Point pos = Host.Frame.Location;
-            pos.Y += Host.Frame.Height > 0 ? Host.Frame.Height - 1 : 0;
-
-            if (position != pos)
-            {
-                Position = position = pos;
-            }
-        }
-
-        Rectangle rect = Menu.MakeFrame (position.X, position.Y, MenuItems.Children);
-
-        if (rect.Right >= viewport.Right)
-        {
-            if (viewport.Right - rect.Width >= 0 || !ForceMinimumPosToZero)
-            {
-                position.X = viewport.Right - rect.Width;
-            }
-            else if (ForceMinimumPosToZero)
-            {
-                position.X = 0;
-            }
-        }
-        else if (ForceMinimumPosToZero && position.X < 0)
-        {
-            position.X = 0;
-        }
-
-        if (rect.Bottom >= viewport.Bottom)
-        {
-            if (viewport.Bottom - rect.Height - 1 >= 0 || !ForceMinimumPosToZero)
-            {
-                if (Host is null)
-                {
-                    position.Y = viewport.Bottom - rect.Height - 1;
-                }
-                else
-                {
-                    Point pos = Host.Frame.Location;
-                    position.Y = pos.Y - rect.Height - 1;
-                }
-            }
-            else if (ForceMinimumPosToZero)
-            {
-                position.Y = 0;
-            }
-        }
-        else if (ForceMinimumPosToZero && position.Y < 0)
-        {
-            position.Y = 0;
-        }
-
-        _menuBar = new MenuBar
-        {
-            X = position.X,
-            Y = position.Y,
-            Width = 0,
-            Height = 0,
-            UseSubMenusSingleFrame = UseSubMenusSingleFrame,
-            Key = Key,
-            Menus = [MenuItems]
-        };
-
-        _menuBar._isContextMenuLoading = true;
-        _menuBar.MenuAllClosed += MenuBar_MenuAllClosed;
-
-        _container.Add (_menuBar);
-        IsShow = true;
-        _menuBar.OpenMenu ();
-    }
-
-    internal static Toplevel? GetTopSuperView (View? view)
-    {
-        if (view is Toplevel toplevel)
-        {
-            return toplevel;
-        }
-
-        for (View? sv = view?.SuperView; sv != null; sv = sv.SuperView)
-        {
-            if (sv is Toplevel top)
-            {
-                return top;
-            }
-        }
-
-        return (Toplevel?)view?.SuperView ?? Application.Top;
-    }
-
-    private void Container_Closing (object? sender, ToplevelClosingEventArgs obj) { Hide (); }
-    private void Container_Deactivate (object? sender, ToplevelEventArgs e) { Hide (); }
-    private void Container_Disposing (object? sender, EventArgs e) { Dispose (); }
-
-    private void MenuBar_MenuAllClosed (object? sender, EventArgs e) { Hide (); }
-}

+ 0 - 104
Terminal.Gui/Views/Menu/ContextMenuv2.cs

@@ -1,104 +0,0 @@
-#nullable enable
-
-using System.Diagnostics;
-
-namespace Terminal.Gui;
-
-/// <summary>
-///     ContextMenuv2 provides a Popover menu that can be positioned anywhere within a <see cref="View"/>.
-///     <para>
-///         To show the ContextMenu, set <see cref="Application.Popover"/> to the ContextMenu object and set
-///         <see cref="View.Visible"/> property to <see langword="true"/>.
-///     </para>
-///     <para>
-///         The menu will be hidden when the user clicks outside the menu or when the user presses <see cref="Application.QuitKey"/>.
-///     </para>
-///     <para>
-///         To explicitly hide the menu, set <see cref="View.Visible"/> property to <see langword="false"/>.
-///     </para>
-///     <para>
-///         <see cref="Key"/> is the key used to activate the ContextMenus (<c>Shift+F10</c> by default). Callers can use this in
-///         their keyboard handling code.
-///     </para>
-///     <para>The menu will be displayed at the current mouse coordinates.</para>
-/// </summary>
-public class ContextMenuv2 : PopoverMenu, IDesignable
-{
-
-    /// <summary>
-    ///     The mouse flags that will trigger the context menu. The default is <see cref="MouseFlags.Button3Clicked"/> which is typically the right mouse button.
-    /// </summary>
-    public MouseFlags MouseFlags { get; set; } = MouseFlags.Button3Clicked;
-
-    /// <summary>Initializes a context menu with no menu items.</summary>
-    public ContextMenuv2 () : this ([]) { }
-
-    /// <inheritdoc/>
-    public ContextMenuv2 (Menuv2? menu) : base (menu)
-    {
-        Key = DefaultKey;
-    }
-
-    /// <inheritdoc/>
-    public ContextMenuv2 (IEnumerable<View>? menuItems) : this (new Menuv2 (menuItems))
-    {
-    }
-
-    private Key _key = DefaultKey;
-
-    /// <summary>Specifies the key that will activate the context menu.</summary>
-    public Key Key
-    {
-        get => _key;
-        set
-        {
-            Key oldKey = _key;
-            _key = value;
-            KeyChanged?.Invoke (this, new KeyChangedEventArgs (oldKey, _key));
-        }
-    }
-
-    /// <summary>Event raised when the <see cref="ContextMenu.Key"/> is changed.</summary>
-    public event EventHandler<KeyChangedEventArgs>? KeyChanged;
-
-    /// <inheritdoc />
-    public bool EnableForDesign ()
-    {
-        var shortcut = new Shortcut
-        {
-            Text = "Quit",
-            Title = "Q_uit",
-            Key = Key.Z.WithCtrl,
-        };
-
-        Add (shortcut);
-
-        shortcut = new Shortcut
-        {
-            Text = "Help Text",
-            Title = "Help",
-            Key = Key.F1,
-        };
-
-        Add (shortcut);
-
-        shortcut = new Shortcut
-        {
-            Text = "Czech",
-            CommandView = new CheckBox ()
-            {
-                Title = "_Check"
-            },
-            Key = Key.F9,
-            CanFocus = false
-        };
-
-        Add (shortcut);
-
-        // HACK: This enables All Views Tester to show the CM if DefaultKey is pressed
-        AddCommand (Command.Context, () => Visible = true);
-        HotKeyBindings.Add (DefaultKey, Command.Context);
-
-        return true;
-    }
-}

+ 1 - 1
Terminal.Gui/Views/Menu/MenuBarItemv2.cs

@@ -74,7 +74,7 @@ public class MenuBarItemv2 : MenuItemv2
                 null,
                 Command.NotBound,
                 commandText,
-                new (new (menuItems)))
+                new (menuItems))
     { }
 
     // TODO: Hide base.SubMenu?

+ 2 - 172
Terminal.Gui/Views/Menu/MenuBarv2.cs

@@ -55,7 +55,7 @@ public class MenuBarv2 : Menuv2, IDesignable
             Border.LineStyle = LineStyle.None;
         }
 
-        // TODO: This needs to be done whenever a menuitem in any memubaritem changes
+        // TODO: This needs to be done whenever a menuitem in any MenuBarItem changes
         foreach (MenuBarItemv2? mbi in SubViews.Select(s => s as MenuBarItemv2))
         {
             Application.Popover?.Register (mbi?.PopoverMenu);
@@ -86,7 +86,7 @@ public class MenuBarv2 : Menuv2, IDesignable
             && Application.Popover?.GetActivePopover () is PopoverMenu popoverMenu
             && popoverMenu?.Root?.SuperMenuItem?.SuperView == this)
         {
-            Application.Popover?.HidePopover (popoverMenu);
+            Application.Popover?.Hide (popoverMenu);
         }
 
         menuBarItem?.PopoverMenu?.MakeVisible (new Point (menuBarItem.FrameToScreen ().X, menuBarItem.FrameToScreen ().Bottom));
@@ -167,176 +167,6 @@ public class MenuBarv2 : Menuv2, IDesignable
                                 ]
                                )
             );
-
-        //        if (context is not Func<string, bool> actionFn)
-        //        {
-        //            actionFn = (_) => true;
-        //        }
-
-        //        View? targetView = context as View;
-
-        //        Add (new MenuItemv2 (targetView,
-        //                             Command.NotBound,
-        //                             "_File",
-        //                             new MenuItem []
-        //                             {
-        //                                 new (
-        //                                      "_New",
-        //                                      "",
-        //                                      () => actionFn ("New"),
-        //                                      null,
-        //                                      null,
-        //                                      KeyCode.CtrlMask | KeyCode.N
-        //                                     ),
-        //                                 new (
-        //                                      "_Open",
-        //                                      "",
-        //                                      () => actionFn ("Open"),
-        //                                      null,
-        //                                      null,
-        //                                      KeyCode.CtrlMask | KeyCode.O
-        //                                     ),
-        //                                 new (
-        //                                      "_Save",
-        //                                      "",
-        //                                      () => actionFn ("Save"),
-        //                                      null,
-        //                                      null,
-        //                                      KeyCode.CtrlMask | KeyCode.S
-        //                                     ),
-        //#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
-        //                                 null,
-        //#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
-
-        //                                 // Don't use Application.Quit so we can disambiguate between quitting and closing the toplevel
-        //                                 new (
-        //                                      "_Quit",
-        //                                      "",
-        //                                      () => actionFn ("Quit"),
-        //                                      null,
-        //                                      null,
-        //                                      KeyCode.CtrlMask | KeyCode.Q
-        //                                     )
-        //                             }
-        //                            ),
-        //            new MenuBarItem (
-        //                             "_Edit",
-        //                             new MenuItem []
-        //                             {
-        //                                 new (
-        //                                      "_Copy",
-        //                                      "",
-        //                                      () => actionFn ("Copy"),
-        //                                      null,
-        //                                      null,
-        //                                      KeyCode.CtrlMask | KeyCode.C
-        //                                     ),
-        //                                 new (
-        //                                      "C_ut",
-        //                                      "",
-        //                                      () => actionFn ("Cut"),
-        //                                      null,
-        //                                      null,
-        //                                      KeyCode.CtrlMask | KeyCode.X
-        //                                     ),
-        //                                 new (
-        //                                      "_Paste",
-        //                                      "",
-        //                                      () => actionFn ("Paste"),
-        //                                      null,
-        //                                      null,
-        //                                      KeyCode.CtrlMask | KeyCode.V
-        //                                     ),
-        //                                 new MenuBarItem (
-        //                                                  "_Find and Replace",
-        //                                                  new MenuItem []
-        //                                                  {
-        //                                                      new (
-        //                                                           "F_ind",
-        //                                                           "",
-        //                                                           () => actionFn ("Find"),
-        //                                                           null,
-        //                                                           null,
-        //                                                           KeyCode.CtrlMask | KeyCode.F
-        //                                                          ),
-        //                                                      new (
-        //                                                           "_Replace",
-        //                                                           "",
-        //                                                           () => actionFn ("Replace"),
-        //                                                           null,
-        //                                                           null,
-        //                                                           KeyCode.CtrlMask | KeyCode.H
-        //                                                          ),
-        //                                                      new MenuBarItem (
-        //                                                                       "_3rd Level",
-        //                                                                       new MenuItem []
-        //                                                                       {
-        //                                                                           new (
-        //                                                                                "_1st",
-        //                                                                                "",
-        //                                                                                () => actionFn (
-        //                                                                                                "1"
-        //                                                                                               ),
-        //                                                                                null,
-        //                                                                                null,
-        //                                                                                KeyCode.F1
-        //                                                                               ),
-        //                                                                           new (
-        //                                                                                "_2nd",
-        //                                                                                "",
-        //                                                                                () => actionFn (
-        //                                                                                                "2"
-        //                                                                                               ),
-        //                                                                                null,
-        //                                                                                null,
-        //                                                                                KeyCode.F2
-        //                                                                               )
-        //                                                                       }
-        //                                                                      ),
-        //                                                      new MenuBarItem (
-        //                                                                       "_4th Level",
-        //                                                                       new MenuItem []
-        //                                                                       {
-        //                                                                           new (
-        //                                                                                "_5th",
-        //                                                                                "",
-        //                                                                                () => actionFn (
-        //                                                                                                "5"
-        //                                                                                               ),
-        //                                                                                null,
-        //                                                                                null,
-        //                                                                                KeyCode.CtrlMask
-        //                                                                                | KeyCode.D5
-        //                                                                               ),
-        //                                                                           new (
-        //                                                                                "_6th",
-        //                                                                                "",
-        //                                                                                () => actionFn (
-        //                                                                                                "6"
-        //                                                                                               ),
-        //                                                                                null,
-        //                                                                                null,
-        //                                                                                KeyCode.CtrlMask
-        //                                                                                | KeyCode.D6
-        //                                                                               )
-        //                                                                       }
-        //                                                                      )
-        //                                                  }
-        //                                                 ),
-        //                                 new (
-        //                                      "_Select All",
-        //                                      "",
-        //                                      () => actionFn ("Select All"),
-        //                                      null,
-        //                                      null,
-        //                                      KeyCode.CtrlMask
-        //                                      | KeyCode.ShiftMask
-        //                                      | KeyCode.S
-        //                                     )
-        //                             }
-        //                            ),
-        //            new MenuBarItem ("_About", "Top-Level", () => actionFn ("About"))
-        //        ];
         return true;
     }
 }

+ 16 - 5
Terminal.Gui/Views/Menu/MenuItemv2.cs

@@ -6,7 +6,7 @@ using Terminal.Gui.Resources;
 namespace Terminal.Gui;
 
 /// <summary>
-///     A <see cref="Shortcut"/>-dervied object to be used as a menu item in a <see cref="Menuv2"/>. Has title, an
+///     A <see cref="Shortcut"/>-derived object to be used as a menu item in a <see cref="Menuv2"/>. Has title, an
 ///     associated help text, and an action to execute on activation.
 /// </summary>
 public class MenuItemv2 : Shortcut
@@ -45,7 +45,18 @@ public class MenuItemv2 : Shortcut
     {
         TargetView = targetView;
         Command = command;
+        SubMenu = subMenu;
+    }
+
+    /// <inheritdoc/>
+    public MenuItemv2 (string? commandText = null, string? helpText = null, Action? action = null, Key? key = null)
+        : base (key ?? Key.Empty, commandText, action, helpText)
+    { }
 
+    /// <inheritdoc/>
+    public MenuItemv2 (string? commandText = null, string? helpText = null, Menuv2? subMenu = null)
+        : base (Key.Empty, commandText, null, helpText)
+    {
         SubMenu = subMenu;
     }
 
@@ -108,7 +119,7 @@ public class MenuItemv2 : Shortcut
             ret = base.DispatchCommand (commandContext);
         }
 
-        Logging.Trace ($"{commandContext?.Source?.Title}");
+        //Logging.Trace ($"{commandContext?.Source?.Title}");
 
         RaiseAccepted (commandContext);
 
@@ -150,7 +161,7 @@ public class MenuItemv2 : Shortcut
     // TODO: Consider moving Accepted to Shortcut?
 
     /// <summary>
-    ///     Riases the <see cref="OnAccepted"/>/<see cref="Accepted"/> event indicating this item (or submenu)
+    ///     Raises the <see cref="OnAccepted"/>/<see cref="Accepted"/> event indicating this item (or submenu)
     ///     was accepted. This is used to determine when to hide the menu.
     /// </summary>
     /// <param name="ctx"></param>
@@ -167,7 +178,7 @@ public class MenuItemv2 : Shortcut
     }
 
     /// <summary>
-    ///     Called when the user has accepted an item in this menu (or submenu. This is used to determine when to hide the
+    ///     Called when the user has accepted an item in this menu (or submenu). This is used to determine when to hide the
     ///     menu.
     /// </summary>
     /// <remarks>
@@ -176,7 +187,7 @@ public class MenuItemv2 : Shortcut
     protected virtual void OnAccepted (CommandEventArgs args) { }
 
     /// <summary>
-    ///     Raised when the user has accepted an item in this menu (or submenu. This is used to determine when to hide the
+    ///     Raised when the user has accepted an item in this menu (or submenu). This is used to determine when to hide the
     ///     menu.
     /// </summary>
     /// <remarks>

+ 26 - 32
Terminal.Gui/Views/Menu/Menuv2.cs

@@ -2,13 +2,16 @@
 namespace Terminal.Gui;
 
 /// <summary>
-///     A <see cref="Bar"/>-derived object to be used as a verticaly-oriented menu. Each subview is a <see cref="MenuItemv2"/>.
+///     A <see cref="Bar"/>-derived object to be used as a vertically-oriented menu. Each subview is a <see cref="MenuItemv2"/>.
 /// </summary>
 public class Menuv2 : Bar
 {
     /// <inheritdoc/>
     public Menuv2 () : this ([]) { }
 
+    /// <inheritdoc/>
+    public Menuv2 (IEnumerable<MenuItemv2>? shortcuts) : this (shortcuts?.Cast<View>()) { }
+
     /// <inheritdoc/>
     public Menuv2 (IEnumerable<View>? shortcuts) : base (shortcuts)
     {
@@ -18,7 +21,6 @@ public class Menuv2 : Bar
 
         Border!.Thickness = new Thickness (1, 1, 1, 1);
         Border.LineStyle = LineStyle.Single;
-
     }
 
     /// <summary>
@@ -50,52 +52,44 @@ public class Menuv2 : Bar
     {
         base.OnSubViewAdded (view);
 
-        if (view is MenuItemv2 menuItem)
+        switch (view)
         {
-            menuItem.CanFocus = true;
-
-            AddCommand (menuItem.Command, RaiseAccepted);
+            case MenuItemv2 menuItem:
+            {
+                menuItem.CanFocus = true;
 
-            menuItem.Selecting += MenuItemOnSelecting;
-            menuItem.Accepting += MenuItemOnAccepting;
-            menuItem.Accepted += MenuItemOnAccepted;
+                AddCommand (menuItem.Command, RaiseAccepted);
 
-            void MenuItemOnSelecting (object? sender, CommandEventArgs e)
-            {
-                Logging.Trace ($"Selecting: {e.Context?.Source?.Title}");
-            }
+                menuItem.Accepted += MenuItemOnAccepted;
 
-            void MenuItemOnAccepting (object? sender, CommandEventArgs e)
-            {
-                Logging.Trace ($"Accepting: {e.Context?.Source?.Title}");
-            }
+                break;
 
-            void MenuItemOnAccepted (object? sender, CommandEventArgs e)
-            {
-                Logging.Trace ($"Accepted: {e.Context?.Source?.Title}");
-                RaiseAccepted (e.Context);
+                void MenuItemOnAccepted (object? sender, CommandEventArgs e)
+                {
+                    //Logging.Trace ($"Accepted: {e.Context?.Source?.Title}");
+                    RaiseAccepted (e.Context);
+                }
             }
-        }
+            case Line line:
+                // Grow line so we get auto-join line
+                line.X = Pos.Func (() => -Border!.Thickness.Left);
+                line.Width = Dim.Fill ()! + Dim.Func (() => Border!.Thickness.Right);
 
-        if (view is Line line)
-        {
-            // Grow line so we get autojoin line
-            line.X = Pos.Func (() => -Border!.Thickness.Left);
-            line.Width = Dim.Fill ()! + Dim.Func (() => Border!.Thickness.Right);
+                break;
         }
     }
 
     // TODO: Consider moving Accepted to Bar?
 
     /// <summary>
-    ///     Riases the <see cref="OnAccepted"/>/<see cref="Accepted"/> event indicating an item in this menu (or submenu)
+    ///     Raises the <see cref="OnAccepted"/>/<see cref="Accepted"/> event indicating an item in this menu (or submenu)
     ///     was accepted. This is used to determine when to hide the menu.
     /// </summary>
     /// <param name="ctx"></param>
     /// <returns></returns>
     protected bool? RaiseAccepted (ICommandContext? ctx)
     {
-        Logging.Trace ($"RaiseAccepted: {ctx}");
+        //Logging.Trace ($"RaiseAccepted: {ctx}");
         CommandEventArgs args = new () { Context = ctx };
 
         OnAccepted (args);
@@ -105,7 +99,7 @@ public class Menuv2 : Bar
     }
 
     /// <summary>
-    ///     Called when the user has accepted an item in this menu (or submenu. This is used to determine when to hide the menu.
+    ///     Called when the user has accepted an item in this menu (or submenu). This is used to determine when to hide the menu.
     /// </summary>
     /// <remarks>
     /// </remarks>
@@ -113,7 +107,7 @@ public class Menuv2 : Bar
     protected virtual void OnAccepted (CommandEventArgs args) { }
 
     /// <summary>
-    ///     Raised when the user has accepted an item in this menu (or submenu. This is used to determine when to hide the menu.
+    ///     Raised when the user has accepted an item in this menu (or submenu). This is used to determine when to hide the menu.
     /// </summary>
     /// <remarks>
     /// <para>
@@ -157,7 +151,7 @@ public class Menuv2 : Bar
     }
 
     /// <summary>
-    ///     Called when the the selected menu item has changed.
+    ///     Called when the selected menu item has changed.
     /// </summary>
     /// <param name="selected"></param>
     protected virtual void OnSelectedMenuItemChanged (MenuItemv2? selected)

+ 99 - 73
Terminal.Gui/Views/Menu/PopoverMenu.cs

@@ -1,24 +1,38 @@
 #nullable enable
-using System.Diagnostics;
-
 namespace Terminal.Gui;
 
 /// <summary>
-///     Provides a cascading popover menu.
+///     Provides a cascading menu that pops over all other content. Can be used as a context menu or a drop-down
+///     menu as part of <see cref="MenuBar"/>.
 /// </summary>
-public class PopoverMenu : PopoverBaseImpl
+/// <remarks>
+///     <para>
+///         To use as a context menu, register the popover menu with <see cref="Application.Popover"/> and call
+///         <see cref="MakeVisible"/>.
+///     </para>
+/// </remarks>
+public class PopoverMenu : PopoverBaseImpl, IDesignable
 {
     /// <summary>
     ///     Initializes a new instance of the <see cref="PopoverMenu"/> class.
     /// </summary>
-    public PopoverMenu () : this (null) { }
+    public PopoverMenu () : this ((Menuv2?)null) { }
+
+    /// <inheritdoc/>
+    public PopoverMenu (IEnumerable<View>? menuItems) : this (new Menuv2 (menuItems)) { }
+
+    /// <inheritdoc/>
+    public PopoverMenu (IEnumerable<MenuItemv2>? menuItems) : this (new Menuv2 (menuItems)) { }
 
     /// <summary>
     ///     Initializes a new instance of the <see cref="PopoverMenu"/> class with the specified root <see cref="Menuv2"/>.
     /// </summary>
     public PopoverMenu (Menuv2? root)
     {
+        Key = DefaultKey;
+
         base.Visible = false;
+
         //base.ColorScheme = Colors.ColorSchemes ["Menu"];
 
         Root = root;
@@ -77,11 +91,6 @@ public class PopoverMenu : PopoverBaseImpl
 
         bool? MoveRight (ICommandContext? ctx)
         {
-            if (Focused == Root)
-            {
-                return false;
-            }
-
             if (MostFocused is MenuItemv2 { SubMenu.Visible: true } focused)
             {
                 focused.SubMenu.SetFocus ();
@@ -93,18 +102,36 @@ public class PopoverMenu : PopoverBaseImpl
         }
     }
 
-    /// <summary>
-    ///     The mouse flags that will cause the popover menu to be visible. The default is
-    ///     <see cref="MouseFlags.Button3Clicked"/> which is typically the right mouse button.
-    /// </summary>
-    public static MouseFlags MouseFlags { get; set; } = MouseFlags.Button3Clicked;
+    private Key _key = DefaultKey;
+
+    /// <summary>Specifies the key that will activate the context menu.</summary>
+    public Key Key
+    {
+        get => _key;
+        set
+        {
+            Key oldKey = _key;
+            _key = value;
+            KeyChanged?.Invoke (this, new (oldKey, _key));
+        }
+    }
+
+    /// <summary>Raised when <see cref="Key"/> is changed.</summary>
+    public event EventHandler<KeyChangedEventArgs>? KeyChanged;
 
     /// <summary>The default key for activating popover menus.</summary>
     [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
     public static Key DefaultKey { get; set; } = Key.F10.WithShift;
 
     /// <summary>
-    ///     Makes the popover menu visible and locates it at <paramref name="idealScreenPosition"/>. The actual position of the menu
+    ///     The mouse flags that will cause the popover menu to be visible. The default is
+    ///     <see cref="MouseFlags.Button3Clicked"/> which is typically the right mouse button.
+    /// </summary>
+    public MouseFlags MouseFlags { get; set; } = MouseFlags.Button3Clicked;
+
+    /// <summary>
+    ///     Makes the popover menu visible and locates it at <paramref name="idealScreenPosition"/>. The actual position of the
+    ///     menu
     ///     will be adjusted to
     ///     ensure the menu fully fits on the screen, and the mouse cursor is over the first cell of the
     ///     first MenuItem.
@@ -114,11 +141,12 @@ public class PopoverMenu : PopoverBaseImpl
     {
         UpdateKeyBindings ();
         SetPosition (idealScreenPosition);
-        Application.Popover?.ShowPopover (this);
+        Application.Popover?.Show (this);
     }
 
     /// <summary>
-    ///     Locates the popover menu at <paramref name="idealScreenPosition"/>. The actual position of the menu will be adjusted to
+    ///     Locates the popover menu at <paramref name="idealScreenPosition"/>. The actual position of the menu will be
+    ///     adjusted to
     ///     ensure the menu fully fits on the screen, and the mouse cursor is over the first cell of the
     ///     first MenuItem (if possible).
     /// </summary>
@@ -127,21 +155,24 @@ public class PopoverMenu : PopoverBaseImpl
     {
         idealScreenPosition ??= Application.GetLastMousePosition ();
 
-        if (idealScreenPosition is { } && Root is { })
+        if (idealScreenPosition is null || Root is null)
         {
-            Point pos = idealScreenPosition.Value;
+            return;
+        }
 
-            if (!Root.IsInitialized)
-            {
-                Root.BeginInit();
-                Root.EndInit ();
-                Root.Layout ();
-            }
-            pos = GetMostVisibleLocationForSubMenu (Root, pos);
+        Point pos = idealScreenPosition.Value;
 
-            Root.X = pos.X;
-            Root.Y = pos.Y;
+        if (!Root.IsInitialized)
+        {
+            Root.BeginInit ();
+            Root.EndInit ();
+            Root.Layout ();
         }
+
+        pos = GetMostVisibleLocationForSubMenu (Root, pos);
+
+        Root.X = pos.X;
+        Root.Y = pos.Y;
     }
 
     /// <inheritdoc/>
@@ -156,7 +187,7 @@ public class PopoverMenu : PopoverBaseImpl
         else
         {
             HideAndRemoveSubMenu (_root);
-            Application.Popover?.HidePopover (this);
+            Application.Popover?.Hide (this);
         }
     }
 
@@ -208,48 +239,34 @@ public class PopoverMenu : PopoverBaseImpl
         // TODO: And it needs to clear them first
         IEnumerable<MenuItemv2> all = GetMenuItemsOfAllSubMenus ();
 
-        foreach (MenuItemv2 menuItem in all.Where(mi => mi.Command != Command.NotBound))
+        foreach (MenuItemv2 menuItem in all.Where (mi => mi.Command != Command.NotBound))
         {
+            Key? key;
             if (menuItem.TargetView is { })
             {
                 // A TargetView implies HotKey
-                // Automatically set MenuItem.Key
-                Key? key = menuItem.TargetView.HotKeyBindings.GetFirstFromCommands (menuItem.Command);
-
-                if (key is { IsValid: true })
-                {
-                    if (menuItem.Key.IsValid)
-                    {
-                        //Logging.Warning ("Do not specify a Key for MenuItems where a Command is specified. Key will be determined automatically.");
-                    }
-
-                    menuItem.Key = key;
-                    Logging.Trace ($"HotKey: {menuItem.Key}->{menuItem.Command}");
-                }
+                key = menuItem.TargetView.HotKeyBindings.GetFirstFromCommands (menuItem.Command);
             }
             else
             {
                 // No TargetView implies Application HotKey
-                Key? key = Application.KeyBindings.GetFirstFromCommands (menuItem.Command);
+                key = Application.KeyBindings.GetFirstFromCommands (menuItem.Command);
+            }
 
-                if (key is { IsValid: true })
-                {
-                    if (menuItem.Key.IsValid)
-                    {
-                        // Logging.Warning ("App HotKey: Do not specify a Key for MenuItems where a Command is specified. Key will be determined automatically.");
-                    }
+            if (key is not { IsValid: true })
+            {
+                continue;
+            }
 
-                    menuItem.Key = key;
-                    Logging.Trace ($"App HotKey: {menuItem.Key}->{menuItem.Command}");
-                }
+            if (menuItem.Key.IsValid)
+            {
+                //Logging.Warning ("Do not specify a Key for MenuItems where a Command is specified. Key will be determined automatically.");
             }
-        }
 
-        foreach (MenuItemv2 menuItem in all.Where (mi => mi is { Command: Command.NotBound, Key.IsValid: true }))
-        {
+            menuItem.Key = key;
 
+            //Logging.Trace ($"HotKey: {menuItem.Key}->{menuItem.Command}");
         }
-
     }
 
     /// <inheritdoc/>
@@ -332,14 +349,9 @@ public class PopoverMenu : PopoverBaseImpl
     {
         var menu = menuItem?.SuperView as Menuv2;
 
-        if (menu is { })
-        {
-            menu.Layout ();
-        }
-        // If there's a visible peer, remove / hide it
-
-        // Debug.Assert (menu is null || menu?.SubViews.Count (v => v is MenuItemv2 { SubMenu.Visible: true }) < 2);
+        menu?.Layout ();
 
+        // If there's a visible peer, remove / hide it
         if (menu?.SubViews.FirstOrDefault (v => v is MenuItemv2 { SubMenu.Visible: true }) is MenuItemv2 visiblePeer)
         {
             HideAndRemoveSubMenu (visiblePeer.SubMenu);
@@ -391,7 +403,7 @@ public class PopoverMenu : PopoverBaseImpl
             // TODO: Find the menu item below the mouse, if any, and select it
 
             // TODO: Enable No Border menu style
-            menu.Border.LineStyle = LineStyle.Single;
+            menu.Border!.LineStyle = LineStyle.Single;
             menu.Border.Thickness = new (1);
 
             if (!menu.IsInitialized)
@@ -403,7 +415,6 @@ public class PopoverMenu : PopoverBaseImpl
             menu.ClearFocus ();
             base.Add (menu);
 
-
             // IMPORTANT: This must be done after adding the menu to the super view or Add will try
             // to set focus to it.
             menu.Visible = true;
@@ -417,8 +428,6 @@ public class PopoverMenu : PopoverBaseImpl
         if (menu is { Visible: true })
         {
             // If there's a visible submenu, remove / hide it
-            // Debug.Assert (menu.SubViews.Count (v => v is MenuItemv2 { SubMenu.Visible: true }) <= 1);
-
             if (menu.SubViews.FirstOrDefault (v => v is MenuItemv2 { SubMenu.Visible: true }) is MenuItemv2 visiblePeer)
             {
                 HideAndRemoveSubMenu (visiblePeer.SubMenu);
@@ -448,12 +457,12 @@ public class PopoverMenu : PopoverBaseImpl
             e.Cancel = true;
         }
 
-        Logging.Trace ($"{e.Context?.Source?.Title}");
+        //Logging.Trace ($"{e.Context?.Source?.Title}");
     }
 
     private void MenuAccepted (object? sender, CommandEventArgs e)
     {
-        Logging.Trace ($"{e.Context?.Source?.Title}");
+        //Logging.Trace ($"{e.Context?.Source?.Title}");
 
         if (e.Context?.Source is MenuItemv2 { SubMenu: null })
         {
@@ -467,14 +476,14 @@ public class PopoverMenu : PopoverBaseImpl
     }
 
     /// <summary>
-    ///     Riases the <see cref="OnAccepted"/>/<see cref="Accepted"/> event indicating a menu (or submenu)
+    ///     Raises the <see cref="OnAccepted"/>/<see cref="Accepted"/> event indicating a menu (or submenu)
     ///     was accepted and the Menus in the PopoverMenu were hidden. Use this to determine when to hide the PopoverMenu.
     /// </summary>
     /// <param name="ctx"></param>
     /// <returns></returns>
     protected bool? RaiseAccepted (ICommandContext? ctx)
     {
-        Logging.Trace ($"RaiseAccepted: {ctx}");
+        //Logging.Trace ($"RaiseAccepted: {ctx}");
         CommandEventArgs args = new () { Context = ctx };
 
         OnAccepted (args);
@@ -529,4 +538,21 @@ public class PopoverMenu : PopoverBaseImpl
 
         base.Dispose (disposing);
     }
+
+
+    /// <inheritdoc/>
+    public bool EnableForDesign<TContext> (ref readonly TContext context) where TContext : notnull
+    {
+        Root = new Menuv2 (
+                           [
+                               new MenuItemv2 (this, Command.Cut),
+                               new MenuItemv2 (this, Command.Copy),
+                               new MenuItemv2 (this, Command.Paste),
+                               new Line (),
+                               new MenuItemv2 (this, Command.SelectAll)
+                           ]);
+
+        Visible = true;
+        return true;
+    }
 }

+ 1 - 2
Terminal.Gui/Views/Menu/Menu.cs → Terminal.Gui/Views/Menuv1/Menu.cs

@@ -3,8 +3,7 @@
 namespace Terminal.Gui;
 
 /// <summary>
-///     An internal class used to represent a menu pop-up menu. Created and managed by <see cref="MenuBar"/> and
-///     <see cref="ContextMenu"/>.
+///     An internal class used to represent a menu pop-up menu. Created and managed by <see cref="MenuBar"/>.
 /// </summary>
 internal sealed class Menu : View
 {

+ 0 - 1
Terminal.Gui/Views/Menu/MenuBar.cs → Terminal.Gui/Views/Menuv1/MenuBar.cs

@@ -17,7 +17,6 @@ namespace Terminal.Gui;
 ///         The <see cref="MenuBar"/> appears on the first row of the <see cref="Toplevel"/> SuperView and uses the full
 ///         width.
 ///     </para>
-///     <para>See also: <see cref="ContextMenu"/></para>
 ///     <para>The <see cref="MenuBar"/> provides global hot keys for the application. See <see cref="MenuItem.HotKey"/>.</para>
 ///     <para>
 ///         When the menu is created key bindings for each menu item and its sub-menu items are added for each menu

+ 0 - 0
Terminal.Gui/Views/Menu/MenuBarItem.cs → Terminal.Gui/Views/Menuv1/MenuBarItem.cs


+ 0 - 0
Terminal.Gui/Views/Menu/MenuClosingEventArgs.cs → Terminal.Gui/Views/Menuv1/MenuClosingEventArgs.cs


+ 1 - 1
Terminal.Gui/Views/Menu/MenuItem.cs → Terminal.Gui/Views/Menuv1/MenuItem.cs

@@ -255,7 +255,7 @@ public class MenuItem
 
     /// <summary>
     ///     Shortcut defines a key binding to the MenuItem that will invoke the MenuItem's action globally for the
-    ///     <see cref="View"/> that is the parent of the <see cref="MenuBar"/> or <see cref="ContextMenu"/> this
+    ///     <see cref="View"/> that is the parent of the <see cref="MenuBar"/> this
     ///     <see cref="MenuItem"/>.
     ///     <para>
     ///         The <see cref="Key"/> will be drawn on the MenuItem to the right of the <see cref="Title"/> and

+ 0 - 0
Terminal.Gui/Views/Menu/MenuItemCheckStyle.cs → Terminal.Gui/Views/Menuv1/MenuItemCheckStyle.cs


+ 0 - 0
Terminal.Gui/Views/Menu/MenuOpenedEventArgs.cs → Terminal.Gui/Views/Menuv1/MenuOpenedEventArgs.cs


+ 0 - 0
Terminal.Gui/Views/Menu/MenuOpeningEventArgs.cs → Terminal.Gui/Views/Menuv1/MenuOpeningEventArgs.cs


+ 5 - 5
Terminal.Gui/Views/TextField.cs

@@ -418,9 +418,9 @@ public class TextField : View
     /// <summary>Gets or sets the foreground <see cref="Color"/> to use when rendering <see cref="Caption"/>.</summary>
     public Color CaptionColor { get; set; }
 
-    /// <summary>Get the <see cref="ContextMenu"/> for this view.</summary>
+    /// <summary>Get the Context Menu for this view.</summary>
     [CanBeNull]
-    public ContextMenuv2 ContextMenu { get; private set; }
+    public PopoverMenu ContextMenu { get; private set; }
 
     /// <summary>Sets or gets the current cursor position.</summary>
     public virtual int CursorPosition
@@ -800,7 +800,7 @@ public class TextField : View
             && !ev.Flags.HasFlag (MouseFlags.ReportMousePosition)
             && !ev.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
             && !ev.Flags.HasFlag (MouseFlags.Button1TripleClicked)
-            && !ev.Flags.HasFlag (PopoverMenu.MouseFlags))
+            && !ev.Flags.HasFlag (ContextMenu!.MouseFlags))
         {
             return false;
         }
@@ -900,7 +900,7 @@ public class TextField : View
             ClearAllSelection ();
             PrepareSelection (0, _text.Count);
         }
-        else if (ev.Flags == PopoverMenu.MouseFlags)
+        else if (ev.Flags == ContextMenu!.MouseFlags)
         {
             PositionCursor (ev);
             ShowContextMenu (false);
@@ -1226,7 +1226,7 @@ public class TextField : View
     private void CreateContextMenu ()
     {
         DisposeContextMenu ();
-        ContextMenuv2 menu = new (new List<MenuItemv2> ()
+        PopoverMenu menu = new (new List<MenuItemv2> ()
         {
             new (this, Command.SelectAll, Strings.ctxSelectAll),
             new (this, Command.DeleteAll, Strings.ctxDeleteAll),

+ 11 - 11
Terminal.Gui/Views/TextView.cs

@@ -2490,8 +2490,8 @@ public class TextView : View
     /// </summary>
     public IAutocomplete Autocomplete { get; protected set; } = new TextViewAutocomplete ();
 
-    /// <summary>Get the <see cref="ContextMenuv2"/> for this view.</summary>
-    public ContextMenuv2? ContextMenu { get; private set; }
+    /// <summary>Get the Context Menu.</summary>
+    public PopoverMenu? ContextMenu { get; private set; }
 
     /// <summary>Gets the cursor column.</summary>
     /// <value>The cursor column.</value>
@@ -4148,17 +4148,17 @@ public class TextView : View
 
     private void AppendClipboard (string text) { Clipboard.Contents += text; }
 
-    private ContextMenuv2 CreateContextMenu ()
+    private PopoverMenu CreateContextMenu ()
     {
-        ContextMenuv2 menu = new (new List<MenuItemv2> ()
+        PopoverMenu menu = new (new List<View> ()
                     {
-            new (this, Command.SelectAll, Strings.ctxSelectAll),
-            new (this, Command.DeleteAll, Strings.ctxDeleteAll),
-            new (this, Command.Copy, Strings.ctxCopy),
-            new (this, Command.Cut, Strings.ctxCut),
-            new (this, Command.Paste, Strings.ctxPaste),
-            new (this, Command.Undo, Strings.ctxUndo),
-            new (this, Command.Redo, Strings.ctxRedo),
+            new MenuItemv2 (this, Command.SelectAll, Strings.ctxSelectAll),
+            new MenuItemv2 (this, Command.DeleteAll, Strings.ctxDeleteAll),
+            new MenuItemv2 (this, Command.Copy, Strings.ctxCopy),
+            new MenuItemv2 (this, Command.Cut, Strings.ctxCut),
+            new MenuItemv2 (this, Command.Paste, Strings.ctxPaste),
+            new MenuItemv2 (this, Command.Undo, Strings.ctxUndo),
+            new MenuItemv2 (this, Command.Redo, Strings.ctxRedo),
         });
 
         menu.KeyChanged += ContextMenu_KeyChanged;

+ 22 - 20
TerminalGuiFluentTesting/GuiTestContext.cs

@@ -57,7 +57,7 @@ public class GuiTestContext : IDisposable
                                                                    .CreateLogger ("Test Logging");
                                      Logging.Logger = logger;
 
-                                     v2.Init (null, GetDriverName());
+                                     v2.Init (null, GetDriverName ());
 
                                      booting.Release ();
 
@@ -93,12 +93,12 @@ public class GuiTestContext : IDisposable
     private string GetDriverName ()
     {
         return _driver switch
-               {
-                   V2TestDriver.V2Win => "v2win",
-                   V2TestDriver.V2Net => "v2net",
-                   _ =>
-                       throw new ArgumentOutOfRangeException ()
-               };
+        {
+            V2TestDriver.V2Win => "v2win",
+            V2TestDriver.V2Net => "v2net",
+            _ =>
+                throw new ArgumentOutOfRangeException ()
+        };
     }
 
     /// <summary>
@@ -299,14 +299,14 @@ public class GuiTestContext : IDisposable
             case V2TestDriver.V2Net:
 
                 int netButton = btn switch
-                                {
-                                    WindowsConsole.ButtonState.Button1Pressed => 0,
-                                    WindowsConsole.ButtonState.Button2Pressed => 1,
-                                    WindowsConsole.ButtonState.Button3Pressed => 2,
-                                    WindowsConsole.ButtonState.RightmostButtonPressed => 2,
-                                    _ => throw new ArgumentOutOfRangeException(nameof(btn))
-                                };
-                foreach (var k in NetSequences.Click(netButton,screenX,screenY))
+                {
+                    WindowsConsole.ButtonState.Button1Pressed => 0,
+                    WindowsConsole.ButtonState.Button2Pressed => 1,
+                    WindowsConsole.ButtonState.Button3Pressed => 2,
+                    WindowsConsole.ButtonState.RightmostButtonPressed => 2,
+                    _ => throw new ArgumentOutOfRangeException (nameof (btn))
+                };
+                foreach (var k in NetSequences.Click (netButton, screenX, screenY))
                 {
                     SendNetKey (k);
                 }
@@ -452,18 +452,20 @@ public class GuiTestContext : IDisposable
 
     /// <summary>
     /// Registers a right click handler on the <see cref="LastView"/> added view (or root view) that
-    /// will open the supplied <paramref name="menuItems"/>.
+    /// will open the supplied <paramref name="contextMenu"/>.
     /// </summary>
-    /// <param name="ctx"></param>
-    /// <param name="menuItems"></param>
+    /// <param name="contextMenu"></param>
     /// <returns></returns>
-    public GuiTestContext WithContextMenu (ContextMenu ctx, MenuBarItem menuItems)
+    public GuiTestContext WithContextMenu (PopoverMenu? contextMenu)
     {
         LastView.MouseEvent += (s, e) =>
                                {
                                    if (e.Flags.HasFlag (MouseFlags.Button3Clicked))
                                    {
-                                       ctx.Show (menuItems);
+                                       // Registering with the PopoverManager will ensure that the context menu is closed when the view is no longer focused
+                                       // and the context menu is disposed when it is closed.
+                                       Application.Popover?.Register (contextMenu);
+                                       contextMenu?.MakeVisible (e.ScreenPosition);
                                    }
                                };
 

+ 21 - 35
Tests/IntegrationTests/FluentTests/BasicFluentAssertionTests.cs

@@ -63,22 +63,16 @@ public class BasicFluentAssertionTests
     {
         var clicked = false;
 
-        var ctx = new ContextMenu ();
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new ("_New File", string.Empty, () => { clicked = true; })
-                                         ]
-                                        );
+        MenuItemv2 [] menuItems =  [new ("_New File", string.Empty, () => { clicked = true; })];
 
         using GuiTestContext c = With.A<Window> (40, 10, d)
-                                     .WithContextMenu (ctx, menuItems)
+                                     .WithContextMenu (new PopoverMenu(menuItems))
                                      .ScreenShot ("Before open menu", _out)
 
                                      // Click in main area inside border
                                      .RightClick (1, 1)
                                      .ScreenShot ("After open menu", _out)
-                                     .LeftClick (3, 3)
+                                     .LeftClick (2, 2)
                                      .Stop ()
                                      .WriteOutLogs (_out);
         Assert.True (clicked);
@@ -90,34 +84,26 @@ public class BasicFluentAssertionTests
     {
         var clicked = false;
 
-        var ctx = new ContextMenu ();
-
-
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new MenuItem ("One", "", null),
-                                             new MenuItem ("Two", "", null),
-                                             new MenuItem ("Three", "", null),
-                                             new MenuBarItem (
-                                                              "Four",
-                                                              [
-                                                                  new MenuItem ("SubMenu1", "", null),
-                                                                  new MenuItem ("SubMenu2", "", ()=>clicked=true),
-                                                                  new MenuItem ("SubMenu3", "", null),
-                                                                  new MenuItem ("SubMenu4", "", null),
-                                                                  new MenuItem ("SubMenu5", "", null),
-                                                                  new MenuItem ("SubMenu6", "", null),
-                                                                  new MenuItem ("SubMenu7", "", null)
-                                                              ]
-                                                             ),
-                                             new MenuItem ("Five", "", null),
-                                             new MenuItem ("Six", "", null)
-                                         ]
-                                        );
+        MenuItemv2 [] menuItems = [
+                                      new ("One", "", null),
+                                      new ("Two", "", null),
+                                      new ("Three", "", null),
+                                      new ("Four", "", new (
+                                           [
+                                               new ("SubMenu1", "", null),
+                                               new ("SubMenu2", "", ()=>clicked=true),
+                                               new ("SubMenu3", "", null),
+                                               new ("SubMenu4", "", null),
+                                               new ("SubMenu5", "", null),
+                                               new ("SubMenu6", "", null),
+                                               new ("SubMenu7", "", null)
+                                           ])),
+                                      new  ("Five", "", null),
+                                      new  ("Six", "", null)
+                                  ];
 
         using GuiTestContext c = With.A<Window> (40, 10,d)
-                                     .WithContextMenu (ctx, menuItems)
+                                     .WithContextMenu (new PopoverMenu (menuItems))
                                      .ScreenShot ("Before open menu", _out)
 
                                      // Click in main area inside border

+ 80 - 342
Tests/UnitTests/Application/ApplicationPopoverTests.cs

@@ -5,7 +5,7 @@ namespace Terminal.Gui.ApplicationTests;
 public class ApplicationPopoverTests
 {
     [Fact]
-    public void Popover_ApplicationInit_Inits ()
+    public void ApplicationInit_Initializes_PopoverManager ()
     {
         // Arrange
         Assert.Null (Application.Popover);
@@ -18,7 +18,7 @@ public class ApplicationPopoverTests
     }
 
     [Fact]
-    public void Popover_ApplicationShutdown_CleansUp ()
+    public void Application_Shutdown_CleansUp_PopoverManager ()
     {
         // Arrange
         Assert.Null (Application.Popover);
@@ -34,7 +34,7 @@ public class ApplicationPopoverTests
     }
 
     [Fact]
-    public void Popover_NotCleanedUp_On_End ()
+    public void Application_End_Does_Not_CleanedUp ()
     {
         // Arrange
         Assert.Null (Application.Popover);
@@ -56,7 +56,7 @@ public class ApplicationPopoverTests
     }
 
     [Fact]
-    public void Popover_Active_Hidden_On_End ()
+    public void Application_End_Hides_Active ()
     {
         // Arrange
         Assert.Null (Application.Popover);
@@ -66,9 +66,9 @@ public class ApplicationPopoverTests
         var top = new Toplevel ();
         RunState rs = Application.Begin (top);
 
-        IPopoverTestClass popover = new ();
+        PopoverTestClass popover = new ();
 
-        Application.Popover?.ShowPopover (popover);
+        Application.Popover?.Show (popover);
         Assert.True (popover.Visible);
 
         // Act
@@ -83,17 +83,80 @@ public class ApplicationPopoverTests
         Application.Shutdown ();
     }
 
-    public class IPopoverTestClass : View, IPopover
+    [Fact]
+    public void Application_Shutdown_Disposes_Registered_Popovers ()
+    {
+        // Arrange
+        Assert.Null (Application.Popover);
+        Application.Init (new FakeDriver ());
+
+        PopoverTestClass popover = new ();
+
+        // Act
+        Application.Popover?.Register (popover);
+        Application.Shutdown ();
+
+        // Test
+        Assert.Equal(1, popover.DisposedCount);
+    }
+
+    [Fact]
+    public void Application_Shutdown_Does_Not_Dispose_DeRegistered_Popovers ()
     {
-        public List<Key> HandledKeys { get; } = new List<Key> ();
+        // Arrange
+        Assert.Null (Application.Popover);
+        Application.Init (new FakeDriver ());
+
+        PopoverTestClass popover = new ();
+
+        Application.Popover?.Register (popover);
+
+        // Act
+        Application.Popover?.DeRegister (popover);
+        Application.Shutdown ();
+
+        // Test
+        Assert.Equal (0, popover.DisposedCount);
+
+        popover.Dispose ();
+    }
+
+    [Fact]
+    public void Application_Shutdown_Does_Not_Dispose_ActiveNotRegistered_Popover ()
+    {
+        // Arrange
+        Assert.Null (Application.Popover);
+        Application.Init (new FakeDriver ());
+
+        PopoverTestClass popover = new ();
+
+        Application.Popover?.Show (popover);
+
+        // Act
+        Application.Shutdown ();
+
+        // Test
+        Assert.Equal (0, popover.DisposedCount);
+
+        popover.Dispose ();
+    }
+
+    public class PopoverTestClass : View, IPopover
+    {
+        public List<Key> HandledKeys { get; } = [];
         public int NewCommandInvokeCount { get; private set; }
 
-        public IPopoverTestClass ()
+        // NOTE: Hides the base DisposedCount property
+        public new int DisposedCount { get; private set; }
+
+        public PopoverTestClass ()
         {
             CanFocus = true;
             AddCommand (Command.New, NewCommandHandler);
             HotKeyBindings.Add (Key.N.WithCtrl, Command.New);
 
+            return;
+
             bool? NewCommandHandler (ICommandContext ctx)
             {
                 NewCommandInvokeCount++;
@@ -107,338 +170,13 @@ public class ApplicationPopoverTests
             HandledKeys.Add (key);
             return false;
         }
+
+        /// <inheritdoc />
+        protected override void Dispose (bool disposing)
+        {
+            base.Dispose (disposing);
+            DisposedCount++;
+        }
     }
-    //[Fact]
-    //public void Popover_SetToNull ()
-    //{
-    //    // Arrange
-    //    var popover = new View ();
-    //    Application.Popover = popover;
-
-    //    // Act
-    //    Application.Popover = null;
-
-    //    // Assert
-    //    Assert.Null (Application.Popover);
-
-    //    Application.ResetState (ignoreDisposed: true);
-    //}
-
-    //[Fact]
-    //public void Popover_VisibleChangedEvent ()
-    //{
-    //    // Arrange
-    //    var popover = new View ()
-    //    {
-    //        Visible = false
-    //    };
-    //    Application.Popover = popover;
-    //    bool eventTriggered = false;
-
-    //    popover.VisibleChanged += (sender, e) => eventTriggered = true;
-
-    //    // Act
-    //    popover.Visible = true;
-
-    //    // Assert
-    //    Assert.True (eventTriggered);
-
-    //    Application.ResetState (ignoreDisposed: true);
-    //}
-
-    //[Fact]
-    //public void Popover_InitializesCorrectly ()
-    //{
-    //    // Arrange
-    //    var popover = new View ();
-
-    //    // Act
-    //    Application.Popover = popover;
-
-    //    // Assert
-    //    Assert.True (popover.IsInitialized);
-
-    //    Application.ResetState (ignoreDisposed: true);
-    //}
-
-    //[Fact]
-    //public void Popover_SetsColorScheme ()
-    //{
-    //    // Arrange
-    //    var popover = new View ();
-    //    var topColorScheme = new ColorScheme ();
-    //    Application.Top = new Toplevel { ColorScheme = topColorScheme };
-
-    //    // Act
-    //    Application.Popover = popover;
-
-    //    // Assert
-    //    Assert.Equal (topColorScheme, popover.ColorScheme);
-
-    //    Application.ResetState (ignoreDisposed: true);
-    //}
-
-    //[Fact]
-    //public void Popover_VisibleChangedToTrue_SetsFocus ()
-    //{
-    //    // Arrange
-    //    var popover = new View ()
-    //    {
-    //        Visible = false,
-    //        CanFocus = true
-    //    };
-    //    Application.Popover = popover;
-
-    //    // Act
-    //    popover.Visible = true;
-
-    //    // Assert
-    //    Assert.True (popover.Visible);
-    //    Assert.True (popover.HasFocus);
-
-    //    Application.ResetState (ignoreDisposed: true);
-    //}
-
-    //[Theory]
-    //[InlineData(-1, -1)]
-    //[InlineData (0, 0)]
-    //[InlineData (2048, 2048)]
-    //[InlineData (2049, 2049)]
-    //public void Popover_VisibleChangedToTrue_Locates_In_Visible_Position (int x, int y)
-    //{
-    //    // Arrange
-    //    var popover = new View ()
-    //    {
-    //        X = x,
-    //        Y = y,
-    //        Visible = false,
-    //        CanFocus = true,
-    //        Width = 1,
-    //        Height = 1
-    //    };
-    //    Application.Popover = popover;
-
-    //    // Act
-    //    popover.Visible = true;
-    //    Application.LayoutAndDraw();
-
-    //    // Assert
-    //    Assert.True (Application.Screen.Contains (popover.Frame));
-
-    //    Application.ResetState (ignoreDisposed: true);
-    //}
-
-    //[Fact]
-    //public void Popover_VisibleChangedToFalse_Hides_And_Removes_Focus ()
-    //{
-    //    // Arrange
-    //    var popover = new View ()
-    //    {
-    //        Visible = false,
-    //        CanFocus = true
-    //    };
-    //    Application.Popover = popover;
-    //    popover.Visible = true;
-
-    //    // Act
-    //    popover.Visible = false;
-
-    //    // Assert
-    //    Assert.False (popover.Visible);
-    //    Assert.False (popover.HasFocus);
-
-    //    Application.ResetState (ignoreDisposed: true);
-    //}
-
-    //[Fact]
-    //public void Popover_Quit_Command_Hides ()
-    //{
-    //    // Arrange
-    //    var popover = new View ()
-    //    {
-    //        Visible = false,
-    //        CanFocus = true
-    //    };
-    //    Application.Popover = popover;
-    //    popover.Visible = true;
-    //    Assert.True (popover.Visible);
-    //    Assert.True (popover.HasFocus);
-
-    //    // Act
-    //    Application.RaiseKeyDownEvent (Application.QuitKey);
-
-    //    // Assert
-    //    Assert.False (popover.Visible);
-    //    Assert.False (popover.HasFocus);
-
-    //    Application.ResetState (ignoreDisposed: true);
-    //}
-
-    //[Fact]
-    //public void Popover_MouseClick_Outside_Hides_Passes_Event_On ()
-    //{
-    //    // Arrange
-    //    Application.Top = new Toplevel ()
-    //    {
-    //        Id = "top",
-    //        Height = 10,
-    //        Width = 10,
-    //    };
-
-    //    View otherView = new ()
-    //    {
-    //        X = 1,
-    //        Y = 1,
-    //        Height = 1,
-    //        Width = 1,
-    //        Id = "otherView",
-    //    };
-
-    //    bool otherViewPressed = false;
-    //    otherView.MouseEvent += (sender, e) =>
-    //                            {
-    //                                otherViewPressed = e.Flags.HasFlag(MouseFlags.Button1Pressed);
-    //                            };
-
-    //    Application.Top.Add (otherView);
-
-    //    var popover = new View ()
-    //    {
-    //        Id = "popover",
-    //        X = 5,
-    //        Y = 5,
-    //        Width = 1,
-    //        Height = 1,
-    //        Visible = false,
-    //        CanFocus = true
-    //    };
-
-    //    Application.Popover = popover;
-    //    popover.Visible = true;
-    //    Assert.True (popover.Visible);
-    //    Assert.True (popover.HasFocus);
-
-    //    // Act
-    //    // Click on popover
-    //    Application.RaiseMouseEvent (new () { Flags = MouseFlags.Button1Pressed, ScreenPosition = new (5, 5) });
-    //    Assert.True (popover.Visible);
-
-    //    // Click outside popover (on button)
-    //    Application.RaiseMouseEvent (new () { Flags = MouseFlags.Button1Pressed, ScreenPosition = new (1, 1) });
-
-    //    // Assert
-    //    Assert.True (otherViewPressed);
-    //    Assert.False (popover.Visible);
-
-    //    Application.Top.Dispose ();
-    //    Application.ResetState (ignoreDisposed: true);
-    //}
-
-    //[Theory]
-    //[InlineData (0, 0, false)]
-    //[InlineData (5, 5, true)]
-    //[InlineData (10, 10, false)]
-    //[InlineData (5, 10, false)]
-    //[InlineData (9, 9, false)]
-    //public void Popover_MouseClick_Outside_Hides (int mouseX, int mouseY, bool expectedVisible)
-    //{
-    //    // Arrange
-    //    Application.Top = new Toplevel ()
-    //    {
-    //        Id = "top",
-    //        Height = 10,
-    //        Width = 10,
-    //    };
-    //    var popover = new View ()
-    //    {
-    //        Id = "popover",
-    //        X = 5,
-    //        Y = 5,
-    //        Width = 1,
-    //        Height = 1,
-    //        Visible = false,
-    //        CanFocus = true
-    //    };
-
-    //    Application.Popover = popover;
-    //    popover.Visible = true;
-    //    Assert.True (popover.Visible);
-    //    Assert.True (popover.HasFocus);
-
-    //    // Act
-    //    Application.RaiseMouseEvent (new () { Flags = MouseFlags.Button1Pressed, ScreenPosition = new (mouseX, mouseY) });
-
-    //    // Assert
-    //    Assert.Equal (expectedVisible, popover.Visible);
-
-    //    Application.Top.Dispose ();
-    //    Application.ResetState (ignoreDisposed: true);
-    //}
-
-    //[Fact]
-    //public void Popover_SetAndGet_ReturnsCorrectValue ()
-    //{
-    //    // Arrange
-    //    var view = new View ();
-
-    //    // Act
-    //    Application.Popover = view;
-
-    //    // Assert
-    //    Assert.Equal (view, Application.Popover);
-
-    //    Application.ResetState (ignoreDisposed: true);
-    //}
-
-    //[Fact]
-    //public void Popover_SetToNull_HidesPreviousPopover ()
-    //{
-    //    // Arrange
-    //    var view = new View { Visible = true };
-    //    Application.Popover = view;
-
-    //    // Act
-    //    Application.Popover = null;
-
-    //    // Assert
-    //    Assert.False (view.Visible);
-    //    Assert.Null (Application.Popover);
-
-    //    Application.ResetState (ignoreDisposed: true);
-    //}
-
-    //[Fact]
-    //public void Popover_SetNewPopover_HidesPreviousPopover ()
-    //{
-    //    // Arrange
-    //    var oldView = new View { Visible = true };
-    //    var newView = new View ();
-    //    Application.Popover = oldView;
-
-    //    // Act
-    //    Application.Popover = newView;
-
-    //    // Assert
-    //    Assert.False (oldView.Visible);
-    //    Assert.Equal (newView, Application.Popover);
-
-    //    Application.ResetState (ignoreDisposed: true);
-    //}
-
-    //[Fact]
-    //public void Popover_SetNewPopover_InitializesAndSetsProperties ()
-    //{
-    //    // Arrange
-    //    var view = new View ();
-
-    //    // Act
-    //    Application.Popover = view;
-
-    //    // Assert
-    //    Assert.True (view.IsInitialized);
-    //    Assert.True (view.Arrangement.HasFlag (ViewArrangement.Overlapped));
-    //    Assert.Equal (Application.Top?.ColorScheme, view.ColorScheme);
-
-    //    Application.ResetState (ignoreDisposed: true);
-    //}
+
 }

+ 0 - 2218
Tests/UnitTests/Views/ContextMenuTests.cs

@@ -1,2218 +0,0 @@
-using UnitTests;
-using Xunit.Abstractions;
-
-namespace Terminal.Gui.ViewsTests;
-
-public class ContextMenuTests (ITestOutputHelper output)
-{
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void ContextMenu_Constructors ()
-    {
-        var cm = new ContextMenu ();
-        var top = new Toplevel ();
-        Application.Begin (top);
-
-        Assert.Equal (Point.Empty, cm.Position);
-        Assert.Null (cm.MenuItems);
-        Assert.Null (cm.Host);
-        cm.Position = new Point (20, 10);
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new MenuItem ("First", "", null)
-                                         ]
-                                        );
-        cm.Show (menuItems);
-        Assert.Equal (new Point (20, 10), cm.Position);
-        Assert.Single (cm.MenuItems!.Children);
-
-        cm = new ContextMenu
-        {
-            Position = new Point (5, 10)
-        };
-
-        menuItems = new MenuBarItem (
-                                     new [] { new MenuItem ("One", "", null), new MenuItem ("Two", "", null) }
-                                    );
-        cm.Show (menuItems);
-        Assert.Equal (new Point (5, 10), cm.Position);
-        Assert.Equal (2, cm.MenuItems!.Children.Length);
-        Assert.Null (cm.Host);
-
-        var view = new View { X = 5, Y = 10 };
-        top.Add (view);
-
-        cm = new ContextMenu
-        {
-            Host = view,
-            Position = new Point (5, 10)
-        };
-
-        menuItems = new MenuBarItem (
-                                     new [] { new MenuItem ("One", "", null), new MenuItem ("Two", "", null) }
-                                    );
-        cm.Show (menuItems);
-        Assert.Equal (new Point (5, 10), cm.Position);
-        Assert.Equal (2, cm.MenuItems.Children.Length);
-        Assert.NotNull (cm.Host);
-
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void ContextMenu_Is_Closed_If_Another_MenuBar_Is_Open_Or_Vice_Versa ()
-    {
-        var cm = new ContextMenu
-        {
-            Position = new Point (10, 5)
-        };
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new MenuItem ("One", "", null),
-                                             new MenuItem ("Two", "", null)
-                                         ]
-                                        );
-
-        var menuBar = new MenuBar
-        {
-            Menus =
-            [
-                new MenuBarItem ("File", "", null),
-                new MenuBarItem ("Edit", "", null)
-            ]
-        };
-
-        var top = new Toplevel ();
-        top.Add (menuBar);
-        Application.Begin (top);
-
-        Assert.Null (Application.MouseGrabView);
-
-        cm.Show (menuItems);
-        Assert.True (ContextMenu.IsShow);
-        Menu menu = (Menu)top.SubViews.First (v => v is Menu);
-        Assert.Equal (menu, Application.MouseGrabView);
-        Assert.False (menuBar.IsMenuOpen);
-        Assert.True (menuBar.NewKeyDownEvent (menuBar.Key));
-        Assert.False (ContextMenu.IsShow);
-        Assert.Equal (menuBar, Application.MouseGrabView);
-        Assert.True (menuBar.IsMenuOpen);
-
-        cm.Show (menuItems);
-        Assert.True (ContextMenu.IsShow);
-        menu = (Menu)top.SubViews.First (v => v is Menu);
-        Assert.Equal (menu, Application.MouseGrabView);
-        Assert.False (menuBar.IsMenuOpen);
-#if SUPPORT_ALT_TO_ACTIVATE_MENU
-        Assert.True (Application.Top.ProcessKeyUp (new (Key.AltMask)));
-        Assert.False (ContextMenu.IsShow);
-        Assert.Equal (menu, Application.MouseGrabView);
-        Assert.True (menu.IsMenuOpen);
-#endif
-
-        cm.Show (menuItems);
-        Assert.True (ContextMenu.IsShow);
-        menu = (Menu)top.SubViews.First (v => v is Menu);
-        Assert.Equal (menu, Application.MouseGrabView);
-        Assert.False (menuBar.IsMenuOpen);
-        Assert.False (menuBar.NewMouseEvent (new MouseEventArgs { Position = new (1, 0), Flags = MouseFlags.ReportMousePosition, View = menuBar }));
-        Assert.True (ContextMenu.IsShow);
-        Assert.Equal (menu, Application.MouseGrabView);
-        Assert.False (menuBar.IsMenuOpen);
-        Assert.True (menuBar.NewMouseEvent (new MouseEventArgs { Position = new (1, 0), Flags = MouseFlags.Button1Clicked, View = menuBar }));
-        Assert.False (ContextMenu.IsShow);
-        Assert.Equal (menuBar, Application.MouseGrabView);
-        Assert.True (menuBar.IsMenuOpen);
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "#3798 Broke. Will fix in #2975")]
-    [AutoInitShutdown]
-    public void Draw_A_ContextMenu_Over_A_Borderless_Top ()
-    {
-        ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
-
-        Assert.Equal (new Rectangle (0, 0, 20, 15), View.GetClip ()!.GetBounds ());
-        DriverAssert.AssertDriverContentsWithFrameAre ("", output);
-
-        var top = new Toplevel { X = 2, Y = 2, Width = 15, Height = 4 };
-        top.Add (new TextField { X = Pos.Center (), Width = 10, Text = "Test" });
-        RunState rs = Application.Begin (top);
-        Application.RunIteration (ref rs);
-
-        Assert.Equal (new Rectangle (2, 2, 15, 4), top.Frame);
-        Assert.Equal (top, Application.Top);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-    Test",
-                                                      output
-                                                     );
-
-        Application.RaiseMouseEvent (new MouseEventArgs { ScreenPosition = new (8, 2), Flags = MouseFlags.Button3Clicked });
-
-        Application.RunIteration (ref rs);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-    Test            
-┌───────────────────
-│ Select All   Ctrl+
-│ Delete All   Ctrl+
-│ Copy         Ctrl+
-│ Cut          Ctrl+
-│ Paste        Ctrl+
-│ Undo         Ctrl+
-│ Redo         Ctrl+
-└───────────────────",
-                                                      output
-                                                     );
-
-        Application.End (rs);
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "#3798 Broke. Will fix in #2975")]
-    [AutoInitShutdown]
-    public void Draw_A_ContextMenu_Over_A_Dialog ()
-    {
-        Toplevel top = new ();
-        var win = new Window ();
-        top.Add (win);
-        RunState rsTop = Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
-
-        Assert.Equal (new Rectangle (0, 0, 20, 15), win.Frame);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-┌──────────────────┐
-│                  │
-│                  │
-│                  │
-│                  │
-│                  │
-│                  │
-│                  │
-│                  │
-│                  │
-│                  │
-│                  │
-│                  │
-│                  │
-└──────────────────┘",
-                                                      output
-                                                     );
-
-        // Don't use Dialog here as it has more layout logic. Use Window instead.
-        var testWindow = new Window { X = 2, Y = 2, Width = 15, Height = 4 };
-        testWindow.Add (new TextField { X = Pos.Center (), Width = 10, Text = "Test" });
-        RunState rsDialog = Application.Begin (testWindow);
-        Application.LayoutAndDraw ();
-
-        Assert.Equal (new Rectangle (2, 2, 15, 4), testWindow.Frame);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-┌──────────────────┐
-│                  │
-│ ┌─────────────┐  │
-│ │ Test        │  │
-│ │             │  │
-│ └─────────────┘  │
-│                  │
-│                  │
-│                  │
-│                  │
-│                  │
-│                  │
-│                  │
-│                  │
-└──────────────────┘",
-                                                      output
-                                                     );
-
-        Application.RaiseMouseEvent (new MouseEventArgs { ScreenPosition = new (9, 3), Flags = MouseFlags.Button3Clicked });
-
-        Application.RunIteration (ref rsDialog);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-┌──────────────────┐
-│                  │
-│ ┌─────────────┐  │
-│ │ Test        │  │
-┌───────────────────
-│ Select All   Ctrl+
-│ Delete All   Ctrl+
-│ Copy         Ctrl+
-│ Cut          Ctrl+
-│ Paste        Ctrl+
-│ Undo         Ctrl+
-│ Redo         Ctrl+
-└───────────────────
-│                  │
-└──────────────────┘",
-                                                      output
-                                                     );
-
-        Application.End (rsDialog);
-        Application.End (rsTop);
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "#3798 Broke. Will fix in #2975")]
-    [AutoInitShutdown]
-    public void Draw_A_ContextMenu_Over_A_Top_Dialog ()
-    {
-        ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
-
-        Assert.Equal (new Rectangle (0, 0, 20, 15), View.GetClip ()!.GetBounds ());
-        DriverAssert.AssertDriverContentsWithFrameAre ("", output);
-
-        // Don't use Dialog here as it has more layout logic. Use Window instead.
-        var dialog = new Window { X = 2, Y = 2, Width = 15, Height = 4 };
-        dialog.Add (new TextField { X = Pos.Center (), Width = 10, Text = "Test" });
-        RunState rs = Application.Begin (dialog);
-        Application.LayoutAndDraw ();
-
-        Assert.Equal (new Rectangle (2, 2, 15, 4), dialog.Frame);
-        Assert.Equal (dialog, Application.Top);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-  ┌─────────────┐
-  │ Test        │
-  │             │
-  └─────────────┘",
-                                                      output
-                                                     );
-
-        Application.RaiseMouseEvent (new MouseEventArgs { ScreenPosition = new (9, 3), Flags = MouseFlags.Button3Clicked });
-
-        var firstIteration = false;
-        Application.RunIteration (ref rs, firstIteration);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-  ┌─────────────┐   
-  │ Test        │   
-┌───────────────────
-│ Select All   Ctrl+
-│ Delete All   Ctrl+
-│ Copy         Ctrl+
-│ Cut          Ctrl+
-│ Paste        Ctrl+
-│ Undo         Ctrl+
-│ Redo         Ctrl+
-└───────────────────",
-                                                      output
-                                                     );
-
-        Application.End (rs);
-        dialog.Dispose ();
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void ForceMinimumPosToZero_True_False ()
-    {
-        var cm = new ContextMenu
-        {
-            Position = new Point (-1, -2)
-        };
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new MenuItem ("One", "", null),
-                                             new MenuItem ("Two", "", null)
-                                         ]
-                                        );
-        Assert.Equal (new Point (-1, -2), cm.Position);
-
-        Toplevel top = new ();
-        Application.Begin (top);
-
-        cm.Show (menuItems);
-        Assert.Equal (new Point (-1, -2), cm.Position);
-        Application.LayoutAndDraw ();
-
-        var expected = @"
-┌──────┐
-│ One  │
-│ Two  │
-└──────┘
-";
-
-        Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
-        Assert.Equal (new Rectangle (0, 1, 8, 4), pos);
-
-        cm.ForceMinimumPosToZero = false;
-        cm.Show (menuItems);
-        Assert.Equal (new Point (-1, -2), cm.Position);
-        Application.LayoutAndDraw ();
-
-        expected = @"
- One  │
- Two  │
-──────┘
-";
-
-        pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
-        Assert.Equal (new Rectangle (1, 0, 7, 3), pos);
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void Hide_Is_Invoke_At_Container_Closing ()
-    {
-        var cm = new ContextMenu
-        {
-            Position = new Point (80, 25)
-        };
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new MenuItem ("One", "", null),
-                                             new MenuItem ("Two", "", null)
-                                         ]
-                                        );
-        Toplevel top = new ();
-        Application.Begin (top);
-        top.Running = true;
-
-        Assert.False (ContextMenu.IsShow);
-
-        cm.Show (menuItems);
-        Assert.True (ContextMenu.IsShow);
-
-        top.RequestStop ();
-        Assert.False (ContextMenu.IsShow);
-        top.Dispose ();
-    }
-
-    //[Fact (Skip = "Redo for CMv2")]
-    //[AutoInitShutdown]
-    //public void Key_Open_And_Close_The_ContextMenu ()
-    //{
-    //    var tf = new TextField ();
-    //    var top = new Toplevel ();
-    //    top.Add (tf);
-    //    Application.Begin (top);
-
-    //    Assert.True (Application.RaiseKeyDownEvent (ContextMenu.DefaultKey));
-    //    Assert.True (tf.ContextMenu.MenuBar!.IsMenuOpen);
-    //    Assert.True (Application.RaiseKeyDownEvent (ContextMenu.DefaultKey));
-
-    //    // The last context menu bar opened is always preserved
-    //    Assert.False (tf.ContextMenu.Visible);
-    //    top.Dispose ();
-    //}
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void KeyChanged_Event ()
-    {
-        var oldKey = Key.Empty;
-        var cm = new ContextMenu ();
-
-        cm.KeyChanged += (s, e) => oldKey = e.OldKey;
-
-        cm.Key = Key.Space.WithCtrl;
-        Assert.Equal (Key.Space.WithCtrl, cm.Key);
-        Assert.Equal (ContextMenu.DefaultKey, oldKey);
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void MenuItens_Changing ()
-    {
-        var cm = new ContextMenu
-        {
-            Position = new Point (10, 5)
-        };
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new MenuItem ("One", "", null),
-                                             new MenuItem ("Two", "", null)
-                                         ]
-                                        );
-        Toplevel top = new ();
-        Application.Begin (top);
-        cm.Show (menuItems);
-        Application.LayoutAndDraw ();
-
-        var expected = @"
-          ┌──────┐
-          │ One  │
-          │ Two  │
-          └──────┘
-";
-
-        DriverAssert.AssertDriverContentsAre (expected, output);
-
-        menuItems = new MenuBarItem (
-                                     [
-                                         new MenuItem ("First", "", null),
-                                         new MenuItem ("Second", "", null),
-                                         new MenuItem ("Third", "", null)
-                                     ]
-                                    );
-
-        cm.Show (menuItems);
-        Application.LayoutAndDraw ();
-
-        expected = @"
-          ┌─────────┐
-          │ First   │
-          │ Second  │
-          │ Third   │
-          └─────────┘
-";
-
-        DriverAssert.AssertDriverContentsAre (expected, output);
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void Menus_And_SubMenus_Always_Try_To_Be_On_Screen ()
-    {
-        var cm = new ContextMenu
-        {
-            Position = new Point (-1, -2)
-        };
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new MenuItem ("One", "", null),
-                                             new MenuItem ("Two", "", null),
-                                             new MenuItem ("Three", "", null),
-                                             new MenuBarItem (
-                                                              "Four",
-                                                              [
-                                                                  new MenuItem ("SubMenu1", "", null),
-                                                                  new MenuItem ("SubMenu2", "", null),
-                                                                  new MenuItem ("SubMenu3", "", null),
-                                                                  new MenuItem ("SubMenu4", "", null),
-                                                                  new MenuItem ("SubMenu5", "", null),
-                                                                  new MenuItem ("SubMenu6", "", null),
-                                                                  new MenuItem ("SubMenu7", "", null)
-                                                              ]
-                                                             ),
-                                             new MenuItem ("Five", "", null),
-                                             new MenuItem ("Six", "", null)
-                                         ]
-                                        );
-        Assert.Equal (new Point (-1, -2), cm.Position);
-
-        Toplevel top = new ();
-        RunState rs = Application.Begin (top);
-
-        cm.Show (menuItems);
-        Application.RunIteration (ref rs);
-
-        Assert.Equal (new Point (-1, -2), cm.Position);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-┌────────┐
-│ One    │
-│ Two    │
-│ Three  │
-│ Four  ►│
-│ Five   │
-│ Six    │
-└────────┘
-",
-                                                      output
-                                                     );
-
-        View menu = top.SubViews.First (v => v is Menu);
-
-        Assert.True (
-                     menu
-                        .NewMouseEvent (
-                                        new MouseEventArgs { Position = new (0, 3), Flags = MouseFlags.ReportMousePosition, View = menu }
-                                       )
-                    );
-        Application.RunIteration (ref rs);
-        Assert.Equal (new Point (-1, -2), cm.Position);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-┌────────┐             
-│ One    │             
-│ Two    │             
-│ Three  │             
-│ Four  ►│┌───────────┐
-│ Five   ││ SubMenu1  │
-│ Six    ││ SubMenu2  │
-└────────┘│ SubMenu3  │
-          │ SubMenu4  │
-          │ SubMenu5  │
-          │ SubMenu6  │
-          │ SubMenu7  │
-          └───────────┘
-",
-                                                      output
-                                                     );
-
-        ((FakeDriver)Application.Driver!).SetBufferSize (40, 20);
-        cm.Position = new Point (41, -2);
-        cm.Show (menuItems);
-        Application.RunIteration (ref rs);
-        Assert.Equal (new Point (41, -2), cm.Position);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-                              ┌────────┐
-                              │ One    │
-                              │ Two    │
-                              │ Three  │
-                              │ Four  ►│
-                              │ Five   │
-                              │ Six    │
-                              └────────┘
-",
-                                                      output
-                                                     );
-
-        menu = top.SubViews.First (v => v is Menu);
-        Assert.True (
-                     menu
-                        .NewMouseEvent (
-                                        new MouseEventArgs { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = menu }
-                                       )
-                    );
-        Application.RunIteration (ref rs);
-        Assert.Equal (new Point (41, -2), cm.Position);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-                              ┌────────┐
-                              │ One    │
-                              │ Two    │
-                              │ Three  │
-                 ┌───────────┐│ Four  ►│
-                 │ SubMenu1  ││ Five   │
-                 │ SubMenu2  ││ Six    │
-                 │ SubMenu3  │└────────┘
-                 │ SubMenu4  │          
-                 │ SubMenu5  │          
-                 │ SubMenu6  │          
-                 │ SubMenu7  │          
-                 └───────────┘          
-",
-                                                      output
-                                                     );
-
-        cm.Position = new Point (41, 9);
-        cm.Show (menuItems);
-        Application.RunIteration (ref rs);
-        Assert.Equal (new Point (41, 9), cm.Position);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-                              ┌────────┐
-                              │ One    │
-                              │ Two    │
-                              │ Three  │
-                              │ Four  ►│
-                              │ Five   │
-                              │ Six    │
-                              └────────┘
-",
-                                                      output
-                                                     );
-
-        menu = top.SubViews.First (v => v is Menu);
-        Assert.True (
-                     menu
-                        .NewMouseEvent (
-                                        new MouseEventArgs { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = menu }
-                                       )
-                    );
-        Application.RunIteration (ref rs);
-        Assert.Equal (new Point (41, 9), cm.Position);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-                              ┌────────┐
-                 ┌───────────┐│ One    │
-                 │ SubMenu1  ││ Two    │
-                 │ SubMenu2  ││ Three  │
-                 │ SubMenu3  ││ Four  ►│
-                 │ SubMenu4  ││ Five   │
-                 │ SubMenu5  ││ Six    │
-                 │ SubMenu6  │└────────┘
-                 │ SubMenu7  │          
-                 └───────────┘          
-",
-                                                      output
-                                                     );
-
-        cm.Position = new Point (41, 22);
-        cm.Show (menuItems);
-        Application.RunIteration (ref rs);
-        Assert.Equal (new Point (41, 22), cm.Position);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-                              ┌────────┐
-                              │ One    │
-                              │ Two    │
-                              │ Three  │
-                              │ Four  ►│
-                              │ Five   │
-                              │ Six    │
-                              └────────┘
-",
-                                                      output
-                                                     );
-
-        menu = top.SubViews.First (v => v is Menu);
-        Assert.True (
-                     menu
-                        .NewMouseEvent (
-                                        new MouseEventArgs { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = menu }
-                                       )
-                    );
-        Application.RunIteration (ref rs);
-        Assert.Equal (new Point (41, 22), cm.Position);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-                 ┌───────────┐          
-                 │ SubMenu1  │┌────────┐
-                 │ SubMenu2  ││ One    │
-                 │ SubMenu3  ││ Two    │
-                 │ SubMenu4  ││ Three  │
-                 │ SubMenu5  ││ Four  ►│
-                 │ SubMenu6  ││ Five   │
-                 │ SubMenu7  ││ Six    │
-                 └───────────┘└────────┘
-",
-                                                      output
-                                                     );
-
-        ((FakeDriver)Application.Driver!).SetBufferSize (18, 8);
-        cm.Position = new Point (19, 10);
-        cm.Show (menuItems);
-        Application.RunIteration (ref rs);
-        Assert.Equal (new Point (19, 10), cm.Position);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-        ┌────────┐
-        │ One    │
-        │ Two    │
-        │ Three  │
-        │ Four  ►│
-        │ Five   │
-        │ Six    │
-        └────────┘
-",
-                                                      output
-                                                     );
-
-        menu = top.SubViews.First (v => v is Menu);
-        Assert.True (
-                     menu
-                        .NewMouseEvent (
-                                        new MouseEventArgs { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = menu }
-                                       )
-                    );
-        Application.RunIteration (ref rs);
-        Assert.Equal (new Point (19, 10), cm.Position);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-┌───────────┐────┐
-│ SubMenu1  │    │
-│ SubMenu2  │    │
-│ SubMenu3  │ee  │
-│ SubMenu4  │r  ►│
-│ SubMenu5  │e   │
-│ SubMenu6  │    │
-│ SubMenu7  │────┘
-",
-                                                      output
-                                                     );
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void MouseFlags_Changing ()
-    {
-        var lbl = new Label { Text = "Original" };
-
-        var cm = new ContextMenu ();
-
-        lbl.MouseClick += (s, e) =>
-                          {
-                              if (e.Flags == cm.MouseFlags)
-                              {
-                                  lbl.Text = "Replaced";
-                                  e.Handled = true;
-                              }
-                          };
-
-        Toplevel top = new ();
-        top.Add (lbl);
-        Application.Begin (top);
-
-        Assert.True (lbl.NewMouseEvent (new MouseEventArgs { Flags = cm.MouseFlags }));
-        Assert.Equal ("Replaced", lbl.Text);
-
-        lbl.Text = "Original";
-        cm.MouseFlags = MouseFlags.Button2Clicked;
-        Assert.True (lbl.NewMouseEvent (new MouseEventArgs { Flags = cm.MouseFlags }));
-        Assert.Equal ("Replaced", lbl.Text);
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    public void MouseFlagsChanged_Event ()
-    {
-        var oldMouseFlags = new MouseFlags ();
-        var cm = new ContextMenu ();
-
-        cm.MouseFlagsChanged += (s, e) => oldMouseFlags = e.OldValue;
-
-        cm.MouseFlags = MouseFlags.Button2Clicked;
-        Assert.Equal (MouseFlags.Button2Clicked, cm.MouseFlags);
-        Assert.Equal (MouseFlags.Button3Clicked, oldMouseFlags);
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void Position_Changing ()
-    {
-        var cm = new ContextMenu
-        {
-            Position = new Point (10, 5)
-        };
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new MenuItem ("One", "", null),
-                                             new MenuItem ("Two", "", null)
-                                         ]
-                                        );
-        Toplevel top = new ();
-        Application.Begin (top);
-        cm.Show (menuItems);
-        Application.LayoutAndDraw ();
-
-        var expected = @"
-          ┌──────┐
-          │ One  │
-          │ Two  │
-          └──────┘
-";
-
-        DriverAssert.AssertDriverContentsAre (expected, output);
-
-        cm.Position = new Point (5, 10);
-
-        cm.Show (menuItems);
-        Application.LayoutAndDraw ();
-
-        expected = @"
-     ┌──────┐
-     │ One  │
-     │ Two  │
-     └──────┘
-";
-
-        DriverAssert.AssertDriverContentsAre (expected, output);
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void RequestStop_While_ContextMenu_Is_Open_Does_Not_Throws ()
-    {
-        ContextMenu cm = new ContextMenu
-        {
-            Position = new Point (10, 5)
-        };
-
-        var menuItems = new MenuBarItem (
-                                         new MenuItem [] { new ("One", "", null), new ("Two", "", null) }
-                                        );
-        Toplevel top = new ();
-        var isMenuAllClosed = false;
-        MenuBarItem mi = null;
-        int iterations = -1;
-
-        Application.Iteration += (s, a) =>
-                                 {
-                                     iterations++;
-
-                                     if (iterations == 0)
-                                     {
-                                         cm.Show (menuItems);
-                                         Assert.True (ContextMenu.IsShow);
-                                         mi = cm.MenuBar.Menus [0];
-
-                                         mi.Action = () =>
-                                                     {
-                                                         Assert.True (ContextMenu.IsShow);
-
-                                                         var dialog1 = new Dialog () { Id = "dialog1" };
-                                                         Application.Run (dialog1);
-                                                         dialog1.Dispose ();
-                                                         Assert.False (ContextMenu.IsShow);
-                                                         Assert.True (isMenuAllClosed);
-                                                     };
-                                         cm.MenuBar.MenuAllClosed += (_, _) => isMenuAllClosed = true;
-                                     }
-                                     else if (iterations == 1)
-                                     {
-                                         mi.Action ();
-                                     }
-                                     else if (iterations == 2)
-                                     {
-                                         Application.RequestStop ();
-                                     }
-                                     else if (iterations == 3)
-                                     {
-                                         isMenuAllClosed = false;
-                                         cm.Show (menuItems);
-                                         Assert.True (ContextMenu.IsShow);
-                                         cm.MenuBar.MenuAllClosed += (_, _) => isMenuAllClosed = true;
-                                     }
-                                     else if (iterations == 4)
-                                     {
-                                         Exception exception = Record.Exception (() => Application.RequestStop ());
-                                         Assert.Null (exception);
-                                     }
-                                     else
-                                     {
-                                         Application.RequestStop ();
-                                     }
-                                 };
-
-        var isTopClosed = false;
-
-        top.Closing += (_, _) =>
-                       {
-                           var dialog2 = new Dialog () { Id = "dialog2" };
-                           Application.Run (dialog2);
-                           dialog2.Dispose ();
-                           Assert.False (ContextMenu.IsShow);
-                           Assert.True (isMenuAllClosed);
-                           isTopClosed = true;
-                       };
-
-        Application.Run (top);
-
-        Assert.True (isTopClosed);
-        Assert.False (ContextMenu.IsShow);
-        Assert.True (isMenuAllClosed);
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void Show_Display_At_Zero_If_The_Toplevel_Height_Is_Less_Than_The_Menu_Height ()
-    {
-        ((FakeDriver)Application.Driver!).SetBufferSize (80, 3);
-
-        var cm = new ContextMenu
-        {
-            Position = Point.Empty
-        };
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new MenuItem ("One", "", null),
-                                             new MenuItem ("Two", "", null)
-                                         ]
-                                        );
-        Assert.Equal (Point.Empty, cm.Position);
-
-        Toplevel top = new ();
-        Application.Begin (top);
-        cm.Show (menuItems);
-        Assert.Equal (Point.Empty, cm.Position);
-        Application.LayoutAndDraw ();
-
-        var expected = @"
-┌──────┐
-│ One  │
-│ Two  │";
-
-        Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
-        Assert.Equal (new Rectangle (0, 0, 8, 3), pos);
-
-        cm.Hide ();
-        Assert.Equal (Point.Empty, cm.Position);
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void Show_Display_At_Zero_If_The_Toplevel_Width_Is_Less_Than_The_Menu_Width ()
-    {
-        ((FakeDriver)Application.Driver!).SetBufferSize (5, 25);
-
-        var cm = new ContextMenu
-        {
-            Position = Point.Empty
-        };
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new MenuItem ("One", "", null),
-                                             new MenuItem ("Two", "", null)
-                                         ]
-                                        );
-        Assert.Equal (Point.Empty, cm.Position);
-
-        Toplevel top = new ();
-        Application.Begin (top);
-        cm.Show (menuItems);
-        Assert.Equal (Point.Empty, cm.Position);
-        Application.LayoutAndDraw ();
-
-        var expected = @"
-┌────
-│ One
-│ Two
-└────";
-
-        Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
-        Assert.Equal (new Rectangle (0, 1, 5, 4), pos);
-
-        cm.Hide ();
-        Assert.Equal (Point.Empty, cm.Position);
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void Show_Display_Below_The_Bottom_Host_If_Has_Enough_Space ()
-    {
-        var view = new View
-        {
-            X = 10,
-            Y = 5,
-            Width = 10,
-            Height = 1,
-            Text = "View"
-        };
-
-        var cm = new ContextMenu
-        {
-            Host = view,
-            Position = new Point (10, 5)
-        };
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new MenuItem ("One", "", null),
-                                             new MenuItem ("Two", "", null)
-                                         ]
-                                        );
-        var top = new Toplevel ();
-        top.Add (view);
-        Application.Begin (top);
-
-        Assert.Equal (new Point (10, 5), cm.Position);
-
-        cm.Show (menuItems);
-        top.Draw ();
-        Assert.Equal (new Point (10, 5), cm.Position);
-
-        var expected = @"
-          View    
-          ┌──────┐
-          │ One  │
-          │ Two  │
-          └──────┘
-";
-
-        Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
-        Assert.Equal (new Rectangle (10, 5, 18, 5), pos);
-
-        cm.Hide ();
-        Assert.Equal (new Point (10, 5), cm.Position);
-        cm.Host.X = 5;
-        cm.Host.Y = 10;
-        cm.Host.Height = 3;
-
-        cm.Show (menuItems);
-        View.SetClipToScreen ();
-        Application.Top.Draw ();
-        Assert.Equal (new Point (5, 12), cm.Position);
-
-        expected = @"
-     View    
-             
-             
-     ┌──────┐
-     │ One  │
-     │ Two  │
-     └──────┘
-";
-
-        pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
-        Assert.Equal (new Rectangle (5, 10, 13, 7), pos);
-
-        cm.Hide ();
-        Assert.Equal (new Point (5, 12), cm.Position);
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void Show_Ensures_Display_Inside_The_Container_But_Preserves_Position ()
-    {
-        var cm = new ContextMenu
-        {
-            Position = new Point (80, 25)
-        };
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new MenuItem ("One", "", null),
-                                             new MenuItem ("Two", "", null)
-                                         ]
-                                        );
-        Assert.Equal (new Point (80, 25), cm.Position);
-
-        Toplevel top = new ();
-        Application.Begin (top);
-        cm.Show (menuItems);
-        Assert.Equal (new Point (80, 25), cm.Position);
-        Application.LayoutAndDraw ();
-
-        var expected = @"
-                                                                        ┌──────┐
-                                                                        │ One  │
-                                                                        │ Two  │
-                                                                        └──────┘
-";
-
-        Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
-        Assert.Equal (new Rectangle (72, 21, 80, 4), pos);
-
-        cm.Hide ();
-        Assert.Equal (new Point (80, 25), cm.Position);
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void Show_Ensures_Display_Inside_The_Container_Without_Overlap_The_Host ()
-    {
-        var view = new View
-        {
-            X = Pos.AnchorEnd (10),
-            Y = Pos.AnchorEnd (1),
-            Width = 10,
-            Height = 1,
-            Text = "View"
-        };
-
-        var cm = new ContextMenu
-        {
-            Host = view
-        };
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new MenuItem ("One", "", null),
-                                             new MenuItem ("Two", "", null)
-                                         ]
-                                        );
-        var top = new Toplevel ();
-        top.Add (view);
-        Application.Begin (top);
-
-        Assert.Equal (new Rectangle (70, 24, 10, 1), view.Frame);
-        Assert.Equal (Point.Empty, cm.Position);
-
-        cm.Show (menuItems);
-        Assert.Equal (new Point (70, 24), cm.Position);
-        top.Draw ();
-
-        var expected = @"
-                                                                      ┌──────┐
-                                                                      │ One  │
-                                                                      │ Two  │
-                                                                      └──────┘
-                                                                      View    
-";
-
-        Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
-        Assert.Equal (new Rectangle (70, 20, 78, 5), pos);
-
-        cm.Hide ();
-        Assert.Equal (new Point (70, 24), cm.Position);
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void Show_Hide_IsShow ()
-    {
-        ContextMenu cm = new ContextMenu
-        {
-            Position = new Point (10, 5)
-        };
-
-        var menuItems = new MenuBarItem (
-                                         new MenuItem [] { new ("One", "", null), new ("Two", "", null) }
-                                        );
-
-        Toplevel top = new ();
-        Application.Begin (top);
-        cm.Show (menuItems);
-        Assert.True (ContextMenu.IsShow);
-        Application.LayoutAndDraw ();
-
-        var expected = @"
-          ┌──────┐
-          │ One  │
-          │ Two  │
-          └──────┘
-";
-
-        DriverAssert.AssertDriverContentsAre (expected, output);
-
-        cm.Hide ();
-        Assert.False (ContextMenu.IsShow);
-
-        Application.LayoutAndDraw ();
-
-        expected = "";
-
-        DriverAssert.AssertDriverContentsAre (expected, output);
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void UseSubMenusSingleFrame_True_By_Mouse ()
-    {
-        var cm = new ContextMenu
-        {
-            Position = new Point (5, 10),
-            UseSubMenusSingleFrame = true
-        };
-
-        var menuItems = new MenuBarItem (
-                                         "Numbers",
-                                         [
-                                             new MenuItem ("One", "", null),
-                                             new MenuBarItem (
-                                                              "Two",
-                                                              [
-                                                                  new MenuItem (
-                                                                                "Sub-Menu 1",
-                                                                                "",
-                                                                                null
-                                                                               ),
-                                                                  new MenuItem ("Sub-Menu 2", "", null)
-                                                              ]
-                                                             ),
-                                             new MenuItem ("Three", "", null)
-                                         ]
-                                        );
-        Toplevel top = new ();
-        RunState rs = Application.Begin (top);
-        cm.Show (menuItems);
-        var menu = Application.Top!.SubViews.First (v => v is Menu);
-        Assert.Equal (new Rectangle (5, 11, 10, 5), menu.Frame);
-        Application.LayoutAndDraw ();
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-     ┌────────┐
-     │ One    │
-     │ Two   ►│
-     │ Three  │
-     └────────┘",
-                                                      output
-                                                     );
-
-        // X=5 is the border and so need to use at least one more
-        Application.RaiseMouseEvent (new MouseEventArgs { ScreenPosition = new (6, 13), Flags = MouseFlags.Button1Clicked });
-
-        var firstIteration = false;
-        Application.RunIteration (ref rs, firstIteration);
-        menu = Application.Top!.SubViews.First (v => v is Menu);
-        Assert.Equal (new Rectangle (5, 11, 10, 5), menu.Frame);
-        menu = Application.Top!.SubViews.Last (v => v is Menu);
-        Assert.Equal (new Rectangle (5, 11, 15, 6), menu.Frame);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-     ┌─────────────┐
-     │◄    Two     │
-     ├─────────────┤
-     │ Sub-Menu 1  │
-     │ Sub-Menu 2  │
-     └─────────────┘",
-                                                      output
-                                                     );
-
-        Application.RaiseMouseEvent (new MouseEventArgs { ScreenPosition = new (6, 12), Flags = MouseFlags.Button1Clicked });
-
-        firstIteration = false;
-        Application.RunIteration (ref rs, firstIteration);
-        menu = Application.Top!.SubViews.First (v => v is Menu);
-        Assert.Equal (new Rectangle (5, 11, 10, 5), menu.Frame);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-     ┌────────┐
-     │ One    │
-     │ Two   ►│
-     │ Three  │
-     └────────┘",
-                                                      output
-                                                     );
-
-        Application.End (rs);
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void UseSubMenusSingleFrame_False_By_Mouse ()
-    {
-        var cm = new ContextMenu
-        {
-            Position = new Point (5, 10)
-        };
-
-        var menuItems = new MenuBarItem (
-                                         "Numbers",
-                                         [
-                                             new MenuItem ("One", "", null),
-                                             new MenuBarItem (
-                                                              "Two",
-                                                              [
-                                                                  new MenuItem (
-                                                                                "Two-Menu 1",
-                                                                                "",
-                                                                                null
-                                                                               ),
-                                                                  new MenuItem ("Two-Menu 2", "", null)
-                                                              ]
-                                                             ),
-                                             new MenuBarItem (
-                                                              "Three",
-                                                              [
-                                                                  new MenuItem (
-                                                                                "Three-Menu 1",
-                                                                                "",
-                                                                                null
-                                                                               ),
-                                                                  new MenuItem ("Three-Menu 2", "", null)
-                                                              ]
-                                                             )
-                                         ]
-                                        );
-        Toplevel top = new ();
-        RunState rs = Application.Begin (top);
-        cm.Show (menuItems);
-
-
-        var menu = Application.Top!.SubViews.First (v => v is Menu);
-
-        Assert.Equal (new Rectangle (5, 11, 10, 5), menu.Frame);
-        Application.LayoutAndDraw ();
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-     ┌────────┐
-     │ One    │
-     │ Two   ►│
-     │ Three ►│
-     └────────┘",
-                                                      output
-                                                     );
-
-        Application.RaiseMouseEvent (new MouseEventArgs { ScreenPosition = new (6, 13), Flags = MouseFlags.ReportMousePosition });
-
-        var firstIteration = false;
-        Application.RunIteration (ref rs, firstIteration);
-        menu = Application.Top!.SubViews.First (v => v is Menu);
-        Assert.Equal (new Rectangle (5, 11, 10, 5), menu.Frame);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-     ┌────────┐               
-     │ One    │               
-     │ Two   ►│┌─────────────┐
-     │ Three ►││ Two-Menu 1  │
-     └────────┘│ Two-Menu 2  │
-               └─────────────┘",
-                                                      output
-                                                     );
-
-        Application.RaiseMouseEvent (new MouseEventArgs { ScreenPosition = new (6, 14), Flags = MouseFlags.ReportMousePosition });
-
-        firstIteration = false;
-        Application.RunIteration (ref rs, firstIteration);
-        menu = Application.Top!.SubViews.First (v => v is Menu);
-        Assert.Equal (new Rectangle (5, 11, 10, 5), menu.Frame);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-     ┌────────┐                 
-     │ One    │                 
-     │ Two   ►│                 
-     │ Three ►│┌───────────────┐
-     └────────┘│ Three-Menu 1  │
-               │ Three-Menu 2  │
-               └───────────────┘",
-                                                      output
-                                                     );
-
-        Application.RaiseMouseEvent (new MouseEventArgs { ScreenPosition = new (6, 13), Flags = MouseFlags.ReportMousePosition });
-
-        firstIteration = false;
-        Application.RunIteration (ref rs, firstIteration);
-        menu = Application.Top!.SubViews.First (v => v is Menu);
-        Assert.Equal (new Rectangle (5, 11, 10, 5), menu.Frame);
-
-        DriverAssert.AssertDriverContentsWithFrameAre (
-                                                      @"
-     ┌────────┐               
-     │ One    │               
-     │ Two   ►│┌─────────────┐
-     │ Three ►││ Two-Menu 1  │
-     └────────┘│ Two-Menu 2  │
-               └─────────────┘",
-                                                      output
-                                                     );
-
-        Application.End (rs);
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void Handling_TextField_With_Opened_ContextMenu_By_Mouse_HasFocus ()
-    {
-        var tf1 = new TextField { Width = 10, Text = "TextField 1" };
-        var tf2 = new TextField { Y = 2, Width = 10, Text = "TextField 2" };
-        var win = new Window ();
-        win.Add (tf1, tf2);
-        var rs = Application.Begin (win);
-
-        Assert.True (tf1.HasFocus);
-        Assert.False (tf2.HasFocus);
-        Assert.Equal (4, win.SubViews.Count); // TF & TV add autocomplete popup's to their superviews.
-        Assert.Empty (Application._cachedViewsUnderMouse);
-
-        // Right click on tf2 to open context menu
-        Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 3), Flags = MouseFlags.Button3Clicked });
-        Assert.False (tf1.HasFocus);
-        Assert.False (tf2.HasFocus);
-        Assert.Equal (6, win.SubViews.Count);
-        //Assert.True (tf2.ContextMenu.IsMenuOpen);
-        Assert.True (win.Focused is Menu);
-        Assert.True (Application.MouseGrabView is Menu);
-        Assert.Equal (tf2, Application._cachedViewsUnderMouse.LastOrDefault ());
-
-        // Click on tf1 to focus it, which cause context menu being closed
-        Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 1), Flags = MouseFlags.Button1Clicked });
-        Assert.True (tf1.HasFocus);
-        Assert.False (tf2.HasFocus);
-        Assert.Equal (5, win.SubViews.Count);
-
-        // The last context menu bar opened is always preserved
-        Assert.NotNull (tf2.ContextMenu);
-        Assert.Equal (win.Focused, tf1);
-        Assert.Null (Application.MouseGrabView);
-        Assert.Equal (tf1, Application._cachedViewsUnderMouse.LastOrDefault ());
-
-        // Click on tf2 to focus it
-        Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 3), Flags = MouseFlags.Button1Clicked });
-        Assert.False (tf1.HasFocus);
-        Assert.True (tf2.HasFocus);
-        Assert.Equal (5, win.SubViews.Count);
-
-        // The last context menu bar opened is always preserved
-        Assert.NotNull (tf2.ContextMenu);
-        Assert.Equal (win.Focused, tf2);
-        Assert.Null (Application.MouseGrabView);
-        Assert.Equal (tf2, Application._cachedViewsUnderMouse.LastOrDefault ());
-
-        Application.End (rs);
-        win.Dispose ();
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void Empty_Menus_Items_Children_Does_Not_Open_The_Menu ()
-    {
-        var cm = new ContextMenu ();
-        Assert.Null (cm.MenuItems);
-
-        var top = new Toplevel ();
-        Application.Begin (top);
-
-        cm.Show (cm.MenuItems);
-        Assert.Null (cm.MenuBar);
-
-        top.Dispose ();
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void KeyBindings_Removed_On_Close_ContextMenu ()
-    {
-        var newFile = false;
-        var renameFile = false;
-        var deleteFile = false;
-
-        var cm = new ContextMenu ();
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new MenuItem ("New File", string.Empty, New, null, null, Key.N.WithCtrl),
-                                             new MenuItem ("Rename File", string.Empty, Rename, null, null, Key.R.WithCtrl),
-                                             new MenuItem ("Delete File", string.Empty, Delete, null, null, Key.D.WithCtrl)
-                                         ]
-                                        );
-        var top = new Toplevel ();
-        Application.Begin (top);
-
-        Assert.Null (cm.MenuBar);
-        Assert.False (Application.RaiseKeyDownEvent (Key.N.WithCtrl));
-        Assert.False (Application.RaiseKeyDownEvent (Key.R.WithCtrl));
-        Assert.False (Application.RaiseKeyDownEvent (Key.D.WithCtrl));
-        Assert.False (newFile);
-        Assert.False (renameFile);
-        Assert.False (deleteFile);
-
-        cm.Show (menuItems);
-        Assert.True (cm.MenuBar!.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
-        Assert.True (cm.MenuBar.HotKeyBindings.TryGet (Key.R.WithCtrl, out _));
-        Assert.True (cm.MenuBar.HotKeyBindings.TryGet (Key.D.WithCtrl, out _));
-
-        Assert.True (Application.RaiseKeyDownEvent (Key.N.WithCtrl));
-        Application.MainLoop!.RunIteration ();
-        Assert.True (newFile);
-        Assert.False (cm.MenuBar!.IsMenuOpen);
-        cm.Show (menuItems);
-        Assert.True (Application.RaiseKeyDownEvent (Key.R.WithCtrl));
-        Application.MainLoop!.RunIteration ();
-        Assert.True (renameFile);
-        Assert.False (cm.MenuBar.IsMenuOpen);
-        cm.Show (menuItems);
-        Assert.True (Application.RaiseKeyDownEvent (Key.D.WithCtrl));
-        Application.MainLoop!.RunIteration ();
-        Assert.True (deleteFile);
-        Assert.False (cm.MenuBar.IsMenuOpen);
-
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.WithCtrl, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.D.WithCtrl, out _));
-
-        newFile = false;
-        renameFile = false;
-        deleteFile = false;
-        Assert.False (Application.RaiseKeyDownEvent (Key.N.WithCtrl));
-        Assert.False (Application.RaiseKeyDownEvent (Key.R.WithCtrl));
-        Assert.False (Application.RaiseKeyDownEvent (Key.D.WithCtrl));
-        Assert.False (newFile);
-        Assert.False (renameFile);
-        Assert.False (deleteFile);
-
-        top.Dispose ();
-
-        void New () { newFile = true; }
-
-        void Rename () { renameFile = true; }
-
-        void Delete () { deleteFile = true; }
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void KeyBindings_With_ContextMenu_And_MenuBar ()
-    {
-        var newFile = false;
-        var renameFile = false;
-
-        var menuBar = new MenuBar
-        {
-            Menus =
-            [
-                new (
-                     "File",
-                     new MenuItem []
-                     {
-                         new ("New", string.Empty, New, null, null, Key.N.WithCtrl)
-                     })
-            ]
-        };
-        var cm = new ContextMenu ();
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new ("Rename File", string.Empty, Rename, null, null, Key.R.WithCtrl),
-                                         ]
-                                        );
-        var top = new Toplevel ();
-        top.Add (menuBar);
-        Application.Begin (top);
-
-        Assert.True (menuBar.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
-        Assert.False (menuBar.HotKeyBindings.TryGet (Key.R.WithCtrl, out _));
-        Assert.Null (cm.MenuBar);
-
-        Assert.True (Application.RaiseKeyDownEvent (Key.N.WithCtrl));
-        Assert.False (Application.RaiseKeyDownEvent (Key.R.WithCtrl));
-        Application.MainLoop!.RunIteration ();
-        Assert.True (newFile);
-        Assert.False (renameFile);
-
-        newFile = false;
-
-        cm.Show (menuItems);
-        Assert.True (menuBar.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
-        Assert.False (menuBar.HotKeyBindings.TryGet (Key.R.WithCtrl, out _));
-        Assert.False (cm.MenuBar!.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
-        Assert.True (cm.MenuBar.HotKeyBindings.TryGet (Key.R.WithCtrl, out _));
-
-        Assert.True (cm.MenuBar.IsMenuOpen);
-        Assert.True (Application.RaiseKeyDownEvent (Key.N.WithCtrl));
-        Application.MainLoop!.RunIteration ();
-        Assert.True (newFile);
-        Assert.False (cm.MenuBar!.IsMenuOpen);
-        cm.Show (menuItems);
-        Assert.True (Application.RaiseKeyDownEvent (Key.R.WithCtrl));
-        Application.MainLoop!.RunIteration ();
-        Assert.True (renameFile);
-        Assert.False (cm.MenuBar.IsMenuOpen);
-
-        Assert.True (menuBar.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
-        Assert.False (menuBar.HotKeyBindings.TryGet (Key.R.WithCtrl, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.WithCtrl, out _));
-
-        newFile = false;
-        renameFile = false;
-        Assert.True (Application.RaiseKeyDownEvent (Key.N.WithCtrl));
-        Assert.False (Application.RaiseKeyDownEvent (Key.R.WithCtrl));
-        Application.MainLoop!.RunIteration ();
-        Assert.True (newFile);
-        Assert.False (renameFile);
-
-        top.Dispose ();
-
-        void New () { newFile = true; }
-
-        void Rename () { renameFile = true; }
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void KeyBindings_With_Same_Shortcut_ContextMenu_And_MenuBar ()
-    {
-        var newMenuBar = false;
-        var newContextMenu = false;
-
-        var menuBar = new MenuBar
-        {
-            Menus =
-            [
-                new (
-                     "File",
-                     new MenuItem []
-                     {
-                         new ("New", string.Empty, NewMenuBar, null, null, Key.N.WithCtrl)
-                     })
-            ]
-        };
-        var cm = new ContextMenu ();
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new ("New File", string.Empty, NewContextMenu, null, null, Key.N.WithCtrl),
-                                         ]
-                                        );
-        var top = new Toplevel ();
-        top.Add (menuBar);
-        Application.Begin (top);
-
-        Assert.True (menuBar.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
-        Assert.Null (cm.MenuBar);
-
-        Assert.True (Application.RaiseKeyDownEvent (Key.N.WithCtrl));
-        Application.MainLoop!.RunIteration ();
-        Assert.True (newMenuBar);
-        Assert.False (newContextMenu);
-
-        newMenuBar = false;
-
-        cm.Show (menuItems);
-        Assert.True (menuBar.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
-        Assert.True (cm.MenuBar!.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
-
-        Assert.True (cm.MenuBar.IsMenuOpen);
-        Assert.True (Application.RaiseKeyDownEvent (Key.N.WithCtrl));
-        Application.MainLoop!.RunIteration ();
-        Assert.False (newMenuBar);
-
-        // The most focused shortcut is executed
-        Assert.True (newContextMenu);
-        Assert.False (cm.MenuBar!.IsMenuOpen);
-
-        Assert.True (menuBar.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
-
-        newMenuBar = false;
-        newContextMenu = false;
-        Assert.True (Application.RaiseKeyDownEvent (Key.N.WithCtrl));
-        Application.MainLoop!.RunIteration ();
-        Assert.True (newMenuBar);
-        Assert.False (newContextMenu);
-
-        top.Dispose ();
-
-        void NewMenuBar () { newMenuBar = true; }
-
-        void NewContextMenu () { newContextMenu = true; }
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void HotKeys_Removed_On_Close_ContextMenu ()
-    {
-        var newFile = false;
-        var renameFile = false;
-        var deleteFile = false;
-
-        var cm = new ContextMenu ();
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new ("_New File", string.Empty, New, null, null),
-                                             new ("_Rename File", string.Empty, Rename, null, null),
-                                             new ("_Delete File", string.Empty, Delete, null, null)
-                                         ]
-                                        );
-        var top = new Toplevel ();
-        Application.Begin (top);
-
-        Assert.Null (cm.MenuBar);
-        Assert.False (Application.RaiseKeyDownEvent (Key.N.WithAlt));
-        Assert.False (Application.RaiseKeyDownEvent (Key.R.WithAlt));
-        Assert.False (Application.RaiseKeyDownEvent (Key.D.WithAlt));
-        Assert.False (newFile);
-        Assert.False (renameFile);
-        Assert.False (deleteFile);
-
-        cm.Show (menuItems);
-        Assert.True (cm.MenuBar!.IsMenuOpen);
-        Assert.False (cm.MenuBar!.HotKeyBindings.TryGet (Key.N.WithAlt, out _));
-        Assert.False (cm.MenuBar!.HotKeyBindings.TryGet (Key.N.NoShift, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.WithAlt, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.NoShift, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.D.WithAlt, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.D.NoShift, out _));
-        Assert.Equal (2, Application.Top!.SubViews.Count);
-        View [] menus = Application.Top!.SubViews.Where (v => v is Menu m && m.Host == cm.MenuBar).ToArray ();
-        Assert.True (menus [0].HotKeyBindings.TryGet (Key.N.WithAlt, out _));
-        Assert.True (menus [0].HotKeyBindings.TryGet (Key.N.NoShift, out _));
-        Assert.True (menus [0].HotKeyBindings.TryGet (Key.R.WithAlt, out _));
-        Assert.True (menus [0].HotKeyBindings.TryGet (Key.R.NoShift, out _));
-        Assert.True (menus [0].HotKeyBindings.TryGet (Key.D.WithAlt, out _));
-        Assert.True (menus [0].HotKeyBindings.TryGet (Key.D.NoShift, out _));
-
-        Assert.True (Application.RaiseKeyDownEvent (Key.N.WithAlt));
-        Assert.False (cm.MenuBar!.IsMenuOpen);
-        Application.MainLoop!.RunIteration ();
-        Assert.True (newFile);
-        cm.Show (menuItems);
-        Assert.True (Application.RaiseKeyDownEvent (Key.R.WithAlt));
-        Assert.False (cm.MenuBar.IsMenuOpen);
-        Application.MainLoop!.RunIteration ();
-        Assert.True (renameFile);
-        cm.Show (menuItems);
-        Assert.True (Application.RaiseKeyDownEvent (Key.D.WithAlt));
-        Assert.False (cm.MenuBar.IsMenuOpen);
-        Application.MainLoop!.RunIteration ();
-        Assert.True (deleteFile);
-
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.N.WithAlt, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.N.NoShift, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.WithAlt, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.NoShift, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.D.WithAlt, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.D.NoShift, out _));
-
-        newFile = false;
-        renameFile = false;
-        deleteFile = false;
-        Assert.False (Application.RaiseKeyDownEvent (Key.N.WithAlt));
-        Assert.False (Application.RaiseKeyDownEvent (Key.R.WithAlt));
-        Assert.False (Application.RaiseKeyDownEvent (Key.D.WithAlt));
-        Assert.False (newFile);
-        Assert.False (renameFile);
-        Assert.False (deleteFile);
-
-        top.Dispose ();
-
-        void New () { newFile = true; }
-
-        void Rename () { renameFile = true; }
-
-        void Delete () { deleteFile = true; }
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void HotKeys_With_ContextMenu_And_MenuBar ()
-    {
-        var newFile = false;
-        var renameFile = false;
-
-        var menuBar = new MenuBar
-        {
-            Menus =
-            [
-                new (
-                     "_File",
-                     new MenuItem []
-                     {
-                         new ("_New", string.Empty, New)
-                     })
-            ]
-        };
-        var cm = new ContextMenu ();
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new MenuBarItem (
-                                                              "_Edit",
-                                                              new MenuItem []
-                                                              {
-                                                                  new ("_Rename File", string.Empty, Rename)
-                                                              }
-                                                             )
-                                         ]
-                                        );
-        var top = new Toplevel ();
-        top.Add (menuBar);
-        Application.Begin (top);
-
-        Assert.True (menuBar.HotKeyBindings.TryGet (Key.F.WithAlt, out _));
-        Assert.False (menuBar.HotKeyBindings.TryGet (Key.N.WithAlt, out _));
-        Assert.False (menuBar.HotKeyBindings.TryGet (Key.R.WithAlt, out _));
-        View [] menus = Application.Top!.SubViews.Where (v => v is Menu m && m.Host == menuBar).ToArray ();
-        Assert.Empty (menus);
-        Assert.Null (cm.MenuBar);
-
-        Assert.True (Application.RaiseKeyDownEvent (Key.F.WithAlt));
-        Assert.True (menuBar.IsMenuOpen);
-        Assert.Equal (2, Application.Top!.SubViews.Count);
-        menus = Application.Top!.SubViews.Where (v => v is Menu m && m.Host == menuBar).ToArray ();
-        Assert.True (menus [0].HotKeyBindings.TryGet (Key.N.WithAlt, out _));
-        Assert.True (Application.RaiseKeyDownEvent (Key.N.WithAlt));
-        Assert.False (menuBar.IsMenuOpen);
-        Assert.False (Application.RaiseKeyDownEvent (Key.R.WithAlt));
-        Application.MainLoop!.RunIteration ();
-        Assert.True (newFile);
-        Assert.False (renameFile);
-
-        newFile = false;
-
-        cm.Show (menuItems);
-        Assert.True (menuBar.HotKeyBindings.TryGet (Key.F.WithAlt, out _));
-        Assert.True (menuBar.HotKeyBindings.TryGet (Key.F.NoShift, out _));
-        Assert.False (menuBar.HotKeyBindings.TryGet (Key.N.WithAlt, out _));
-        Assert.False (menuBar.HotKeyBindings.TryGet (Key.N.NoShift, out _));
-        Assert.False (menuBar.HotKeyBindings.TryGet (Key.E.WithAlt, out _));
-        Assert.False (menuBar.HotKeyBindings.TryGet (Key.E.NoShift, out _));
-        Assert.False (menuBar.HotKeyBindings.TryGet (Key.R.WithAlt, out _));
-        Assert.False (menuBar.HotKeyBindings.TryGet (Key.R.NoShift, out _));
-        Assert.True (cm.MenuBar!.IsMenuOpen);
-        Assert.False (cm.MenuBar!.HotKeyBindings.TryGet (Key.F.WithAlt, out _));
-        Assert.False (cm.MenuBar!.HotKeyBindings.TryGet (Key.F.NoShift, out _));
-        Assert.False (cm.MenuBar!.HotKeyBindings.TryGet (Key.N.WithAlt, out _));
-        Assert.False (cm.MenuBar!.HotKeyBindings.TryGet (Key.N.NoShift, out _));
-        Assert.False (cm.MenuBar!.HotKeyBindings.TryGet (Key.E.WithAlt, out _));
-        Assert.False (cm.MenuBar!.HotKeyBindings.TryGet (Key.E.NoShift, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.WithAlt, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.NoShift, out _));
-        Assert.Equal (4, Application.Top!.SubViews.Count);
-        menus = Application.Top!.SubViews.Where (v => v is Menu m && m.Host == cm.MenuBar).ToArray ();
-        Assert.True (menus [0].HotKeyBindings.TryGet (Key.E.WithAlt, out _));
-        Assert.True (menus [0].HotKeyBindings.TryGet (Key.E.NoShift, out _));
-        Assert.True (menus [1].HotKeyBindings.TryGet (Key.R.WithAlt, out _));
-        Assert.True (menus [1].HotKeyBindings.TryGet (Key.R.NoShift, out _));
-        Assert.True (cm.MenuBar.IsMenuOpen);
-        Assert.True (Application.RaiseKeyDownEvent (Key.F.WithAlt));
-        Assert.False (cm.MenuBar.IsMenuOpen);
-        Assert.True (Application.RaiseKeyDownEvent (Key.N.WithAlt));
-        Application.MainLoop!.RunIteration ();
-        Assert.True (newFile);
-
-        cm.Show (menuItems);
-        Assert.True (cm.MenuBar.IsMenuOpen);
-        Assert.Equal (4, Application.Top!.SubViews.Count);
-        menus = Application.Top!.SubViews.Where (v => v is Menu m && m.Host == cm.MenuBar).ToArray ();
-        Assert.True (menus [0].HotKeyBindings.TryGet (Key.E.WithAlt, out _));
-        Assert.True (menus [0].HotKeyBindings.TryGet (Key.E.NoShift, out _));
-        Assert.False (menus [0].HotKeyBindings.TryGet (Key.R.WithAlt, out _));
-        Assert.False (menus [0].HotKeyBindings.TryGet (Key.R.NoShift, out _));
-        Assert.False (menus [1].HotKeyBindings.TryGet (Key.E.WithAlt, out _));
-        Assert.False (menus [1].HotKeyBindings.TryGet (Key.E.NoShift, out _));
-        Assert.True (menus [1].HotKeyBindings.TryGet (Key.R.WithAlt, out _));
-        Assert.True (menus [1].HotKeyBindings.TryGet (Key.R.NoShift, out _));
-        Assert.True (Application.RaiseKeyDownEvent (Key.E.NoShift));
-        Assert.True (Application.RaiseKeyDownEvent (Key.R.WithAlt));
-        Assert.False (cm.MenuBar.IsMenuOpen);
-        Application.MainLoop!.RunIteration ();
-        Assert.True (renameFile);
-
-        Assert.Equal (2, Application.Top!.SubViews.Count);
-        Assert.True (menuBar.HotKeyBindings.TryGet (Key.F.WithAlt, out _));
-        Assert.True (menuBar.HotKeyBindings.TryGet (Key.F.NoShift, out _));
-        Assert.False (menuBar.HotKeyBindings.TryGet (Key.N.WithAlt, out _));
-        Assert.False (menuBar.HotKeyBindings.TryGet (Key.N.NoShift, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.E.WithAlt, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.E.NoShift, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.WithAlt, out _));
-        Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.NoShift, out _));
-
-        newFile = false;
-        renameFile = false;
-        Assert.True (Application.RaiseKeyDownEvent (Key.F.WithAlt));
-        Assert.True (Application.RaiseKeyDownEvent (Key.N.WithAlt));
-        Assert.False (Application.RaiseKeyDownEvent (Key.R.WithAlt));
-        Application.MainLoop!.RunIteration ();
-        Assert.True (newFile);
-        Assert.False (renameFile);
-
-        top.Dispose ();
-
-        void New () { newFile = true; }
-
-        void Rename () { renameFile = true; }
-    }
-
-    [Fact (Skip = "Redo for CMv2")]
-    [AutoInitShutdown]
-    public void Opened_MenuBar_Is_Closed_When_Another_MenuBar_Is_Opening_Also_By_HotKey ()
-    {
-        var menuBar = new MenuBar
-        {
-            Menus =
-            [
-                new (
-                     "_File",
-                     new MenuItem []
-                     {
-                         new ("_New", string.Empty, null)
-                     })
-            ]
-        };
-        var cm = new ContextMenu ();
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new MenuBarItem (
-                                                              "_Edit",
-                                                              new MenuItem []
-                                                              {
-                                                                  new ("_Rename File", string.Empty, null)
-                                                              }
-                                                             )
-                                         ]
-                                        );
-        var top = new Toplevel ();
-        top.Add (menuBar);
-        Application.Begin (top);
-
-        Assert.True (Application.RaiseKeyDownEvent (Key.F.WithAlt));
-        Assert.True (menuBar.IsMenuOpen);
-
-        cm.Show (menuItems);
-        Assert.False (menuBar.IsMenuOpen);
-        Assert.True (cm.MenuBar!.IsMenuOpen);
-
-        Assert.True (Application.RaiseKeyDownEvent (Key.F.WithAlt));
-        Assert.True (menuBar.IsMenuOpen);
-        Assert.False (cm.MenuBar!.IsMenuOpen);
-
-        top.Dispose ();
-    }
-
-    [Theory]
-    [InlineData (1)]
-    [InlineData (2)]
-    [InlineData (3)]
-    [AutoInitShutdown]
-    public void Mouse_Pressed_Released_Clicked (int button)
-    {
-        var actionRaised = false;
-
-        var menuBar = new MenuBar
-        {
-            Menus =
-            [
-                new (
-                     "_File",
-                     new MenuItem []
-                     {
-                         new ("_New", string.Empty, () => actionRaised = true)
-                     })
-            ]
-        };
-        var cm = new ContextMenu ();
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new ("_Rename File", string.Empty, () => actionRaised = true)
-                                         ]
-                                        );
-        var top = new Toplevel ();
-
-        top.MouseClick += (s, e) =>
-                          {
-                              if (e.Flags == cm.MouseFlags)
-                              {
-                                  cm.Position = new (e.Position.X, e.Position.Y);
-                                  cm.Show (menuItems);
-                                  e.Handled = true;
-                              }
-                          };
-
-        top.Add (menuBar);
-        Application.Begin (top);
-
-        // MenuBar
-        Application.RaiseMouseEvent (new () { Flags = MouseFlags.Button1Pressed });
-        Assert.True (menuBar.IsMenuOpen);
-
-        switch (button)
-        {
-            // Left Button
-            case 1:
-                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 2), Flags = MouseFlags.Button1Pressed });
-                Assert.True (menuBar.IsMenuOpen);
-                Application.MainLoop.RunIteration ();
-                Assert.False (actionRaised);
-                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 2), Flags = MouseFlags.Button1Released });
-                Assert.True (menuBar.IsMenuOpen);
-                Application.MainLoop.RunIteration ();
-                Assert.False (actionRaised);
-                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 2), Flags = MouseFlags.Button1Clicked });
-                Assert.False (menuBar.IsMenuOpen);
-                Application.MainLoop.RunIteration ();
-                Assert.True (actionRaised);
-                actionRaised = false;
-
-                break;
-            // Middle Button
-            case 2:
-            // Right Button
-            case 3:
-                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 2), Flags = MouseFlags.Button3Pressed });
-                Assert.True (menuBar.IsMenuOpen);
-                Application.MainLoop.RunIteration ();
-                Assert.False (actionRaised);
-                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 2), Flags = MouseFlags.Button3Released });
-                Assert.True (menuBar.IsMenuOpen);
-                Application.MainLoop.RunIteration ();
-                Assert.False (actionRaised);
-                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 2), Flags = MouseFlags.Button3Clicked });
-                Assert.True (menuBar.IsMenuOpen);
-                Application.MainLoop.RunIteration ();
-                Assert.False (actionRaised);
-
-                break;
-        }
-
-        // ContextMenu
-        Application.RaiseMouseEvent (new () { ScreenPosition = new (0, 4), Flags = cm.MouseFlags });
-        Assert.False (menuBar.IsMenuOpen);
-        Assert.True (cm.MenuBar!.IsMenuOpen);
-
-        switch (button)
-        {
-            // Left Button
-            case 1:
-                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 6), Flags = MouseFlags.Button1Pressed });
-                Assert.True (cm.MenuBar!.IsMenuOpen);
-                Application.MainLoop.RunIteration ();
-                Assert.False (actionRaised);
-                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 6), Flags = MouseFlags.Button1Released });
-                Assert.True (cm.MenuBar!.IsMenuOpen);
-                Application.MainLoop.RunIteration ();
-                Assert.False (actionRaised);
-                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 6), Flags = MouseFlags.Button1Clicked });
-                Assert.False (cm.MenuBar!.IsMenuOpen);
-                Application.MainLoop.RunIteration ();
-                Assert.True (actionRaised);
-                actionRaised = false;
-
-                break;
-            // Middle Button
-            case 2:
-                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 4), Flags = MouseFlags.Button2Pressed });
-                Assert.False (cm.MenuBar!.IsMenuOpen);
-                Application.MainLoop.RunIteration ();
-                Assert.False (actionRaised);
-                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 4), Flags = MouseFlags.Button2Released });
-                Assert.False (cm.MenuBar!.IsMenuOpen);
-                Application.MainLoop.RunIteration ();
-                Assert.False (actionRaised);
-                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 4), Flags = MouseFlags.Button2Clicked });
-                Assert.False (cm.MenuBar!.IsMenuOpen);
-                Application.MainLoop.RunIteration ();
-                Assert.False (actionRaised);
-
-                break;
-            // Right Button
-            case 3:
-                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 4), Flags = MouseFlags.Button3Pressed });
-                Assert.False (cm.MenuBar!.IsMenuOpen);
-                Application.MainLoop.RunIteration ();
-                Assert.False (actionRaised);
-                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 4), Flags = MouseFlags.Button3Released });
-                Assert.False (cm.MenuBar!.IsMenuOpen);
-                Application.MainLoop.RunIteration ();
-                Assert.False (actionRaised);
-                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 4), Flags = MouseFlags.Button3Clicked });
-                // MouseFlags is the same as cm.MouseFlags. So the context menu is closed and reopened again
-                Assert.True (cm.MenuBar!.IsMenuOpen);
-                Application.MainLoop.RunIteration ();
-                Assert.False (actionRaised);
-
-                break;
-        }
-
-        top.Dispose ();
-    }
-
-    [Fact]
-    [AutoInitShutdown]
-    public void Menu_Without_SubMenu_Is_Closed_When_Pressing_Key_Right_Or_Key_Left ()
-    {
-        var cm = new ContextMenu ();
-
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new ("_New", string.Empty, null),
-                                             new ("_Save", string.Empty, null)
-                                         ]
-                                        );
-        var top = new Toplevel ();
-        Application.Begin (top);
-
-        cm.Show (menuItems);
-        Assert.True (cm.MenuBar!.IsMenuOpen);
-
-        Assert.True (Application.RaiseKeyDownEvent (Key.CursorRight));
-        Assert.False (cm.MenuBar!.IsMenuOpen);
-
-        cm.Show (menuItems);
-        Assert.True (cm.MenuBar!.IsMenuOpen);
-
-        Assert.True (Application.RaiseKeyDownEvent (Key.CursorLeft));
-        Assert.False (cm.MenuBar!.IsMenuOpen);
-
-        top.Dispose ();
-    }
-
-    [Fact]
-    [AutoInitShutdown]
-    public void Menu_Opened_In_SuperView_With_TabView_Has_Precedence_On_Key_Press ()
-    {
-        var win = new Window
-        {
-            Title = "My Window",
-            X = 0,
-            Y = 0,
-            Width = Dim.Fill (),
-            Height = Dim.Fill ()
-        };
-
-        // Tab View
-        var tabView = new TabView
-        {
-            X = 1,
-            Y = 1,
-            Width = Dim.Fill () - 2,
-            Height = Dim.Fill () - 2
-        };
-        tabView.AddTab (new () { DisplayText = "Tab 1" }, true);
-        tabView.AddTab (new () { DisplayText = "Tab 2" }, false);
-        win.Add (tabView);
-
-        // Context Menu
-        var menuItems = new MenuBarItem (
-                                         [
-                                             new ("Item 1", "First item", () => MessageBox.Query ("Action", "Item 1 Clicked", "OK")),
-                                             new MenuBarItem (
-                                                              "Submenu",
-                                                              new List<MenuItem []>
-                                                              {
-                                                                  new []
-                                                                  {
-                                                                      new MenuItem (
-                                                                                    "Sub Item 1",
-                                                                                    "Submenu item",
-                                                                                    () => { MessageBox.Query ("Action", "Sub Item 1 Clicked", "OK"); })
-                                                                  }
-                                                              })
-                                         ]);
-
-        var cm = new ContextMenu ();
-
-        win.MouseClick += (s, e) =>
-                          {
-                              if (e.Flags.HasFlag (MouseFlags.Button3Clicked)) // Right-click
-                              {
-                                  cm.Position = e.Position;
-                                  cm.Show (menuItems);
-                              }
-                          };
-        Application.Begin (win);
-
-        cm.Show (menuItems);
-        Assert.True (cm.MenuBar!.IsMenuOpen);
-
-        Assert.True (Application.RaiseKeyDownEvent (Key.CursorDown));
-        Assert.True (cm.MenuBar!.IsMenuOpen);
-
-        Assert.True (Application.RaiseKeyDownEvent (Key.CursorUp));
-        Assert.True (cm.MenuBar!.IsMenuOpen);
-
-        Assert.True (Application.RaiseKeyDownEvent (Key.CursorDown));
-        Assert.True (cm.MenuBar!.IsMenuOpen);
-
-        Assert.True (Application.RaiseKeyDownEvent (Key.CursorRight));
-        Assert.True (cm.MenuBar!.IsMenuOpen);
-
-        Assert.True (Application.RaiseKeyDownEvent (Key.CursorLeft));
-        Assert.True (cm.MenuBar!.IsMenuOpen);
-
-        Assert.True (Application.RaiseKeyDownEvent (Key.CursorLeft));
-        Assert.False (cm.MenuBar!.IsMenuOpen);
-        Assert.True (tabView.HasFocus);
-
-        win.Dispose ();
-    }
-}

+ 1 - 1
Tests/UnitTests/Views/TextViewTests.cs

@@ -5533,7 +5533,7 @@ This is the second line.
         Assert.False (tv.NewKeyDownEvent (Key.F6.WithShift));
         Assert.False (tv.NewKeyDownEvent (Application.PrevTabGroupKey));
 
-        Assert.True (tv.NewKeyDownEvent (ContextMenu.DefaultKey));
+        Assert.True (tv.NewKeyDownEvent (PopoverMenu.DefaultKey));
         Assert.True (tv.ContextMenu != null && tv.ContextMenu.Visible);
         top.Dispose ();
     }

+ 9 - 9
Tests/UnitTestsParallelizable/Application/ApplicationPopoverTests.cs

@@ -35,29 +35,29 @@ public class ApplicationPopoverTests
     }
 
     [Fact]
-    public void ShowPopover_SetsActivePopover ()
+    public void Show_SetsActivePopover ()
     {
         // Arrange
         var popover = new Mock<IPopoverTestClass> ().Object;
         var popoverManager = new ApplicationPopover ();
 
         // Act
-        popoverManager.ShowPopover (popover);
+        popoverManager.Show (popover);
 
         // Assert
         Assert.Equal (popover, popoverManager.GetActivePopover ());
     }
 
     [Fact]
-    public void HidePopover_ClearsActivePopover ()
+    public void Hide_ClearsActivePopover ()
     {
         // Arrange
         var popover = new Mock<IPopover> ().Object;
         var popoverManager = new ApplicationPopover ();
-        popoverManager.ShowPopover (popover);
+        popoverManager.Show (popover);
 
         // Act
-        popoverManager.HidePopover (popover);
+        popoverManager.Hide (popover);
 
         // Assert
         Assert.Null (popoverManager.GetActivePopover ());
@@ -70,7 +70,7 @@ public class ApplicationPopoverTests
         // Arrange
         var popover = new IPopoverTestClass ();
         var popoverManager = new ApplicationPopover ();
-        popoverManager.ShowPopover (popover);
+        popoverManager.Show (popover);
 
         // Act
         popoverManager.DispatchKeyDown (Key.A);
@@ -86,7 +86,7 @@ public class ApplicationPopoverTests
         // Arrange
         var popover = new IPopoverTestClass ();
         var popoverManager = new ApplicationPopover ();
-        popoverManager.ShowPopover (popover);
+        popoverManager.Show (popover);
 
         // Act
         popoverManager.DispatchKeyDown (Key.N.WithCtrl);
@@ -104,7 +104,7 @@ public class ApplicationPopoverTests
         var activePopover = new IPopoverTestClass () { Id = "activePopover" };
         var inactivePopover = new IPopoverTestClass () { Id = "inactivePopover" }; ;
         var popoverManager = new ApplicationPopover ();
-        popoverManager.ShowPopover (activePopover);
+        popoverManager.Show (activePopover);
         popoverManager.Register (inactivePopover);
 
         // Act
@@ -124,7 +124,7 @@ public class ApplicationPopoverTests
         var activePopover = new IPopoverTestClass ();
         var inactivePopover = new IPopoverTestClass ();
         var popoverManager = new ApplicationPopover ();
-        popoverManager.ShowPopover (activePopover);
+        popoverManager.Show (activePopover);
         popoverManager.Register (inactivePopover);
 
         // Act

+ 2 - 2
UICatalog/Scenarios/ContextMenus.cs

@@ -9,7 +9,7 @@ namespace UICatalog.Scenarios;
 public class ContextMenus : Scenario
 {
     [CanBeNull]
-    private ContextMenuv2 _winContextMenu;
+    private PopoverMenu _winContextMenu;
     private TextField _tfTopLeft, _tfTopRight, _tfMiddle, _tfBottomLeft, _tfBottomRight;
     private readonly List<CultureInfo> _cultureInfos = Application.SupportedCultures;
     private readonly Key _winContextMenuKey = Key.Space.WithCtrl;
@@ -42,7 +42,7 @@ public class ContextMenus : Scenario
         {
             X = Pos.Center (),
             Y = Pos.Bottom (label),
-            Text = $"Press '{ContextMenu.DefaultKey}' to open the TextField context menu."
+            Text = $"Press '{PopoverMenu.DefaultKey}' to open the TextField context menu."
         };
         appWindow.Add (label);
 

+ 0 - 18
UICatalog/Scenarios/MenusV2.cs

@@ -121,8 +121,6 @@ public class MenusV2 : Scenario
 
             KeyBindings.Add (PopoverMenu.DefaultKey, Command.Context);
 
-            MouseBindings.ReplaceCommands (PopoverMenu.MouseFlags, Command.Context);
-
             AddCommand (
                         Command.Cancel,
                         ctx =>
@@ -504,22 +502,6 @@ public class MenusV2 : Scenario
 
             menu.Add (deeperDetail, new Line (), shortcut4);
         }
-
-        /// <inheritdoc/>
-        protected override void Dispose (bool disposing)
-        {
-            if (disposing)
-            {
-                //    if (FilePopoverMenu is { })
-                //    {
-                //        FilePopoverMenu.Visible = false;
-                //        FilePopoverMenu?.Dispose ();
-                //        FilePopoverMenu = null;
-                //    }
-            }
-
-            base.Dispose (disposing);
-        }
     }
 
     private const string LOGFILE_LOCATION = "./logs";

+ 21 - 23
UICatalog/Scenarios/Notepad.cs

@@ -333,39 +333,37 @@ public class Notepad : Scenario
             return;
         }
 
-        MenuBarItem items;
+        View [] items;
 
         if (e.Tab == null)
         {
-            items = new (
-                         new MenuItem [] { new ("Open", "", () => Open ()) }
-                        );
+            items = [new MenuItemv2 ("Open", "", Open)];
         }
         else
         {
             var tv = (TabView)sender;
             var t = (OpenedFile)e.Tab;
 
-            items = new (
-                         new MenuItem []
-                         {
-                             new ("Save", "", () => Save (_focusedTabView, e.Tab)),
-                             new ("Close", "", () => Close (tv, e.Tab)),
-                             null,
-                             new ("Split Up", "", () => SplitUp (tv, t)),
-                             new ("Split Down", "", () => SplitDown (tv, t)),
-                             new ("Split Right", "", () => SplitRight (tv, t)),
-                             new ("Split Left", "", () => SplitLeft (tv, t))
-                         }
-                        );
+            items =
+            [
+                new MenuItemv2 ("Save", "", () => Save (_focusedTabView, e.Tab)),
+                new MenuItemv2 ("Close", "", () => Close (tv, e.Tab)),
+                new Line (),
+                new MenuItemv2 ("Split Up", "", () => SplitUp (tv, t)),
+                new MenuItemv2 ("Split Down", "", () => SplitDown (tv, t)),
+                new MenuItemv2 ("Split Right", "", () => SplitRight (tv, t)),
+                new MenuItemv2 ("Split Left", "", () => SplitLeft (tv, t))
+            ];
+
+            PopoverMenu? contextMenu = new (items);
+
+            // Registering with the PopoverManager will ensure that the context menu is closed when the view is no longer focused
+            // and the context menu is disposed when it is closed.
+            Application.Popover?.Register (contextMenu);
+            contextMenu?.MakeVisible (e.MouseEvent.ScreenPosition);
+
+            e.MouseEvent.Handled = true;
         }
-
-        var screen = ((View)sender).ViewportToScreen (e.MouseEvent.Position);
-
-        var contextMenu = new ContextMenu { Position = screen };
-
-        contextMenu.Show (items);
-        e.MouseEvent.Handled = true;
     }
 
     private class OpenedFile (Notepad notepad) : Tab

+ 28 - 37
UICatalog/Scenarios/TableEditor.cs

@@ -1,9 +1,5 @@
-using System;
-using System.Collections.Generic;
-using System.Data;
+using System.Data;
 using System.Globalization;
-using System.IO;
-using System.Linq;
 using System.Text;
 using Terminal.Gui;
 
@@ -827,10 +823,10 @@ public class TableEditor : Scenario
         var ok = new Button { Text = "Ok", IsDefault = true };
 
         ok.Accepting += (s, e) =>
-                     {
-                         okPressed = true;
-                         Application.RequestStop ();
-                     };
+                        {
+                            okPressed = true;
+                            Application.RequestStop ();
+                        };
         var cancel = new Button { Text = "Cancel" };
         cancel.Accepting += (s, e) => { Application.RequestStop (); };
         var d = new Dialog { Title = title, Buttons = [ok, cancel] };
@@ -1025,12 +1021,13 @@ public class TableEditor : Scenario
         var ok = new Button { Text = "Ok", IsDefault = true };
 
         ok.Accepting += (s, e) =>
-                     {
-                         accepted = true;
-                         Application.RequestStop ();
-                     };
+                        {
+                            accepted = true;
+                            Application.RequestStop ();
+                        };
         var cancel = new Button { Text = "Cancel" };
         cancel.Accepting += (s, e) => { Application.RequestStop (); };
+
         var d = new Dialog
         {
             Title = prompt,
@@ -1212,30 +1209,24 @@ public class TableEditor : Scenario
         string sort = GetProposedNewSortOrder (clickedCol, out bool isAsc);
         string colName = _tableView.Table.ColumnNames [clickedCol];
 
-        var contextMenu = new ContextMenu
-        {
-            Position = new (e.Position.X + 1, e.Position.Y + 1)
-        };
+        PopoverMenu? contextMenu = new (
+                                        [
+                                            new (
+                                                 $"Hide {TrimArrows (colName)}",
+                                                 "",
+                                                 () => HideColumn (clickedCol)
+                                                ),
+                                            new (
+                                                 $"Sort {StripArrows (sort)}",
+                                                 "",
+                                                 () => SortColumn (clickedCol, sort, isAsc)
+                                                )
+                                        ]);
 
-        MenuBarItem menuItems = new (
-                                     [
-                                         new (
-                                              $"Hide {TrimArrows (colName)}",
-                                              "",
-                                              () => HideColumn (clickedCol)
-                                             ),
-                                         new (
-                                              $"Sort {StripArrows (sort)}",
-                                              "",
-                                              () => SortColumn (
-                                                                clickedCol,
-                                                                sort,
-                                                                isAsc
-                                                               )
-                                             )
-                                     ]
-                                    );
-        contextMenu.Show (menuItems);
+        // Registering with the PopoverManager will ensure that the context menu is closed when the view is no longer focused
+        // and the context menu is disposed when it is closed.
+        Application.Popover?.Register (contextMenu);
+        contextMenu?.MakeVisible (new (e.ScreenPosition.X + 1, e.ScreenPosition.Y + 1));
     }
 
     private void SortColumn (int clickedCol)
@@ -1413,7 +1404,7 @@ public class TableEditor : Scenario
                                                                              _checkedFileSystemInfos.Contains,
                                                                              CheckOrUncheckFile
                                                                             )
-            { UseRadioButtons = radio };
+                { UseRadioButtons = radio };
         }
         else
         {

+ 162 - 164
UICatalog/Scenarios/TreeViewFileSystem.cs

@@ -1,7 +1,4 @@
-using System.Collections.Generic;
-using System.IO;
 using System.IO.Abstractions;
-using System.Linq;
 using System.Text;
 using Terminal.Gui;
 
@@ -37,6 +34,7 @@ public class TreeViewFileSystem : Scenario
     public override void Main ()
     {
         Application.Init ();
+
         var win = new Window
         {
             Title = GetName (),
@@ -49,142 +47,142 @@ public class TreeViewFileSystem : Scenario
         {
             Menus =
             [
-                new MenuBarItem (
-                                 "_File",
-                                 new MenuItem []
-                                 {
-                                     new (
-                                          "_Quit",
-                                          $"{Application.QuitKey}",
-                                          () => Quit ()
-                                         )
-                                 }
-                                ),
-                new MenuBarItem (
-                                 "_View",
-                                 new []
-                                 {
-                                     _miFullPaths =
-                                         new MenuItem ("_Full Paths", "", () => SetFullName ())
-                                         {
-                                             Checked = false, CheckType = MenuItemCheckStyle.Checked
-                                         },
-                                     _miMultiSelect = new MenuItem (
-                                                                    "_Multi Select",
-                                                                    "",
-                                                                    () => SetMultiSelect ()
-                                                                   )
-                                     {
-                                         Checked = true,
-                                         CheckType = MenuItemCheckStyle
-                                             .Checked
-                                     }
-                                 }
-                                ),
-                new MenuBarItem (
-                                 "_Style",
-                                 new []
-                                 {
-                                     _miShowLines =
-                                         new MenuItem ("_Show Lines", "", () => ShowLines ())
-                                         {
-                                             Checked = true, CheckType = MenuItemCheckStyle.Checked
-                                         },
-                                     null /*separator*/,
-                                     _miPlusMinus =
-                                         new MenuItem (
-                                                       "_Plus Minus Symbols",
-                                                       "+ -",
-                                                       () => SetExpandableSymbols (
-                                                                                   (Rune)'+',
-                                                                                   (Rune)'-'
-                                                                                  )
-                                                      ) { Checked = true, CheckType = MenuItemCheckStyle.Radio },
-                                     _miArrowSymbols =
-                                         new MenuItem (
-                                                       "_Arrow Symbols",
-                                                       "> v",
-                                                       () => SetExpandableSymbols (
-                                                                                   (Rune)'>',
-                                                                                   (Rune)'v'
-                                                                                  )
-                                                      ) { Checked = false, CheckType = MenuItemCheckStyle.Radio },
-                                     _miNoSymbols =
-                                         new MenuItem (
-                                                       "_No Symbols",
-                                                       "",
-                                                       () => SetExpandableSymbols (
-                                                                                   default (Rune),
-                                                                                   null
-                                                                                  )
-                                                      ) { Checked = false, CheckType = MenuItemCheckStyle.Radio },
-                                     null /*separator*/,
-                                     _miColoredSymbols =
-                                         new MenuItem (
-                                                       "_Colored Symbols",
-                                                       "",
-                                                       () => ShowColoredExpandableSymbols ()
-                                                      ) { Checked = false, CheckType = MenuItemCheckStyle.Checked },
-                                     _miInvertSymbols =
-                                         new MenuItem (
-                                                       "_Invert Symbols",
-                                                       "",
-                                                       () => InvertExpandableSymbols ()
-                                                      ) { Checked = false, CheckType = MenuItemCheckStyle.Checked },
-                                     null /*separator*/,
-                                     _miBasicIcons =
-                                         new MenuItem ("_Basic Icons", null, SetNoIcons)
-                                         {
-                                             Checked = false, CheckType = MenuItemCheckStyle.Radio
-                                         },
-                                     _miUnicodeIcons =
-                                         new MenuItem ("_Unicode Icons", null, SetUnicodeIcons)
-                                         {
-                                             Checked = false, CheckType = MenuItemCheckStyle.Radio
-                                         },
-                                     _miNerdIcons =
-                                         new MenuItem ("_Nerd Icons", null, SetNerdIcons)
-                                         {
-                                             Checked = false, CheckType = MenuItemCheckStyle.Radio
-                                         },
-                                     null /*separator*/,
-                                     _miLeaveLastRow =
-                                         new MenuItem (
-                                                       "_Leave Last Row",
-                                                       "",
-                                                       () => SetLeaveLastRow ()
-                                                      ) { Checked = true, CheckType = MenuItemCheckStyle.Checked },
-                                     _miHighlightModelTextOnly =
-                                         new MenuItem (
-                                                       "_Highlight Model Text Only",
-                                                       "",
-                                                       () => SetCheckHighlightModelTextOnly ()
-                                                      ) { Checked = false, CheckType = MenuItemCheckStyle.Checked },
-                                     null /*separator*/,
-                                     _miCustomColors =
-                                         new MenuItem (
-                                                       "C_ustom Colors Hidden Files",
-                                                       "Yellow/Red",
-                                                       () => SetCustomColors ()
-                                                      ) { Checked = false, CheckType = MenuItemCheckStyle.Checked },
-                                     null /*separator*/,
-                                     _miCursor = new MenuItem (
-                                                               "Curs_or (MultiSelect only)",
-                                                               "",
-                                                               () => SetCursor ()
-                                                              ) { Checked = false, CheckType = MenuItemCheckStyle.Checked }
-                                 }
-                                )
+                new (
+                     "_File",
+                     new MenuItem []
+                     {
+                         new (
+                              "_Quit",
+                              $"{Application.QuitKey}",
+                              () => Quit ()
+                             )
+                     }
+                    ),
+                new (
+                     "_View",
+                     new []
+                     {
+                         _miFullPaths =
+                             new ("_Full Paths", "", () => SetFullName ())
+                             {
+                                 Checked = false, CheckType = MenuItemCheckStyle.Checked
+                             },
+                         _miMultiSelect = new (
+                                               "_Multi Select",
+                                               "",
+                                               () => SetMultiSelect ()
+                                              )
+                         {
+                             Checked = true,
+                             CheckType = MenuItemCheckStyle
+                                 .Checked
+                         }
+                     }
+                    ),
+                new (
+                     "_Style",
+                     new []
+                     {
+                         _miShowLines =
+                             new ("_Show Lines", "", () => ShowLines ())
+                             {
+                                 Checked = true, CheckType = MenuItemCheckStyle.Checked
+                             },
+                         null /*separator*/,
+                         _miPlusMinus =
+                             new (
+                                  "_Plus Minus Symbols",
+                                  "+ -",
+                                  () => SetExpandableSymbols (
+                                                              (Rune)'+',
+                                                              (Rune)'-'
+                                                             )
+                                 ) { Checked = true, CheckType = MenuItemCheckStyle.Radio },
+                         _miArrowSymbols =
+                             new (
+                                  "_Arrow Symbols",
+                                  "> v",
+                                  () => SetExpandableSymbols (
+                                                              (Rune)'>',
+                                                              (Rune)'v'
+                                                             )
+                                 ) { Checked = false, CheckType = MenuItemCheckStyle.Radio },
+                         _miNoSymbols =
+                             new (
+                                  "_No Symbols",
+                                  "",
+                                  () => SetExpandableSymbols (
+                                                              default (Rune),
+                                                              null
+                                                             )
+                                 ) { Checked = false, CheckType = MenuItemCheckStyle.Radio },
+                         null /*separator*/,
+                         _miColoredSymbols =
+                             new (
+                                  "_Colored Symbols",
+                                  "",
+                                  () => ShowColoredExpandableSymbols ()
+                                 ) { Checked = false, CheckType = MenuItemCheckStyle.Checked },
+                         _miInvertSymbols =
+                             new (
+                                  "_Invert Symbols",
+                                  "",
+                                  () => InvertExpandableSymbols ()
+                                 ) { Checked = false, CheckType = MenuItemCheckStyle.Checked },
+                         null /*separator*/,
+                         _miBasicIcons =
+                             new ("_Basic Icons", null, SetNoIcons)
+                             {
+                                 Checked = false, CheckType = MenuItemCheckStyle.Radio
+                             },
+                         _miUnicodeIcons =
+                             new ("_Unicode Icons", null, SetUnicodeIcons)
+                             {
+                                 Checked = false, CheckType = MenuItemCheckStyle.Radio
+                             },
+                         _miNerdIcons =
+                             new ("_Nerd Icons", null, SetNerdIcons)
+                             {
+                                 Checked = false, CheckType = MenuItemCheckStyle.Radio
+                             },
+                         null /*separator*/,
+                         _miLeaveLastRow =
+                             new (
+                                  "_Leave Last Row",
+                                  "",
+                                  () => SetLeaveLastRow ()
+                                 ) { Checked = true, CheckType = MenuItemCheckStyle.Checked },
+                         _miHighlightModelTextOnly =
+                             new (
+                                  "_Highlight Model Text Only",
+                                  "",
+                                  () => SetCheckHighlightModelTextOnly ()
+                                 ) { Checked = false, CheckType = MenuItemCheckStyle.Checked },
+                         null /*separator*/,
+                         _miCustomColors =
+                             new (
+                                  "C_ustom Colors Hidden Files",
+                                  "Yellow/Red",
+                                  () => SetCustomColors ()
+                                 ) { Checked = false, CheckType = MenuItemCheckStyle.Checked },
+                         null /*separator*/,
+                         _miCursor = new (
+                                          "Curs_or (MultiSelect only)",
+                                          "",
+                                          () => SetCursor ()
+                                         ) { Checked = false, CheckType = MenuItemCheckStyle.Checked }
+                     }
+                    )
             ]
         };
         top.Add (menu);
 
-        _treeViewFiles = new TreeView<IFileSystemInfo> { X = 0, Y = 0, Width = Dim.Percent (50), Height = Dim.Fill () };
+        _treeViewFiles = new() { X = 0, Y = 0, Width = Dim.Percent (50), Height = Dim.Fill () };
         _treeViewFiles.DrawLine += TreeViewFiles_DrawLine;
 
         _treeViewFiles.VerticalScrollBar.AutoShow = false;
 
-        _detailsFrame = new DetailsFrame (_iconProvider)
+        _detailsFrame = new (_iconProvider)
         {
             X = Pos.Right (_treeViewFiles), Y = 0, Width = Dim.Fill (), Height = Dim.Fill ()
         };
@@ -249,16 +247,16 @@ public class TreeViewFileSystem : Scenario
                                          {
                                              if (m is IDirectoryInfo && m.Attributes.HasFlag (FileAttributes.Hidden))
                                              {
-                                                 return new ColorScheme
+                                                 return new()
                                                  {
-                                                     Focus = new Attribute (
-                                                                            Color.BrightRed,
-                                                                            _treeViewFiles.ColorScheme.Focus.Background
-                                                                           ),
-                                                     Normal = new Attribute (
-                                                                             Color.BrightYellow,
-                                                                             _treeViewFiles.ColorScheme.Normal.Background
-                                                                            )
+                                                     Focus = new (
+                                                                  Color.BrightRed,
+                                                                  _treeViewFiles.ColorScheme.Focus.Background
+                                                                 ),
+                                                     Normal = new (
+                                                                   Color.BrightYellow,
+                                                                   _treeViewFiles.ColorScheme.Normal.Background
+                                                                  )
                                                  };
 
                                                  ;
@@ -266,16 +264,16 @@ public class TreeViewFileSystem : Scenario
 
                                              if (m is IFileInfo && m.Attributes.HasFlag (FileAttributes.Hidden))
                                              {
-                                                 return new ColorScheme
+                                                 return new()
                                                  {
-                                                     Focus = new Attribute (
-                                                                            Color.BrightRed,
-                                                                            _treeViewFiles.ColorScheme.Focus.Background
-                                                                           ),
-                                                     Normal = new Attribute (
-                                                                             Color.BrightYellow,
-                                                                             _treeViewFiles.ColorScheme.Normal.Background
-                                                                            )
+                                                     Focus = new (
+                                                                  Color.BrightRed,
+                                                                  _treeViewFiles.ColorScheme.Focus.Background
+                                                                 ),
+                                                     Normal = new (
+                                                                   Color.BrightYellow,
+                                                                   _treeViewFiles.ColorScheme.Normal.Background
+                                                                  )
                                                  };
 
                                                  ;
@@ -417,13 +415,13 @@ public class TreeViewFileSystem : Scenario
 
     private void ShowContextMenu (Point screenPoint, IFileSystemInfo forObject)
     {
-        var menu = new ContextMenu { Position = screenPoint };
+        PopoverMenu? contextMenu = new ([new ("Properties", $"Show {forObject.Name} properties", () => ShowPropertiesOf (forObject))]);
 
-        var menuItems = new MenuBarItem (
-                                         new [] { new MenuItem ("Properties", null, () => ShowPropertiesOf (forObject)) }
-                                        );
+        // Registering with the PopoverManager will ensure that the context menu is closed when the view is no longer focused
+        // and the context menu is disposed when it is closed.
+        Application.Popover?.Register (contextMenu);
 
-        Application.Invoke (() => menu.Show (menuItems));
+        Application.Invoke (() => contextMenu?.MakeVisible (screenPoint));
     }
 
     private void ShowLines ()
@@ -477,10 +475,10 @@ public class TreeViewFileSystem : Scenario
             }
 
             ShowContextMenu (
-                             new Point (
-                                        5 + _treeViewFiles.Frame.X,
-                                        location.Value + _treeViewFiles.Frame.Y + 2
-                                       ),
+                             new (
+                                  5 + _treeViewFiles.Frame.X,
+                                  location.Value + _treeViewFiles.Frame.Y + 2
+                                 ),
                              selected
                             );
         }
@@ -500,10 +498,10 @@ public class TreeViewFileSystem : Scenario
             }
 
             ShowContextMenu (
-                             new Point (
-                                        obj.Position.X + _treeViewFiles.Frame.X,
-                                        obj.Position.Y + _treeViewFiles.Frame.Y + 2
-                                       ),
+                             new (
+                                  obj.Position.X + _treeViewFiles.Frame.X,
+                                  obj.Position.Y + _treeViewFiles.Frame.Y + 2
+                                 ),
                              rightClicked
                             );
         }
@@ -543,7 +541,7 @@ public class TreeViewFileSystem : Scenario
                 if (_fileInfo is IFileInfo f)
                 {
                     Title = $"{_iconProvider.GetIconWithOptionalSpace (f)}{f.Name}".Trim ();
-                    sb = new StringBuilder ();
+                    sb = new ();
                     sb.AppendLine ($"Path:\n {f.FullName}\n");
                     sb.AppendLine ($"Size:\n {f.Length:N0} bytes\n");
                     sb.AppendLine ($"Modified:\n {f.LastWriteTime}\n");
@@ -553,7 +551,7 @@ public class TreeViewFileSystem : Scenario
                 if (_fileInfo is IDirectoryInfo dir)
                 {
                     Title = $"{_iconProvider.GetIconWithOptionalSpace (dir)}{dir.Name}".Trim ();
-                    sb = new StringBuilder ();
+                    sb = new ();
                     sb.AppendLine ($"Path:\n {dir?.FullName}\n");
                     sb.AppendLine ($"Modified:\n {dir.LastWriteTime}\n");
                     sb.AppendLine ($"Created:\n {dir.CreationTime}\n");

+ 18 - 0
docfx/docs/migratingfromv1.md

@@ -470,6 +470,24 @@ In v1, only Views derived from `Toplevel` could be overlapped. In v2, any view c
 
 v1 conflated the concepts of 
 
+## `ContextMenu` replaced by `PopoverMenu`
+
+`PopoverMenu` replaces `ContrextMenu`. 
+
+## `MenuItem` is now based on `Shortcut`
+
+
+```diff
+new (
+      Strings.charMapCopyGlyph,
+      "",
+      CopyGlyph,
+-      null,
+-      null,
+      (KeyCode)Key.G.WithCtrl
+     ),
+```	
+
 ## Others...
 
 * `View` and all subclasses support `IDisposable` and must be disposed (by calling `view.Dispose ()`) by whatever code owns the instance when the instance is longer needed.