MenuBarScenario.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. using System;
  2. using Terminal.Gui;
  3. namespace UICatalog.Scenarios;
  4. [ScenarioMetadata ("MenuBar", "Demonstrates the MenuBar using the same menu used in unit tests.")]
  5. [ScenarioCategory ("Controls")]
  6. [ScenarioCategory ("Menus")]
  7. public class MenuBarScenario : Scenario
  8. {
  9. private Label _currentMenuBarItem;
  10. private Label _currentMenuItem;
  11. private Label _focusedView;
  12. private Label _lastAction;
  13. private Label _lastKey;
  14. /// <summary>
  15. /// This method creates at test menu bar. It is called by the MenuBar unit tests, so it's possible to do both unit
  16. /// testing and user-experience testing with the same setup.
  17. /// </summary>
  18. /// <param name="actionFn"></param>
  19. /// <returns></returns>
  20. public static MenuBar CreateTestMenu (Func<string, bool> actionFn)
  21. {
  22. // TODO: add a disabled menu item to this
  23. var mb = new MenuBar
  24. {
  25. Menus =
  26. [
  27. new MenuBarItem (
  28. "_File",
  29. new MenuItem []
  30. {
  31. new (
  32. "_New",
  33. "",
  34. () => actionFn ("New"),
  35. null,
  36. null,
  37. KeyCode.CtrlMask | KeyCode.N
  38. ),
  39. new (
  40. "_Open",
  41. "",
  42. () => actionFn ("Open"),
  43. null,
  44. null,
  45. KeyCode.CtrlMask | KeyCode.O
  46. ),
  47. new (
  48. "_Save",
  49. "",
  50. () => actionFn ("Save"),
  51. null,
  52. null,
  53. KeyCode.CtrlMask | KeyCode.S
  54. ),
  55. null,
  56. // Don't use Ctrl-Q so we can disambiguate between quitting and closing the toplevel
  57. new (
  58. "_Quit",
  59. "",
  60. () => actionFn ("Quit"),
  61. null,
  62. null,
  63. KeyCode.AltMask
  64. | KeyCode.CtrlMask
  65. | KeyCode.Q
  66. )
  67. }
  68. ),
  69. new MenuBarItem (
  70. "_Edit",
  71. new MenuItem []
  72. {
  73. new (
  74. "_Copy",
  75. "",
  76. () => actionFn ("Copy"),
  77. null,
  78. null,
  79. KeyCode.CtrlMask | KeyCode.C
  80. ),
  81. new (
  82. "C_ut",
  83. "",
  84. () => actionFn ("Cut"),
  85. null,
  86. null,
  87. KeyCode.CtrlMask | KeyCode.X
  88. ),
  89. new (
  90. "_Paste",
  91. "",
  92. () => actionFn ("Paste"),
  93. null,
  94. null,
  95. KeyCode.CtrlMask | KeyCode.V
  96. ),
  97. new MenuBarItem (
  98. "_Find and Replace",
  99. new MenuItem []
  100. {
  101. new (
  102. "F_ind",
  103. "",
  104. () => actionFn ("Find"),
  105. null,
  106. null,
  107. KeyCode.CtrlMask | KeyCode.F
  108. ),
  109. new (
  110. "_Replace",
  111. "",
  112. () => actionFn ("Replace"),
  113. null,
  114. null,
  115. KeyCode.CtrlMask | KeyCode.H
  116. ),
  117. new MenuBarItem (
  118. "_3rd Level",
  119. new MenuItem []
  120. {
  121. new (
  122. "_1st",
  123. "",
  124. () => actionFn (
  125. "1"
  126. ),
  127. null,
  128. null,
  129. KeyCode.F1
  130. ),
  131. new (
  132. "_2nd",
  133. "",
  134. () => actionFn (
  135. "2"
  136. ),
  137. null,
  138. null,
  139. KeyCode.F2
  140. )
  141. }
  142. ),
  143. new MenuBarItem (
  144. "_4th Level",
  145. new MenuItem []
  146. {
  147. new (
  148. "_5th",
  149. "",
  150. () => actionFn (
  151. "5"
  152. ),
  153. null,
  154. null,
  155. KeyCode.CtrlMask
  156. | KeyCode.D5
  157. ),
  158. new (
  159. "_6th",
  160. "",
  161. () => actionFn (
  162. "6"
  163. ),
  164. null,
  165. null,
  166. KeyCode.CtrlMask
  167. | KeyCode.D6
  168. )
  169. }
  170. )
  171. }
  172. ),
  173. new (
  174. "_Select All",
  175. "",
  176. () => actionFn ("Select All"),
  177. null,
  178. null,
  179. KeyCode.CtrlMask
  180. | KeyCode.ShiftMask
  181. | KeyCode.S
  182. )
  183. }
  184. ),
  185. new MenuBarItem ("_About", "Top-Level", () => actionFn ("About"))
  186. ]
  187. };
  188. mb.UseKeysUpDownAsKeysLeftRight = true;
  189. mb.Key = KeyCode.F9;
  190. mb.Title = "TestMenuBar";
  191. return mb;
  192. }
  193. public override void Main ()
  194. {
  195. // Init
  196. Application.Init ();
  197. // Setup - Create a top-level application window and configure it.
  198. Window appWindow = new ()
  199. {
  200. Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
  201. BorderStyle = LineStyle.None
  202. };
  203. MenuItem mbiCurrent = null;
  204. MenuItem miCurrent = null;
  205. var label = new Label { X = 0, Y = 10, Text = "Last Key: " };
  206. appWindow.Add (label);
  207. _lastKey = new Label { X = Pos.Right (label), Y = Pos.Top (label), Text = "" };
  208. appWindow.Add (_lastKey);
  209. label = new Label { X = 0, Y = Pos.Bottom (label), Text = "Current MenuBarItem: " };
  210. appWindow.Add (label);
  211. _currentMenuBarItem = new Label { X = Pos.Right (label), Y = Pos.Top (label), Text = "" };
  212. appWindow.Add (_currentMenuBarItem);
  213. label = new Label { X = 0, Y = Pos.Bottom (label), Text = "Current MenuItem: " };
  214. appWindow.Add (label);
  215. _currentMenuItem = new Label { X = Pos.Right (label), Y = Pos.Top (label), Text = "" };
  216. appWindow.Add (_currentMenuItem);
  217. label = new Label { X = 0, Y = Pos.Bottom (label), Text = "Last Action: " };
  218. appWindow.Add (label);
  219. _lastAction = new Label { X = Pos.Right (label), Y = Pos.Top (label), Text = "" };
  220. appWindow.Add (_lastAction);
  221. label = new Label { X = 0, Y = Pos.Bottom (label), Text = "Focused View: " };
  222. appWindow.Add (label);
  223. _focusedView = new Label { X = Pos.Right (label), Y = Pos.Top (label), Text = "" };
  224. appWindow.Add (_focusedView);
  225. MenuBar menuBar = CreateTestMenu (
  226. s =>
  227. {
  228. _lastAction.Text = s;
  229. return true;
  230. }
  231. );
  232. menuBar.MenuOpening += (s, e) =>
  233. {
  234. mbiCurrent = e.CurrentMenu;
  235. SetCurrentMenuBarItem (mbiCurrent);
  236. SetCurrentMenuItem (miCurrent);
  237. _lastAction.Text = string.Empty;
  238. };
  239. menuBar.MenuOpened += (s, e) =>
  240. {
  241. miCurrent = e.MenuItem;
  242. SetCurrentMenuBarItem (mbiCurrent);
  243. SetCurrentMenuItem (miCurrent);
  244. };
  245. menuBar.MenuClosing += (s, e) =>
  246. {
  247. mbiCurrent = null;
  248. miCurrent = null;
  249. SetCurrentMenuBarItem (mbiCurrent);
  250. SetCurrentMenuItem (miCurrent);
  251. };
  252. Application.KeyDown += (s, e) =>
  253. {
  254. _lastAction.Text = string.Empty;
  255. _lastKey.Text = e.ToString ();
  256. };
  257. // There's no focus change event, so this is a bit of a hack.
  258. menuBar.LayoutComplete += (s, e) => { _focusedView.Text = appWindow.MostFocused?.ToString () ?? "None"; };
  259. var openBtn = new Button { X = Pos.Center (), Y = 4, Text = "_Open Menu", IsDefault = true };
  260. openBtn.Accept += (s, e) => { menuBar.OpenMenu (); };
  261. appWindow.Add (openBtn);
  262. var hideBtn = new Button { X = Pos.Center (), Y = Pos.Bottom (openBtn), Text = "Toggle Menu._Visible" };
  263. hideBtn.Accept += (s, e) => { menuBar.Visible = !menuBar.Visible; };
  264. appWindow.Add (hideBtn);
  265. var enableBtn = new Button { X = Pos.Center (), Y = Pos.Bottom (hideBtn), Text = "_Toggle Menu.Enable" };
  266. enableBtn.Accept += (s, e) => { menuBar.Enabled = !menuBar.Enabled; };
  267. appWindow.Add (enableBtn);
  268. appWindow.Add (menuBar);
  269. // Run - Start the application.
  270. Application.Run (appWindow);
  271. appWindow.Dispose ();
  272. // Shutdown - Calling Application.Shutdown is required.
  273. Application.Shutdown ();
  274. }
  275. private void SetCurrentMenuBarItem (MenuItem mbi) { _currentMenuBarItem.Text = mbi != null ? mbi.Title : "Closed"; }
  276. private void SetCurrentMenuItem (MenuItem mi) { _currentMenuItem.Text = mi != null ? mi.Title : "None"; }
  277. }