| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- using System.Diagnostics;
- namespace Terminal.Gui.Views;
- /// <summary>
- /// A <see cref="Shortcut"/>-derived object to be used as items in a <see cref="MenuBar"/>.
- /// MenuBarItems hold a <see cref="PopoverMenu"/> instead of a <see cref="SubMenu"/>.
- /// </summary>
- public class MenuBarItem : MenuItem
- {
- /// <summary>
- /// Creates a new instance of <see cref="MenuBarItem"/>.
- /// </summary>
- public MenuBarItem () : base (null, Command.NotBound) { }
- /// <summary>
- /// Creates a new instance of <see cref="MenuBarItem"/>. Each MenuBarItem typically has a <see cref="PopoverMenu"/>
- /// that is
- /// shown when the item is selected.
- /// </summary>
- /// <remarks>
- /// </remarks>
- /// <param name="targetView">
- /// The View that <paramref name="command"/> will be invoked on when user does something that causes the MenuBarItems's
- /// Accept event to be raised.
- /// </param>
- /// <param name="command">
- /// The Command to invoke on <paramref name="targetView"/>. The Key <paramref name="targetView"/>
- /// has bound to <paramref name="command"/> will be used as <see cref="Key"/>
- /// </param>
- /// <param name="commandText">The text to display for the command.</param>
- /// <param name="popoverMenu">The Popover Menu that will be displayed when this item is selected.</param>
- public MenuBarItem (View? targetView, Command command, string? commandText, PopoverMenu? popoverMenu = null)
- : base (
- targetView,
- command,
- commandText)
- {
- TargetView = targetView;
- Command = command;
- PopoverMenu = popoverMenu;
- }
- /// <summary>
- /// Creates a new instance of <see cref="MenuBarItem"/> with the specified <paramref name="popoverMenu"/>. This is a
- /// helper for the most common MenuBar use-cases.
- /// </summary>
- /// <remarks>
- /// </remarks>
- /// <param name="commandText">The text to display for the command.</param>
- /// <param name="popoverMenu">The Popover Menu that will be displayed when this item is selected.</param>
- public MenuBarItem (string commandText, PopoverMenu? popoverMenu = null)
- : this (
- null,
- Command.NotBound,
- commandText,
- popoverMenu)
- { }
- /// <summary>
- /// Creates a new instance of <see cref="MenuBarItem"/> with the <paramref name="menuItems"/> automatcialy added to a
- /// <see cref="PopoverMenu"/>.
- /// This is a helper for the most common MenuBar use-cases.
- /// </summary>
- /// <remarks>
- /// </remarks>
- /// <param name="commandText">The text to display for the command.</param>
- /// <param name="menuItems">
- /// The menu items that will be added to the Popover Menu that will be displayed when this item is
- /// selected.
- /// </param>
- public MenuBarItem (string commandText, IEnumerable<View> menuItems)
- : this (
- null,
- Command.NotBound,
- commandText,
- new (menuItems) { Title = $"PopoverMenu for {commandText}" })
- { }
- /// <summary>
- /// Do not use this property. MenuBarItem does not support SubMenu. Use <see cref="PopoverMenu"/> instead.
- /// </summary>
- /// <exception cref="InvalidOperationException"></exception>
- public new Menu? SubMenu
- {
- get => null;
- set => throw new InvalidOperationException ("MenuBarItem does not support SubMenu. Use PopoverMenu instead.");
- }
- private PopoverMenu? _popoverMenu;
- /// <summary>
- /// The Popover Menu that will be displayed when this item is selected.
- /// </summary>
- 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;
- /// <summary>
- /// Gets or sets whether the MenuBarItem is active. This is used to determine if the MenuBarItem should be
- /// </summary>
- public bool PopoverMenuOpen
- {
- get => _popoverMenuOpen;
- set
- {
- if (_popoverMenuOpen == value)
- {
- return;
- }
- _popoverMenuOpen = value;
- RaisePopoverMenuOpenChanged();
- }
- }
- /// <summary>
- ///
- /// </summary>
- public void RaisePopoverMenuOpenChanged ()
- {
- OnPopoverMenuOpenChanged();
- PopoverMenuOpenChanged?.Invoke (this, new EventArgs<bool> (PopoverMenuOpen));
- }
- /// <summary>
- ///
- /// </summary>
- protected virtual void OnPopoverMenuOpenChanged () {}
- /// <summary>
- ///
- /// </summary>
- public event EventHandler<EventArgs<bool>>? PopoverMenuOpenChanged;
- /// <inheritdoc />
- 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;
- }
- /// <inheritdoc/>
- protected override void OnHasFocusChanged (bool newHasFocus, View? previousFocusedView, View? focusedView)
- {
- // Logging.Debug ($"CanFocus = {CanFocus}, HasFocus = {HasFocus}");
- }
- /// <inheritdoc/>
- protected override void Dispose (bool disposing)
- {
- if (disposing)
- {
- PopoverMenu?.Dispose ();
- PopoverMenu = null;
- }
- base.Dispose (disposing);
- }
- }
|