From ff962b64df93b5662a363ac0c486c8ec4ca69a95 Mon Sep 17 00:00:00 2001 From: BDisp Date: Sun, 6 Feb 2022 22:38:11 +0000 Subject: [PATCH] Added MenuOpened event and others bug fixes. (#1572) * Added MenuOpened event and others bug fixes. * Fixing typo. * Unifying constructors initializations. --- Terminal.Gui/Views/Menu.cs | 218 ++++++++++++------ UnitTests/MenuTests.cs | 453 +++++++++++++++++++++++++++++++++++++ 2 files changed, 596 insertions(+), 75 deletions(-) create mode 100644 UnitTests/MenuTests.cs diff --git a/Terminal.Gui/Views/Menu.cs b/Terminal.Gui/Views/Menu.cs index 2c77abcfb..bf073e4d1 100644 --- a/Terminal.Gui/Views/Menu.cs +++ b/Terminal.Gui/Views/Menu.cs @@ -47,15 +47,7 @@ namespace Terminal.Gui { /// /// Initializes a new instance of /// - public MenuItem (Key shortcut = Key.Null) - { - Title = ""; - Help = ""; - shortcutHelper = new ShortcutHelper (); - if (shortcut != Key.Null) { - shortcutHelper.Shortcut = shortcut; - } - } + public MenuItem (Key shortcut = Key.Null) : this ("", "", null, null, null, shortcut) { } /// /// Initializes a new instance of . @@ -216,8 +208,7 @@ namespace Terminal.Gui { /// The parent of this if exist, otherwise is null. public MenuBarItem (ustring title, ustring help, Action action, Func canExecute = null, MenuItem parent = null) : base (title, help, action, canExecute, parent) { - SetTitle (title ?? ""); - Children = null; + Initialize (title, null, null, true); } /// @@ -228,15 +219,7 @@ namespace Terminal.Gui { /// The parent of this if exist, otherwise is null. public MenuBarItem (ustring title, MenuItem [] children, MenuItem parent = null) { - if (children == null) { - throw new ArgumentNullException (nameof (children), "The parameter cannot be null. Use an empty array instead."); - } - SetTitle (title ?? ""); - if (parent != null) { - Parent = parent; - } - SetChildrensParent (children); - Children = children; + Initialize (title, children, parent); } /// @@ -247,22 +230,7 @@ namespace Terminal.Gui { /// The parent of this if exist, otherwise is null. public MenuBarItem (ustring title, List children, MenuItem parent = null) { - if (children == null) { - throw new ArgumentNullException (nameof (children), "The parameter cannot be null. Use an empty array instead."); - } - SetTitle (title ?? ""); - if (parent != null) { - Parent = parent; - } - MenuItem [] childrens = new MenuItem [] { }; - foreach (var item in children) { - for (int i = 0; i < item.Length; i++) { - SetChildrensParent (item); - Array.Resize (ref childrens, childrens.Length + 1); - childrens [childrens.Length - 1] = item [i]; - } - } - Children = childrens; + Initialize (title, children, parent); } /// @@ -276,6 +244,33 @@ namespace Terminal.Gui { /// public MenuBarItem () : this (children: new MenuItem [] { }) { } + void Initialize (ustring title, object children, MenuItem parent = null, bool isTopLevel = false) + { + if (!isTopLevel && children == null) { + throw new ArgumentNullException (nameof (children), "The parameter cannot be null. Use an empty array instead."); + } + SetTitle (title ?? ""); + if (parent != null) { + Parent = parent; + } + if (children is List) { + MenuItem [] childrens = new MenuItem [] { }; + foreach (var item in (List)children) { + for (int i = 0; i < item.Length; i++) { + SetChildrensParent (item); + Array.Resize (ref childrens, childrens.Length + 1); + childrens [childrens.Length - 1] = item [i]; + } + } + Children = childrens; + } else if (children is MenuItem []) { + SetChildrensParent ((MenuItem [])children); + Children = (MenuItem [])children; + } else { + Children = null; + } + } + //static int GetMaxTitleLength (MenuItem [] children) //{ // int maxLength = 0; @@ -570,15 +565,10 @@ namespace Terminal.Gui { host.NextMenu (barItems.IsTopLevel || (barItems.Children != null && current > -1 && current < barItems.Children.Length && barItems.Children [current].IsFromSubMenu) ? true : false); return true; case Key.Esc: - Application.UngrabMouse (); - host.CloseAllMenus (); + CloseAllMenus (); return true; case Key.Enter: - if (barItems.IsTopLevel) { - Run (barItems.Action); - } else if (current > -1) { - Run (barItems.Children [current].Action); - } + RunSelected (); return true; default: // TODO: rune-ify @@ -598,6 +588,21 @@ namespace Terminal.Gui { return false; } + void RunSelected () + { + if (barItems.IsTopLevel) { + Run (barItems.Action); + } else if (current > -1) { + Run (barItems.Children [current].Action); + } + } + + void CloseAllMenus () + { + Application.UngrabMouse (); + host.CloseAllMenus (); + } + bool MoveDown () { if (barItems.IsTopLevel) { @@ -630,6 +635,7 @@ namespace Terminal.Gui { } } while (barItems.Children [current] == null || disabled); SetNeedsDisplay (); + host.OnMenuOpened (); return true; } @@ -674,6 +680,7 @@ namespace Terminal.Gui { } } while (barItems.Children [current] == null || disabled); SetNeedsDisplay (); + host.OnMenuOpened (); return true; } @@ -708,6 +715,7 @@ namespace Terminal.Gui { if (item != null && !disabled) current = me.Y - 1; CheckSubMenu (); + host.OnMenuOpened (); return true; } return false; @@ -970,13 +978,27 @@ namespace Terminal.Gui { /// public event Action MenuOpening; + /// + /// Raised when a menu is opened. + /// + public event Action MenuOpened; + /// /// Raised when a menu is closing. /// public event Action MenuClosing; internal Menu openMenu; - internal Menu openCurrentMenu; + Menu ocm; + internal Menu openCurrentMenu { + get => ocm; + set { + if (ocm != value) { + ocm = value; + OnMenuOpened (); + } + } + } internal List openSubMenu; View previousFocused; internal bool isMenuOpening; @@ -999,6 +1021,18 @@ namespace Terminal.Gui { return ev; } + /// + /// Virtual method that will invoke the event if it's defined. + /// + public virtual void OnMenuOpened () + { + MenuItem mi = null; + if (openCurrentMenu.barItems.Children != null) { + mi = openCurrentMenu.barItems.Children [openCurrentMenu.current]; + } + MenuOpened?.Invoke (mi); + } + /// /// Virtual method that will invoke the /// @@ -1021,7 +1055,7 @@ namespace Terminal.Gui { if (newMenu.Cancel) { return; } - if (newMenu.NewMenuBarItem != null && Menus [index].Title == newMenu.NewMenuBarItem.Title) { + if (newMenu.NewMenuBarItem != null) { Menus [index] = newMenu.NewMenuBarItem; } int pos = 0; @@ -1208,12 +1242,15 @@ namespace Terminal.Gui { return; for (int i = openSubMenu.Count - 1; i > index; i--) { isMenuClosing = true; + Menu menu; if (openSubMenu.Count - 1 > 0) - openSubMenu [i - 1].SetFocus (); + menu = openSubMenu [i - 1]; else - openMenu.SetFocus (); + menu = openMenu; + openCurrentMenu = menu; + openCurrentMenu.SetFocus (); if (openSubMenu != null) { - var menu = openSubMenu [i]; + menu = openSubMenu [i]; SuperView.Remove (menu); openSubMenu.Remove (menu); menu.Dispose (); @@ -1405,6 +1442,10 @@ namespace Terminal.Gui { private void ProcessMenu (int i, MenuBarItem mi) { + if (selected < 0) { + return; + } + if (mi.IsTopLevel) { var menu = new Menu (this, i, 0, mi); menu.Run (mi.Action); @@ -1419,6 +1460,7 @@ namespace Terminal.Gui { } openCurrentMenu.CheckSubMenu (); } + SetNeedsDisplay (); } /// @@ -1451,30 +1493,22 @@ namespace Terminal.Gui { { switch (kb.Key) { case Key.CursorLeft: - selected--; - if (selected < 0) - selected = Menus.Length - 1; - break; + MoveLeft (); + return true; + case Key.CursorRight: - selected = (selected + 1) % Menus.Length; - break; + MoveRight (); + return true; case Key.Esc: case Key.C | Key.CtrlMask: - //TODO: Running = false; - CloseMenu (); - if (openedByAltKey) { - openedByAltKey = false; - LastFocused?.SetFocus (); - } - break; + CloseMenuBar (); + return true; case Key.CursorDown: case Key.Enter: - if (selected > -1) { - ProcessMenu (selected, Menus [selected]); - } - break; + ProcessMenu (selected, Menus [selected]); + return true; default: var key = kb.KeyValue; @@ -1499,8 +1533,32 @@ namespace Terminal.Gui { return false; } + } + + void CloseMenuBar () + { + CloseMenu (); + if (openedByAltKey) { + openedByAltKey = false; + LastFocused?.SetFocus (); + } + SetNeedsDisplay (); + } + + void MoveRight () + { + selected = (selected + 1) % Menus.Length; + OpenMenu (selected); + SetNeedsDisplay (); + } + + void MoveLeft () + { + selected--; + if (selected < 0) + selected = Menus.Length - 1; + OpenMenu (selected); SetNeedsDisplay (); - return true; } /// @@ -1564,15 +1622,25 @@ namespace Terminal.Gui { Application.UngrabMouse (); var v = me.View; Application.GrabMouse (v); - var newxy = v.ScreenToView (me.X, me.Y); - var nme = new MouseEvent () { - X = newxy.X, - Y = newxy.Y, - Flags = me.Flags, - OfX = me.X - newxy.X, - OfY = me.Y - newxy.Y, - View = v - }; + MouseEvent nme; + if (me.Y > -1) { + var newxy = v.ScreenToView (me.X, me.Y); + nme = new MouseEvent () { + X = newxy.X, + Y = newxy.Y, + Flags = me.Flags, + OfX = me.X - newxy.X, + OfY = me.Y - newxy.Y, + View = v + }; + } else { + nme = new MouseEvent () { + X = me.X + current.Frame.X, + Y = 0, + Flags = me.Flags, + View = v + }; + } v.MouseEvent (nme); return false; diff --git a/UnitTests/MenuTests.cs b/UnitTests/MenuTests.cs new file mode 100644 index 000000000..e15eb4424 --- /dev/null +++ b/UnitTests/MenuTests.cs @@ -0,0 +1,453 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace Terminal.Gui.Views { + public class MenuTests { + [Fact] + public void Constuctors_Defaults () + { + var menu = new Menu (new MenuBar (), 0, 0, new MenuBarItem ()); + Assert.Equal (Colors.Menu, menu.ColorScheme); + Assert.True (menu.CanFocus); + Assert.False (menu.WantContinuousButtonPressed); + + var menuBar = new MenuBar (); + Assert.Equal (0, menuBar.X); + Assert.Equal (0, menuBar.Y); + Assert.IsType (menuBar.Width); + Assert.Equal (1, menuBar.Height); + Assert.Empty (menuBar.Menus); + Assert.Equal (Colors.Menu, menuBar.ColorScheme); + Assert.True (menuBar.WantMousePositionReports); + Assert.False (menuBar.IsMenuOpen); + + menuBar = new MenuBar (new MenuBarItem [] { }); + Assert.Equal (0, menuBar.X); + Assert.Equal (0, menuBar.Y); + Assert.IsType (menuBar.Width); + Assert.Equal (1, menuBar.Height); + Assert.Empty (menuBar.Menus); + Assert.Equal (Colors.Menu, menuBar.ColorScheme); + Assert.True (menuBar.WantMousePositionReports); + Assert.False (menuBar.IsMenuOpen); + + var menuBarItem = new MenuBarItem (); + Assert.Equal ("", menuBarItem.Title); + Assert.Null (menuBarItem.Parent); + Assert.Empty (menuBarItem.Children); + + menuBarItem = new MenuBarItem (new MenuBarItem [] { }); + Assert.Equal ("", menuBarItem.Title); + Assert.Null (menuBarItem.Parent); + Assert.Empty (menuBarItem.Children); + + menuBarItem = new MenuBarItem ("Test", new MenuBarItem [] { }); + Assert.Equal ("Test", menuBarItem.Title); + Assert.Null (menuBarItem.Parent); + Assert.Empty (menuBarItem.Children); + + menuBarItem = new MenuBarItem ("Test", new List ()); + Assert.Equal ("Test", menuBarItem.Title); + Assert.Null (menuBarItem.Parent); + Assert.Empty (menuBarItem.Children); + + menuBarItem = new MenuBarItem ("Test", "Help", null); + Assert.Equal ("Test", menuBarItem.Title); + Assert.Equal ("Help", menuBarItem.Help); + Assert.Null (menuBarItem.Action); + Assert.Null (menuBarItem.CanExecute); + Assert.Null (menuBarItem.Parent); + Assert.Equal (Key.Null, menuBarItem.Shortcut); + + var menuItem = new MenuItem (); + Assert.Equal ("", menuItem.Title); + Assert.Equal ("", menuItem.Help); + Assert.Null (menuItem.Action); + Assert.Null (menuItem.CanExecute); + Assert.Null (menuItem.Parent); + Assert.Equal (Key.Null, menuItem.Shortcut); + + menuItem = new MenuItem ("Test", "Help", Run, () => { return true; }, new MenuItem (), Key.F1); + Assert.Equal ("Test", menuItem.Title); + Assert.Equal ("Help", menuItem.Help); + Assert.Equal (Run, menuItem.Action); + Assert.NotNull (menuItem.CanExecute); + Assert.NotNull (menuItem.Parent); + Assert.Equal (Key.F1, menuItem.Shortcut); + + void Run () { } + } + + [Fact] + public void Exceptions () + { + Assert.Throws (() => new MenuBarItem ("Test", (MenuItem [])null, null)); + Assert.Throws (() => new MenuBarItem ("Test", (List)null, null)); + } + + [Fact] + [AutoInitShutdown] + public void MenuOpening_MenuOpened_MenuClosing_Events () + { + var miAction = ""; + var isMenuClosed = true; + var menu = new MenuBar (new MenuBarItem [] { + new MenuBarItem ("_File", new MenuItem [] { + new MenuItem ("_New", "Creates new file.", New) + }) + }); + menu.MenuOpening += (e) => { + Assert.Equal ("_File", e.CurrentMenu.Title); + Assert.Equal ("_New", e.CurrentMenu.Children [0].Title); + Assert.Equal ("Creates new file.", e.CurrentMenu.Children [0].Help); + Assert.Equal (New, e.CurrentMenu.Children [0].Action); + e.CurrentMenu.Children [0].Action (); + Assert.Equal ("New", miAction); + e.NewMenuBarItem = new MenuBarItem ("_Edit", new MenuItem [] { + new MenuItem ("_Copy", "Copies the selection.", Copy) + }); + }; + menu.MenuOpened += (e) => { + Assert.Equal ("_Edit", e.Parent.Title); + Assert.Equal ("_Copy", e.Title); + Assert.Equal ("Copies the selection.", e.Help); + Assert.Equal (Copy, e.Action); + e.Action (); + Assert.Equal ("Copy", miAction); + }; + menu.MenuClosing += () => { + Assert.False (isMenuClosed); + isMenuClosed = true; + }; + Application.Top.Add (menu); + + Assert.True (menu.ProcessHotKey (new KeyEvent (Key.F9, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + isMenuClosed = !menu.IsMenuOpen; + Assert.False (isMenuClosed); + + Assert.True (menu.ProcessHotKey (new KeyEvent (Key.F9, new KeyModifiers ()))); + Assert.False (menu.IsMenuOpen); + Assert.True (isMenuClosed); + + void New () => miAction = "New"; + void Copy () => miAction = "Copy"; + } + + [Fact] + [AutoInitShutdown] + public void MouseEvent_Test () + { + MenuItem miCurrent = null; + Menu mCurrent = null; + var menu = new MenuBar (new MenuBarItem [] { + new MenuBarItem ("_File", new MenuItem [] { + new MenuItem ("_New", "", null), + new MenuItem ("_Open", "", null), + new MenuItem ("_Save", "", null) + }), + new MenuBarItem ("_Edit", new MenuItem [] { + new MenuItem ("_Copy", "", null), + new MenuItem ("C_ut", "", null), + new MenuItem ("_Paste", "", null) + }) + }); + menu.MenuOpened += (e) => { + miCurrent = e; + mCurrent = menu.openCurrentMenu; + }; + Application.Top.Add (menu); + + Assert.True (menu.MouseEvent (new MouseEvent () { + X = 10, + Y = 0, + Flags = MouseFlags.Button1Pressed, + View = menu + })); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_Edit", miCurrent.Parent.Title); + Assert.Equal ("_Copy", miCurrent.Title); + + Assert.True (mCurrent.MouseEvent (new MouseEvent () { + X = 10, + Y = 3, + Flags = MouseFlags.ReportMousePosition, + View = mCurrent + })); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_Edit", miCurrent.Parent.Title); + Assert.Equal ("_Paste", miCurrent.Title); + + for (int i = 2; i >= -1; i--) { + View view; + if (i == -1) { + Assert.False (mCurrent.MouseEvent (new MouseEvent () { + X = 10, + Y = i, + Flags = MouseFlags.ReportMousePosition, + View = menu + })); + } else { + Assert.True (mCurrent.MouseEvent (new MouseEvent () { + X = 10, + Y = i, + Flags = MouseFlags.ReportMousePosition, + View = mCurrent + })); + } + Assert.True (menu.IsMenuOpen); + if (i == 2) { + Assert.Equal ("_Edit", miCurrent.Parent.Title); + Assert.Equal ("C_ut", miCurrent.Title); + } else if (i == 1) { + Assert.Equal ("_Edit", miCurrent.Parent.Title); + Assert.Equal ("_Copy", miCurrent.Title); + } else if (i == 0) { + Assert.Equal ("_Edit", miCurrent.Parent.Title); + Assert.Equal ("_Copy", miCurrent.Title); + } else { + Assert.Equal ("_Edit", miCurrent.Parent.Title); + Assert.Equal ("_Copy", miCurrent.Title); + } + } + } + + [Fact] + [AutoInitShutdown] + public void KeyBindings_Command () + { + var miAction = ""; + MenuItem mbiCurrent = null; + MenuItem miCurrent = null; + Menu mCurrent = null; + + var menu = new MenuBar (new MenuBarItem [] { + new MenuBarItem ("_File", new MenuItem [] { + new MenuItem ("_New", "", () => miAction ="New"), + new MenuItem ("_Open", "", () => miAction ="Open"), + new MenuItem ("_Save", "", () => miAction ="Save"), + null, + new MenuItem ("_Quit", "", () => miAction ="Quit"), + }), + new MenuBarItem ("_Edit", new MenuItem [] { + new MenuItem ("_Copy", "", () => miAction ="Copy"), + new MenuItem ("C_ut", "", () => miAction ="Cut"), + new MenuItem ("_Paste", "", () => miAction ="Paste"), + new MenuBarItem ("_Find and Replace", new MenuItem [] { + new MenuItem ("F_ind", "", null), + new MenuItem ("_Replace", "", null) + }), + new MenuItem ("_Select All", "", () => miAction ="Select All") + }), + new MenuBarItem ("_About", "Top-Level", () => miAction ="About") + }); + menu.MenuOpening += (e) => mbiCurrent = e.CurrentMenu; + menu.MenuOpened += (e) => { + miCurrent = e; + mCurrent = menu.openCurrentMenu; + }; + menu.MenuClosing += () => { + mbiCurrent = null; + miCurrent = null; + mCurrent = null; + }; + Application.Top.Add (menu); + Application.Begin (Application.Top); + + Assert.True (menu.ProcessHotKey (new KeyEvent (Key.F9, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_File", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_New", GetCurrentMenuTitle ()); + + Assert.True (menu.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_About", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("None", GetCurrentMenuTitle ()); + + Assert.True (menu.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_File", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_New", GetCurrentMenuTitle ()); + + Assert.True (menu.ProcessKey (new KeyEvent (Key.Esc, new KeyModifiers ()))); + Assert.False (menu.IsMenuOpen); + Assert.Equal ("Closed", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("None", GetCurrentMenuTitle ()); + + Assert.True (menu.ProcessHotKey (new KeyEvent (Key.F9, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_File", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_New", GetCurrentMenuTitle ()); + Assert.True (menu.ProcessKey (new KeyEvent (Key.C | Key.CtrlMask, new KeyModifiers ()))); + Assert.False (menu.IsMenuOpen); + Assert.Equal ("Closed", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("None", GetCurrentMenuTitle ()); + + Assert.True (menu.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_File", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_New", GetCurrentMenuTitle ()); + Assert.True (menu.ProcessKey (new KeyEvent (Key.Esc, new KeyModifiers ()))); + Assert.False (menu.IsMenuOpen); + Assert.Equal ("Closed", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("None", GetCurrentMenuTitle ()); + + Assert.True (menu.ProcessKey (new KeyEvent (Key.Enter, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_File", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_New", GetCurrentMenuTitle ()); + + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ()))); + Assert.False (menu.IsMenuOpen); + Assert.Equal ("Closed", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("None", GetCurrentMenuTitle ()); + + Assert.True (menu.ProcessHotKey (new KeyEvent (Key.F9, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_File", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_New", GetCurrentMenuTitle ()); + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_File", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_Quit", GetCurrentMenuTitle ()); + + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_File", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_New", GetCurrentMenuTitle ()); + + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_About", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("None", GetCurrentMenuTitle ()); + + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_File", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_New", GetCurrentMenuTitle ()); + + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.Esc, new KeyModifiers ()))); + Assert.False (menu.IsMenuOpen); + Assert.Equal ("Closed", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("None", GetCurrentMenuTitle ()); + + Assert.True (menu.ProcessHotKey (new KeyEvent (Key.F9, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_File", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_New", GetCurrentMenuTitle ()); + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.Enter, new KeyModifiers ()))); + Assert.False (menu.IsMenuOpen); + Assert.Equal ("Closed", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("None", GetCurrentMenuTitle ()); + Application.MainLoop.MainIteration (); + Assert.Equal ("New", miAction); + + Assert.True (menu.ProcessHotKey (new KeyEvent (Key.F9, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_File", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_New", GetCurrentMenuTitle ()); + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_About", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("None", GetCurrentMenuTitle ()); + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.Enter, new KeyModifiers ()))); + Assert.False (menu.IsMenuOpen); + Assert.Equal ("Closed", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("None", GetCurrentMenuTitle ()); + Application.MainLoop.MainIteration (); + Assert.Equal ("About", miAction); + + Assert.True (menu.ProcessHotKey (new KeyEvent (Key.F9, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_File", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_New", GetCurrentMenuTitle ()); + Assert.True (menu.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_Edit", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_Copy", GetCurrentMenuTitle ()); + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_Edit", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("C_ut", GetCurrentMenuTitle ()); + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_Edit", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_Edit", GetCurrenParenttMenuItemTitle ()); + Assert.Equal ("_Paste", GetCurrentMenuTitle ()); + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_Edit", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_Find and Replace", GetCurrenParenttMenuItemTitle ()); + Assert.Equal ("F_ind", GetCurrentMenuTitle ()); + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_Edit", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_Find and Replace", GetCurrenParenttMenuItemTitle ()); + Assert.Equal ("_Replace", GetCurrentMenuTitle ()); + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_Edit", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_Find and Replace", GetCurrenParenttMenuItemTitle ()); + Assert.Equal ("F_ind", GetCurrentMenuTitle ()); + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_Edit", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_Edit", GetCurrenParenttMenuItemTitle ()); + Assert.Equal ("_Find and Replace", GetCurrentMenuTitle ()); + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_Edit", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_Edit", GetCurrenParenttMenuItemTitle ()); + Assert.Equal ("_Select All", GetCurrentMenuTitle ()); + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_Edit", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_Find and Replace", GetCurrenParenttMenuItemTitle ()); + Assert.Equal ("F_ind", GetCurrentMenuTitle ()); + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_Edit", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_Edit", GetCurrenParenttMenuItemTitle ()); + Assert.Equal ("_Find and Replace", GetCurrentMenuTitle ()); + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_Edit", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_Edit", GetCurrenParenttMenuItemTitle ()); + Assert.Equal ("_Paste", GetCurrentMenuTitle ()); + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_Edit", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("C_ut", GetCurrentMenuTitle ()); + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.Equal ("_Edit", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("_Copy", GetCurrentMenuTitle ()); + Assert.True (mCurrent.ProcessKey (new KeyEvent (Key.Enter, new KeyModifiers ()))); + Assert.False (menu.IsMenuOpen); + Assert.Equal ("Closed", GetCurrentMenuBarItemTitle ()); + Assert.Equal ("None", GetCurrentMenuTitle ()); + Application.MainLoop.MainIteration (); + Assert.Equal ("Copy", miAction); + + + string GetCurrentMenuBarItemTitle () + { + return mbiCurrent != null ? mbiCurrent.Title.ToString () : "Closed"; + } + + string GetCurrenParenttMenuItemTitle () + { + return miCurrent?.Parent != null ? miCurrent.Parent.Title.ToString () : "None"; + } + + string GetCurrentMenuTitle () + { + return miCurrent != null ? miCurrent.Title.ToString () : "None"; + } + } + } +}