using System.Diagnostics; namespace Terminal.Gui.Views; /// /// A -derived object to be used as items in a . /// MenuBarItems hold a instead of a . /// public class MenuBarItem : MenuItem { /// /// Creates a new instance of . /// public MenuBarItem () : base (null, Command.NotBound) { } /// /// Creates a new instance of . Each MenuBarItem typically has a /// that is /// shown when the item is selected. /// /// /// /// /// The View that will be invoked on when user does something that causes the MenuBarItems's /// Accept event to be raised. /// /// /// The Command to invoke on . The Key /// has bound to will be used as /// /// The text to display for the command. /// The Popover Menu that will be displayed when this item is selected. public MenuBarItem (View? targetView, Command command, string? commandText, PopoverMenu? popoverMenu = null) : base ( targetView, command, commandText) { TargetView = targetView; Command = command; PopoverMenu = popoverMenu; } /// /// Creates a new instance of with the specified . This is a /// helper for the most common MenuBar use-cases. /// /// /// /// The text to display for the command. /// The Popover Menu that will be displayed when this item is selected. public MenuBarItem (string commandText, PopoverMenu? popoverMenu = null) : this ( null, Command.NotBound, commandText, popoverMenu) { } /// /// Creates a new instance of with the automatcialy added to a /// . /// This is a helper for the most common MenuBar use-cases. /// /// /// /// The text to display for the command. /// /// The menu items that will be added to the Popover Menu that will be displayed when this item is /// selected. /// public MenuBarItem (string commandText, IEnumerable menuItems) : this ( null, Command.NotBound, commandText, new (menuItems) { Title = $"PopoverMenu for {commandText}" }) { } /// /// Do not use this property. MenuBarItem does not support SubMenu. Use instead. /// /// public new Menu? SubMenu { get => null; set => throw new InvalidOperationException ("MenuBarItem does not support SubMenu. Use PopoverMenu instead."); } private PopoverMenu? _popoverMenu; /// /// The Popover Menu that will be displayed when this item is selected. /// public PopoverMenu? PopoverMenu { get => _popoverMenu; set { if (_popoverMenu == value) { return; } if (_popoverMenu is { }) { _popoverMenu.VisibleChanged -= OnPopoverVisibleChanged; _popoverMenu.Accepted -= OnPopoverMenuOnAccepted; } _popoverMenu = value; if (_popoverMenu is { }) { _popoverMenu.App = App; PopoverMenuOpen = _popoverMenu.Visible; _popoverMenu.VisibleChanged += OnPopoverVisibleChanged; _popoverMenu.Accepted += OnPopoverMenuOnAccepted; } return; void OnPopoverVisibleChanged (object? sender, EventArgs args) { // Logging.Debug ($"OnPopoverVisibleChanged - {Title} - Visible = {_popoverMenu?.Visible} "); PopoverMenuOpen = _popoverMenu?.Visible ?? false; } void OnPopoverMenuOnAccepted (object? sender, CommandEventArgs args) { // Logging.Debug ($"OnPopoverMenuOnAccepted - {Title} - {args.Context?.Source?.Title} - {args.Context?.Command}"); RaiseAccepted (args.Context); } } } private bool _popoverMenuOpen; /// /// Gets or sets whether the MenuBarItem is active. This is used to determine if the MenuBarItem should be /// public bool PopoverMenuOpen { get => _popoverMenuOpen; set { if (_popoverMenuOpen == value) { return; } _popoverMenuOpen = value; RaisePopoverMenuOpenChanged(); } } /// /// /// public void RaisePopoverMenuOpenChanged () { OnPopoverMenuOpenChanged(); PopoverMenuOpenChanged?.Invoke (this, new EventArgs (PopoverMenuOpen)); } /// /// /// protected virtual void OnPopoverMenuOpenChanged () {} /// /// /// public event EventHandler>? PopoverMenuOpenChanged; /// protected override bool OnKeyDownNotHandled (Key key) { Logging.Trace ($"{key}"); if (PopoverMenu is { Visible: true } && HotKeyBindings.TryGet (key, out _)) { // If the user presses the hotkey for a menu item that is already open, // it should close the menu item (Test: MenuBarItem_HotKey_DeActivates) if (SuperView is MenuBar { } menuBar) { menuBar.HideActiveItem (); } return true; } return false; } /// protected override void OnHasFocusChanged (bool newHasFocus, View? previousFocusedView, View? focusedView) { // Logging.Debug ($"CanFocus = {CanFocus}, HasFocus = {HasFocus}"); } /// protected override void Dispose (bool disposing) { if (disposing) { PopoverMenu?.Dispose (); PopoverMenu = null; } base.Dispose (disposing); } }