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.Shortcut != KeyCode.Null) { KeyBinding keyBinding = new ([Command.Select], KeyBindingScope.HotKey, menuItem); menuBar.KeyBindings.Remove (menuItem.Shortcut); menuBar.KeyBindings.Add (menuItem.Shortcut, keyBinding); } 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; } }