ApplicationTests.cs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290
  1. using System;
  2. using System.Linq;
  3. using System.Threading;
  4. using System.Threading.Tasks;
  5. using Xunit;
  6. // Alias Console to MockConsole so we don't accidentally use Console
  7. using Console = Terminal.Gui.FakeConsole;
  8. namespace Terminal.Gui.Core {
  9. public class ApplicationTests {
  10. public ApplicationTests ()
  11. {
  12. #if DEBUG_IDISPOSABLE
  13. Responder.Instances.Clear ();
  14. #endif
  15. }
  16. [Fact]
  17. public void Init_Shutdown_Cleans_Up ()
  18. {
  19. // Verify initial state is per spec
  20. Pre_Init_State ();
  21. Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
  22. // Verify post-Init state is correct
  23. Post_Init_State ();
  24. // MockDriver is always 80x25
  25. Assert.Equal (80, Application.Driver.Cols);
  26. Assert.Equal (25, Application.Driver.Rows);
  27. Application.Shutdown ();
  28. // Verify state is back to initial
  29. Pre_Init_State ();
  30. }
  31. void Pre_Init_State ()
  32. {
  33. Assert.Null (Application.Driver);
  34. Assert.Null (Application.Top);
  35. Assert.Null (Application.Current);
  36. Assert.Throws<ArgumentNullException> (() => Application.HeightAsBuffer == true);
  37. Assert.False (Application.AlwaysSetPosition);
  38. Assert.Null (Application.MainLoop);
  39. Assert.Null (Application.Iteration);
  40. Assert.Null (Application.RootMouseEvent);
  41. Assert.Null (Application.Resized);
  42. }
  43. void Post_Init_State ()
  44. {
  45. Assert.NotNull (Application.Driver);
  46. Assert.NotNull (Application.Top);
  47. Assert.NotNull (Application.Current);
  48. Assert.False (Application.HeightAsBuffer);
  49. Assert.False (Application.AlwaysSetPosition);
  50. Assert.NotNull (Application.MainLoop);
  51. Assert.Null (Application.Iteration);
  52. Assert.Null (Application.RootMouseEvent);
  53. Assert.Null (Application.Resized);
  54. }
  55. [Fact]
  56. public void RunState_Dispose_Cleans_Up ()
  57. {
  58. var rs = new Application.RunState (null);
  59. Assert.NotNull (rs);
  60. // Should not throw because Toplevel was null
  61. rs.Dispose ();
  62. var top = new Toplevel ();
  63. rs = new Application.RunState (top);
  64. Assert.NotNull (rs);
  65. // Should throw because there's no stack
  66. Assert.Throws<InvalidOperationException> (() => rs.Dispose ());
  67. }
  68. void Init ()
  69. {
  70. Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
  71. Assert.NotNull (Application.Driver);
  72. Assert.NotNull (Application.MainLoop);
  73. }
  74. void Shutdown ()
  75. {
  76. Application.Shutdown ();
  77. }
  78. [Fact]
  79. public void Begin_End_Cleana_Up ()
  80. {
  81. // Setup Mock driver
  82. Init ();
  83. // Test null Toplevel
  84. Assert.Throws<ArgumentNullException> (() => Application.Begin (null));
  85. var top = new Toplevel ();
  86. var rs = Application.Begin (top);
  87. Assert.NotNull (rs);
  88. Assert.Equal (top, Application.Current);
  89. Application.End (rs);
  90. Assert.Null (Application.Current);
  91. Assert.NotNull (Application.Top);
  92. Assert.NotNull (Application.MainLoop);
  93. Assert.NotNull (Application.Driver);
  94. Shutdown ();
  95. Assert.Null (Application.Top);
  96. Assert.Null (Application.MainLoop);
  97. Assert.Null (Application.Driver);
  98. }
  99. [Fact]
  100. public void RequestStop_Stops ()
  101. {
  102. // Setup Mock driver
  103. Init ();
  104. var top = new Toplevel ();
  105. var rs = Application.Begin (top);
  106. Assert.NotNull (rs);
  107. Assert.Equal (top, Application.Current);
  108. Application.Iteration = () => {
  109. Application.RequestStop ();
  110. };
  111. Application.Run (top);
  112. Application.Shutdown ();
  113. Assert.Null (Application.Current);
  114. Assert.Null (Application.Top);
  115. Assert.Null (Application.MainLoop);
  116. Assert.Null (Application.Driver);
  117. }
  118. [Fact]
  119. public void RunningFalse_Stops ()
  120. {
  121. // Setup Mock driver
  122. Init ();
  123. var top = new Toplevel ();
  124. var rs = Application.Begin (top);
  125. Assert.NotNull (rs);
  126. Assert.Equal (top, Application.Current);
  127. Application.Iteration = () => {
  128. top.Running = false;
  129. };
  130. Application.Run (top);
  131. Application.Shutdown ();
  132. Assert.Null (Application.Current);
  133. Assert.Null (Application.Top);
  134. Assert.Null (Application.MainLoop);
  135. Assert.Null (Application.Driver);
  136. }
  137. [Fact]
  138. public void KeyUp_Event ()
  139. {
  140. // Setup Mock driver
  141. Init ();
  142. // Setup some fake keypresses (This)
  143. var input = "Tests";
  144. // Put a control-q in at the end
  145. Console.MockKeyPresses.Push (new ConsoleKeyInfo ('q', ConsoleKey.Q, shift: false, alt: false, control: true));
  146. foreach (var c in input.Reverse ()) {
  147. if (char.IsLetter (c)) {
  148. Console.MockKeyPresses.Push (new ConsoleKeyInfo (c, (ConsoleKey)char.ToUpper (c), shift: char.IsUpper (c), alt: false, control: false));
  149. } else {
  150. Console.MockKeyPresses.Push (new ConsoleKeyInfo (c, (ConsoleKey)c, shift: false, alt: false, control: false));
  151. }
  152. }
  153. int stackSize = Console.MockKeyPresses.Count;
  154. int iterations = 0;
  155. Application.Iteration = () => {
  156. iterations++;
  157. // Stop if we run out of control...
  158. if (iterations > 10) {
  159. Application.RequestStop ();
  160. }
  161. };
  162. int keyUps = 0;
  163. var output = string.Empty;
  164. Application.Top.KeyUp += (View.KeyEventEventArgs args) => {
  165. if (args.KeyEvent.Key != (Key.CtrlMask | Key.Q)) {
  166. output += (char)args.KeyEvent.KeyValue;
  167. }
  168. keyUps++;
  169. };
  170. Application.Run (Application.Top);
  171. // Input string should match output
  172. Assert.Equal (input, output);
  173. // # of key up events should match stack size
  174. //Assert.Equal (stackSize, keyUps);
  175. // We can't use numbers variables on the left side of an Assert.Equal/NotEqual,
  176. // it must be literal (Linux only).
  177. Assert.Equal (6, keyUps);
  178. // # of key up events should match # of iterations
  179. Assert.Equal (stackSize, iterations);
  180. Application.Shutdown ();
  181. Assert.Null (Application.Current);
  182. Assert.Null (Application.Top);
  183. Assert.Null (Application.MainLoop);
  184. Assert.Null (Application.Driver);
  185. }
  186. [Fact]
  187. public void Loaded_Ready_Unlodaded_Events ()
  188. {
  189. Init ();
  190. var top = Application.Top;
  191. var count = 0;
  192. top.Loaded += () => count++;
  193. top.Ready += () => count++;
  194. top.Unloaded += () => count++;
  195. Application.Iteration = () => Application.RequestStop ();
  196. Application.Run ();
  197. Application.Shutdown ();
  198. Assert.Equal (3, count);
  199. }
  200. [Fact]
  201. public void Shutdown_Allows_Async ()
  202. {
  203. static async Task TaskWithAsyncContinuation ()
  204. {
  205. await Task.Yield ();
  206. await Task.Yield ();
  207. }
  208. Init ();
  209. Application.Shutdown ();
  210. var task = TaskWithAsyncContinuation ();
  211. Thread.Sleep (20);
  212. Assert.True (task.IsCompletedSuccessfully);
  213. }
  214. [Fact]
  215. public void Shutdown_Resets_SyncContext ()
  216. {
  217. Init ();
  218. Application.Shutdown ();
  219. Assert.Null (SynchronizationContext.Current);
  220. }
  221. [Fact]
  222. public void AlternateForwardKey_AlternateBackwardKey_Tests ()
  223. {
  224. Init ();
  225. var top = Application.Top;
  226. var w1 = new Window ();
  227. var v1 = new TextField ();
  228. var v2 = new TextView ();
  229. w1.Add (v1, v2);
  230. var w2 = new Window ();
  231. var v3 = new CheckBox ();
  232. var v4 = new Button ();
  233. w2.Add (v3, v4);
  234. top.Add (w1, w2);
  235. Application.Iteration += () => {
  236. Assert.True (v1.HasFocus);
  237. // Using default keys.
  238. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab,
  239. new KeyModifiers () { Ctrl = true }));
  240. Assert.True (v2.HasFocus);
  241. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab,
  242. new KeyModifiers () { Ctrl = true }));
  243. Assert.True (v3.HasFocus);
  244. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab,
  245. new KeyModifiers () { Ctrl = true }));
  246. Assert.True (v4.HasFocus);
  247. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab,
  248. new KeyModifiers () { Ctrl = true }));
  249. Assert.True (v1.HasFocus);
  250. top.ProcessKey (new KeyEvent (Key.ShiftMask | Key.CtrlMask | Key.Tab,
  251. new KeyModifiers () { Shift = true, Ctrl = true }));
  252. Assert.True (v4.HasFocus);
  253. top.ProcessKey (new KeyEvent (Key.ShiftMask | Key.CtrlMask | Key.Tab,
  254. new KeyModifiers () { Shift = true, Ctrl = true }));
  255. Assert.True (v3.HasFocus);
  256. top.ProcessKey (new KeyEvent (Key.ShiftMask | Key.CtrlMask | Key.Tab,
  257. new KeyModifiers () { Shift = true, Ctrl = true }));
  258. Assert.True (v2.HasFocus);
  259. top.ProcessKey (new KeyEvent (Key.ShiftMask | Key.CtrlMask | Key.Tab,
  260. new KeyModifiers () { Shift = true, Ctrl = true }));
  261. Assert.True (v1.HasFocus);
  262. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageDown,
  263. new KeyModifiers () { Ctrl = true }));
  264. Assert.True (v2.HasFocus);
  265. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageDown,
  266. new KeyModifiers () { Ctrl = true }));
  267. Assert.True (v3.HasFocus);
  268. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageDown,
  269. new KeyModifiers () { Ctrl = true }));
  270. Assert.True (v4.HasFocus);
  271. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageDown,
  272. new KeyModifiers () { Ctrl = true }));
  273. Assert.True (v1.HasFocus);
  274. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageUp,
  275. new KeyModifiers () { Ctrl = true }));
  276. Assert.True (v4.HasFocus);
  277. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageUp,
  278. new KeyModifiers () { Ctrl = true }));
  279. Assert.True (v3.HasFocus);
  280. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageUp,
  281. new KeyModifiers () { Ctrl = true }));
  282. Assert.True (v2.HasFocus);
  283. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageUp,
  284. new KeyModifiers () { Ctrl = true }));
  285. Assert.True (v1.HasFocus);
  286. // Using another's alternate keys.
  287. Application.AlternateForwardKey = Key.F7;
  288. Application.AlternateBackwardKey = Key.F6;
  289. top.ProcessKey (new KeyEvent (Key.F7, new KeyModifiers ()));
  290. Assert.True (v2.HasFocus);
  291. top.ProcessKey (new KeyEvent (Key.F7, new KeyModifiers ()));
  292. Assert.True (v3.HasFocus);
  293. top.ProcessKey (new KeyEvent (Key.F7, new KeyModifiers ()));
  294. Assert.True (v4.HasFocus);
  295. top.ProcessKey (new KeyEvent (Key.F7, new KeyModifiers ()));
  296. Assert.True (v1.HasFocus);
  297. top.ProcessKey (new KeyEvent (Key.F6, new KeyModifiers ()));
  298. Assert.True (v4.HasFocus);
  299. top.ProcessKey (new KeyEvent (Key.F6, new KeyModifiers ()));
  300. Assert.True (v3.HasFocus);
  301. top.ProcessKey (new KeyEvent (Key.F6, new KeyModifiers ()));
  302. Assert.True (v2.HasFocus);
  303. top.ProcessKey (new KeyEvent (Key.F6, new KeyModifiers ()));
  304. Assert.True (v1.HasFocus);
  305. Application.RequestStop ();
  306. };
  307. Application.Run (top);
  308. // Replacing the defaults keys to avoid errors on others unit tests that are using it.
  309. Application.AlternateForwardKey = Key.PageDown | Key.CtrlMask;
  310. Application.AlternateBackwardKey = Key.PageUp | Key.CtrlMask;
  311. Application.QuitKey = Key.Q | Key.CtrlMask;
  312. Assert.Equal (Key.PageDown | Key.CtrlMask, Application.AlternateForwardKey);
  313. Assert.Equal (Key.PageUp | Key.CtrlMask, Application.AlternateBackwardKey);
  314. Assert.Equal (Key.Q | Key.CtrlMask, Application.QuitKey);
  315. // Shutdown must be called to safely clean up Application if Init has been called
  316. Application.Shutdown ();
  317. }
  318. [Fact]
  319. public void Application_RequestStop_With_Params_On_A_Not_MdiContainer_Always_Use_The_Application_Current ()
  320. {
  321. Init ();
  322. var top1 = new Toplevel ();
  323. var top2 = new Toplevel ();
  324. var top3 = new Window ();
  325. var top4 = new Window ();
  326. var d = new Dialog ();
  327. // top1, top2, top3, d1 = 4
  328. var iterations = 4;
  329. top1.Ready += () => {
  330. Assert.Null (Application.MdiChildes);
  331. Application.Run (top2);
  332. };
  333. top2.Ready += () => {
  334. Assert.Null (Application.MdiChildes);
  335. Application.Run (top3);
  336. };
  337. top3.Ready += () => {
  338. Assert.Null (Application.MdiChildes);
  339. Application.Run (top4);
  340. };
  341. top4.Ready += () => {
  342. Assert.Null (Application.MdiChildes);
  343. Application.Run (d);
  344. };
  345. d.Ready += () => {
  346. Assert.Null (Application.MdiChildes);
  347. // This will close the d because on a not MdiContainer the Application.Current it always used.
  348. Application.RequestStop (top1);
  349. Assert.True (Application.Current == d);
  350. };
  351. d.Closed += (e) => Application.RequestStop (top1);
  352. Application.Iteration += () => {
  353. Assert.Null (Application.MdiChildes);
  354. if (iterations == 4) {
  355. Assert.True (Application.Current == d);
  356. } else if (iterations == 3) {
  357. Assert.True (Application.Current == top4);
  358. } else if (iterations == 2) {
  359. Assert.True (Application.Current == top3);
  360. } else if (iterations == 1) {
  361. Assert.True (Application.Current == top2);
  362. } else {
  363. Assert.True (Application.Current == top1);
  364. }
  365. Application.RequestStop (top1);
  366. iterations--;
  367. };
  368. Application.Run (top1);
  369. Assert.Null (Application.MdiChildes);
  370. Application.Shutdown ();
  371. }
  372. class Mdi : Toplevel {
  373. public Mdi ()
  374. {
  375. IsMdiContainer = true;
  376. }
  377. }
  378. [Fact]
  379. public void MdiContainer_With_Toplevel_RequestStop_Balanced ()
  380. {
  381. Init ();
  382. var mdi = new Mdi ();
  383. var c1 = new Toplevel ();
  384. var c2 = new Window ();
  385. var c3 = new Window ();
  386. var d = new Dialog ();
  387. // MdiChild = c1, c2, c3
  388. // d1 = 1
  389. var iterations = 4;
  390. mdi.Ready += () => {
  391. Assert.Empty (Application.MdiChildes);
  392. Application.Run (c1);
  393. };
  394. c1.Ready += () => {
  395. Assert.Single (Application.MdiChildes);
  396. Application.Run (c2);
  397. };
  398. c2.Ready += () => {
  399. Assert.Equal (2, Application.MdiChildes.Count);
  400. Application.Run (c3);
  401. };
  402. c3.Ready += () => {
  403. Assert.Equal (3, Application.MdiChildes.Count);
  404. Application.Run (d);
  405. };
  406. // More easy because the Mdi Container handles all at once
  407. d.Ready += () => {
  408. Assert.Equal (3, Application.MdiChildes.Count);
  409. // This will not close the MdiContainer because d is a modal toplevel and will be closed.
  410. mdi.RequestStop ();
  411. };
  412. // Now this will close the MdiContainer propagating through the MdiChildes.
  413. d.Closed += (e) => {
  414. mdi.RequestStop ();
  415. };
  416. Application.Iteration += () => {
  417. if (iterations == 4) {
  418. // The Dialog was not closed before and will be closed now.
  419. Assert.True (Application.Current == d);
  420. Assert.False (d.Running);
  421. } else {
  422. Assert.Equal (iterations, Application.MdiChildes.Count);
  423. for (int i = 0; i < iterations; i++) {
  424. Assert.Equal ((iterations - i + 1).ToString (), Application.MdiChildes [i].Id);
  425. }
  426. }
  427. iterations--;
  428. };
  429. Application.Run (mdi);
  430. Assert.Empty (Application.MdiChildes);
  431. Application.Shutdown ();
  432. }
  433. [Fact]
  434. public void MdiContainer_With_Application_RequestStop_MdiTop_With_Params ()
  435. {
  436. Init ();
  437. var mdi = new Mdi ();
  438. var c1 = new Toplevel ();
  439. var c2 = new Window ();
  440. var c3 = new Window ();
  441. var d = new Dialog ();
  442. // MdiChild = c1, c2, c3
  443. // d1 = 1
  444. var iterations = 4;
  445. mdi.Ready += () => {
  446. Assert.Empty (Application.MdiChildes);
  447. Application.Run (c1);
  448. };
  449. c1.Ready += () => {
  450. Assert.Single (Application.MdiChildes);
  451. Application.Run (c2);
  452. };
  453. c2.Ready += () => {
  454. Assert.Equal (2, Application.MdiChildes.Count);
  455. Application.Run (c3);
  456. };
  457. c3.Ready += () => {
  458. Assert.Equal (3, Application.MdiChildes.Count);
  459. Application.Run (d);
  460. };
  461. // Also easy because the Mdi Container handles all at once
  462. d.Ready += () => {
  463. Assert.Equal (3, Application.MdiChildes.Count);
  464. // This will not close the MdiContainer because d is a modal toplevel
  465. Application.RequestStop (mdi);
  466. };
  467. // Now this will close the MdiContainer propagating through the MdiChildes.
  468. d.Closed += (e) => Application.RequestStop (mdi);
  469. Application.Iteration += () => {
  470. if (iterations == 4) {
  471. // The Dialog was not closed before and will be closed now.
  472. Assert.True (Application.Current == d);
  473. Assert.False (d.Running);
  474. } else {
  475. Assert.Equal (iterations, Application.MdiChildes.Count);
  476. for (int i = 0; i < iterations; i++) {
  477. Assert.Equal ((iterations - i + 1).ToString (), Application.MdiChildes [i].Id);
  478. }
  479. }
  480. iterations--;
  481. };
  482. Application.Run (mdi);
  483. Assert.Empty (Application.MdiChildes);
  484. Application.Shutdown ();
  485. }
  486. [Fact]
  487. public void MdiContainer_With_Application_RequestStop_MdiTop_Without_Params ()
  488. {
  489. Init ();
  490. var mdi = new Mdi ();
  491. var c1 = new Toplevel ();
  492. var c2 = new Window ();
  493. var c3 = new Window ();
  494. var d = new Dialog ();
  495. // MdiChild = c1, c2, c3 = 3
  496. // d1 = 1
  497. var iterations = 4;
  498. mdi.Ready += () => {
  499. Assert.Empty (Application.MdiChildes);
  500. Application.Run (c1);
  501. };
  502. c1.Ready += () => {
  503. Assert.Single (Application.MdiChildes);
  504. Application.Run (c2);
  505. };
  506. c2.Ready += () => {
  507. Assert.Equal (2, Application.MdiChildes.Count);
  508. Application.Run (c3);
  509. };
  510. c3.Ready += () => {
  511. Assert.Equal (3, Application.MdiChildes.Count);
  512. Application.Run (d);
  513. };
  514. //More harder because it's sequential.
  515. d.Ready += () => {
  516. Assert.Equal (3, Application.MdiChildes.Count);
  517. // Close the Dialog
  518. Application.RequestStop ();
  519. };
  520. // Now this will close the MdiContainer propagating through the MdiChildes.
  521. d.Closed += (e) => Application.RequestStop (mdi);
  522. Application.Iteration += () => {
  523. if (iterations == 4) {
  524. // The Dialog still is the current top and we can't request stop to MdiContainer
  525. // because we are not using parameter calls.
  526. Assert.True (Application.Current == d);
  527. Assert.False (d.Running);
  528. } else {
  529. Assert.Equal (iterations, Application.MdiChildes.Count);
  530. for (int i = 0; i < iterations; i++) {
  531. Assert.Equal ((iterations - i + 1).ToString (), Application.MdiChildes [i].Id);
  532. }
  533. }
  534. iterations--;
  535. };
  536. Application.Run (mdi);
  537. Assert.Empty (Application.MdiChildes);
  538. Application.Shutdown ();
  539. }
  540. [Fact]
  541. public void IsMdiChild_Testing ()
  542. {
  543. Init ();
  544. var mdi = new Mdi ();
  545. var c1 = new Toplevel ();
  546. var c2 = new Window ();
  547. var c3 = new Window ();
  548. var d = new Dialog ();
  549. Application.Iteration += () => {
  550. Assert.False (mdi.IsMdiChild);
  551. Assert.True (c1.IsMdiChild);
  552. Assert.True (c2.IsMdiChild);
  553. Assert.True (c3.IsMdiChild);
  554. Assert.False (d.IsMdiChild);
  555. mdi.RequestStop ();
  556. };
  557. Application.Run (mdi);
  558. Application.Shutdown ();
  559. }
  560. [Fact]
  561. public void Modal_Toplevel_Can_Open_Another_Modal_Toplevel_But_RequestStop_To_The_Caller_Also_Sets_Current_Running_To_False_Too ()
  562. {
  563. Init ();
  564. var mdi = new Mdi ();
  565. var c1 = new Toplevel ();
  566. var c2 = new Window ();
  567. var c3 = new Window ();
  568. var d1 = new Dialog ();
  569. var d2 = new Dialog ();
  570. // MdiChild = c1, c2, c3 = 3
  571. // d1, d2 = 2
  572. var iterations = 5;
  573. mdi.Ready += () => {
  574. Assert.Empty (Application.MdiChildes);
  575. Application.Run (c1);
  576. };
  577. c1.Ready += () => {
  578. Assert.Single (Application.MdiChildes);
  579. Application.Run (c2);
  580. };
  581. c2.Ready += () => {
  582. Assert.Equal (2, Application.MdiChildes.Count);
  583. Application.Run (c3);
  584. };
  585. c3.Ready += () => {
  586. Assert.Equal (3, Application.MdiChildes.Count);
  587. Application.Run (d1);
  588. };
  589. d1.Ready += () => {
  590. Assert.Equal (3, Application.MdiChildes.Count);
  591. Application.Run (d2);
  592. };
  593. d2.Ready += () => {
  594. Assert.Equal (3, Application.MdiChildes.Count);
  595. Assert.True (Application.Current == d2);
  596. Assert.True (Application.Current.Running);
  597. // Trying to close the Dialog1
  598. d1.RequestStop ();
  599. };
  600. // Now this will close the MdiContainer propagating through the MdiChildes.
  601. d1.Closed += (e) => {
  602. Assert.True (Application.Current == d1);
  603. Assert.False (Application.Current.Running);
  604. mdi.RequestStop ();
  605. };
  606. Application.Iteration += () => {
  607. if (iterations == 5) {
  608. // The Dialog2 still is the current top and we can't request stop to MdiContainer
  609. // because Dialog2 and Dialog1 must be closed first.
  610. // Dialog2 will be closed in this iteration.
  611. Assert.True (Application.Current == d2);
  612. Assert.False (Application.Current.Running);
  613. Assert.False (d1.Running);
  614. } else if (iterations == 4) {
  615. // Dialog1 will be closed in this iteration.
  616. Assert.True (Application.Current == d1);
  617. Assert.False (Application.Current.Running);
  618. } else {
  619. Assert.Equal (iterations, Application.MdiChildes.Count);
  620. for (int i = 0; i < iterations; i++) {
  621. Assert.Equal ((iterations - i + 1).ToString (), Application.MdiChildes [i].Id);
  622. }
  623. }
  624. iterations--;
  625. };
  626. Application.Run (mdi);
  627. Assert.Empty (Application.MdiChildes);
  628. Application.Shutdown ();
  629. }
  630. [Fact]
  631. public void Modal_Toplevel_Can_Open_Another_Not_Modal_Toplevel_But_RequestStop_To_The_Caller_Also_Sets_Current_Running_To_False_Too ()
  632. {
  633. Init ();
  634. var mdi = new Mdi ();
  635. var c1 = new Toplevel ();
  636. var c2 = new Window ();
  637. var c3 = new Window ();
  638. var d1 = new Dialog ();
  639. var c4 = new Toplevel ();
  640. // MdiChild = c1, c2, c3, c4 = 4
  641. // d1 = 1
  642. var iterations = 5;
  643. mdi.Ready += () => {
  644. Assert.Empty (Application.MdiChildes);
  645. Application.Run (c1);
  646. };
  647. c1.Ready += () => {
  648. Assert.Single (Application.MdiChildes);
  649. Application.Run (c2);
  650. };
  651. c2.Ready += () => {
  652. Assert.Equal (2, Application.MdiChildes.Count);
  653. Application.Run (c3);
  654. };
  655. c3.Ready += () => {
  656. Assert.Equal (3, Application.MdiChildes.Count);
  657. Application.Run (d1);
  658. };
  659. d1.Ready += () => {
  660. Assert.Equal (3, Application.MdiChildes.Count);
  661. Application.Run (c4);
  662. };
  663. c4.Ready += () => {
  664. Assert.Equal (4, Application.MdiChildes.Count);
  665. // Trying to close the Dialog1
  666. d1.RequestStop ();
  667. };
  668. // Now this will close the MdiContainer propagating through the MdiChildes.
  669. d1.Closed += (e) => {
  670. mdi.RequestStop ();
  671. };
  672. Application.Iteration += () => {
  673. if (iterations == 5) {
  674. // The Dialog2 still is the current top and we can't request stop to MdiContainer
  675. // because Dialog2 and Dialog1 must be closed first.
  676. // Using request stop here will call the Dialog again without need
  677. Assert.True (Application.Current == d1);
  678. Assert.False (Application.Current.Running);
  679. Assert.True (c4.Running);
  680. } else {
  681. Assert.Equal (iterations, Application.MdiChildes.Count);
  682. for (int i = 0; i < iterations; i++) {
  683. Assert.Equal ((iterations - i + (iterations == 4 && i == 0 ? 2 : 1)).ToString (),
  684. Application.MdiChildes [i].Id);
  685. }
  686. }
  687. iterations--;
  688. };
  689. Application.Run (mdi);
  690. Assert.Empty (Application.MdiChildes);
  691. Application.Shutdown ();
  692. }
  693. [Fact]
  694. public void MoveCurrent_Returns_False_If_The_Current_And_Top_Parameter_Are_Both_With_Running_Set_To_False ()
  695. {
  696. Init ();
  697. var mdi = new Mdi ();
  698. var c1 = new Toplevel ();
  699. var c2 = new Window ();
  700. var c3 = new Window ();
  701. // MdiChild = c1, c2, c3
  702. var iterations = 3;
  703. mdi.Ready += () => {
  704. Assert.Empty (Application.MdiChildes);
  705. Application.Run (c1);
  706. };
  707. c1.Ready += () => {
  708. Assert.Single (Application.MdiChildes);
  709. Application.Run (c2);
  710. };
  711. c2.Ready += () => {
  712. Assert.Equal (2, Application.MdiChildes.Count);
  713. Application.Run (c3);
  714. };
  715. c3.Ready += () => {
  716. Assert.Equal (3, Application.MdiChildes.Count);
  717. c3.RequestStop ();
  718. c1.RequestStop ();
  719. };
  720. // Now this will close the MdiContainer propagating through the MdiChildes.
  721. c1.Closed += (e) => {
  722. mdi.RequestStop ();
  723. };
  724. Application.Iteration += () => {
  725. if (iterations == 3) {
  726. // The Current still is c3 because Current.Running is false.
  727. Assert.True (Application.Current == c3);
  728. Assert.False (Application.Current.Running);
  729. // But the childes order were reorder by Running = false
  730. Assert.True (Application.MdiChildes [0] == c3);
  731. Assert.True (Application.MdiChildes [1] == c1);
  732. Assert.True (Application.MdiChildes [^1] == c2);
  733. } else if (iterations == 2) {
  734. // The Current is c1 and Current.Running is false.
  735. Assert.True (Application.Current == c1);
  736. Assert.False (Application.Current.Running);
  737. Assert.True (Application.MdiChildes [0] == c1);
  738. Assert.True (Application.MdiChildes [^1] == c2);
  739. } else if (iterations == 1) {
  740. // The Current is c2 and Current.Running is false.
  741. Assert.True (Application.Current == c2);
  742. Assert.False (Application.Current.Running);
  743. Assert.True (Application.MdiChildes [^1] == c2);
  744. } else {
  745. // The Current is mdi.
  746. Assert.True (Application.Current == mdi);
  747. Assert.Empty (Application.MdiChildes);
  748. }
  749. iterations--;
  750. };
  751. Application.Run (mdi);
  752. Assert.Empty (Application.MdiChildes);
  753. Application.Shutdown ();
  754. }
  755. [Fact]
  756. public void MdiContainer_Throws_If_More_Than_One ()
  757. {
  758. Init ();
  759. var mdi = new Mdi ();
  760. var mdi2 = new Mdi ();
  761. mdi.Ready += () => {
  762. Assert.Throws<InvalidOperationException> (() => Application.Run (mdi2));
  763. mdi.RequestStop ();
  764. };
  765. Application.Run (mdi);
  766. Application.Shutdown ();
  767. }
  768. [Fact]
  769. public void MdiContainer_Open_And_Close_Modal_And_Open_Not_Modal_Toplevels_Randomly ()
  770. {
  771. Init ();
  772. var mdi = new Mdi ();
  773. var logger = new Toplevel ();
  774. var iterations = 1; // The logger
  775. var running = true;
  776. var stageCompleted = true;
  777. var allStageClosed = false;
  778. var mdiRequestStop = false;
  779. mdi.Ready += () => {
  780. Assert.Empty (Application.MdiChildes);
  781. Application.Run (logger);
  782. };
  783. logger.Ready += () => Assert.Single (Application.MdiChildes);
  784. Application.Iteration += () => {
  785. if (stageCompleted && running) {
  786. stageCompleted = false;
  787. var stage = new Window () { Modal = true };
  788. stage.Ready += () => {
  789. Assert.Equal (iterations, Application.MdiChildes.Count);
  790. stage.RequestStop ();
  791. };
  792. stage.Closed += (_) => {
  793. if (iterations == 11) {
  794. allStageClosed = true;
  795. }
  796. Assert.Equal (iterations, Application.MdiChildes.Count);
  797. if (running) {
  798. stageCompleted = true;
  799. var rpt = new Window ();
  800. rpt.Ready += () => {
  801. iterations++;
  802. Assert.Equal (iterations, Application.MdiChildes.Count);
  803. };
  804. Application.Run (rpt);
  805. }
  806. };
  807. Application.Run (stage);
  808. } else if (iterations == 11 && running) {
  809. running = false;
  810. Assert.Equal (iterations, Application.MdiChildes.Count);
  811. } else if (!mdiRequestStop && running && !allStageClosed) {
  812. Assert.Equal (iterations, Application.MdiChildes.Count);
  813. } else if (!mdiRequestStop && !running && allStageClosed) {
  814. Assert.Equal (iterations, Application.MdiChildes.Count);
  815. mdiRequestStop = true;
  816. mdi.RequestStop ();
  817. } else {
  818. Assert.Empty (Application.MdiChildes);
  819. }
  820. };
  821. Application.Run (mdi);
  822. Assert.Empty (Application.MdiChildes);
  823. Application.Shutdown ();
  824. }
  825. [Fact]
  826. public void AllChildClosed_Event_Test ()
  827. {
  828. Init ();
  829. var mdi = new Mdi ();
  830. var c1 = new Toplevel ();
  831. var c2 = new Window ();
  832. var c3 = new Window ();
  833. // MdiChild = c1, c2, c3
  834. var iterations = 3;
  835. mdi.Ready += () => {
  836. Assert.Empty (Application.MdiChildes);
  837. Application.Run (c1);
  838. };
  839. c1.Ready += () => {
  840. Assert.Single (Application.MdiChildes);
  841. Application.Run (c2);
  842. };
  843. c2.Ready += () => {
  844. Assert.Equal (2, Application.MdiChildes.Count);
  845. Application.Run (c3);
  846. };
  847. c3.Ready += () => {
  848. Assert.Equal (3, Application.MdiChildes.Count);
  849. c3.RequestStop ();
  850. c2.RequestStop ();
  851. c1.RequestStop ();
  852. };
  853. // Now this will close the MdiContainer when all MdiChildes was closed
  854. mdi.AllChildClosed += () => {
  855. mdi.RequestStop ();
  856. };
  857. Application.Iteration += () => {
  858. if (iterations == 3) {
  859. // The Current still is c3 because Current.Running is false.
  860. Assert.True (Application.Current == c3);
  861. Assert.False (Application.Current.Running);
  862. // But the childes order were reorder by Running = false
  863. Assert.True (Application.MdiChildes [0] == c3);
  864. Assert.True (Application.MdiChildes [1] == c2);
  865. Assert.True (Application.MdiChildes [^1] == c1);
  866. } else if (iterations == 2) {
  867. // The Current is c2 and Current.Running is false.
  868. Assert.True (Application.Current == c2);
  869. Assert.False (Application.Current.Running);
  870. Assert.True (Application.MdiChildes [0] == c2);
  871. Assert.True (Application.MdiChildes [^1] == c1);
  872. } else if (iterations == 1) {
  873. // The Current is c1 and Current.Running is false.
  874. Assert.True (Application.Current == c1);
  875. Assert.False (Application.Current.Running);
  876. Assert.True (Application.MdiChildes [^1] == c1);
  877. } else {
  878. // The Current is mdi.
  879. Assert.True (Application.Current == mdi);
  880. Assert.False (Application.Current.Running);
  881. Assert.Empty (Application.MdiChildes);
  882. }
  883. iterations--;
  884. };
  885. Application.Run (mdi);
  886. Assert.Empty (Application.MdiChildes);
  887. Application.Shutdown ();
  888. }
  889. [Fact]
  890. public void SetCurrentAsTop_Run_A_Not_Modal_Toplevel_Make_It_The_Current_Application_Top ()
  891. {
  892. Init ();
  893. var t1 = new Toplevel ();
  894. var t2 = new Toplevel ();
  895. var t3 = new Toplevel ();
  896. var d = new Dialog ();
  897. var t4 = new Toplevel ();
  898. // t1, t2, t3, d, t4
  899. var iterations = 5;
  900. t1.Ready += () => {
  901. Assert.Equal (t1, Application.Top);
  902. Application.Run (t2);
  903. };
  904. t2.Ready += () => {
  905. Assert.Equal (t2, Application.Top);
  906. Application.Run (t3);
  907. };
  908. t3.Ready += () => {
  909. Assert.Equal (t3, Application.Top);
  910. Application.Run (d);
  911. };
  912. d.Ready += () => {
  913. Assert.Equal (t3, Application.Top);
  914. Application.Run (t4);
  915. };
  916. t4.Ready += () => {
  917. Assert.Equal (t4, Application.Top);
  918. t4.RequestStop ();
  919. d.RequestStop ();
  920. t3.RequestStop ();
  921. t2.RequestStop ();
  922. };
  923. // Now this will close the MdiContainer when all MdiChildes was closed
  924. t2.Closed += (_) => {
  925. t1.RequestStop ();
  926. };
  927. Application.Iteration += () => {
  928. if (iterations == 5) {
  929. // The Current still is t4 because Current.Running is false.
  930. Assert.Equal (t4, Application.Current);
  931. Assert.False (Application.Current.Running);
  932. Assert.Equal (t4, Application.Top);
  933. } else if (iterations == 4) {
  934. // The Current is d and Current.Running is false.
  935. Assert.Equal (d, Application.Current);
  936. Assert.False (Application.Current.Running);
  937. Assert.Equal (t4, Application.Top);
  938. } else if (iterations == 3) {
  939. // The Current is t3 and Current.Running is false.
  940. Assert.Equal (t3, Application.Current);
  941. Assert.False (Application.Current.Running);
  942. Assert.Equal (t3, Application.Top);
  943. } else if (iterations == 2) {
  944. // The Current is t2 and Current.Running is false.
  945. Assert.Equal (t2, Application.Current);
  946. Assert.False (Application.Current.Running);
  947. Assert.Equal (t2, Application.Top);
  948. } else {
  949. // The Current is t1.
  950. Assert.Equal (t1, Application.Current);
  951. Assert.False (Application.Current.Running);
  952. Assert.Equal (t1, Application.Top);
  953. }
  954. iterations--;
  955. };
  956. Application.Run (t1);
  957. Assert.Equal (t1, Application.Top);
  958. Application.Shutdown ();
  959. Assert.Null (Application.Top);
  960. }
  961. [Fact]
  962. [AutoInitShutdown]
  963. public void Internal_Tests ()
  964. {
  965. Assert.True (Application._initialized);
  966. Assert.NotNull (Application.Top);
  967. var rs = Application.Begin (Application.Top);
  968. Assert.Equal (Application.Top, rs.Toplevel);
  969. Assert.Null (Application.mouseGrabView);
  970. Assert.Null (Application.wantContinuousButtonPressedView);
  971. Assert.False (Application.DebugDrawBounds);
  972. Assert.False (Application.ShowChild (Application.Top));
  973. Application.End (Application.Top);
  974. }
  975. [Fact]
  976. [AutoInitShutdown]
  977. public void QuitKey_Getter_Setter ()
  978. {
  979. var top = Application.Top;
  980. var isQuiting = false;
  981. top.Closing += (e) => {
  982. isQuiting = true;
  983. e.Cancel = true;
  984. };
  985. Application.Begin (top);
  986. top.Running = true;
  987. Assert.Equal (Key.Q | Key.CtrlMask, Application.QuitKey);
  988. Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true);
  989. Assert.True (isQuiting);
  990. isQuiting = false;
  991. Application.QuitKey = Key.C | Key.CtrlMask;
  992. Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true);
  993. Assert.False (isQuiting);
  994. Application.Driver.SendKeys ('c', ConsoleKey.C, false, false, true);
  995. Assert.True (isQuiting);
  996. // Reset the QuitKey to avoid throws errors on another tests
  997. Application.QuitKey = Key.Q | Key.CtrlMask;
  998. }
  999. [Fact]
  1000. [AutoInitShutdown]
  1001. public void EnsuresTopOnFront_CanFocus_True_By_Keyboard_And_Mouse ()
  1002. {
  1003. var top = Application.Top;
  1004. var win = new Window ("win") { X = 0, Y = 0, Width = 20, Height = 10 };
  1005. var tf = new TextField () { Width = 10 };
  1006. win.Add (tf);
  1007. var win2 = new Window ("win2") { X = 22, Y = 0, Width = 20, Height = 10 };
  1008. var tf2 = new TextField () { Width = 10 };
  1009. win2.Add (tf2);
  1010. top.Add (win, win2);
  1011. Application.Begin (top);
  1012. Assert.True (win.CanFocus);
  1013. Assert.True (win.HasFocus);
  1014. Assert.True (win2.CanFocus);
  1015. Assert.False (win2.HasFocus);
  1016. Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title);
  1017. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab, new KeyModifiers ()));
  1018. Assert.True (win.CanFocus);
  1019. Assert.False (win.HasFocus);
  1020. Assert.True (win2.CanFocus);
  1021. Assert.True (win2.HasFocus);
  1022. Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title);
  1023. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab, new KeyModifiers ()));
  1024. Assert.True (win.CanFocus);
  1025. Assert.True (win.HasFocus);
  1026. Assert.True (win2.CanFocus);
  1027. Assert.False (win2.HasFocus);
  1028. Assert.Equal ("win", ((Window)top.Subviews [top.Subviews.Count - 1]).Title);
  1029. win2.MouseEvent (new MouseEvent () { Flags = MouseFlags.Button1Pressed });
  1030. Assert.True (win.CanFocus);
  1031. Assert.False (win.HasFocus);
  1032. Assert.True (win2.CanFocus);
  1033. Assert.True (win2.HasFocus);
  1034. Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title);
  1035. win2.MouseEvent (new MouseEvent () { Flags = MouseFlags.Button1Released });
  1036. Assert.Null (Toplevel.dragPosition);
  1037. }
  1038. [Fact]
  1039. [AutoInitShutdown]
  1040. public void EnsuresTopOnFront_CanFocus_False_By_Keyboard_And_Mouse ()
  1041. {
  1042. var top = Application.Top;
  1043. var win = new Window ("win") { X = 0, Y = 0, Width = 20, Height = 10 };
  1044. var tf = new TextField () { Width = 10 };
  1045. win.Add (tf);
  1046. var win2 = new Window ("win2") { X = 22, Y = 0, Width = 20, Height = 10 };
  1047. var tf2 = new TextField () { Width = 10 };
  1048. win2.Add (tf2);
  1049. top.Add (win, win2);
  1050. Application.Begin (top);
  1051. Assert.True (win.CanFocus);
  1052. Assert.True (win.HasFocus);
  1053. Assert.True (win2.CanFocus);
  1054. Assert.False (win2.HasFocus);
  1055. Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title);
  1056. win.CanFocus = false;
  1057. Assert.False (win.CanFocus);
  1058. Assert.False (win.HasFocus);
  1059. Assert.True (win2.CanFocus);
  1060. Assert.True (win2.HasFocus);
  1061. Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title);
  1062. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab, new KeyModifiers ()));
  1063. Assert.True (win2.CanFocus);
  1064. Assert.False (win.HasFocus);
  1065. Assert.True (win2.CanFocus);
  1066. Assert.True (win2.HasFocus);
  1067. Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title);
  1068. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab, new KeyModifiers ()));
  1069. Assert.False (win.CanFocus);
  1070. Assert.False (win.HasFocus);
  1071. Assert.True (win2.CanFocus);
  1072. Assert.True (win2.HasFocus);
  1073. Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title);
  1074. win.MouseEvent (new MouseEvent () { Flags = MouseFlags.Button1Pressed });
  1075. Assert.False (win.CanFocus);
  1076. Assert.False (win.HasFocus);
  1077. Assert.True (win2.CanFocus);
  1078. Assert.True (win2.HasFocus);
  1079. Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title);
  1080. win2.MouseEvent (new MouseEvent () { Flags = MouseFlags.Button1Released });
  1081. Assert.Null (Toplevel.dragPosition);
  1082. }
  1083. [Fact, AutoInitShutdown]
  1084. public void GetSupportedCultures_Method ()
  1085. {
  1086. var cultures = Application.GetSupportedCultures ();
  1087. Assert.Equal (cultures.Count, Application.SupportedCultures.Count);
  1088. }
  1089. }
  1090. }