namespace Terminal.Gui; /// /// is a menu item on . MenuBarItems do not support /// . /// public class MenuBarItem : MenuItem { /// Initializes a new as a . /// Title for the menu item. /// Help text to display. Will be displayed next to the Title surrounded by parentheses. /// Action to invoke when the menu item is activated. /// Function to determine if the action can currently be executed. /// The parent of this if any. public MenuBarItem ( string title, string help, Action action, Func canExecute = null, MenuItem parent = null ) : base (title, help, action, canExecute, parent) { SetInitialProperties (title, null, null, true); } /// Initializes a new . /// Title for the menu item. /// The items in the current menu. /// The parent of this if any. public MenuBarItem (string title, MenuItem [] children, MenuItem parent = null) { SetInitialProperties (title, children, parent); } /// Initializes a new with separate list of items. /// Title for the menu item. /// The list of items in the current menu. /// The parent of this if any. public MenuBarItem (string title, List children, MenuItem parent = null) { SetInitialProperties (title, children, parent); } /// Initializes a new . /// The items in the current menu. public MenuBarItem (MenuItem [] children) : this ("", children) { } /// Initializes a new . public MenuBarItem () : this ([]) { } /// /// Gets or sets an array of objects that are the children of this /// /// /// The children. public MenuItem [] Children { get; set; } internal bool IsTopLevel => Parent is null && (Children is null || Children.Length == 0) && Action != null; /// Get the index of a child . /// /// Returns a greater than -1 if the is a child. public int GetChildrenIndex (MenuItem children) { var i = 0; if (Children is null) { return -1; } foreach (MenuItem child in Children) { if (child == children) { return i; } i++; } return -1; } /// Check if a is a submenu of this MenuBar. /// /// Returns true if it is a submenu. false otherwise. public bool IsSubMenuOf (MenuItem menuItem) { return Children.Any (child => child == menuItem && child.Parent == menuItem.Parent); } /// Check if a is a . /// /// Returns a or null otherwise. public MenuBarItem SubMenu (MenuItem menuItem) { return menuItem as MenuBarItem; } internal void AddShortcutKeyBindings (MenuBar menuBar) { if (Children is null) { return; } foreach (MenuItem menuItem in Children.Where (m => m is { })) { // For MenuBar only add shortcuts for submenus if (menuItem.ShortcutKey != Key.Empty) { menuItem.UpdateShortcutKeyBinding (Key.Empty); } SubMenu (menuItem)?.AddShortcutKeyBindings (menuBar); } } private void SetInitialProperties (string title, object children, MenuItem parent = null, bool isTopLevel = false) { if (!isTopLevel && children is null) { throw new ArgumentNullException ( nameof (children), @"The parameter cannot be null. Use an empty array instead." ); } SetTitle (title ?? ""); if (parent is { }) { Parent = parent; } switch (children) { case List childrenList: { MenuItem [] newChildren = []; foreach (MenuItem [] grandChild in childrenList) { foreach (MenuItem child in grandChild) { SetParent (grandChild); Array.Resize (ref newChildren, newChildren.Length + 1); newChildren [^1] = child; } } Children = newChildren; break; } case MenuItem [] items: SetParent (items); Children = items; break; default: Children = null; break; } } private void SetParent (MenuItem [] children) { foreach (MenuItem child in children) { if (child is { Parent: null }) { child.Parent = this; } } } private void SetTitle (string title) { title ??= string.Empty; Title = title; } /// /// Add a dynamically into the .Menus. /// /// public void AddMenuBarItem (MenuItem menuItem = null) { if (menuItem is null) { MenuBarItem [] menus = _menuBar.Menus; Array.Resize (ref menus, menus.Length + 1); menus [^1] = this; _menuBar.Menus = menus; } else { MenuItem [] childrens = Children ?? []; Array.Resize (ref childrens, childrens.Length + 1); childrens [^1] = menuItem; Children = childrens; } } /// public override void RemoveMenuItem () { if (Children is { }) { foreach (MenuItem menuItem in Children) { if (menuItem.ShortcutKey != Key.Empty) { // Remove an existent ShortcutKey _menuBar?.KeyBindings.Remove (menuItem.ShortcutKey); } } } if (ShortcutKey != Key.Empty) { // Remove an existent ShortcutKey _menuBar?.KeyBindings.Remove (ShortcutKey); } var index = _menuBar!.Menus.IndexOf (this); if (index > -1) { if (_menuBar!.Menus [index].HotKey != Key.Empty) { // Remove an existent HotKey _menuBar?.KeyBindings.Remove (HotKey.WithAlt); } _menuBar!.Menus [index] = null; } var i = 0; foreach (MenuBarItem m in _menuBar.Menus) { if (m != null) { _menuBar.Menus [i] = m; i++; } } MenuBarItem [] menus = _menuBar.Menus; Array.Resize (ref menus, menus.Length - 1); _menuBar.Menus = menus; } }