ContextMenuTests.cs 81 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138
  1. using UnitTests;
  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. var top = new Toplevel ();
  12. Application.Begin (top);
  13. Assert.Equal (Point.Empty, cm.Position);
  14. Assert.Null (cm.MenuItems);
  15. Assert.Null (cm.Host);
  16. cm.Position = new Point (20, 10);
  17. var menuItems = new MenuBarItem (
  18. [
  19. new MenuItem ("First", "", null)
  20. ]
  21. );
  22. cm.Show (menuItems);
  23. Assert.Equal (new Point (20, 10), cm.Position);
  24. Assert.Single (cm.MenuItems!.Children);
  25. cm = new ContextMenu
  26. {
  27. Position = new Point (5, 10)
  28. };
  29. menuItems = new MenuBarItem (
  30. new [] { new MenuItem ("One", "", null), new MenuItem ("Two", "", null) }
  31. );
  32. cm.Show (menuItems);
  33. Assert.Equal (new Point (5, 10), cm.Position);
  34. Assert.Equal (2, cm.MenuItems!.Children.Length);
  35. Assert.Null (cm.Host);
  36. var view = new View { X = 5, Y = 10 };
  37. top.Add (view);
  38. cm = new ContextMenu
  39. {
  40. Host = view,
  41. Position = new Point (5, 10)
  42. };
  43. menuItems = new MenuBarItem (
  44. new [] { new MenuItem ("One", "", null), new MenuItem ("Two", "", null) }
  45. );
  46. cm.Show (menuItems);
  47. Assert.Equal (new Point (5, 10), cm.Position);
  48. Assert.Equal (2, cm.MenuItems.Children.Length);
  49. Assert.NotNull (cm.Host);
  50. top.Dispose ();
  51. }
  52. [Fact]
  53. [AutoInitShutdown]
  54. public void ContextMenu_Is_Closed_If_Another_MenuBar_Is_Open_Or_Vice_Versa ()
  55. {
  56. var cm = new ContextMenu
  57. {
  58. Position = new Point (10, 5)
  59. };
  60. var menuItems = new MenuBarItem (
  61. [
  62. new MenuItem ("One", "", null),
  63. new MenuItem ("Two", "", null)
  64. ]
  65. );
  66. var menuBar = new MenuBar
  67. {
  68. Menus =
  69. [
  70. new MenuBarItem ("File", "", null),
  71. new MenuBarItem ("Edit", "", null)
  72. ]
  73. };
  74. var top = new Toplevel ();
  75. top.Add (menuBar);
  76. Application.Begin (top);
  77. Assert.Null (Application.MouseGrabView);
  78. cm.Show (menuItems);
  79. Assert.True (ContextMenu.IsShow);
  80. Menu menu = (Menu)top.SubViews.First (v => v is Menu);
  81. Assert.Equal (menu, Application.MouseGrabView);
  82. Assert.False (menuBar.IsMenuOpen);
  83. Assert.True (menuBar.NewKeyDownEvent (menuBar.Key));
  84. Assert.False (ContextMenu.IsShow);
  85. Assert.Equal (menuBar, Application.MouseGrabView);
  86. Assert.True (menuBar.IsMenuOpen);
  87. cm.Show (menuItems);
  88. Assert.True (ContextMenu.IsShow);
  89. menu = (Menu)top.SubViews.First (v => v is Menu);
  90. Assert.Equal (menu, Application.MouseGrabView);
  91. Assert.False (menuBar.IsMenuOpen);
  92. #if SUPPORT_ALT_TO_ACTIVATE_MENU
  93. Assert.True (Application.Top.ProcessKeyUp (new (Key.AltMask)));
  94. Assert.False (ContextMenu.IsShow);
  95. Assert.Equal (menu, Application.MouseGrabView);
  96. Assert.True (menu.IsMenuOpen);
  97. #endif
  98. cm.Show (menuItems);
  99. Assert.True (ContextMenu.IsShow);
  100. menu = (Menu)top.SubViews.First (v => v is Menu);
  101. Assert.Equal (menu, Application.MouseGrabView);
  102. Assert.False (menuBar.IsMenuOpen);
  103. Assert.False (menuBar.NewMouseEvent (new MouseEventArgs { Position = new (1, 0), Flags = MouseFlags.ReportMousePosition, View = menuBar }));
  104. Assert.True (ContextMenu.IsShow);
  105. Assert.Equal (menu, Application.MouseGrabView);
  106. Assert.False (menuBar.IsMenuOpen);
  107. Assert.True (menuBar.NewMouseEvent (new MouseEventArgs { Position = new (1, 0), Flags = MouseFlags.Button1Clicked, View = menuBar }));
  108. Assert.False (ContextMenu.IsShow);
  109. Assert.Equal (menuBar, Application.MouseGrabView);
  110. Assert.True (menuBar.IsMenuOpen);
  111. top.Dispose ();
  112. }
  113. [Fact (Skip = "#3798 Broke. Will fix in #2975")]
  114. [AutoInitShutdown]
  115. public void Draw_A_ContextMenu_Over_A_Borderless_Top ()
  116. {
  117. ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
  118. Assert.Equal (new Rectangle (0, 0, 20, 15), View.GetClip ()!.GetBounds ());
  119. DriverAssert.AssertDriverContentsWithFrameAre ("", output);
  120. var top = new Toplevel { X = 2, Y = 2, Width = 15, Height = 4 };
  121. top.Add (new TextField { X = Pos.Center (), Width = 10, Text = "Test" });
  122. RunState rs = Application.Begin (top);
  123. Application.RunIteration (ref rs);
  124. Assert.Equal (new Rectangle (2, 2, 15, 4), top.Frame);
  125. Assert.Equal (top, Application.Top);
  126. DriverAssert.AssertDriverContentsWithFrameAre (
  127. @"
  128. Test",
  129. output
  130. );
  131. Application.RaiseMouseEvent (new MouseEventArgs { ScreenPosition = new (8, 2), Flags = MouseFlags.Button3Clicked });
  132. Application.RunIteration (ref rs);
  133. DriverAssert.AssertDriverContentsWithFrameAre (
  134. @"
  135. Test
  136. ┌───────────────────
  137. │ Select All Ctrl+
  138. │ Delete All Ctrl+
  139. │ Copy Ctrl+
  140. │ Cut Ctrl+
  141. │ Paste Ctrl+
  142. │ Undo Ctrl+
  143. │ Redo Ctrl+
  144. └───────────────────",
  145. output
  146. );
  147. Application.End (rs);
  148. top.Dispose ();
  149. }
  150. [Fact (Skip = "#3798 Broke. Will fix in #2975")]
  151. [AutoInitShutdown]
  152. public void Draw_A_ContextMenu_Over_A_Dialog ()
  153. {
  154. Toplevel top = new ();
  155. var win = new Window ();
  156. top.Add (win);
  157. RunState rsTop = Application.Begin (top);
  158. ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
  159. Assert.Equal (new Rectangle (0, 0, 20, 15), win.Frame);
  160. DriverAssert.AssertDriverContentsWithFrameAre (
  161. @"
  162. ┌──────────────────┐
  163. │ │
  164. │ │
  165. │ │
  166. │ │
  167. │ │
  168. │ │
  169. │ │
  170. │ │
  171. │ │
  172. │ │
  173. │ │
  174. │ │
  175. │ │
  176. └──────────────────┘",
  177. output
  178. );
  179. // Don't use Dialog here as it has more layout logic. Use Window instead.
  180. var testWindow = new Window { X = 2, Y = 2, Width = 15, Height = 4 };
  181. testWindow.Add (new TextField { X = Pos.Center (), Width = 10, Text = "Test" });
  182. RunState rsDialog = Application.Begin (testWindow);
  183. Application.LayoutAndDraw ();
  184. Assert.Equal (new Rectangle (2, 2, 15, 4), testWindow.Frame);
  185. DriverAssert.AssertDriverContentsWithFrameAre (
  186. @"
  187. ┌──────────────────┐
  188. │ │
  189. │ ┌─────────────┐ │
  190. │ │ Test │ │
  191. │ │ │ │
  192. │ └─────────────┘ │
  193. │ │
  194. │ │
  195. │ │
  196. │ │
  197. │ │
  198. │ │
  199. │ │
  200. │ │
  201. └──────────────────┘",
  202. output
  203. );
  204. Application.RaiseMouseEvent (new MouseEventArgs { ScreenPosition = new (9, 3), Flags = MouseFlags.Button3Clicked });
  205. Application.RunIteration (ref rsDialog);
  206. DriverAssert.AssertDriverContentsWithFrameAre (
  207. @"
  208. ┌──────────────────┐
  209. │ │
  210. │ ┌─────────────┐ │
  211. │ │ Test │ │
  212. ┌───────────────────
  213. │ Select All Ctrl+
  214. │ Delete All Ctrl+
  215. │ Copy Ctrl+
  216. │ Cut Ctrl+
  217. │ Paste Ctrl+
  218. │ Undo Ctrl+
  219. │ Redo Ctrl+
  220. └───────────────────
  221. │ │
  222. └──────────────────┘",
  223. output
  224. );
  225. Application.End (rsDialog);
  226. Application.End (rsTop);
  227. top.Dispose ();
  228. }
  229. [Fact (Skip = "#3798 Broke. Will fix in #2975")]
  230. [AutoInitShutdown]
  231. public void Draw_A_ContextMenu_Over_A_Top_Dialog ()
  232. {
  233. ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
  234. Assert.Equal (new Rectangle (0, 0, 20, 15), View.GetClip ()!.GetBounds ());
  235. DriverAssert.AssertDriverContentsWithFrameAre ("", output);
  236. // Don't use Dialog here as it has more layout logic. Use Window instead.
  237. var dialog = new Window { X = 2, Y = 2, Width = 15, Height = 4 };
  238. dialog.Add (new TextField { X = Pos.Center (), Width = 10, Text = "Test" });
  239. RunState rs = Application.Begin (dialog);
  240. Application.LayoutAndDraw ();
  241. Assert.Equal (new Rectangle (2, 2, 15, 4), dialog.Frame);
  242. Assert.Equal (dialog, Application.Top);
  243. DriverAssert.AssertDriverContentsWithFrameAre (
  244. @"
  245. ┌─────────────┐
  246. │ Test │
  247. │ │
  248. └─────────────┘",
  249. output
  250. );
  251. Application.RaiseMouseEvent (new MouseEventArgs { ScreenPosition = new (9, 3), Flags = MouseFlags.Button3Clicked });
  252. var firstIteration = false;
  253. Application.RunIteration (ref rs, firstIteration);
  254. DriverAssert.AssertDriverContentsWithFrameAre (
  255. @"
  256. ┌─────────────┐
  257. │ Test │
  258. ┌───────────────────
  259. │ Select All Ctrl+
  260. │ Delete All Ctrl+
  261. │ Copy Ctrl+
  262. │ Cut Ctrl+
  263. │ Paste Ctrl+
  264. │ Undo Ctrl+
  265. │ Redo Ctrl+
  266. └───────────────────",
  267. output
  268. );
  269. Application.End (rs);
  270. dialog.Dispose ();
  271. }
  272. [Fact]
  273. [AutoInitShutdown]
  274. public void ForceMinimumPosToZero_True_False ()
  275. {
  276. var cm = new ContextMenu
  277. {
  278. Position = new Point (-1, -2)
  279. };
  280. var menuItems = new MenuBarItem (
  281. [
  282. new MenuItem ("One", "", null),
  283. new MenuItem ("Two", "", null)
  284. ]
  285. );
  286. Assert.Equal (new Point (-1, -2), cm.Position);
  287. Toplevel top = new ();
  288. Application.Begin (top);
  289. cm.Show (menuItems);
  290. Assert.Equal (new Point (-1, -2), cm.Position);
  291. Application.LayoutAndDraw ();
  292. var expected = @"
  293. ┌──────┐
  294. │ One │
  295. │ Two │
  296. └──────┘
  297. ";
  298. Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
  299. Assert.Equal (new Rectangle (0, 1, 8, 4), pos);
  300. cm.ForceMinimumPosToZero = false;
  301. cm.Show (menuItems);
  302. Assert.Equal (new Point (-1, -2), cm.Position);
  303. Application.LayoutAndDraw ();
  304. expected = @"
  305. One │
  306. Two │
  307. ──────┘
  308. ";
  309. pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
  310. Assert.Equal (new Rectangle (1, 0, 7, 3), pos);
  311. top.Dispose ();
  312. }
  313. [Fact]
  314. [AutoInitShutdown]
  315. public void Hide_Is_Invoke_At_Container_Closing ()
  316. {
  317. var cm = new ContextMenu
  318. {
  319. Position = new Point (80, 25)
  320. };
  321. var menuItems = new MenuBarItem (
  322. [
  323. new MenuItem ("One", "", null),
  324. new MenuItem ("Two", "", null)
  325. ]
  326. );
  327. Toplevel top = new ();
  328. Application.Begin (top);
  329. top.Running = true;
  330. Assert.False (ContextMenu.IsShow);
  331. cm.Show (menuItems);
  332. Assert.True (ContextMenu.IsShow);
  333. top.RequestStop ();
  334. Assert.False (ContextMenu.IsShow);
  335. top.Dispose ();
  336. }
  337. [Fact]
  338. [AutoInitShutdown]
  339. public void Key_Open_And_Close_The_ContextMenu ()
  340. {
  341. var tf = new TextField ();
  342. var top = new Toplevel ();
  343. top.Add (tf);
  344. Application.Begin (top);
  345. Assert.True (Application.RaiseKeyDownEvent (ContextMenu.DefaultKey));
  346. Assert.True (tf.ContextMenu.MenuBar!.IsMenuOpen);
  347. Assert.True (Application.RaiseKeyDownEvent (ContextMenu.DefaultKey));
  348. // The last context menu bar opened is always preserved
  349. Assert.NotNull (tf.ContextMenu.MenuBar);
  350. top.Dispose ();
  351. }
  352. [Fact]
  353. [AutoInitShutdown]
  354. public void KeyChanged_Event ()
  355. {
  356. var oldKey = Key.Empty;
  357. var cm = new ContextMenu ();
  358. cm.KeyChanged += (s, e) => oldKey = e.OldKey;
  359. cm.Key = Key.Space.WithCtrl;
  360. Assert.Equal (Key.Space.WithCtrl, cm.Key);
  361. Assert.Equal (ContextMenu.DefaultKey, oldKey);
  362. }
  363. [Fact]
  364. [AutoInitShutdown]
  365. public void MenuItens_Changing ()
  366. {
  367. var cm = new ContextMenu
  368. {
  369. Position = new Point (10, 5)
  370. };
  371. var menuItems = new MenuBarItem (
  372. [
  373. new MenuItem ("One", "", null),
  374. new MenuItem ("Two", "", null)
  375. ]
  376. );
  377. Toplevel top = new ();
  378. Application.Begin (top);
  379. cm.Show (menuItems);
  380. Application.LayoutAndDraw ();
  381. var expected = @"
  382. ┌──────┐
  383. │ One │
  384. │ Two │
  385. └──────┘
  386. ";
  387. DriverAssert.AssertDriverContentsAre (expected, output);
  388. menuItems = new MenuBarItem (
  389. [
  390. new MenuItem ("First", "", null),
  391. new MenuItem ("Second", "", null),
  392. new MenuItem ("Third", "", null)
  393. ]
  394. );
  395. cm.Show (menuItems);
  396. Application.LayoutAndDraw ();
  397. expected = @"
  398. ┌─────────┐
  399. │ First │
  400. │ Second │
  401. │ Third │
  402. └─────────┘
  403. ";
  404. DriverAssert.AssertDriverContentsAre (expected, output);
  405. top.Dispose ();
  406. }
  407. [Fact]
  408. [AutoInitShutdown]
  409. public void Menus_And_SubMenus_Always_Try_To_Be_On_Screen ()
  410. {
  411. var cm = new ContextMenu
  412. {
  413. Position = new Point (-1, -2)
  414. };
  415. var menuItems = new MenuBarItem (
  416. [
  417. new MenuItem ("One", "", null),
  418. new MenuItem ("Two", "", null),
  419. new MenuItem ("Three", "", null),
  420. new MenuBarItem (
  421. "Four",
  422. [
  423. new MenuItem ("SubMenu1", "", null),
  424. new MenuItem ("SubMenu2", "", null),
  425. new MenuItem ("SubMenu3", "", null),
  426. new MenuItem ("SubMenu4", "", null),
  427. new MenuItem ("SubMenu5", "", null),
  428. new MenuItem ("SubMenu6", "", null),
  429. new MenuItem ("SubMenu7", "", null)
  430. ]
  431. ),
  432. new MenuItem ("Five", "", null),
  433. new MenuItem ("Six", "", null)
  434. ]
  435. );
  436. Assert.Equal (new Point (-1, -2), cm.Position);
  437. Toplevel top = new ();
  438. RunState rs = Application.Begin (top);
  439. cm.Show (menuItems);
  440. Application.RunIteration (ref rs);
  441. Assert.Equal (new Point (-1, -2), cm.Position);
  442. DriverAssert.AssertDriverContentsWithFrameAre (
  443. @"
  444. ┌────────┐
  445. │ One │
  446. │ Two │
  447. │ Three │
  448. │ Four ►│
  449. │ Five │
  450. │ Six │
  451. └────────┘
  452. ",
  453. output
  454. );
  455. View menu = top.SubViews.First (v => v is Menu);
  456. Assert.True (
  457. menu
  458. .NewMouseEvent (
  459. new MouseEventArgs { Position = new (0, 3), Flags = MouseFlags.ReportMousePosition, View = menu }
  460. )
  461. );
  462. Application.RunIteration (ref rs);
  463. Assert.Equal (new Point (-1, -2), cm.Position);
  464. DriverAssert.AssertDriverContentsWithFrameAre (
  465. @"
  466. ┌────────┐
  467. │ One │
  468. │ Two │
  469. │ Three │
  470. │ Four ►│┌───────────┐
  471. │ Five ││ SubMenu1 │
  472. │ Six ││ SubMenu2 │
  473. └────────┘│ SubMenu3 │
  474. │ SubMenu4 │
  475. │ SubMenu5 │
  476. │ SubMenu6 │
  477. │ SubMenu7 │
  478. └───────────┘
  479. ",
  480. output
  481. );
  482. ((FakeDriver)Application.Driver!).SetBufferSize (40, 20);
  483. cm.Position = new Point (41, -2);
  484. cm.Show (menuItems);
  485. Application.RunIteration (ref rs);
  486. Assert.Equal (new Point (41, -2), cm.Position);
  487. DriverAssert.AssertDriverContentsWithFrameAre (
  488. @"
  489. ┌────────┐
  490. │ One │
  491. │ Two │
  492. │ Three │
  493. │ Four ►│
  494. │ Five │
  495. │ Six │
  496. └────────┘
  497. ",
  498. output
  499. );
  500. menu = top.SubViews.First (v => v is Menu);
  501. Assert.True (
  502. menu
  503. .NewMouseEvent (
  504. new MouseEventArgs { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = menu }
  505. )
  506. );
  507. Application.RunIteration (ref rs);
  508. Assert.Equal (new Point (41, -2), cm.Position);
  509. DriverAssert.AssertDriverContentsWithFrameAre (
  510. @"
  511. ┌────────┐
  512. │ One │
  513. │ Two │
  514. │ Three │
  515. ┌───────────┐│ Four ►│
  516. │ SubMenu1 ││ Five │
  517. │ SubMenu2 ││ Six │
  518. │ SubMenu3 │└────────┘
  519. │ SubMenu4 │
  520. │ SubMenu5 │
  521. │ SubMenu6 │
  522. │ SubMenu7 │
  523. └───────────┘
  524. ",
  525. output
  526. );
  527. cm.Position = new Point (41, 9);
  528. cm.Show (menuItems);
  529. Application.RunIteration (ref rs);
  530. Assert.Equal (new Point (41, 9), cm.Position);
  531. DriverAssert.AssertDriverContentsWithFrameAre (
  532. @"
  533. ┌────────┐
  534. │ One │
  535. │ Two │
  536. │ Three │
  537. │ Four ►│
  538. │ Five │
  539. │ Six │
  540. └────────┘
  541. ",
  542. output
  543. );
  544. menu = top.SubViews.First (v => v is Menu);
  545. Assert.True (
  546. menu
  547. .NewMouseEvent (
  548. new MouseEventArgs { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = menu }
  549. )
  550. );
  551. Application.RunIteration (ref rs);
  552. Assert.Equal (new Point (41, 9), cm.Position);
  553. DriverAssert.AssertDriverContentsWithFrameAre (
  554. @"
  555. ┌────────┐
  556. ┌───────────┐│ One │
  557. │ SubMenu1 ││ Two │
  558. │ SubMenu2 ││ Three │
  559. │ SubMenu3 ││ Four ►│
  560. │ SubMenu4 ││ Five │
  561. │ SubMenu5 ││ Six │
  562. │ SubMenu6 │└────────┘
  563. │ SubMenu7 │
  564. └───────────┘
  565. ",
  566. output
  567. );
  568. cm.Position = new Point (41, 22);
  569. cm.Show (menuItems);
  570. Application.RunIteration (ref rs);
  571. Assert.Equal (new Point (41, 22), cm.Position);
  572. DriverAssert.AssertDriverContentsWithFrameAre (
  573. @"
  574. ┌────────┐
  575. │ One │
  576. │ Two │
  577. │ Three │
  578. │ Four ►│
  579. │ Five │
  580. │ Six │
  581. └────────┘
  582. ",
  583. output
  584. );
  585. menu = top.SubViews.First (v => v is Menu);
  586. Assert.True (
  587. menu
  588. .NewMouseEvent (
  589. new MouseEventArgs { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = menu }
  590. )
  591. );
  592. Application.RunIteration (ref rs);
  593. Assert.Equal (new Point (41, 22), cm.Position);
  594. DriverAssert.AssertDriverContentsWithFrameAre (
  595. @"
  596. ┌───────────┐
  597. │ SubMenu1 │┌────────┐
  598. │ SubMenu2 ││ One │
  599. │ SubMenu3 ││ Two │
  600. │ SubMenu4 ││ Three │
  601. │ SubMenu5 ││ Four ►│
  602. │ SubMenu6 ││ Five │
  603. │ SubMenu7 ││ Six │
  604. └───────────┘└────────┘
  605. ",
  606. output
  607. );
  608. ((FakeDriver)Application.Driver!).SetBufferSize (18, 8);
  609. cm.Position = new Point (19, 10);
  610. cm.Show (menuItems);
  611. Application.RunIteration (ref rs);
  612. Assert.Equal (new Point (19, 10), cm.Position);
  613. DriverAssert.AssertDriverContentsWithFrameAre (
  614. @"
  615. ┌────────┐
  616. │ One │
  617. │ Two │
  618. │ Three │
  619. │ Four ►│
  620. │ Five │
  621. │ Six │
  622. └────────┘
  623. ",
  624. output
  625. );
  626. menu = top.SubViews.First (v => v is Menu);
  627. Assert.True (
  628. menu
  629. .NewMouseEvent (
  630. new MouseEventArgs { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = menu }
  631. )
  632. );
  633. Application.RunIteration (ref rs);
  634. Assert.Equal (new Point (19, 10), cm.Position);
  635. DriverAssert.AssertDriverContentsWithFrameAre (
  636. @"
  637. ┌───────────┐────┐
  638. │ SubMenu1 │ │
  639. │ SubMenu2 │ │
  640. │ SubMenu3 │ee │
  641. │ SubMenu4 │r ►│
  642. │ SubMenu5 │e │
  643. │ SubMenu6 │ │
  644. │ SubMenu7 │────┘
  645. ",
  646. output
  647. );
  648. top.Dispose ();
  649. }
  650. [Fact]
  651. [AutoInitShutdown]
  652. public void MouseFlags_Changing ()
  653. {
  654. var lbl = new Label { Text = "Original" };
  655. var cm = new ContextMenu ();
  656. lbl.MouseClick += (s, e) =>
  657. {
  658. if (e.Flags == cm.MouseFlags)
  659. {
  660. lbl.Text = "Replaced";
  661. e.Handled = true;
  662. }
  663. };
  664. Toplevel top = new ();
  665. top.Add (lbl);
  666. Application.Begin (top);
  667. Assert.True (lbl.NewMouseEvent (new MouseEventArgs { Flags = cm.MouseFlags }));
  668. Assert.Equal ("Replaced", lbl.Text);
  669. lbl.Text = "Original";
  670. cm.MouseFlags = MouseFlags.Button2Clicked;
  671. Assert.True (lbl.NewMouseEvent (new MouseEventArgs { Flags = cm.MouseFlags }));
  672. Assert.Equal ("Replaced", lbl.Text);
  673. top.Dispose ();
  674. }
  675. [Fact]
  676. public void MouseFlagsChanged_Event ()
  677. {
  678. var oldMouseFlags = new MouseFlags ();
  679. var cm = new ContextMenu ();
  680. cm.MouseFlagsChanged += (s, e) => oldMouseFlags = e.OldValue;
  681. cm.MouseFlags = MouseFlags.Button2Clicked;
  682. Assert.Equal (MouseFlags.Button2Clicked, cm.MouseFlags);
  683. Assert.Equal (MouseFlags.Button3Clicked, oldMouseFlags);
  684. }
  685. [Fact]
  686. [AutoInitShutdown]
  687. public void Position_Changing ()
  688. {
  689. var cm = new ContextMenu
  690. {
  691. Position = new Point (10, 5)
  692. };
  693. var menuItems = new MenuBarItem (
  694. [
  695. new MenuItem ("One", "", null),
  696. new MenuItem ("Two", "", null)
  697. ]
  698. );
  699. Toplevel top = new ();
  700. Application.Begin (top);
  701. cm.Show (menuItems);
  702. Application.LayoutAndDraw ();
  703. var expected = @"
  704. ┌──────┐
  705. │ One │
  706. │ Two │
  707. └──────┘
  708. ";
  709. DriverAssert.AssertDriverContentsAre (expected, output);
  710. cm.Position = new Point (5, 10);
  711. cm.Show (menuItems);
  712. Application.LayoutAndDraw ();
  713. expected = @"
  714. ┌──────┐
  715. │ One │
  716. │ Two │
  717. └──────┘
  718. ";
  719. DriverAssert.AssertDriverContentsAre (expected, output);
  720. top.Dispose ();
  721. }
  722. [Fact]
  723. [AutoInitShutdown]
  724. public void RequestStop_While_ContextMenu_Is_Open_Does_Not_Throws ()
  725. {
  726. ContextMenu cm = new ContextMenu
  727. {
  728. Position = new Point (10, 5)
  729. };
  730. var menuItems = new MenuBarItem (
  731. new MenuItem [] { new ("One", "", null), new ("Two", "", null) }
  732. );
  733. Toplevel top = new ();
  734. var isMenuAllClosed = false;
  735. MenuBarItem mi = null;
  736. int iterations = -1;
  737. Application.Iteration += (s, a) =>
  738. {
  739. iterations++;
  740. if (iterations == 0)
  741. {
  742. cm.Show (menuItems);
  743. Assert.True (ContextMenu.IsShow);
  744. mi = cm.MenuBar.Menus [0];
  745. mi.Action = () =>
  746. {
  747. Assert.True (ContextMenu.IsShow);
  748. var dialog1 = new Dialog () { Id = "dialog1" };
  749. Application.Run (dialog1);
  750. dialog1.Dispose ();
  751. Assert.False (ContextMenu.IsShow);
  752. Assert.True (isMenuAllClosed);
  753. };
  754. cm.MenuBar.MenuAllClosed += (_, _) => isMenuAllClosed = true;
  755. }
  756. else if (iterations == 1)
  757. {
  758. mi.Action ();
  759. }
  760. else if (iterations == 2)
  761. {
  762. Application.RequestStop ();
  763. }
  764. else if (iterations == 3)
  765. {
  766. isMenuAllClosed = false;
  767. cm.Show (menuItems);
  768. Assert.True (ContextMenu.IsShow);
  769. cm.MenuBar.MenuAllClosed += (_, _) => isMenuAllClosed = true;
  770. }
  771. else if (iterations == 4)
  772. {
  773. Exception exception = Record.Exception (() => Application.RequestStop ());
  774. Assert.Null (exception);
  775. }
  776. else
  777. {
  778. Application.RequestStop ();
  779. }
  780. };
  781. var isTopClosed = false;
  782. top.Closing += (_, _) =>
  783. {
  784. var dialog2 = new Dialog () { Id = "dialog2" };
  785. Application.Run (dialog2);
  786. dialog2.Dispose ();
  787. Assert.False (ContextMenu.IsShow);
  788. Assert.True (isMenuAllClosed);
  789. isTopClosed = true;
  790. };
  791. Application.Run (top);
  792. Assert.True (isTopClosed);
  793. Assert.False (ContextMenu.IsShow);
  794. Assert.True (isMenuAllClosed);
  795. top.Dispose ();
  796. }
  797. [Fact]
  798. [AutoInitShutdown]
  799. public void Show_Display_At_Zero_If_The_Toplevel_Height_Is_Less_Than_The_Menu_Height ()
  800. {
  801. ((FakeDriver)Application.Driver!).SetBufferSize (80, 3);
  802. var cm = new ContextMenu
  803. {
  804. Position = Point.Empty
  805. };
  806. var menuItems = new MenuBarItem (
  807. [
  808. new MenuItem ("One", "", null),
  809. new MenuItem ("Two", "", null)
  810. ]
  811. );
  812. Assert.Equal (Point.Empty, cm.Position);
  813. Toplevel top = new ();
  814. Application.Begin (top);
  815. cm.Show (menuItems);
  816. Assert.Equal (Point.Empty, cm.Position);
  817. Application.LayoutAndDraw ();
  818. var expected = @"
  819. ┌──────┐
  820. │ One │
  821. │ Two │";
  822. Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
  823. Assert.Equal (new Rectangle (0, 0, 8, 3), pos);
  824. cm.Hide ();
  825. Assert.Equal (Point.Empty, cm.Position);
  826. top.Dispose ();
  827. }
  828. [Fact]
  829. [AutoInitShutdown]
  830. public void Show_Display_At_Zero_If_The_Toplevel_Width_Is_Less_Than_The_Menu_Width ()
  831. {
  832. ((FakeDriver)Application.Driver!).SetBufferSize (5, 25);
  833. var cm = new ContextMenu
  834. {
  835. Position = Point.Empty
  836. };
  837. var menuItems = new MenuBarItem (
  838. [
  839. new MenuItem ("One", "", null),
  840. new MenuItem ("Two", "", null)
  841. ]
  842. );
  843. Assert.Equal (Point.Empty, cm.Position);
  844. Toplevel top = new ();
  845. Application.Begin (top);
  846. cm.Show (menuItems);
  847. Assert.Equal (Point.Empty, cm.Position);
  848. Application.LayoutAndDraw ();
  849. var expected = @"
  850. ┌────
  851. │ One
  852. │ Two
  853. └────";
  854. Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
  855. Assert.Equal (new Rectangle (0, 1, 5, 4), pos);
  856. cm.Hide ();
  857. Assert.Equal (Point.Empty, cm.Position);
  858. top.Dispose ();
  859. }
  860. [Fact]
  861. [AutoInitShutdown]
  862. public void Show_Display_Below_The_Bottom_Host_If_Has_Enough_Space ()
  863. {
  864. var view = new View
  865. {
  866. X = 10,
  867. Y = 5,
  868. Width = 10,
  869. Height = 1,
  870. Text = "View"
  871. };
  872. var cm = new ContextMenu
  873. {
  874. Host = view,
  875. Position = new Point (10, 5)
  876. };
  877. var menuItems = new MenuBarItem (
  878. [
  879. new MenuItem ("One", "", null),
  880. new MenuItem ("Two", "", null)
  881. ]
  882. );
  883. var top = new Toplevel ();
  884. top.Add (view);
  885. Application.Begin (top);
  886. Assert.Equal (new Point (10, 5), cm.Position);
  887. cm.Show (menuItems);
  888. top.Draw ();
  889. Assert.Equal (new Point (10, 5), cm.Position);
  890. var expected = @"
  891. View
  892. ┌──────┐
  893. │ One │
  894. │ Two │
  895. └──────┘
  896. ";
  897. Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
  898. Assert.Equal (new Rectangle (10, 5, 18, 5), pos);
  899. cm.Hide ();
  900. Assert.Equal (new Point (10, 5), cm.Position);
  901. cm.Host.X = 5;
  902. cm.Host.Y = 10;
  903. cm.Host.Height = 3;
  904. cm.Show (menuItems);
  905. View.SetClipToScreen ();
  906. Application.Top.Draw ();
  907. Assert.Equal (new Point (5, 12), cm.Position);
  908. expected = @"
  909. View
  910. ┌──────┐
  911. │ One │
  912. │ Two │
  913. └──────┘
  914. ";
  915. pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
  916. Assert.Equal (new Rectangle (5, 10, 13, 7), pos);
  917. cm.Hide ();
  918. Assert.Equal (new Point (5, 12), cm.Position);
  919. top.Dispose ();
  920. }
  921. [Fact]
  922. [AutoInitShutdown]
  923. public void Show_Ensures_Display_Inside_The_Container_But_Preserves_Position ()
  924. {
  925. var cm = new ContextMenu
  926. {
  927. Position = new Point (80, 25)
  928. };
  929. var menuItems = new MenuBarItem (
  930. [
  931. new MenuItem ("One", "", null),
  932. new MenuItem ("Two", "", null)
  933. ]
  934. );
  935. Assert.Equal (new Point (80, 25), cm.Position);
  936. Toplevel top = new ();
  937. Application.Begin (top);
  938. cm.Show (menuItems);
  939. Assert.Equal (new Point (80, 25), cm.Position);
  940. Application.LayoutAndDraw ();
  941. var expected = @"
  942. ┌──────┐
  943. │ One │
  944. │ Two │
  945. └──────┘
  946. ";
  947. Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
  948. Assert.Equal (new Rectangle (72, 21, 80, 4), pos);
  949. cm.Hide ();
  950. Assert.Equal (new Point (80, 25), cm.Position);
  951. top.Dispose ();
  952. }
  953. [Fact]
  954. [AutoInitShutdown]
  955. public void Show_Ensures_Display_Inside_The_Container_Without_Overlap_The_Host ()
  956. {
  957. var view = new View
  958. {
  959. X = Pos.AnchorEnd (10),
  960. Y = Pos.AnchorEnd (1),
  961. Width = 10,
  962. Height = 1,
  963. Text = "View"
  964. };
  965. var cm = new ContextMenu
  966. {
  967. Host = view
  968. };
  969. var menuItems = new MenuBarItem (
  970. [
  971. new MenuItem ("One", "", null),
  972. new MenuItem ("Two", "", null)
  973. ]
  974. );
  975. var top = new Toplevel ();
  976. top.Add (view);
  977. Application.Begin (top);
  978. Assert.Equal (new Rectangle (70, 24, 10, 1), view.Frame);
  979. Assert.Equal (Point.Empty, cm.Position);
  980. cm.Show (menuItems);
  981. Assert.Equal (new Point (70, 24), cm.Position);
  982. top.Draw ();
  983. var expected = @"
  984. ┌──────┐
  985. │ One │
  986. │ Two │
  987. └──────┘
  988. View
  989. ";
  990. Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
  991. Assert.Equal (new Rectangle (70, 20, 78, 5), pos);
  992. cm.Hide ();
  993. Assert.Equal (new Point (70, 24), cm.Position);
  994. top.Dispose ();
  995. }
  996. [Fact]
  997. [AutoInitShutdown]
  998. public void Show_Hide_IsShow ()
  999. {
  1000. ContextMenu cm = new ContextMenu
  1001. {
  1002. Position = new Point (10, 5)
  1003. };
  1004. var menuItems = new MenuBarItem (
  1005. new MenuItem [] { new ("One", "", null), new ("Two", "", null) }
  1006. );
  1007. Toplevel top = new ();
  1008. Application.Begin (top);
  1009. cm.Show (menuItems);
  1010. Assert.True (ContextMenu.IsShow);
  1011. Application.LayoutAndDraw ();
  1012. var expected = @"
  1013. ┌──────┐
  1014. │ One │
  1015. │ Two │
  1016. └──────┘
  1017. ";
  1018. DriverAssert.AssertDriverContentsAre (expected, output);
  1019. cm.Hide ();
  1020. Assert.False (ContextMenu.IsShow);
  1021. Application.LayoutAndDraw ();
  1022. expected = "";
  1023. DriverAssert.AssertDriverContentsAre (expected, output);
  1024. top.Dispose ();
  1025. }
  1026. [Fact]
  1027. [AutoInitShutdown]
  1028. public void UseSubMenusSingleFrame_True_By_Mouse ()
  1029. {
  1030. var cm = new ContextMenu
  1031. {
  1032. Position = new Point (5, 10),
  1033. UseSubMenusSingleFrame = true
  1034. };
  1035. var menuItems = new MenuBarItem (
  1036. "Numbers",
  1037. [
  1038. new MenuItem ("One", "", null),
  1039. new MenuBarItem (
  1040. "Two",
  1041. [
  1042. new MenuItem (
  1043. "Sub-Menu 1",
  1044. "",
  1045. null
  1046. ),
  1047. new MenuItem ("Sub-Menu 2", "", null)
  1048. ]
  1049. ),
  1050. new MenuItem ("Three", "", null)
  1051. ]
  1052. );
  1053. Toplevel top = new ();
  1054. RunState rs = Application.Begin (top);
  1055. cm.Show (menuItems);
  1056. var menu = Application.Top!.SubViews.First (v => v is Menu);
  1057. Assert.Equal (new Rectangle (5, 11, 10, 5), menu.Frame);
  1058. Application.LayoutAndDraw ();
  1059. DriverAssert.AssertDriverContentsWithFrameAre (
  1060. @"
  1061. ┌────────┐
  1062. │ One │
  1063. │ Two ►│
  1064. │ Three │
  1065. └────────┘",
  1066. output
  1067. );
  1068. // X=5 is the border and so need to use at least one more
  1069. Application.RaiseMouseEvent (new MouseEventArgs { ScreenPosition = new (6, 13), Flags = MouseFlags.Button1Clicked });
  1070. var firstIteration = false;
  1071. Application.RunIteration (ref rs, firstIteration);
  1072. menu = Application.Top!.SubViews.First (v => v is Menu);
  1073. Assert.Equal (new Rectangle (5, 11, 10, 5), menu.Frame);
  1074. menu = Application.Top!.SubViews.Last (v => v is Menu);
  1075. Assert.Equal (new Rectangle (5, 11, 15, 6), menu.Frame);
  1076. DriverAssert.AssertDriverContentsWithFrameAre (
  1077. @"
  1078. ┌─────────────┐
  1079. │◄ Two │
  1080. ├─────────────┤
  1081. │ Sub-Menu 1 │
  1082. │ Sub-Menu 2 │
  1083. └─────────────┘",
  1084. output
  1085. );
  1086. Application.RaiseMouseEvent (new MouseEventArgs { ScreenPosition = new (6, 12), Flags = MouseFlags.Button1Clicked });
  1087. firstIteration = false;
  1088. Application.RunIteration (ref rs, firstIteration);
  1089. menu = Application.Top!.SubViews.First (v => v is Menu);
  1090. Assert.Equal (new Rectangle (5, 11, 10, 5), menu.Frame);
  1091. DriverAssert.AssertDriverContentsWithFrameAre (
  1092. @"
  1093. ┌────────┐
  1094. │ One │
  1095. │ Two ►│
  1096. │ Three │
  1097. └────────┘",
  1098. output
  1099. );
  1100. Application.End (rs);
  1101. top.Dispose ();
  1102. }
  1103. [Fact]
  1104. [AutoInitShutdown]
  1105. public void UseSubMenusSingleFrame_False_By_Mouse ()
  1106. {
  1107. var cm = new ContextMenu
  1108. {
  1109. Position = new Point (5, 10)
  1110. };
  1111. var menuItems = new MenuBarItem (
  1112. "Numbers",
  1113. [
  1114. new MenuItem ("One", "", null),
  1115. new MenuBarItem (
  1116. "Two",
  1117. [
  1118. new MenuItem (
  1119. "Two-Menu 1",
  1120. "",
  1121. null
  1122. ),
  1123. new MenuItem ("Two-Menu 2", "", null)
  1124. ]
  1125. ),
  1126. new MenuBarItem (
  1127. "Three",
  1128. [
  1129. new MenuItem (
  1130. "Three-Menu 1",
  1131. "",
  1132. null
  1133. ),
  1134. new MenuItem ("Three-Menu 2", "", null)
  1135. ]
  1136. )
  1137. ]
  1138. );
  1139. Toplevel top = new ();
  1140. RunState rs = Application.Begin (top);
  1141. cm.Show (menuItems);
  1142. var menu = Application.Top!.SubViews.First (v => v is Menu);
  1143. Assert.Equal (new Rectangle (5, 11, 10, 5), menu.Frame);
  1144. Application.LayoutAndDraw ();
  1145. DriverAssert.AssertDriverContentsWithFrameAre (
  1146. @"
  1147. ┌────────┐
  1148. │ One │
  1149. │ Two ►│
  1150. │ Three ►│
  1151. └────────┘",
  1152. output
  1153. );
  1154. Application.RaiseMouseEvent (new MouseEventArgs { ScreenPosition = new (6, 13), Flags = MouseFlags.ReportMousePosition });
  1155. var firstIteration = false;
  1156. Application.RunIteration (ref rs, firstIteration);
  1157. menu = Application.Top!.SubViews.First (v => v is Menu);
  1158. Assert.Equal (new Rectangle (5, 11, 10, 5), menu.Frame);
  1159. DriverAssert.AssertDriverContentsWithFrameAre (
  1160. @"
  1161. ┌────────┐
  1162. │ One │
  1163. │ Two ►│┌─────────────┐
  1164. │ Three ►││ Two-Menu 1 │
  1165. └────────┘│ Two-Menu 2 │
  1166. └─────────────┘",
  1167. output
  1168. );
  1169. Application.RaiseMouseEvent (new MouseEventArgs { ScreenPosition = new (6, 14), Flags = MouseFlags.ReportMousePosition });
  1170. firstIteration = false;
  1171. Application.RunIteration (ref rs, firstIteration);
  1172. menu = Application.Top!.SubViews.First (v => v is Menu);
  1173. Assert.Equal (new Rectangle (5, 11, 10, 5), menu.Frame);
  1174. DriverAssert.AssertDriverContentsWithFrameAre (
  1175. @"
  1176. ┌────────┐
  1177. │ One │
  1178. │ Two ►│
  1179. │ Three ►│┌───────────────┐
  1180. └────────┘│ Three-Menu 1 │
  1181. │ Three-Menu 2 │
  1182. └───────────────┘",
  1183. output
  1184. );
  1185. Application.RaiseMouseEvent (new MouseEventArgs { ScreenPosition = new (6, 13), Flags = MouseFlags.ReportMousePosition });
  1186. firstIteration = false;
  1187. Application.RunIteration (ref rs, firstIteration);
  1188. menu = Application.Top!.SubViews.First (v => v is Menu);
  1189. Assert.Equal (new Rectangle (5, 11, 10, 5), menu.Frame);
  1190. DriverAssert.AssertDriverContentsWithFrameAre (
  1191. @"
  1192. ┌────────┐
  1193. │ One │
  1194. │ Two ►│┌─────────────┐
  1195. │ Three ►││ Two-Menu 1 │
  1196. └────────┘│ Two-Menu 2 │
  1197. └─────────────┘",
  1198. output
  1199. );
  1200. Application.End (rs);
  1201. top.Dispose ();
  1202. }
  1203. [Fact]
  1204. [AutoInitShutdown]
  1205. public void Handling_TextField_With_Opened_ContextMenu_By_Mouse_HasFocus ()
  1206. {
  1207. var tf1 = new TextField { Width = 10, Text = "TextField 1" };
  1208. var tf2 = new TextField { Y = 2, Width = 10, Text = "TextField 2" };
  1209. var win = new Window ();
  1210. win.Add (tf1, tf2);
  1211. var rs = Application.Begin (win);
  1212. Assert.True (tf1.HasFocus);
  1213. Assert.False (tf2.HasFocus);
  1214. Assert.Equal (4, win.SubViews.Count); // TF & TV add autocomplete popup's to their superviews.
  1215. Assert.Empty (Application._cachedViewsUnderMouse);
  1216. // Right click on tf2 to open context menu
  1217. Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 3), Flags = MouseFlags.Button3Clicked });
  1218. Assert.False (tf1.HasFocus);
  1219. Assert.False (tf2.HasFocus);
  1220. Assert.Equal (6, win.SubViews.Count);
  1221. Assert.True (tf2.ContextMenu.MenuBar.IsMenuOpen);
  1222. Assert.True (win.Focused is Menu);
  1223. Assert.True (Application.MouseGrabView is Menu);
  1224. Assert.Equal (tf2, Application._cachedViewsUnderMouse.LastOrDefault ());
  1225. // Click on tf1 to focus it, which cause context menu being closed
  1226. Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 1), Flags = MouseFlags.Button1Clicked });
  1227. Assert.True (tf1.HasFocus);
  1228. Assert.False (tf2.HasFocus);
  1229. Assert.Equal (5, win.SubViews.Count);
  1230. // The last context menu bar opened is always preserved
  1231. Assert.NotNull (tf2.ContextMenu.MenuBar);
  1232. Assert.Equal (win.Focused, tf1);
  1233. Assert.Null (Application.MouseGrabView);
  1234. Assert.Equal (tf1, Application._cachedViewsUnderMouse.LastOrDefault ());
  1235. // Click on tf2 to focus it
  1236. Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 3), Flags = MouseFlags.Button1Clicked });
  1237. Assert.False (tf1.HasFocus);
  1238. Assert.True (tf2.HasFocus);
  1239. Assert.Equal (5, win.SubViews.Count);
  1240. // The last context menu bar opened is always preserved
  1241. Assert.NotNull (tf2.ContextMenu.MenuBar);
  1242. Assert.Equal (win.Focused, tf2);
  1243. Assert.Null (Application.MouseGrabView);
  1244. Assert.Equal (tf2, Application._cachedViewsUnderMouse.LastOrDefault ());
  1245. Application.End (rs);
  1246. win.Dispose ();
  1247. }
  1248. [Fact]
  1249. [AutoInitShutdown]
  1250. public void Empty_Menus_Items_Children_Does_Not_Open_The_Menu ()
  1251. {
  1252. var cm = new ContextMenu ();
  1253. Assert.Null (cm.MenuItems);
  1254. var top = new Toplevel ();
  1255. Application.Begin (top);
  1256. cm.Show (cm.MenuItems);
  1257. Assert.Null (cm.MenuBar);
  1258. top.Dispose ();
  1259. }
  1260. [Fact]
  1261. [AutoInitShutdown]
  1262. public void KeyBindings_Removed_On_Close_ContextMenu ()
  1263. {
  1264. var newFile = false;
  1265. var renameFile = false;
  1266. var deleteFile = false;
  1267. var cm = new ContextMenu ();
  1268. var menuItems = new MenuBarItem (
  1269. [
  1270. new MenuItem ("New File", string.Empty, New, null, null, Key.N.WithCtrl),
  1271. new MenuItem ("Rename File", string.Empty, Rename, null, null, Key.R.WithCtrl),
  1272. new MenuItem ("Delete File", string.Empty, Delete, null, null, Key.D.WithCtrl)
  1273. ]
  1274. );
  1275. var top = new Toplevel ();
  1276. Application.Begin (top);
  1277. Assert.Null (cm.MenuBar);
  1278. Assert.False (Application.RaiseKeyDownEvent (Key.N.WithCtrl));
  1279. Assert.False (Application.RaiseKeyDownEvent (Key.R.WithCtrl));
  1280. Assert.False (Application.RaiseKeyDownEvent (Key.D.WithCtrl));
  1281. Assert.False (newFile);
  1282. Assert.False (renameFile);
  1283. Assert.False (deleteFile);
  1284. cm.Show (menuItems);
  1285. Assert.True (cm.MenuBar!.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
  1286. Assert.True (cm.MenuBar.HotKeyBindings.TryGet (Key.R.WithCtrl, out _));
  1287. Assert.True (cm.MenuBar.HotKeyBindings.TryGet (Key.D.WithCtrl, out _));
  1288. Assert.True (Application.RaiseKeyDownEvent (Key.N.WithCtrl));
  1289. Application.MainLoop!.RunIteration ();
  1290. Assert.True (newFile);
  1291. Assert.False (cm.MenuBar!.IsMenuOpen);
  1292. cm.Show (menuItems);
  1293. Assert.True (Application.RaiseKeyDownEvent (Key.R.WithCtrl));
  1294. Application.MainLoop!.RunIteration ();
  1295. Assert.True (renameFile);
  1296. Assert.False (cm.MenuBar.IsMenuOpen);
  1297. cm.Show (menuItems);
  1298. Assert.True (Application.RaiseKeyDownEvent (Key.D.WithCtrl));
  1299. Application.MainLoop!.RunIteration ();
  1300. Assert.True (deleteFile);
  1301. Assert.False (cm.MenuBar.IsMenuOpen);
  1302. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
  1303. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.WithCtrl, out _));
  1304. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.D.WithCtrl, out _));
  1305. newFile = false;
  1306. renameFile = false;
  1307. deleteFile = false;
  1308. Assert.False (Application.RaiseKeyDownEvent (Key.N.WithCtrl));
  1309. Assert.False (Application.RaiseKeyDownEvent (Key.R.WithCtrl));
  1310. Assert.False (Application.RaiseKeyDownEvent (Key.D.WithCtrl));
  1311. Assert.False (newFile);
  1312. Assert.False (renameFile);
  1313. Assert.False (deleteFile);
  1314. top.Dispose ();
  1315. void New () { newFile = true; }
  1316. void Rename () { renameFile = true; }
  1317. void Delete () { deleteFile = true; }
  1318. }
  1319. [Fact]
  1320. [AutoInitShutdown]
  1321. public void KeyBindings_With_ContextMenu_And_MenuBar ()
  1322. {
  1323. var newFile = false;
  1324. var renameFile = false;
  1325. var menuBar = new MenuBar
  1326. {
  1327. Menus =
  1328. [
  1329. new (
  1330. "File",
  1331. new MenuItem []
  1332. {
  1333. new ("New", string.Empty, New, null, null, Key.N.WithCtrl)
  1334. })
  1335. ]
  1336. };
  1337. var cm = new ContextMenu ();
  1338. var menuItems = new MenuBarItem (
  1339. [
  1340. new ("Rename File", string.Empty, Rename, null, null, Key.R.WithCtrl),
  1341. ]
  1342. );
  1343. var top = new Toplevel ();
  1344. top.Add (menuBar);
  1345. Application.Begin (top);
  1346. Assert.True (menuBar.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
  1347. Assert.False (menuBar.HotKeyBindings.TryGet (Key.R.WithCtrl, out _));
  1348. Assert.Null (cm.MenuBar);
  1349. Assert.True (Application.RaiseKeyDownEvent (Key.N.WithCtrl));
  1350. Assert.False (Application.RaiseKeyDownEvent (Key.R.WithCtrl));
  1351. Application.MainLoop!.RunIteration ();
  1352. Assert.True (newFile);
  1353. Assert.False (renameFile);
  1354. newFile = false;
  1355. cm.Show (menuItems);
  1356. Assert.True (menuBar.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
  1357. Assert.False (menuBar.HotKeyBindings.TryGet (Key.R.WithCtrl, out _));
  1358. Assert.False (cm.MenuBar!.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
  1359. Assert.True (cm.MenuBar.HotKeyBindings.TryGet (Key.R.WithCtrl, out _));
  1360. Assert.True (cm.MenuBar.IsMenuOpen);
  1361. Assert.True (Application.RaiseKeyDownEvent (Key.N.WithCtrl));
  1362. Application.MainLoop!.RunIteration ();
  1363. Assert.True (newFile);
  1364. Assert.False (cm.MenuBar!.IsMenuOpen);
  1365. cm.Show (menuItems);
  1366. Assert.True (Application.RaiseKeyDownEvent (Key.R.WithCtrl));
  1367. Application.MainLoop!.RunIteration ();
  1368. Assert.True (renameFile);
  1369. Assert.False (cm.MenuBar.IsMenuOpen);
  1370. Assert.True (menuBar.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
  1371. Assert.False (menuBar.HotKeyBindings.TryGet (Key.R.WithCtrl, out _));
  1372. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
  1373. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.WithCtrl, out _));
  1374. newFile = false;
  1375. renameFile = false;
  1376. Assert.True (Application.RaiseKeyDownEvent (Key.N.WithCtrl));
  1377. Assert.False (Application.RaiseKeyDownEvent (Key.R.WithCtrl));
  1378. Application.MainLoop!.RunIteration ();
  1379. Assert.True (newFile);
  1380. Assert.False (renameFile);
  1381. top.Dispose ();
  1382. void New () { newFile = true; }
  1383. void Rename () { renameFile = true; }
  1384. }
  1385. [Fact]
  1386. [AutoInitShutdown]
  1387. public void KeyBindings_With_Same_Shortcut_ContextMenu_And_MenuBar ()
  1388. {
  1389. var newMenuBar = false;
  1390. var newContextMenu = false;
  1391. var menuBar = new MenuBar
  1392. {
  1393. Menus =
  1394. [
  1395. new (
  1396. "File",
  1397. new MenuItem []
  1398. {
  1399. new ("New", string.Empty, NewMenuBar, null, null, Key.N.WithCtrl)
  1400. })
  1401. ]
  1402. };
  1403. var cm = new ContextMenu ();
  1404. var menuItems = new MenuBarItem (
  1405. [
  1406. new ("New File", string.Empty, NewContextMenu, null, null, Key.N.WithCtrl),
  1407. ]
  1408. );
  1409. var top = new Toplevel ();
  1410. top.Add (menuBar);
  1411. Application.Begin (top);
  1412. Assert.True (menuBar.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
  1413. Assert.Null (cm.MenuBar);
  1414. Assert.True (Application.RaiseKeyDownEvent (Key.N.WithCtrl));
  1415. Application.MainLoop!.RunIteration ();
  1416. Assert.True (newMenuBar);
  1417. Assert.False (newContextMenu);
  1418. newMenuBar = false;
  1419. cm.Show (menuItems);
  1420. Assert.True (menuBar.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
  1421. Assert.True (cm.MenuBar!.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
  1422. Assert.True (cm.MenuBar.IsMenuOpen);
  1423. Assert.True (Application.RaiseKeyDownEvent (Key.N.WithCtrl));
  1424. Application.MainLoop!.RunIteration ();
  1425. Assert.False (newMenuBar);
  1426. // The most focused shortcut is executed
  1427. Assert.True (newContextMenu);
  1428. Assert.False (cm.MenuBar!.IsMenuOpen);
  1429. Assert.True (menuBar.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
  1430. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.N.WithCtrl, out _));
  1431. newMenuBar = false;
  1432. newContextMenu = false;
  1433. Assert.True (Application.RaiseKeyDownEvent (Key.N.WithCtrl));
  1434. Application.MainLoop!.RunIteration ();
  1435. Assert.True (newMenuBar);
  1436. Assert.False (newContextMenu);
  1437. top.Dispose ();
  1438. void NewMenuBar () { newMenuBar = true; }
  1439. void NewContextMenu () { newContextMenu = true; }
  1440. }
  1441. [Fact]
  1442. [AutoInitShutdown]
  1443. public void HotKeys_Removed_On_Close_ContextMenu ()
  1444. {
  1445. var newFile = false;
  1446. var renameFile = false;
  1447. var deleteFile = false;
  1448. var cm = new ContextMenu ();
  1449. var menuItems = new MenuBarItem (
  1450. [
  1451. new ("_New File", string.Empty, New, null, null),
  1452. new ("_Rename File", string.Empty, Rename, null, null),
  1453. new ("_Delete File", string.Empty, Delete, null, null)
  1454. ]
  1455. );
  1456. var top = new Toplevel ();
  1457. Application.Begin (top);
  1458. Assert.Null (cm.MenuBar);
  1459. Assert.False (Application.RaiseKeyDownEvent (Key.N.WithAlt));
  1460. Assert.False (Application.RaiseKeyDownEvent (Key.R.WithAlt));
  1461. Assert.False (Application.RaiseKeyDownEvent (Key.D.WithAlt));
  1462. Assert.False (newFile);
  1463. Assert.False (renameFile);
  1464. Assert.False (deleteFile);
  1465. cm.Show (menuItems);
  1466. Assert.True (cm.MenuBar!.IsMenuOpen);
  1467. Assert.False (cm.MenuBar!.HotKeyBindings.TryGet (Key.N.WithAlt, out _));
  1468. Assert.False (cm.MenuBar!.HotKeyBindings.TryGet (Key.N.NoShift, out _));
  1469. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.WithAlt, out _));
  1470. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.NoShift, out _));
  1471. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.D.WithAlt, out _));
  1472. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.D.NoShift, out _));
  1473. Assert.Equal (2, Application.Top!.SubViews.Count);
  1474. View [] menus = Application.Top!.SubViews.Where (v => v is Menu m && m.Host == cm.MenuBar).ToArray ();
  1475. Assert.True (menus [0].HotKeyBindings.TryGet (Key.N.WithAlt, out _));
  1476. Assert.True (menus [0].HotKeyBindings.TryGet (Key.N.NoShift, out _));
  1477. Assert.True (menus [0].HotKeyBindings.TryGet (Key.R.WithAlt, out _));
  1478. Assert.True (menus [0].HotKeyBindings.TryGet (Key.R.NoShift, out _));
  1479. Assert.True (menus [0].HotKeyBindings.TryGet (Key.D.WithAlt, out _));
  1480. Assert.True (menus [0].HotKeyBindings.TryGet (Key.D.NoShift, out _));
  1481. Assert.True (Application.RaiseKeyDownEvent (Key.N.WithAlt));
  1482. Assert.False (cm.MenuBar!.IsMenuOpen);
  1483. Application.MainLoop!.RunIteration ();
  1484. Assert.True (newFile);
  1485. cm.Show (menuItems);
  1486. Assert.True (Application.RaiseKeyDownEvent (Key.R.WithAlt));
  1487. Assert.False (cm.MenuBar.IsMenuOpen);
  1488. Application.MainLoop!.RunIteration ();
  1489. Assert.True (renameFile);
  1490. cm.Show (menuItems);
  1491. Assert.True (Application.RaiseKeyDownEvent (Key.D.WithAlt));
  1492. Assert.False (cm.MenuBar.IsMenuOpen);
  1493. Application.MainLoop!.RunIteration ();
  1494. Assert.True (deleteFile);
  1495. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.N.WithAlt, out _));
  1496. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.N.NoShift, out _));
  1497. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.WithAlt, out _));
  1498. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.NoShift, out _));
  1499. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.D.WithAlt, out _));
  1500. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.D.NoShift, out _));
  1501. newFile = false;
  1502. renameFile = false;
  1503. deleteFile = false;
  1504. Assert.False (Application.RaiseKeyDownEvent (Key.N.WithAlt));
  1505. Assert.False (Application.RaiseKeyDownEvent (Key.R.WithAlt));
  1506. Assert.False (Application.RaiseKeyDownEvent (Key.D.WithAlt));
  1507. Assert.False (newFile);
  1508. Assert.False (renameFile);
  1509. Assert.False (deleteFile);
  1510. top.Dispose ();
  1511. void New () { newFile = true; }
  1512. void Rename () { renameFile = true; }
  1513. void Delete () { deleteFile = true; }
  1514. }
  1515. [Fact]
  1516. [AutoInitShutdown]
  1517. public void HotKeys_With_ContextMenu_And_MenuBar ()
  1518. {
  1519. var newFile = false;
  1520. var renameFile = false;
  1521. var menuBar = new MenuBar
  1522. {
  1523. Menus =
  1524. [
  1525. new (
  1526. "_File",
  1527. new MenuItem []
  1528. {
  1529. new ("_New", string.Empty, New)
  1530. })
  1531. ]
  1532. };
  1533. var cm = new ContextMenu ();
  1534. var menuItems = new MenuBarItem (
  1535. [
  1536. new MenuBarItem (
  1537. "_Edit",
  1538. new MenuItem []
  1539. {
  1540. new ("_Rename File", string.Empty, Rename)
  1541. }
  1542. )
  1543. ]
  1544. );
  1545. var top = new Toplevel ();
  1546. top.Add (menuBar);
  1547. Application.Begin (top);
  1548. Assert.True (menuBar.HotKeyBindings.TryGet (Key.F.WithAlt, out _));
  1549. Assert.False (menuBar.HotKeyBindings.TryGet (Key.N.WithAlt, out _));
  1550. Assert.False (menuBar.HotKeyBindings.TryGet (Key.R.WithAlt, out _));
  1551. View [] menus = Application.Top!.SubViews.Where (v => v is Menu m && m.Host == menuBar).ToArray ();
  1552. Assert.Empty (menus);
  1553. Assert.Null (cm.MenuBar);
  1554. Assert.True (Application.RaiseKeyDownEvent (Key.F.WithAlt));
  1555. Assert.True (menuBar.IsMenuOpen);
  1556. Assert.Equal (2, Application.Top!.SubViews.Count);
  1557. menus = Application.Top!.SubViews.Where (v => v is Menu m && m.Host == menuBar).ToArray ();
  1558. Assert.True (menus [0].HotKeyBindings.TryGet (Key.N.WithAlt, out _));
  1559. Assert.True (Application.RaiseKeyDownEvent (Key.N.WithAlt));
  1560. Assert.False (menuBar.IsMenuOpen);
  1561. Assert.False (Application.RaiseKeyDownEvent (Key.R.WithAlt));
  1562. Application.MainLoop!.RunIteration ();
  1563. Assert.True (newFile);
  1564. Assert.False (renameFile);
  1565. newFile = false;
  1566. cm.Show (menuItems);
  1567. Assert.True (menuBar.HotKeyBindings.TryGet (Key.F.WithAlt, out _));
  1568. Assert.True (menuBar.HotKeyBindings.TryGet (Key.F.NoShift, out _));
  1569. Assert.False (menuBar.HotKeyBindings.TryGet (Key.N.WithAlt, out _));
  1570. Assert.False (menuBar.HotKeyBindings.TryGet (Key.N.NoShift, out _));
  1571. Assert.False (menuBar.HotKeyBindings.TryGet (Key.E.WithAlt, out _));
  1572. Assert.False (menuBar.HotKeyBindings.TryGet (Key.E.NoShift, out _));
  1573. Assert.False (menuBar.HotKeyBindings.TryGet (Key.R.WithAlt, out _));
  1574. Assert.False (menuBar.HotKeyBindings.TryGet (Key.R.NoShift, out _));
  1575. Assert.True (cm.MenuBar!.IsMenuOpen);
  1576. Assert.False (cm.MenuBar!.HotKeyBindings.TryGet (Key.F.WithAlt, out _));
  1577. Assert.False (cm.MenuBar!.HotKeyBindings.TryGet (Key.F.NoShift, out _));
  1578. Assert.False (cm.MenuBar!.HotKeyBindings.TryGet (Key.N.WithAlt, out _));
  1579. Assert.False (cm.MenuBar!.HotKeyBindings.TryGet (Key.N.NoShift, out _));
  1580. Assert.False (cm.MenuBar!.HotKeyBindings.TryGet (Key.E.WithAlt, out _));
  1581. Assert.False (cm.MenuBar!.HotKeyBindings.TryGet (Key.E.NoShift, out _));
  1582. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.WithAlt, out _));
  1583. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.NoShift, out _));
  1584. Assert.Equal (4, Application.Top!.SubViews.Count);
  1585. menus = Application.Top!.SubViews.Where (v => v is Menu m && m.Host == cm.MenuBar).ToArray ();
  1586. Assert.True (menus [0].HotKeyBindings.TryGet (Key.E.WithAlt, out _));
  1587. Assert.True (menus [0].HotKeyBindings.TryGet (Key.E.NoShift, out _));
  1588. Assert.True (menus [1].HotKeyBindings.TryGet (Key.R.WithAlt, out _));
  1589. Assert.True (menus [1].HotKeyBindings.TryGet (Key.R.NoShift, out _));
  1590. Assert.True (cm.MenuBar.IsMenuOpen);
  1591. Assert.True (Application.RaiseKeyDownEvent (Key.F.WithAlt));
  1592. Assert.False (cm.MenuBar.IsMenuOpen);
  1593. Assert.True (Application.RaiseKeyDownEvent (Key.N.WithAlt));
  1594. Application.MainLoop!.RunIteration ();
  1595. Assert.True (newFile);
  1596. cm.Show (menuItems);
  1597. Assert.True (cm.MenuBar.IsMenuOpen);
  1598. Assert.Equal (4, Application.Top!.SubViews.Count);
  1599. menus = Application.Top!.SubViews.Where (v => v is Menu m && m.Host == cm.MenuBar).ToArray ();
  1600. Assert.True (menus [0].HotKeyBindings.TryGet (Key.E.WithAlt, out _));
  1601. Assert.True (menus [0].HotKeyBindings.TryGet (Key.E.NoShift, out _));
  1602. Assert.False (menus [0].HotKeyBindings.TryGet (Key.R.WithAlt, out _));
  1603. Assert.False (menus [0].HotKeyBindings.TryGet (Key.R.NoShift, out _));
  1604. Assert.False (menus [1].HotKeyBindings.TryGet (Key.E.WithAlt, out _));
  1605. Assert.False (menus [1].HotKeyBindings.TryGet (Key.E.NoShift, out _));
  1606. Assert.True (menus [1].HotKeyBindings.TryGet (Key.R.WithAlt, out _));
  1607. Assert.True (menus [1].HotKeyBindings.TryGet (Key.R.NoShift, out _));
  1608. Assert.True (Application.RaiseKeyDownEvent (Key.E.NoShift));
  1609. Assert.True (Application.RaiseKeyDownEvent (Key.R.WithAlt));
  1610. Assert.False (cm.MenuBar.IsMenuOpen);
  1611. Application.MainLoop!.RunIteration ();
  1612. Assert.True (renameFile);
  1613. Assert.Equal (2, Application.Top!.SubViews.Count);
  1614. Assert.True (menuBar.HotKeyBindings.TryGet (Key.F.WithAlt, out _));
  1615. Assert.True (menuBar.HotKeyBindings.TryGet (Key.F.NoShift, out _));
  1616. Assert.False (menuBar.HotKeyBindings.TryGet (Key.N.WithAlt, out _));
  1617. Assert.False (menuBar.HotKeyBindings.TryGet (Key.N.NoShift, out _));
  1618. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.E.WithAlt, out _));
  1619. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.E.NoShift, out _));
  1620. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.WithAlt, out _));
  1621. Assert.False (cm.MenuBar.HotKeyBindings.TryGet (Key.R.NoShift, out _));
  1622. newFile = false;
  1623. renameFile = false;
  1624. Assert.True (Application.RaiseKeyDownEvent (Key.F.WithAlt));
  1625. Assert.True (Application.RaiseKeyDownEvent (Key.N.WithAlt));
  1626. Assert.False (Application.RaiseKeyDownEvent (Key.R.WithAlt));
  1627. Application.MainLoop!.RunIteration ();
  1628. Assert.True (newFile);
  1629. Assert.False (renameFile);
  1630. top.Dispose ();
  1631. void New () { newFile = true; }
  1632. void Rename () { renameFile = true; }
  1633. }
  1634. [Fact]
  1635. [AutoInitShutdown]
  1636. public void Opened_MenuBar_Is_Closed_When_Another_MenuBar_Is_Opening_Also_By_HotKey ()
  1637. {
  1638. var menuBar = new MenuBar
  1639. {
  1640. Menus =
  1641. [
  1642. new (
  1643. "_File",
  1644. new MenuItem []
  1645. {
  1646. new ("_New", string.Empty, null)
  1647. })
  1648. ]
  1649. };
  1650. var cm = new ContextMenu ();
  1651. var menuItems = new MenuBarItem (
  1652. [
  1653. new MenuBarItem (
  1654. "_Edit",
  1655. new MenuItem []
  1656. {
  1657. new ("_Rename File", string.Empty, null)
  1658. }
  1659. )
  1660. ]
  1661. );
  1662. var top = new Toplevel ();
  1663. top.Add (menuBar);
  1664. Application.Begin (top);
  1665. Assert.True (Application.RaiseKeyDownEvent (Key.F.WithAlt));
  1666. Assert.True (menuBar.IsMenuOpen);
  1667. cm.Show (menuItems);
  1668. Assert.False (menuBar.IsMenuOpen);
  1669. Assert.True (cm.MenuBar!.IsMenuOpen);
  1670. Assert.True (Application.RaiseKeyDownEvent (Key.F.WithAlt));
  1671. Assert.True (menuBar.IsMenuOpen);
  1672. Assert.False (cm.MenuBar!.IsMenuOpen);
  1673. top.Dispose ();
  1674. }
  1675. [Theory]
  1676. [InlineData (1)]
  1677. [InlineData (2)]
  1678. [InlineData (3)]
  1679. [AutoInitShutdown]
  1680. public void Mouse_Pressed_Released_Clicked (int button)
  1681. {
  1682. var actionRaised = false;
  1683. var menuBar = new MenuBar
  1684. {
  1685. Menus =
  1686. [
  1687. new (
  1688. "_File",
  1689. new MenuItem []
  1690. {
  1691. new ("_New", string.Empty, () => actionRaised = true)
  1692. })
  1693. ]
  1694. };
  1695. var cm = new ContextMenu ();
  1696. var menuItems = new MenuBarItem (
  1697. [
  1698. new ("_Rename File", string.Empty, () => actionRaised = true)
  1699. ]
  1700. );
  1701. var top = new Toplevel ();
  1702. top.MouseClick += (s, e) =>
  1703. {
  1704. if (e.Flags == cm.MouseFlags)
  1705. {
  1706. cm.Position = new (e.Position.X, e.Position.Y);
  1707. cm.Show (menuItems);
  1708. e.Handled = true;
  1709. }
  1710. };
  1711. top.Add (menuBar);
  1712. Application.Begin (top);
  1713. // MenuBar
  1714. Application.RaiseMouseEvent (new () { Flags = MouseFlags.Button1Pressed });
  1715. Assert.True (menuBar.IsMenuOpen);
  1716. switch (button)
  1717. {
  1718. // Left Button
  1719. case 1:
  1720. Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 2), Flags = MouseFlags.Button1Pressed });
  1721. Assert.True (menuBar.IsMenuOpen);
  1722. Application.MainLoop.RunIteration ();
  1723. Assert.False (actionRaised);
  1724. Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 2), Flags = MouseFlags.Button1Released });
  1725. Assert.True (menuBar.IsMenuOpen);
  1726. Application.MainLoop.RunIteration ();
  1727. Assert.False (actionRaised);
  1728. Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 2), Flags = MouseFlags.Button1Clicked });
  1729. Assert.False (menuBar.IsMenuOpen);
  1730. Application.MainLoop.RunIteration ();
  1731. Assert.True (actionRaised);
  1732. actionRaised = false;
  1733. break;
  1734. // Middle Button
  1735. case 2:
  1736. // Right Button
  1737. case 3:
  1738. Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 2), Flags = MouseFlags.Button3Pressed });
  1739. Assert.True (menuBar.IsMenuOpen);
  1740. Application.MainLoop.RunIteration ();
  1741. Assert.False (actionRaised);
  1742. Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 2), Flags = MouseFlags.Button3Released });
  1743. Assert.True (menuBar.IsMenuOpen);
  1744. Application.MainLoop.RunIteration ();
  1745. Assert.False (actionRaised);
  1746. Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 2), Flags = MouseFlags.Button3Clicked });
  1747. Assert.True (menuBar.IsMenuOpen);
  1748. Application.MainLoop.RunIteration ();
  1749. Assert.False (actionRaised);
  1750. break;
  1751. }
  1752. // ContextMenu
  1753. Application.RaiseMouseEvent (new () { ScreenPosition = new (0, 4), Flags = cm.MouseFlags });
  1754. Assert.False (menuBar.IsMenuOpen);
  1755. Assert.True (cm.MenuBar!.IsMenuOpen);
  1756. switch (button)
  1757. {
  1758. // Left Button
  1759. case 1:
  1760. Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 6), Flags = MouseFlags.Button1Pressed });
  1761. Assert.True (cm.MenuBar!.IsMenuOpen);
  1762. Application.MainLoop.RunIteration ();
  1763. Assert.False (actionRaised);
  1764. Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 6), Flags = MouseFlags.Button1Released });
  1765. Assert.True (cm.MenuBar!.IsMenuOpen);
  1766. Application.MainLoop.RunIteration ();
  1767. Assert.False (actionRaised);
  1768. Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 6), Flags = MouseFlags.Button1Clicked });
  1769. Assert.False (cm.MenuBar!.IsMenuOpen);
  1770. Application.MainLoop.RunIteration ();
  1771. Assert.True (actionRaised);
  1772. actionRaised = false;
  1773. break;
  1774. // Middle Button
  1775. case 2:
  1776. Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 4), Flags = MouseFlags.Button2Pressed });
  1777. Assert.False (cm.MenuBar!.IsMenuOpen);
  1778. Application.MainLoop.RunIteration ();
  1779. Assert.False (actionRaised);
  1780. Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 4), Flags = MouseFlags.Button2Released });
  1781. Assert.False (cm.MenuBar!.IsMenuOpen);
  1782. Application.MainLoop.RunIteration ();
  1783. Assert.False (actionRaised);
  1784. Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 4), Flags = MouseFlags.Button2Clicked });
  1785. Assert.False (cm.MenuBar!.IsMenuOpen);
  1786. Application.MainLoop.RunIteration ();
  1787. Assert.False (actionRaised);
  1788. break;
  1789. // Right Button
  1790. case 3:
  1791. Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 4), Flags = MouseFlags.Button3Pressed });
  1792. Assert.False (cm.MenuBar!.IsMenuOpen);
  1793. Application.MainLoop.RunIteration ();
  1794. Assert.False (actionRaised);
  1795. Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 4), Flags = MouseFlags.Button3Released });
  1796. Assert.False (cm.MenuBar!.IsMenuOpen);
  1797. Application.MainLoop.RunIteration ();
  1798. Assert.False (actionRaised);
  1799. Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 4), Flags = MouseFlags.Button3Clicked });
  1800. // MouseFlags is the same as cm.MouseFlags. So the context menu is closed and reopened again
  1801. Assert.True (cm.MenuBar!.IsMenuOpen);
  1802. Application.MainLoop.RunIteration ();
  1803. Assert.False (actionRaised);
  1804. break;
  1805. }
  1806. top.Dispose ();
  1807. }
  1808. [Fact]
  1809. [AutoInitShutdown]
  1810. public void Menu_Without_SubMenu_Is_Closed_When_Pressing_Key_Right_Or_Key_Left ()
  1811. {
  1812. var cm = new ContextMenu ();
  1813. var menuItems = new MenuBarItem (
  1814. [
  1815. new ("_New", string.Empty, null),
  1816. new ("_Save", string.Empty, null)
  1817. ]
  1818. );
  1819. var top = new Toplevel ();
  1820. Application.Begin (top);
  1821. cm.Show (menuItems);
  1822. Assert.True (cm.MenuBar!.IsMenuOpen);
  1823. Assert.True (Application.RaiseKeyDownEvent (Key.CursorRight));
  1824. Assert.False (cm.MenuBar!.IsMenuOpen);
  1825. cm.Show (menuItems);
  1826. Assert.True (cm.MenuBar!.IsMenuOpen);
  1827. Assert.True (Application.RaiseKeyDownEvent (Key.CursorLeft));
  1828. Assert.False (cm.MenuBar!.IsMenuOpen);
  1829. top.Dispose ();
  1830. }
  1831. }