From 40e777acc11fe906f0d719771ba6059b6aaa91b3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 22 Nov 2025 01:39:11 +0000 Subject: [PATCH] Add OpenMenu() method to MenuBar for dropdown list support Co-authored-by: tig <585482+tig@users.noreply.github.com> --- Terminal.Gui/Views/Menu/MenuBar.cs | 24 +++++++++ Tests/UnitTests/Views/MenuBarTests.cs | 76 +++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/Terminal.Gui/Views/Menu/MenuBar.cs b/Terminal.Gui/Views/Menu/MenuBar.cs index 67312b01e..f446a1157 100644 --- a/Terminal.Gui/Views/Menu/MenuBar.cs +++ b/Terminal.Gui/Views/Menu/MenuBar.cs @@ -225,6 +225,30 @@ public class MenuBar : Menu, IDesignable /// public bool IsOpen () { return SubViews.OfType ().Count (sv => sv is { PopoverMenuOpen: true }) > 0; } + /// + /// Opens the first menu item with a . This is useful for programmatically opening + /// the menu, for example when using the MenuBar as a dropdown list. + /// + /// if a menu was opened; otherwise. + /// + /// + /// This method activates the MenuBar and shows the first MenuBarItem that has a PopoverMenu. + /// The first menu item in the PopoverMenu will be selected and focused. + /// + /// + public bool OpenMenu () + { + if (SubViews.OfType ().FirstOrDefault (mbi => mbi.PopoverMenu is { }) is { } first) + { + Active = true; + ShowItem (first); + + return true; + } + + return false; + } + private bool _active; /// diff --git a/Tests/UnitTests/Views/MenuBarTests.cs b/Tests/UnitTests/Views/MenuBarTests.cs index b15501a07..f67fcb779 100644 --- a/Tests/UnitTests/Views/MenuBarTests.cs +++ b/Tests/UnitTests/Views/MenuBarTests.cs @@ -718,4 +718,80 @@ public class MenuBarTests () Application.End (rs); top.Dispose (); } + + [Fact] + [AutoInitShutdown] + public void OpenMenu_Opens_First_MenuBarItem () + { + // Arrange + var top = new Toplevel () + { + App = ApplicationImpl.Instance + }; + + var menuBar = new MenuBar () { Id = "menuBar" }; + top.Add (menuBar); + + var menuItem1 = new MenuItem { Id = "menuItem1", Title = "Item _1" }; + var menuItem2 = new MenuItem { Id = "menuItem2", Title = "Item _2" }; + var menu = new Menu ([menuItem1, menuItem2]) { Id = "menu" }; + var menuBarItem = new MenuBarItem { Id = "menuBarItem", Title = "_File" }; + var menuBarItemPopover = new PopoverMenu (); + + menuBar.Add (menuBarItem); + menuBarItem.PopoverMenu = menuBarItemPopover; + menuBarItemPopover.Root = menu; + + SessionToken rs = Application.Begin (top); + Assert.False (menuBar.Active); + Assert.False (menuBar.IsOpen ()); + + // Act + bool result = menuBar.OpenMenu (); + + // Assert + Assert.True (result); + Assert.True (menuBar.Active); + Assert.True (menuBar.IsOpen ()); + Assert.True (menuBar.CanFocus); + Assert.True (menuBarItem.PopoverMenu.Visible); + Assert.True (menuBarItem.PopoverMenu.HasFocus); + Assert.Equal (menuItem1, menu.SelectedMenuItem); + + Application.End (rs); + top.Dispose (); + } + + [Fact] + [AutoInitShutdown] + public void OpenMenu_Returns_False_When_No_MenuBarItem_With_PopoverMenu () + { + // Arrange + var top = new Toplevel () + { + App = ApplicationImpl.Instance + }; + + var menuBar = new MenuBar () { Id = "menuBar" }; + top.Add (menuBar); + + var menuBarItem = new MenuBarItem { Id = "menuBarItem", Title = "_File" }; + menuBar.Add (menuBarItem); + // Note: No PopoverMenu set + + SessionToken rs = Application.Begin (top); + Assert.False (menuBar.Active); + Assert.False (menuBar.IsOpen ()); + + // Act + bool result = menuBar.OpenMenu (); + + // Assert + Assert.False (result); + Assert.False (menuBar.Active); + Assert.False (menuBar.IsOpen ()); + + Application.End (rs); + top.Dispose (); + } }