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);
}
}