ContextMenuTests.cs 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417
  1. using System.Globalization;
  2. using Xunit.Abstractions;
  3. namespace Terminal.Gui.ViewsTests;
  4. public class ContextMenuTests (ITestOutputHelper output)
  5. {
  6. [Fact]
  7. [AutoInitShutdown]
  8. public void ContextMenu_Constructors ()
  9. {
  10. var cm = new ContextMenu ();
  11. Assert.Equal (Point.Empty, cm.Position);
  12. Assert.Empty (cm.MenuItems.Children);
  13. Assert.Null (cm.Host);
  14. cm.Position = new Point (20, 10);
  15. cm.MenuItems = new MenuBarItem (
  16. [
  17. new MenuItem ("First", "", null)
  18. ]
  19. );
  20. Assert.Equal (new Point (20, 10), cm.Position);
  21. Assert.Single (cm.MenuItems.Children);
  22. cm = new ContextMenu
  23. {
  24. Position = new Point (5, 10),
  25. MenuItems = new MenuBarItem (
  26. new [] { new MenuItem ("One", "", null), new MenuItem ("Two", "", null) }
  27. )
  28. };
  29. Assert.Equal (new Point (5, 10), cm.Position);
  30. Assert.Equal (2, cm.MenuItems.Children.Length);
  31. Assert.Null (cm.Host);
  32. cm = new ContextMenu
  33. {
  34. Host = new View { X = 5, Y = 10 },
  35. Position = new Point (5, 10),
  36. MenuItems = new MenuBarItem (
  37. new [] { new MenuItem ("One", "", null), new MenuItem ("Two", "", null) }
  38. )
  39. };
  40. Assert.Equal (new Point (5, 10), cm.Position);
  41. Assert.Equal (2, cm.MenuItems.Children.Length);
  42. Assert.NotNull (cm.Host);
  43. }
  44. [Fact]
  45. [AutoInitShutdown]
  46. public void ContextMenu_Is_Closed_If_Another_MenuBar_Is_Open_Or_Vice_Versa ()
  47. {
  48. var cm = new ContextMenu
  49. {
  50. Position = new Point (10, 5),
  51. MenuItems = new MenuBarItem (
  52. [
  53. new MenuItem ("One", "", null),
  54. new MenuItem ("Two", "", null)
  55. ]
  56. )
  57. };
  58. var menu = new MenuBar
  59. {
  60. Menus =
  61. [
  62. new MenuBarItem ("File", "", null),
  63. new MenuBarItem ("Edit", "", null)
  64. ]
  65. };
  66. var top = new Toplevel ();
  67. top.Add (menu);
  68. Application.Begin (top);
  69. Assert.Null (Application.MouseGrabView);
  70. cm.Show ();
  71. Assert.True (ContextMenu.IsShow);
  72. Assert.Equal (cm.MenuBar, Application.MouseGrabView);
  73. Assert.False (menu.IsMenuOpen);
  74. Assert.True (menu.NewKeyDownEvent (menu.Key));
  75. Assert.False (ContextMenu.IsShow);
  76. Assert.Equal (menu, Application.MouseGrabView);
  77. Assert.True (menu.IsMenuOpen);
  78. cm.Show ();
  79. Assert.True (ContextMenu.IsShow);
  80. Assert.Equal (cm.MenuBar, Application.MouseGrabView);
  81. Assert.False (menu.IsMenuOpen);
  82. #if SUPPORT_ALT_TO_ACTIVATE_MENU
  83. Assert.True (Application.Top.ProcessKeyUp (new (Key.AltMask)));
  84. Assert.False (ContextMenu.IsShow);
  85. Assert.Equal (menu, Application.MouseGrabView);
  86. Assert.True (menu.IsMenuOpen);
  87. #endif
  88. cm.Show ();
  89. Assert.True (ContextMenu.IsShow);
  90. Assert.Equal (cm.MenuBar, Application.MouseGrabView);
  91. Assert.False (menu.IsMenuOpen);
  92. Assert.False (menu.NewMouseEvent (new MouseEvent { Position = new (1, 0), Flags = MouseFlags.ReportMousePosition, View = menu }));
  93. Assert.True (ContextMenu.IsShow);
  94. Assert.Equal (cm.MenuBar, Application.MouseGrabView);
  95. Assert.False (menu.IsMenuOpen);
  96. Assert.True (menu.NewMouseEvent (new MouseEvent { Position = new (1, 0), Flags = MouseFlags.Button1Clicked, View = menu }));
  97. Assert.False (ContextMenu.IsShow);
  98. Assert.Equal (menu, Application.MouseGrabView);
  99. Assert.True (menu.IsMenuOpen);
  100. top.Dispose ();
  101. }
  102. [Fact]
  103. [AutoInitShutdown]
  104. public void Draw_A_ContextMenu_Over_A_Borderless_Top ()
  105. {
  106. ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
  107. Assert.Equal (new Rectangle (0, 0, 20, 15), Application.Driver?.Clip);
  108. TestHelpers.AssertDriverContentsWithFrameAre ("", output);
  109. var top = new Toplevel { X = 2, Y = 2, Width = 15, Height = 4 };
  110. top.Add (new TextField { X = Pos.Center (), Width = 10, Text = "Test" });
  111. RunState rs = Application.Begin (top);
  112. Assert.Equal (new Rectangle (2, 2, 15, 4), top.Frame);
  113. Assert.Equal (top, Application.Top);
  114. TestHelpers.AssertDriverContentsWithFrameAre (
  115. @"
  116. Test",
  117. output
  118. );
  119. Application.OnMouseEvent (new MouseEvent { Position = new (8, 2), Flags = MouseFlags.Button3Clicked });
  120. var firstIteration = false;
  121. Application.RunIteration (ref rs, ref firstIteration);
  122. TestHelpers.AssertDriverContentsWithFrameAre (
  123. @"
  124. Test
  125. ┌───────────────────
  126. │ Select All Ctrl+
  127. │ Delete All Ctrl+
  128. │ Copy Ctrl+
  129. │ Cut Ctrl+
  130. │ Paste Ctrl+
  131. │ Undo Ctrl+
  132. │ Redo Ctrl+
  133. └───────────────────",
  134. output
  135. );
  136. Application.End (rs);
  137. top.Dispose ();
  138. }
  139. [Fact]
  140. [AutoInitShutdown]
  141. public void Draw_A_ContextMenu_Over_A_Dialog ()
  142. {
  143. Toplevel top = new ();
  144. var win = new Window ();
  145. top.Add (win);
  146. RunState rsTop = Application.Begin (top);
  147. ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
  148. Assert.Equal (new Rectangle (0, 0, 20, 15), win.Frame);
  149. TestHelpers.AssertDriverContentsWithFrameAre (
  150. @"
  151. ┌──────────────────┐
  152. │ │
  153. │ │
  154. │ │
  155. │ │
  156. │ │
  157. │ │
  158. │ │
  159. │ │
  160. │ │
  161. │ │
  162. │ │
  163. │ │
  164. │ │
  165. └──────────────────┘",
  166. output
  167. );
  168. // Don't use Dialog here as it has more layout logic. Use Window instead.
  169. var dialog = new Window { X = 2, Y = 2, Width = 15, Height = 4 };
  170. dialog.Add (new TextField { X = Pos.Center (), Width = 10, Text = "Test" });
  171. RunState rsDialog = Application.Begin (dialog);
  172. Assert.Equal (new Rectangle (2, 2, 15, 4), dialog.Frame);
  173. TestHelpers.AssertDriverContentsWithFrameAre (
  174. @"
  175. ┌──────────────────┐
  176. │ │
  177. │ ┌─────────────┐ │
  178. │ │ Test │ │
  179. │ │ │ │
  180. │ └─────────────┘ │
  181. │ │
  182. │ │
  183. │ │
  184. │ │
  185. │ │
  186. │ │
  187. │ │
  188. │ │
  189. └──────────────────┘",
  190. output
  191. );
  192. Application.OnMouseEvent (new MouseEvent { Position = new (9, 3), Flags = MouseFlags.Button3Clicked });
  193. var firstIteration = false;
  194. Application.RunIteration (ref rsDialog, ref firstIteration);
  195. TestHelpers.AssertDriverContentsWithFrameAre (
  196. @"
  197. ┌──────────────────┐
  198. │ │
  199. │ ┌─────────────┐ │
  200. │ │ Test │ │
  201. ┌───────────────────
  202. │ Select All Ctrl+
  203. │ Delete All Ctrl+
  204. │ Copy Ctrl+
  205. │ Cut Ctrl+
  206. │ Paste Ctrl+
  207. │ Undo Ctrl+
  208. │ Redo Ctrl+
  209. └───────────────────
  210. │ │
  211. └──────────────────┘",
  212. output
  213. );
  214. Application.End (rsDialog);
  215. Application.End (rsTop);
  216. top.Dispose ();
  217. }
  218. [Fact]
  219. [AutoInitShutdown]
  220. public void Draw_A_ContextMenu_Over_A_Top_Dialog ()
  221. {
  222. ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
  223. Assert.Equal (new Rectangle (0, 0, 20, 15), Application.Driver?.Clip);
  224. TestHelpers.AssertDriverContentsWithFrameAre ("", output);
  225. // Don't use Dialog here as it has more layout logic. Use Window instead.
  226. var dialog = new Window { X = 2, Y = 2, Width = 15, Height = 4 };
  227. dialog.Add (new TextField { X = Pos.Center (), Width = 10, Text = "Test" });
  228. RunState rs = Application.Begin (dialog);
  229. Assert.Equal (new Rectangle (2, 2, 15, 4), dialog.Frame);
  230. Assert.Equal (dialog, Application.Top);
  231. TestHelpers.AssertDriverContentsWithFrameAre (
  232. @"
  233. ┌─────────────┐
  234. │ Test │
  235. │ │
  236. └─────────────┘",
  237. output
  238. );
  239. Application.OnMouseEvent (new MouseEvent { Position = new (9, 3), Flags = MouseFlags.Button3Clicked });
  240. var firstIteration = false;
  241. Application.RunIteration (ref rs, ref firstIteration);
  242. TestHelpers.AssertDriverContentsWithFrameAre (
  243. @"
  244. ┌─────────────┐
  245. │ Test │
  246. ┌───────────────────
  247. │ Select All Ctrl+
  248. │ Delete All Ctrl+
  249. │ Copy Ctrl+
  250. │ Cut Ctrl+
  251. │ Paste Ctrl+
  252. │ Undo Ctrl+
  253. │ Redo Ctrl+
  254. └───────────────────",
  255. output
  256. );
  257. Application.End (rs);
  258. dialog.Dispose ();
  259. }
  260. [Fact]
  261. [AutoInitShutdown]
  262. public void ForceMinimumPosToZero_True_False ()
  263. {
  264. var cm = new ContextMenu
  265. {
  266. Position = new Point (-1, -2),
  267. MenuItems = new MenuBarItem (
  268. [
  269. new MenuItem ("One", "", null),
  270. new MenuItem ("Two", "", null)
  271. ]
  272. )
  273. };
  274. Assert.Equal (new Point (-1, -2), cm.Position);
  275. Toplevel top = new ();
  276. Application.Begin (top);
  277. cm.Show ();
  278. Assert.Equal (new Point (-1, -2), cm.Position);
  279. Application.Refresh ();
  280. var expected = @"
  281. ┌──────┐
  282. │ One │
  283. │ Two │
  284. └──────┘
  285. ";
  286. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  287. Assert.Equal (new Rectangle (0, 1, 8, 4), pos);
  288. cm.ForceMinimumPosToZero = false;
  289. cm.Show ();
  290. Assert.Equal (new Point (-1, -2), cm.Position);
  291. Application.Refresh ();
  292. expected = @"
  293. One │
  294. Two │
  295. ──────┘
  296. ";
  297. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  298. Assert.Equal (new Rectangle (1, 0, 7, 3), pos);
  299. top.Dispose ();
  300. }
  301. [Fact]
  302. [AutoInitShutdown]
  303. public void Hide_Is_Invoke_At_Container_Closing ()
  304. {
  305. var cm = new ContextMenu
  306. {
  307. Position = new Point (80, 25),
  308. MenuItems = new MenuBarItem (
  309. [
  310. new MenuItem ("One", "", null),
  311. new MenuItem ("Two", "", null)
  312. ]
  313. )
  314. };
  315. Toplevel top = new ();
  316. Application.Begin (top);
  317. top.Running = true;
  318. Assert.False (ContextMenu.IsShow);
  319. cm.Show ();
  320. Assert.True (ContextMenu.IsShow);
  321. top.RequestStop ();
  322. Assert.False (ContextMenu.IsShow);
  323. top.Dispose ();
  324. }
  325. [Fact]
  326. [AutoInitShutdown]
  327. public void Key_Open_And_Close_The_ContextMenu ()
  328. {
  329. var tf = new TextField ();
  330. var top = new Toplevel ();
  331. top.Add (tf);
  332. Application.Begin (top);
  333. Assert.True (Application.OnKeyDown (ContextMenu.DefaultKey));
  334. Assert.True (tf.ContextMenu.MenuBar.IsMenuOpen);
  335. Assert.True (Application.OnKeyDown (ContextMenu.DefaultKey));
  336. Assert.Null (tf.ContextMenu.MenuBar);
  337. top.Dispose ();
  338. }
  339. [Fact]
  340. [AutoInitShutdown]
  341. public void KeyChanged_Event ()
  342. {
  343. var oldKey = Key.Empty;
  344. var cm = new ContextMenu ();
  345. cm.KeyChanged += (s, e) => oldKey = e.OldKey;
  346. cm.Key = Key.Space.WithCtrl;
  347. Assert.Equal (Key.Space.WithCtrl, cm.Key);
  348. Assert.Equal (ContextMenu.DefaultKey, oldKey);
  349. }
  350. [Fact]
  351. [AutoInitShutdown]
  352. public void MenuItens_Changing ()
  353. {
  354. var cm = new ContextMenu
  355. {
  356. Position = new Point (10, 5),
  357. MenuItems = new MenuBarItem (
  358. [
  359. new MenuItem ("One", "", null),
  360. new MenuItem ("Two", "", null)
  361. ]
  362. )
  363. };
  364. Toplevel top = new ();
  365. Application.Begin (top);
  366. cm.Show ();
  367. Application.Refresh ();
  368. var expected = @"
  369. ┌──────┐
  370. │ One │
  371. │ Two │
  372. └──────┘
  373. ";
  374. TestHelpers.AssertDriverContentsAre (expected, output);
  375. cm.MenuItems = new MenuBarItem (
  376. [
  377. new MenuItem ("First", "", null),
  378. new MenuItem ("Second", "", null),
  379. new MenuItem ("Third", "", null)
  380. ]
  381. );
  382. cm.Show ();
  383. Application.Refresh ();
  384. expected = @"
  385. ┌─────────┐
  386. │ First │
  387. │ Second │
  388. │ Third │
  389. └─────────┘
  390. ";
  391. TestHelpers.AssertDriverContentsAre (expected, output);
  392. top.Dispose ();
  393. }
  394. [Fact]
  395. [AutoInitShutdown]
  396. public void Menus_And_SubMenus_Always_Try_To_Be_On_Screen ()
  397. {
  398. var cm = new ContextMenu
  399. {
  400. Position = new Point (-1, -2),
  401. MenuItems = new MenuBarItem (
  402. [
  403. new MenuItem ("One", "", null),
  404. new MenuItem ("Two", "", null),
  405. new MenuItem ("Three", "", null),
  406. new MenuBarItem (
  407. "Four",
  408. [
  409. new MenuItem ("SubMenu1", "", null),
  410. new MenuItem ("SubMenu2", "", null),
  411. new MenuItem ("SubMenu3", "", null),
  412. new MenuItem ("SubMenu4", "", null),
  413. new MenuItem ("SubMenu5", "", null),
  414. new MenuItem ("SubMenu6", "", null),
  415. new MenuItem ("SubMenu7", "", null)
  416. ]
  417. ),
  418. new MenuItem ("Five", "", null),
  419. new MenuItem ("Six", "", null)
  420. ]
  421. )
  422. };
  423. Assert.Equal (new Point (-1, -2), cm.Position);
  424. Toplevel top = new ();
  425. Application.Begin (top);
  426. cm.Show ();
  427. Application.Refresh ();
  428. Assert.Equal (new Point (-1, -2), cm.Position);
  429. TestHelpers.AssertDriverContentsWithFrameAre (
  430. @"
  431. ┌────────┐
  432. │ One │
  433. │ Two │
  434. │ Three │
  435. │ Four ►│
  436. │ Five │
  437. │ Six │
  438. └────────┘
  439. ",
  440. output
  441. );
  442. Assert.True (
  443. top.Subviews [0]
  444. .NewMouseEvent (
  445. new MouseEvent { Position = new (0, 3), Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] }
  446. )
  447. );
  448. Application.Refresh ();
  449. Assert.Equal (new Point (-1, -2), cm.Position);
  450. TestHelpers.AssertDriverContentsWithFrameAre (
  451. @"
  452. ┌────────┐
  453. │ One │
  454. │ Two │
  455. │ Three │
  456. │ Four ►│┌───────────┐
  457. │ Five ││ SubMenu1 │
  458. │ Six ││ SubMenu2 │
  459. └────────┘│ SubMenu3 │
  460. │ SubMenu4 │
  461. │ SubMenu5 │
  462. │ SubMenu6 │
  463. │ SubMenu7 │
  464. └───────────┘
  465. ",
  466. output
  467. );
  468. ((FakeDriver)Application.Driver!).SetBufferSize (40, 20);
  469. cm.Position = new Point (41, -2);
  470. cm.Show ();
  471. Application.Refresh ();
  472. Assert.Equal (new Point (41, -2), cm.Position);
  473. TestHelpers.AssertDriverContentsWithFrameAre (
  474. @"
  475. ┌────────┐
  476. │ One │
  477. │ Two │
  478. │ Three │
  479. │ Four ►│
  480. │ Five │
  481. │ Six │
  482. └────────┘
  483. ",
  484. output
  485. );
  486. Assert.True (
  487. top.Subviews [0]
  488. .NewMouseEvent (
  489. new MouseEvent { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] }
  490. )
  491. );
  492. Application.Refresh ();
  493. Assert.Equal (new Point (41, -2), cm.Position);
  494. TestHelpers.AssertDriverContentsWithFrameAre (
  495. @"
  496. ┌────────┐
  497. │ One │
  498. │ Two │
  499. │ Three │
  500. ┌───────────┐│ Four ►│
  501. │ SubMenu1 ││ Five │
  502. │ SubMenu2 ││ Six │
  503. │ SubMenu3 │└────────┘
  504. │ SubMenu4 │
  505. │ SubMenu5 │
  506. │ SubMenu6 │
  507. │ SubMenu7 │
  508. └───────────┘
  509. ",
  510. output
  511. );
  512. cm.Position = new Point (41, 9);
  513. cm.Show ();
  514. Application.Refresh ();
  515. Assert.Equal (new Point (41, 9), cm.Position);
  516. TestHelpers.AssertDriverContentsWithFrameAre (
  517. @"
  518. ┌────────┐
  519. │ One │
  520. │ Two │
  521. │ Three │
  522. │ Four ►│
  523. │ Five │
  524. │ Six │
  525. └────────┘
  526. ",
  527. output
  528. );
  529. Assert.True (
  530. top.Subviews [0]
  531. .NewMouseEvent (
  532. new MouseEvent { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] }
  533. )
  534. );
  535. Application.Refresh ();
  536. Assert.Equal (new Point (41, 9), cm.Position);
  537. TestHelpers.AssertDriverContentsWithFrameAre (
  538. @"
  539. ┌────────┐
  540. ┌───────────┐│ One │
  541. │ SubMenu1 ││ Two │
  542. │ SubMenu2 ││ Three │
  543. │ SubMenu3 ││ Four ►│
  544. │ SubMenu4 ││ Five │
  545. │ SubMenu5 ││ Six │
  546. │ SubMenu6 │└────────┘
  547. │ SubMenu7 │
  548. └───────────┘
  549. ",
  550. output
  551. );
  552. cm.Position = new Point (41, 22);
  553. cm.Show ();
  554. Application.Refresh ();
  555. Assert.Equal (new Point (41, 22), cm.Position);
  556. TestHelpers.AssertDriverContentsWithFrameAre (
  557. @"
  558. ┌────────┐
  559. │ One │
  560. │ Two │
  561. │ Three │
  562. │ Four ►│
  563. │ Five │
  564. │ Six │
  565. └────────┘
  566. ",
  567. output
  568. );
  569. Assert.True (
  570. top.Subviews [0]
  571. .NewMouseEvent (
  572. new MouseEvent { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] }
  573. )
  574. );
  575. Application.Refresh ();
  576. Assert.Equal (new Point (41, 22), cm.Position);
  577. TestHelpers.AssertDriverContentsWithFrameAre (
  578. @"
  579. ┌───────────┐
  580. │ SubMenu1 │┌────────┐
  581. │ SubMenu2 ││ One │
  582. │ SubMenu3 ││ Two │
  583. │ SubMenu4 ││ Three │
  584. │ SubMenu5 ││ Four ►│
  585. │ SubMenu6 ││ Five │
  586. │ SubMenu7 ││ Six │
  587. └───────────┘└────────┘
  588. ",
  589. output
  590. );
  591. ((FakeDriver)Application.Driver!).SetBufferSize (18, 8);
  592. cm.Position = new Point (19, 10);
  593. cm.Show ();
  594. Application.Refresh ();
  595. Assert.Equal (new Point (19, 10), cm.Position);
  596. TestHelpers.AssertDriverContentsWithFrameAre (
  597. @"
  598. ┌────────┐
  599. │ One │
  600. │ Two │
  601. │ Three │
  602. │ Four ►│
  603. │ Five │
  604. │ Six │
  605. └────────┘
  606. ",
  607. output
  608. );
  609. Assert.True (
  610. top.Subviews [0]
  611. .NewMouseEvent (
  612. new MouseEvent { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] }
  613. )
  614. );
  615. Application.Refresh ();
  616. Assert.Equal (new Point (19, 10), cm.Position);
  617. TestHelpers.AssertDriverContentsWithFrameAre (
  618. @"
  619. ┌───────────┐────┐
  620. │ SubMenu1 │ │
  621. │ SubMenu2 │ │
  622. │ SubMenu3 │ee │
  623. │ SubMenu4 │r ►│
  624. │ SubMenu5 │e │
  625. │ SubMenu6 │ │
  626. │ SubMenu7 │────┘
  627. ",
  628. output
  629. );
  630. top.Dispose ();
  631. }
  632. [Fact]
  633. [AutoInitShutdown]
  634. public void MouseFlags_Changing ()
  635. {
  636. var lbl = new Label { Text = "Original" };
  637. var cm = new ContextMenu ();
  638. lbl.MouseClick += (s, e) =>
  639. {
  640. if (e.MouseEvent.Flags == cm.MouseFlags)
  641. {
  642. lbl.Text = "Replaced";
  643. e.Handled = true;
  644. }
  645. };
  646. Toplevel top = new ();
  647. top.Add (lbl);
  648. Application.Begin (top);
  649. Assert.True (lbl.NewMouseEvent (new MouseEvent { Flags = cm.MouseFlags }));
  650. Assert.Equal ("Replaced", lbl.Text);
  651. lbl.Text = "Original";
  652. cm.MouseFlags = MouseFlags.Button2Clicked;
  653. Assert.True (lbl.NewMouseEvent (new MouseEvent { Flags = cm.MouseFlags }));
  654. Assert.Equal ("Replaced", lbl.Text);
  655. top.Dispose ();
  656. }
  657. [Fact]
  658. public void MouseFlagsChanged_Event ()
  659. {
  660. var oldMouseFlags = new MouseFlags ();
  661. var cm = new ContextMenu ();
  662. cm.MouseFlagsChanged += (s, e) => oldMouseFlags = e.OldValue;
  663. cm.MouseFlags = MouseFlags.Button2Clicked;
  664. Assert.Equal (MouseFlags.Button2Clicked, cm.MouseFlags);
  665. Assert.Equal (MouseFlags.Button3Clicked, oldMouseFlags);
  666. }
  667. [Fact]
  668. [AutoInitShutdown]
  669. public void Position_Changing ()
  670. {
  671. var cm = new ContextMenu
  672. {
  673. Position = new Point (10, 5),
  674. MenuItems = new MenuBarItem (
  675. [
  676. new MenuItem ("One", "", null),
  677. new MenuItem ("Two", "", null)
  678. ]
  679. )
  680. };
  681. Toplevel top = new ();
  682. Application.Begin (top);
  683. cm.Show ();
  684. Application.Refresh ();
  685. var expected = @"
  686. ┌──────┐
  687. │ One │
  688. │ Two │
  689. └──────┘
  690. ";
  691. TestHelpers.AssertDriverContentsAre (expected, output);
  692. cm.Position = new Point (5, 10);
  693. cm.Show ();
  694. Application.Refresh ();
  695. expected = @"
  696. ┌──────┐
  697. │ One │
  698. │ Two │
  699. └──────┘
  700. ";
  701. TestHelpers.AssertDriverContentsAre (expected, output);
  702. top.Dispose ();
  703. }
  704. [Fact]
  705. [AutoInitShutdown]
  706. public void RequestStop_While_ContextMenu_Is_Open_Does_Not_Throws ()
  707. {
  708. ContextMenu cm = Create_ContextMenu_With_Two_MenuItem (10, 5);
  709. Toplevel top = new ();
  710. var isMenuAllClosed = false;
  711. MenuBarItem mi = null;
  712. int iterations = -1;
  713. Application.Iteration += (s, a) =>
  714. {
  715. iterations++;
  716. if (iterations == 0)
  717. {
  718. cm.Show ();
  719. Assert.True (ContextMenu.IsShow);
  720. mi = cm.MenuBar.Menus [0];
  721. mi.Action = () =>
  722. {
  723. var dialog1 = new Dialog ();
  724. Application.Run (dialog1);
  725. dialog1.Dispose ();
  726. Assert.False (ContextMenu.IsShow);
  727. Assert.True (isMenuAllClosed);
  728. };
  729. cm.MenuBar.MenuAllClosed += (_, _) => isMenuAllClosed = true;
  730. }
  731. else if (iterations == 1)
  732. {
  733. mi.Action ();
  734. }
  735. else if (iterations == 2)
  736. {
  737. Application.RequestStop ();
  738. }
  739. else if (iterations == 3)
  740. {
  741. isMenuAllClosed = false;
  742. cm.Show ();
  743. Assert.True (ContextMenu.IsShow);
  744. cm.MenuBar.MenuAllClosed += (_, _) => isMenuAllClosed = true;
  745. }
  746. else if (iterations == 4)
  747. {
  748. Exception exception = Record.Exception (() => Application.RequestStop ());
  749. Assert.Null (exception);
  750. }
  751. else
  752. {
  753. Application.RequestStop ();
  754. }
  755. };
  756. var isTopClosed = false;
  757. top.Closing += (_, _) =>
  758. {
  759. var dialog2 = new Dialog ();
  760. Application.Run (dialog2);
  761. dialog2.Dispose ();
  762. Assert.False (ContextMenu.IsShow);
  763. Assert.True (isMenuAllClosed);
  764. isTopClosed = true;
  765. };
  766. Application.Run (top);
  767. Assert.True (isTopClosed);
  768. Assert.False (ContextMenu.IsShow);
  769. Assert.True (isMenuAllClosed);
  770. top.Dispose ();
  771. }
  772. [Fact]
  773. [AutoInitShutdown]
  774. public void Show_Display_At_Zero_If_The_Toplevel_Height_Is_Less_Than_The_Menu_Height ()
  775. {
  776. ((FakeDriver)Application.Driver!).SetBufferSize (80, 3);
  777. var cm = new ContextMenu
  778. {
  779. Position = Point.Empty,
  780. MenuItems = new MenuBarItem (
  781. [
  782. new MenuItem ("One", "", null),
  783. new MenuItem ("Two", "", null)
  784. ]
  785. )
  786. };
  787. Assert.Equal (Point.Empty, cm.Position);
  788. Toplevel top = new ();
  789. Application.Begin (top);
  790. cm.Show ();
  791. Assert.Equal (Point.Empty, cm.Position);
  792. Application.Refresh ();
  793. var expected = @"
  794. ┌──────┐
  795. │ One │
  796. │ Two │";
  797. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  798. Assert.Equal (new Rectangle (0, 0, 8, 3), pos);
  799. cm.Hide ();
  800. Assert.Equal (Point.Empty, cm.Position);
  801. top.Dispose ();
  802. }
  803. [Fact]
  804. [AutoInitShutdown]
  805. public void Show_Display_At_Zero_If_The_Toplevel_Width_Is_Less_Than_The_Menu_Width ()
  806. {
  807. ((FakeDriver)Application.Driver!).SetBufferSize (5, 25);
  808. var cm = new ContextMenu
  809. {
  810. Position = Point.Empty,
  811. MenuItems = new MenuBarItem (
  812. [
  813. new MenuItem ("One", "", null),
  814. new MenuItem ("Two", "", null)
  815. ]
  816. )
  817. };
  818. Assert.Equal (Point.Empty, cm.Position);
  819. Toplevel top = new ();
  820. Application.Begin (top);
  821. cm.Show ();
  822. Assert.Equal (Point.Empty, cm.Position);
  823. Application.Refresh ();
  824. var expected = @"
  825. ┌────
  826. │ One
  827. │ Two
  828. └────";
  829. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  830. Assert.Equal (new Rectangle (0, 1, 5, 4), pos);
  831. cm.Hide ();
  832. Assert.Equal (Point.Empty, cm.Position);
  833. top.Dispose ();
  834. }
  835. [Fact]
  836. [AutoInitShutdown]
  837. public void Show_Display_Below_The_Bottom_Host_If_Has_Enough_Space ()
  838. {
  839. var view = new View
  840. {
  841. X = 10,
  842. Y = 5,
  843. Width = 10,
  844. Height = 1,
  845. Text = "View"
  846. };
  847. var cm = new ContextMenu
  848. {
  849. Host = view,
  850. Position = new Point (10, 5),
  851. MenuItems = new MenuBarItem (
  852. [
  853. new MenuItem ("One", "", null),
  854. new MenuItem ("Two", "", null)
  855. ]
  856. )
  857. };
  858. var top = new Toplevel ();
  859. top.Add (view);
  860. Application.Begin (top);
  861. Assert.Equal (new Point (10, 5), cm.Position);
  862. cm.Show ();
  863. top.Draw ();
  864. Assert.Equal (new Point (10, 5), cm.Position);
  865. var expected = @"
  866. View
  867. ┌──────┐
  868. │ One │
  869. │ Two │
  870. └──────┘
  871. ";
  872. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  873. Assert.Equal (new Rectangle (10, 5, 18, 5), pos);
  874. cm.Hide ();
  875. Assert.Equal (new Point (10, 5), cm.Position);
  876. cm.Host.X = 5;
  877. cm.Host.Y = 10;
  878. cm.Host.Height = 3;
  879. cm.Show ();
  880. Application.Top.Draw ();
  881. Assert.Equal (new Point (5, 12), cm.Position);
  882. expected = @"
  883. View
  884. ┌──────┐
  885. │ One │
  886. │ Two │
  887. └──────┘
  888. ";
  889. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  890. Assert.Equal (new Rectangle (5, 10, 13, 7), pos);
  891. cm.Hide ();
  892. Assert.Equal (new Point (5, 12), cm.Position);
  893. top.Dispose ();
  894. }
  895. [Fact]
  896. [AutoInitShutdown]
  897. public void Show_Ensures_Display_Inside_The_Container_But_Preserves_Position ()
  898. {
  899. var cm = new ContextMenu
  900. {
  901. Position = new Point (80, 25),
  902. MenuItems = new MenuBarItem (
  903. [
  904. new MenuItem ("One", "", null),
  905. new MenuItem ("Two", "", null)
  906. ]
  907. )
  908. };
  909. Assert.Equal (new Point (80, 25), cm.Position);
  910. Toplevel top = new ();
  911. Application.Begin (top);
  912. cm.Show ();
  913. Assert.Equal (new Point (80, 25), cm.Position);
  914. Application.Refresh ();
  915. var expected = @"
  916. ┌──────┐
  917. │ One │
  918. │ Two │
  919. └──────┘
  920. ";
  921. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  922. Assert.Equal (new Rectangle (72, 21, 80, 4), pos);
  923. cm.Hide ();
  924. Assert.Equal (new Point (80, 25), cm.Position);
  925. top.Dispose ();
  926. }
  927. [Fact]
  928. [AutoInitShutdown]
  929. public void Show_Ensures_Display_Inside_The_Container_Without_Overlap_The_Host ()
  930. {
  931. var view = new View
  932. {
  933. X = Pos.AnchorEnd (10),
  934. Y = Pos.AnchorEnd (1),
  935. Width = 10,
  936. Height = 1,
  937. Text = "View"
  938. };
  939. var cm = new ContextMenu
  940. {
  941. Host = view,
  942. MenuItems = new MenuBarItem (
  943. [
  944. new MenuItem ("One", "", null),
  945. new MenuItem ("Two", "", null)
  946. ]
  947. )
  948. };
  949. var top = new Toplevel ();
  950. top.Add (view);
  951. Application.Begin (top);
  952. Assert.Equal (new Rectangle (70, 24, 10, 1), view.Frame);
  953. Assert.Equal (Point.Empty, cm.Position);
  954. cm.Show ();
  955. Assert.Equal (new Point (70, 24), cm.Position);
  956. top.Draw ();
  957. var expected = @"
  958. ┌──────┐
  959. │ One │
  960. │ Two │
  961. └──────┘
  962. View
  963. ";
  964. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  965. Assert.Equal (new Rectangle (70, 20, 78, 5), pos);
  966. cm.Hide ();
  967. Assert.Equal (new Point (70, 24), cm.Position);
  968. top.Dispose ();
  969. }
  970. [Fact]
  971. [AutoInitShutdown]
  972. public void Show_Hide_IsShow ()
  973. {
  974. ContextMenu cm = Create_ContextMenu_With_Two_MenuItem (10, 5);
  975. Toplevel top = new ();
  976. Application.Begin (top);
  977. cm.Show ();
  978. Assert.True (ContextMenu.IsShow);
  979. Application.Refresh ();
  980. var expected = @"
  981. ┌──────┐
  982. │ One │
  983. │ Two │
  984. └──────┘
  985. ";
  986. TestHelpers.AssertDriverContentsAre (expected, output);
  987. cm.Hide ();
  988. Assert.False (ContextMenu.IsShow);
  989. Application.Refresh ();
  990. expected = "";
  991. TestHelpers.AssertDriverContentsAre (expected, output);
  992. top.Dispose ();
  993. }
  994. [Fact]
  995. [AutoInitShutdown]
  996. public void UseSubMenusSingleFrame_True_By_Mouse ()
  997. {
  998. var cm = new ContextMenu
  999. {
  1000. Position = new Point (5, 10),
  1001. MenuItems = new MenuBarItem (
  1002. "Numbers",
  1003. [
  1004. new MenuItem ("One", "", null),
  1005. new MenuBarItem (
  1006. "Two",
  1007. [
  1008. new MenuItem (
  1009. "Sub-Menu 1",
  1010. "",
  1011. null
  1012. ),
  1013. new MenuItem ("Sub-Menu 2", "", null)
  1014. ]
  1015. ),
  1016. new MenuItem ("Three", "", null)
  1017. ]
  1018. ),
  1019. UseSubMenusSingleFrame = true
  1020. };
  1021. Toplevel top = new ();
  1022. RunState rs = Application.Begin (top);
  1023. top.SetFocus ();
  1024. Assert.NotNull (Application.Current);
  1025. cm.Show ();
  1026. Assert.True(ContextMenu.IsShow);
  1027. Assert.True (Application.Top.Subviews [0].HasFocus);
  1028. Assert.Equal(Application.Top.Subviews [0], Application.Navigation.GetFocused());
  1029. Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);
  1030. Application.Refresh ();
  1031. TestHelpers.AssertDriverContentsWithFrameAre (
  1032. @"
  1033. ┌────────┐
  1034. │ One │
  1035. │ Two ►│
  1036. │ Three │
  1037. └────────┘",
  1038. output
  1039. );
  1040. // X=5 is the border and so need to use at least one more
  1041. Application.OnMouseEvent (new MouseEvent { Position = new (6, 13), Flags = MouseFlags.Button1Clicked });
  1042. var firstIteration = false;
  1043. Application.RunIteration (ref rs, ref firstIteration);
  1044. Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);
  1045. Assert.Equal (new Rectangle (5, 11, 15, 6), Application.Top.Subviews [1].Frame);
  1046. TestHelpers.AssertDriverContentsWithFrameAre (
  1047. @"
  1048. ┌─────────────┐
  1049. │◄ Two │
  1050. ├─────────────┤
  1051. │ Sub-Menu 1 │
  1052. │ Sub-Menu 2 │
  1053. └─────────────┘",
  1054. output
  1055. );
  1056. Application.OnMouseEvent (new MouseEvent { Position = new (6, 12), Flags = MouseFlags.Button1Clicked });
  1057. firstIteration = false;
  1058. Application.RunIteration (ref rs, ref firstIteration);
  1059. Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);
  1060. TestHelpers.AssertDriverContentsWithFrameAre (
  1061. @"
  1062. ┌────────┐
  1063. │ One │
  1064. │ Two ►│
  1065. │ Three │
  1066. └────────┘",
  1067. output
  1068. );
  1069. Application.End (rs);
  1070. top.Dispose ();
  1071. }
  1072. [Fact]
  1073. [AutoInitShutdown]
  1074. public void UseSubMenusSingleFrame_False_By_Mouse ()
  1075. {
  1076. var cm = new ContextMenu
  1077. {
  1078. Position = new Point (5, 10),
  1079. MenuItems = new MenuBarItem (
  1080. "Numbers",
  1081. [
  1082. new MenuItem ("One", "", null),
  1083. new MenuBarItem (
  1084. "Two",
  1085. [
  1086. new MenuItem (
  1087. "Two-Menu 1",
  1088. "",
  1089. null
  1090. ),
  1091. new MenuItem ("Two-Menu 2", "", null)
  1092. ]
  1093. ),
  1094. new MenuBarItem ("Three",
  1095. [
  1096. new MenuItem (
  1097. "Three-Menu 1",
  1098. "",
  1099. null
  1100. ),
  1101. new MenuItem ("Three-Menu 2", "", null)
  1102. ]
  1103. )
  1104. ]
  1105. )
  1106. };
  1107. Toplevel top = new ();
  1108. RunState rs = Application.Begin (top);
  1109. cm.Show ();
  1110. Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);
  1111. Application.Refresh ();
  1112. TestHelpers.AssertDriverContentsWithFrameAre (
  1113. @"
  1114. ┌────────┐
  1115. │ One │
  1116. │ Two ►│
  1117. │ Three ►│
  1118. └────────┘",
  1119. output
  1120. );
  1121. Application.OnMouseEvent (new MouseEvent { Position = new (6, 13), Flags = MouseFlags.ReportMousePosition });
  1122. var firstIteration = false;
  1123. Application.RunIteration (ref rs, ref firstIteration);
  1124. Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);
  1125. TestHelpers.AssertDriverContentsWithFrameAre (
  1126. @"
  1127. ┌────────┐
  1128. │ One │
  1129. │ Two ►│┌─────────────┐
  1130. │ Three ►││ Two-Menu 1 │
  1131. └────────┘│ Two-Menu 2 │
  1132. └─────────────┘",
  1133. output
  1134. );
  1135. Application.OnMouseEvent (new MouseEvent { Position = new (6, 14), Flags = MouseFlags.ReportMousePosition });
  1136. firstIteration = false;
  1137. Application.RunIteration (ref rs, ref firstIteration);
  1138. Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);
  1139. TestHelpers.AssertDriverContentsWithFrameAre (
  1140. @"
  1141. ┌────────┐
  1142. │ One │
  1143. │ Two ►│
  1144. │ Three ►│┌───────────────┐
  1145. └────────┘│ Three-Menu 1 │
  1146. │ Three-Menu 2 │
  1147. └───────────────┘",
  1148. output
  1149. );
  1150. Application.OnMouseEvent (new MouseEvent { Position = new (6, 13), Flags = MouseFlags.ReportMousePosition });
  1151. firstIteration = false;
  1152. Application.RunIteration (ref rs, ref firstIteration);
  1153. Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);
  1154. TestHelpers.AssertDriverContentsWithFrameAre (
  1155. @"
  1156. ┌────────┐
  1157. │ One │
  1158. │ Two ►│┌─────────────┐
  1159. │ Three ►││ Two-Menu 1 │
  1160. └────────┘│ Two-Menu 2 │
  1161. └─────────────┘",
  1162. output
  1163. );
  1164. Application.End (rs);
  1165. top.Dispose ();
  1166. }
  1167. private ContextMenu Create_ContextMenu_With_Two_MenuItem (int x, int y)
  1168. {
  1169. return new ContextMenu
  1170. {
  1171. Position = new Point (x, y),
  1172. MenuItems = new MenuBarItem (
  1173. new MenuItem [] { new ("One", "", null), new ("Two", "", null) }
  1174. )
  1175. };
  1176. }
  1177. [Fact]
  1178. [AutoInitShutdown]
  1179. public void Handling_TextField_With_Opened_ContextMenu_By_Mouse_HasFocus ()
  1180. {
  1181. var tf1 = new TextField { Width = 10, Text = "TextField 1" };
  1182. var tf2 = new TextField { Y = 2, Width = 10, Text = "TextField 2" };
  1183. var win = new Window ();
  1184. win.Add (tf1, tf2);
  1185. var rs = Application.Begin (win);
  1186. Assert.True (tf1.HasFocus);
  1187. Assert.False (tf2.HasFocus);
  1188. Assert.Equal (2, win.Subviews.Count);
  1189. Assert.Null (Application.MouseEnteredView);
  1190. // Right click on tf2 to open context menu
  1191. Application.OnMouseEvent (new () { Position = new (1, 3), Flags = MouseFlags.Button3Clicked });
  1192. Assert.False (tf1.HasFocus);
  1193. Assert.False (tf2.HasFocus);
  1194. Assert.Equal (3, win.Subviews.Count);
  1195. Assert.True (tf2.ContextMenu.MenuBar.IsMenuOpen);
  1196. Assert.True (win.Focused is Menu);
  1197. Assert.True (Application.MouseGrabView is MenuBar);
  1198. Assert.Equal (tf2, Application.MouseEnteredView);
  1199. // Click on tf1 to focus it, which cause context menu being closed
  1200. Application.OnMouseEvent (new () { Position = new (1, 1), Flags = MouseFlags.Button1Clicked });
  1201. Assert.True (tf1.HasFocus);
  1202. Assert.False (tf2.HasFocus);
  1203. Assert.Equal (2, win.Subviews.Count);
  1204. Assert.Null (tf2.ContextMenu.MenuBar);
  1205. Assert.Equal (win.Focused, tf1);
  1206. Assert.Null (Application.MouseGrabView);
  1207. Assert.Equal (tf1, Application.MouseEnteredView);
  1208. // Click on tf2 to focus it
  1209. Application.OnMouseEvent (new () { Position = new (1, 3), Flags = MouseFlags.Button1Clicked });
  1210. Assert.False (tf1.HasFocus);
  1211. Assert.True (tf2.HasFocus);
  1212. Assert.Equal (2, win.Subviews.Count);
  1213. Assert.Null (tf2.ContextMenu.MenuBar);
  1214. Assert.Equal (win.Focused, tf2);
  1215. Assert.Null (Application.MouseGrabView);
  1216. Assert.Equal (tf2, Application.MouseEnteredView);
  1217. Application.End (rs);
  1218. win.Dispose ();
  1219. }
  1220. }