| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- #nullable enable
- namespace Terminal.Gui;
- /// <summary>
- /// A <see cref="Bar"/>-derived object to be used as a vertically-oriented menu. Each subview is a <see cref="MenuItemv2"/>.
- /// </summary>
- public class Menuv2 : Bar
- {
- /// <inheritdoc/>
- public Menuv2 () : this ([]) { }
- /// <inheritdoc/>
- public Menuv2 (IEnumerable<MenuItemv2>? menuItems) : this (menuItems?.Cast<View> ()) { }
- /// <inheritdoc/>
- public Menuv2 (IEnumerable<View>? shortcuts) : base (shortcuts)
- {
- Orientation = Orientation.Vertical;
- Width = Dim.Auto ();
- Height = Dim.Auto (DimAutoStyle.Content, 1);
- Border!.Thickness = new Thickness (1, 1, 1, 1);
- Border.LineStyle = LineStyle.Single;
- }
- /// <summary>
- /// Gets or sets the menu item that opened this menu as a sub-menu.
- /// </summary>
- public MenuItemv2? SuperMenuItem { get; set; }
- /// <inheritdoc />
- protected override void OnVisibleChanged ()
- {
- if (Visible)
- {
- SelectedMenuItem = SubViews.Where (mi => mi is MenuItemv2).ElementAtOrDefault (0) as MenuItemv2;
- }
- }
- /// <inheritdoc />
- public override void EndInit ()
- {
- base.EndInit ();
- if (Border is { })
- {
- }
- }
- /// <inheritdoc />
- protected override void OnSubViewAdded (View view)
- {
- base.OnSubViewAdded (view);
- switch (view)
- {
- case MenuItemv2 menuItem:
- {
- menuItem.CanFocus = true;
- AddCommand (menuItem.Command, RaiseAccepted);
- menuItem.Accepted += MenuItemOnAccepted;
- break;
- void MenuItemOnAccepted (object? sender, CommandEventArgs e)
- {
- Logging.Trace ($"MenuItemOnAccepted: {e.Context?.Source?.Title}");
- RaiseAccepted (e.Context);
- }
- }
- case Line line:
- // Grow line so we get auto-join line
- line.X = Pos.Func (() => -Border!.Thickness.Left);
- line.Width = Dim.Fill ()! + Dim.Func (() => Border!.Thickness.Right);
- break;
- }
- }
- /// <inheritdoc />
- protected override bool OnAccepting (CommandEventArgs args)
- {
- Logging.Trace ($"{args.Context}");
- if (SuperMenuItem is { })
- {
- Logging.Trace ($"Invoking Accept on SuperMenuItem: {SuperMenuItem.Title}...");
- return SuperMenuItem?.SuperView?.InvokeCommand (Command.Accept, args.Context) is true;
- }
- return false;
- }
- // TODO: Consider moving Accepted to Bar?
- /// <summary>
- /// Raises the <see cref="OnAccepted"/>/<see cref="Accepted"/> event indicating an item in this menu (or submenu)
- /// was accepted. This is used to determine when to hide the menu.
- /// </summary>
- /// <param name="ctx"></param>
- /// <returns></returns>
- protected bool? RaiseAccepted (ICommandContext? ctx)
- {
- //Logging.Trace ($"RaiseAccepted: {ctx}");
- CommandEventArgs args = new () { Context = ctx };
- OnAccepted (args);
- Accepted?.Invoke (this, args);
- return true;
- }
- /// <summary>
- /// Called when the user has accepted an item in this menu (or submenu). This is used to determine when to hide the menu.
- /// </summary>
- /// <remarks>
- /// </remarks>
- /// <param name="args"></param>
- protected virtual void OnAccepted (CommandEventArgs args) { }
- /// <summary>
- /// Raised when the user has accepted an item in this menu (or submenu). This is used to determine when to hide the menu.
- /// </summary>
- /// <remarks>
- /// <para>
- /// See <see cref="RaiseAccepted"/> for more information.
- /// </para>
- /// </remarks>
- public event EventHandler<CommandEventArgs>? Accepted;
- /// <inheritdoc />
- protected override void OnFocusedChanged (View? previousFocused, View? focused)
- {
- base.OnFocusedChanged (previousFocused, focused);
- SelectedMenuItem = focused as MenuItemv2;
- RaiseSelectedMenuItemChanged (SelectedMenuItem);
- }
- /// <summary>
- /// Gets or set the currently selected menu item. This is a helper that
- /// tracks <see cref="View.Focused"/>.
- /// </summary>
- public MenuItemv2? SelectedMenuItem
- {
- get => Focused as MenuItemv2;
- set
- {
- if (value == Focused)
- {
- return;
- }
- // Note we DO NOT set focus here; This property tracks Focused
- }
- }
- internal void RaiseSelectedMenuItemChanged (MenuItemv2? selected)
- {
- //Logging.Trace ($"RaiseSelectedMenuItemChanged: {selected?.Title}");
- OnSelectedMenuItemChanged (selected);
- SelectedMenuItemChanged?.Invoke (this, selected);
- }
- /// <summary>
- /// Called when the selected menu item has changed.
- /// </summary>
- /// <param name="selected"></param>
- protected virtual void OnSelectedMenuItemChanged (MenuItemv2? selected)
- {
- }
- /// <summary>
- /// Raised when the selected menu item has changed.
- /// </summary>
- public event EventHandler<MenuItemv2?>? SelectedMenuItemChanged;
- }
|