MenuBarv2.cs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #nullable enable
  2. namespace Terminal.Gui;
  3. /// <summary>
  4. /// A horizontal list of <see cref="MenuBarItemv2"/>s. Each <see cref="MenuBarItemv2"/> can have a
  5. /// <see cref="PopoverMenu"/> that is shown when the <see cref="MenuBarItemv2"/> is selected.
  6. /// </summary>
  7. /// <remarks>
  8. /// MenuBars may be hosted by any View and will, by default, be positioned the full width across the top of the View's
  9. /// Viewport.
  10. /// </remarks>
  11. public class MenuBarv2 : Menuv2, IDesignable
  12. {
  13. /// <inheritdoc/>
  14. public MenuBarv2 () : this ([]) { }
  15. /// <inheritdoc/>
  16. public MenuBarv2 (IEnumerable<MenuBarItemv2> menuBarItems) : base (menuBarItems)
  17. {
  18. TabStop = TabBehavior.TabGroup;
  19. Y = 0;
  20. Width = Dim.Fill ();
  21. Orientation = Orientation.Horizontal;
  22. AddCommand (Command.Right, MoveRight);
  23. KeyBindings.Add (Key.CursorRight, Command.Right);
  24. AddCommand (Command.Left, MoveLeft);
  25. KeyBindings.Add (Key.CursorLeft, Command.Left);
  26. return;
  27. bool? MoveLeft (ICommandContext? ctx) { return AdvanceFocus (NavigationDirection.Backward, TabBehavior.TabStop); }
  28. bool? MoveRight (ICommandContext? ctx) { return AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop); }
  29. }
  30. /// <inheritdoc/>
  31. protected override void OnSelectedMenuItemChanged (MenuItemv2? selected)
  32. {
  33. if (selected is MenuBarItemv2 { } selectedMenuBarItem)
  34. {
  35. ShowPopover (selectedMenuBarItem);
  36. }
  37. }
  38. /// <inheritdoc/>
  39. public override void EndInit ()
  40. {
  41. base.EndInit ();
  42. if (Border is { })
  43. {
  44. Border.Thickness = new (0);
  45. Border.LineStyle = LineStyle.None;
  46. }
  47. // TODO: This needs to be done whenever a menuitem in any MenuBarItem changes
  48. foreach (MenuBarItemv2? mbi in SubViews.Select(s => s as MenuBarItemv2))
  49. {
  50. Application.Popover?.Register (mbi?.PopoverMenu);
  51. }
  52. }
  53. /// <inheritdoc/>
  54. protected override bool OnAccepting (CommandEventArgs args)
  55. {
  56. if (args.Context?.Source is MenuBarItemv2 { PopoverMenu: { } } menuBarItem)
  57. {
  58. ShowPopover (menuBarItem);
  59. }
  60. return base.OnAccepting (args);
  61. }
  62. private void ShowPopover (MenuBarItemv2? menuBarItem)
  63. {
  64. if (menuBarItem?.PopoverMenu is { IsInitialized: false })
  65. {
  66. menuBarItem.PopoverMenu.BeginInit ();
  67. menuBarItem.PopoverMenu.EndInit ();
  68. }
  69. // If the active popover is a PopoverMenu and part of this MenuBar...
  70. if (menuBarItem?.PopoverMenu is null
  71. && Application.Popover?.GetActivePopover () is PopoverMenu popoverMenu
  72. && popoverMenu?.Root?.SuperMenuItem?.SuperView == this)
  73. {
  74. Application.Popover?.Hide (popoverMenu);
  75. }
  76. menuBarItem?.PopoverMenu?.MakeVisible (new Point (menuBarItem.FrameToScreen ().X, menuBarItem.FrameToScreen ().Bottom));
  77. if (menuBarItem?.PopoverMenu?.Root is { })
  78. {
  79. menuBarItem.PopoverMenu.Root.SuperMenuItem = menuBarItem;
  80. }
  81. }
  82. /// <inheritdoc/>
  83. public bool EnableForDesign<TContext> (ref readonly TContext context) where TContext : notnull
  84. {
  85. Add (
  86. new MenuBarItemv2 (
  87. "_File",
  88. [
  89. new MenuItemv2 (this, Command.New),
  90. new MenuItemv2 (this, Command.Open),
  91. new MenuItemv2 (this, Command.Save),
  92. new MenuItemv2 (this, Command.SaveAs),
  93. new Line (),
  94. new MenuItemv2
  95. {
  96. Title = "_Preferences",
  97. SubMenu = new (
  98. [
  99. new MenuItemv2
  100. {
  101. CommandView = new CheckBox ()
  102. {
  103. Title = "O_ption",
  104. },
  105. HelpText = "Toggle option"
  106. },
  107. new MenuItemv2
  108. {
  109. Title = "_Settings...",
  110. HelpText = "More settings",
  111. Action = () => MessageBox.Query ("Settings", "This is the Settings Dialog\n", ["_Ok", "_Cancel"])
  112. }
  113. ]
  114. )
  115. },
  116. new Line (),
  117. new MenuItemv2 (this, Command.Quit)
  118. ]
  119. )
  120. );
  121. Add (
  122. new MenuBarItemv2 (
  123. "_Edit",
  124. [
  125. new MenuItemv2 (this, Command.Cut),
  126. new MenuItemv2 (this, Command.Copy),
  127. new MenuItemv2 (this, Command.Paste),
  128. new Line (),
  129. new MenuItemv2 (this, Command.SelectAll)
  130. ]
  131. )
  132. );
  133. Add (
  134. new MenuBarItemv2 (
  135. "_Help",
  136. [
  137. new MenuItemv2
  138. {
  139. Title = "_Online Help...",
  140. Action = () => MessageBox.Query ("Online Help", "https://gui-cs.github.io/Terminal.GuiV2Docs", "Ok")
  141. },
  142. new MenuItemv2
  143. {
  144. Title = "About...",
  145. Action = () => MessageBox.Query ("About", "Something About Mary.", "Ok")
  146. }
  147. ]
  148. )
  149. );
  150. return true;
  151. }
  152. }