OverlappedTests.cs 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009
  1. using Xunit.Abstractions;
  2. namespace Terminal.Gui.ViewsTests;
  3. public class OverlappedTests
  4. {
  5. private readonly ITestOutputHelper _output;
  6. public OverlappedTests (ITestOutputHelper output)
  7. {
  8. _output = output;
  9. #if DEBUG_IDISPOSABLE
  10. Responder.Instances.Clear ();
  11. RunState.Instances.Clear ();
  12. #endif
  13. }
  14. [Fact]
  15. [AutoInitShutdown]
  16. public void AllChildClosed_Event_Test ()
  17. {
  18. var overlapped = new Overlapped ();
  19. var c1 = new Toplevel ();
  20. var c2 = new Window ();
  21. var c3 = new Window ();
  22. // OverlappedChild = c1, c2, c3
  23. var iterations = 3;
  24. overlapped.Ready += (s, e) =>
  25. {
  26. Assert.Empty (Application.OverlappedChildren);
  27. Application.Run (c1);
  28. };
  29. c1.Ready += (s, e) =>
  30. {
  31. Assert.Single (Application.OverlappedChildren);
  32. Application.Run (c2);
  33. };
  34. c2.Ready += (s, e) =>
  35. {
  36. Assert.Equal (2, Application.OverlappedChildren.Count);
  37. Application.Run (c3);
  38. };
  39. c3.Ready += (s, e) =>
  40. {
  41. Assert.Equal (3, Application.OverlappedChildren.Count);
  42. c3.RequestStop ();
  43. c2.RequestStop ();
  44. c1.RequestStop ();
  45. };
  46. // Now this will close the OverlappedContainer when all OverlappedChildren was closed
  47. overlapped.AllChildClosed += (s, e) => { overlapped.RequestStop (); };
  48. Application.Iteration += (s, a) =>
  49. {
  50. if (iterations == 3)
  51. {
  52. // The Current still is c3 because Current.Running is false.
  53. Assert.True (Application.Current == c3);
  54. Assert.False (Application.Current.Running);
  55. // But the Children order were reorder by Running = false
  56. Assert.True (Application.OverlappedChildren [0] == c3);
  57. Assert.True (Application.OverlappedChildren [1] == c2);
  58. Assert.True (Application.OverlappedChildren [^1] == c1);
  59. }
  60. else if (iterations == 2)
  61. {
  62. // The Current is c2 and Current.Running is false.
  63. Assert.True (Application.Current == c2);
  64. Assert.False (Application.Current.Running);
  65. Assert.True (Application.OverlappedChildren [0] == c2);
  66. Assert.True (Application.OverlappedChildren [^1] == c1);
  67. }
  68. else if (iterations == 1)
  69. {
  70. // The Current is c1 and Current.Running is false.
  71. Assert.True (Application.Current == c1);
  72. Assert.False (Application.Current.Running);
  73. Assert.True (Application.OverlappedChildren [^1] == c1);
  74. }
  75. else
  76. {
  77. // The Current is overlapped.
  78. Assert.True (Application.Current == overlapped);
  79. Assert.False (Application.Current.Running);
  80. Assert.Empty (Application.OverlappedChildren);
  81. }
  82. iterations--;
  83. };
  84. Application.Run (overlapped);
  85. Assert.Empty (Application.OverlappedChildren);
  86. Assert.NotNull (Application.OverlappedTop);
  87. Assert.NotNull (Application.Top);
  88. }
  89. [Fact]
  90. [AutoInitShutdown]
  91. public void Application_RequestStop_With_Params_On_A_Not_OverlappedContainer_Always_Use_Application_Current ()
  92. {
  93. var top1 = new Toplevel ();
  94. var top2 = new Toplevel ();
  95. var top3 = new Window ();
  96. var top4 = new Window ();
  97. var d = new Dialog ();
  98. // top1, top2, top3, d1 = 4
  99. var iterations = 4;
  100. top1.Ready += (s, e) =>
  101. {
  102. Assert.Null (Application.OverlappedChildren);
  103. Application.Run (top2);
  104. };
  105. top2.Ready += (s, e) =>
  106. {
  107. Assert.Null (Application.OverlappedChildren);
  108. Application.Run (top3);
  109. };
  110. top3.Ready += (s, e) =>
  111. {
  112. Assert.Null (Application.OverlappedChildren);
  113. Application.Run (top4);
  114. };
  115. top4.Ready += (s, e) =>
  116. {
  117. Assert.Null (Application.OverlappedChildren);
  118. Application.Run (d);
  119. };
  120. d.Ready += (s, e) =>
  121. {
  122. Assert.Null (Application.OverlappedChildren);
  123. // This will close the d because on a not OverlappedContainer the Application.Current it always used.
  124. Application.RequestStop (top1);
  125. Assert.True (Application.Current == d);
  126. };
  127. d.Closed += (s, e) => Application.RequestStop (top1);
  128. Application.Iteration += (s, a) =>
  129. {
  130. Assert.Null (Application.OverlappedChildren);
  131. if (iterations == 4)
  132. {
  133. Assert.True (Application.Current == d);
  134. }
  135. else if (iterations == 3)
  136. {
  137. Assert.True (Application.Current == top4);
  138. }
  139. else if (iterations == 2)
  140. {
  141. Assert.True (Application.Current == top3);
  142. }
  143. else if (iterations == 1)
  144. {
  145. Assert.True (Application.Current == top2);
  146. }
  147. else
  148. {
  149. Assert.True (Application.Current == top1);
  150. }
  151. Application.RequestStop (top1);
  152. iterations--;
  153. };
  154. Application.Run (top1);
  155. Assert.Null (Application.OverlappedChildren);
  156. }
  157. [Fact]
  158. [TestRespondersDisposed]
  159. public void Dispose_Toplevel_IsOverlappedContainer_False_With_Begin_End ()
  160. {
  161. Application.Init (new FakeDriver ());
  162. var top = new Toplevel ();
  163. RunState rs = Application.Begin (top);
  164. Application.End (rs);
  165. top.Dispose ();
  166. Application.Shutdown ();
  167. #if DEBUG_IDISPOSABLE
  168. Assert.Empty (Responder.Instances);
  169. #endif
  170. }
  171. [Fact]
  172. [TestRespondersDisposed]
  173. public void Dispose_Toplevel_IsOverlappedContainer_True_With_Begin ()
  174. {
  175. Application.Init (new FakeDriver ());
  176. var overlapped = new Toplevel { IsOverlappedContainer = true };
  177. RunState rs = Application.Begin (overlapped);
  178. Application.End (rs);
  179. overlapped.Dispose ();
  180. Application.Shutdown ();
  181. }
  182. [Fact]
  183. [AutoInitShutdown]
  184. public void IsOverlappedChild_Testing ()
  185. {
  186. var overlapped = new Overlapped ();
  187. var c1 = new Toplevel ();
  188. var c2 = new Window ();
  189. var c3 = new Window ();
  190. var d = new Dialog ();
  191. Application.Iteration += (s, a) =>
  192. {
  193. Assert.False (overlapped.IsOverlapped);
  194. Assert.True (c1.IsOverlapped);
  195. Assert.True (c2.IsOverlapped);
  196. Assert.True (c3.IsOverlapped);
  197. Assert.False (d.IsOverlapped);
  198. overlapped.RequestStop ();
  199. };
  200. Application.Run (overlapped);
  201. }
  202. [Fact]
  203. [AutoInitShutdown]
  204. public void
  205. Modal_Toplevel_Can_Open_Another_Modal_Toplevel_But_RequestStop_To_The_Caller_Also_Sets_Current_Running_To_False_Too ()
  206. {
  207. var overlapped = new Overlapped ();
  208. var c1 = new Toplevel ();
  209. var c2 = new Window ();
  210. var c3 = new Window ();
  211. var d1 = new Dialog ();
  212. var d2 = new Dialog ();
  213. // OverlappedChild = c1, c2, c3 = 3
  214. // d1, d2 = 2
  215. var iterations = 5;
  216. overlapped.Ready += (s, e) =>
  217. {
  218. Assert.Empty (Application.OverlappedChildren);
  219. Application.Run (c1);
  220. };
  221. c1.Ready += (s, e) =>
  222. {
  223. Assert.Single (Application.OverlappedChildren);
  224. Application.Run (c2);
  225. };
  226. c2.Ready += (s, e) =>
  227. {
  228. Assert.Equal (2, Application.OverlappedChildren.Count);
  229. Application.Run (c3);
  230. };
  231. c3.Ready += (s, e) =>
  232. {
  233. Assert.Equal (3, Application.OverlappedChildren.Count);
  234. Application.Run (d1);
  235. };
  236. d1.Ready += (s, e) =>
  237. {
  238. Assert.Equal (3, Application.OverlappedChildren.Count);
  239. Application.Run (d2);
  240. };
  241. d2.Ready += (s, e) =>
  242. {
  243. Assert.Equal (3, Application.OverlappedChildren.Count);
  244. Assert.True (Application.Current == d2);
  245. Assert.True (Application.Current.Running);
  246. // Trying to close the Dialog1
  247. d1.RequestStop ();
  248. };
  249. // Now this will close the OverlappedContainer propagating through the OverlappedChildren.
  250. d1.Closed += (s, e) =>
  251. {
  252. Assert.True (Application.Current == d1);
  253. Assert.False (Application.Current.Running);
  254. overlapped.RequestStop ();
  255. };
  256. Application.Iteration += (s, a) =>
  257. {
  258. if (iterations == 5)
  259. {
  260. // The Dialog2 still is the current top and we can't request stop to OverlappedContainer
  261. // because Dialog2 and Dialog1 must be closed first.
  262. // Dialog2 will be closed in this iteration.
  263. Assert.True (Application.Current == d2);
  264. Assert.False (Application.Current.Running);
  265. Assert.False (d1.Running);
  266. }
  267. else if (iterations == 4)
  268. {
  269. // Dialog1 will be closed in this iteration.
  270. Assert.True (Application.Current == d1);
  271. Assert.False (Application.Current.Running);
  272. }
  273. else
  274. {
  275. Assert.Equal (iterations, Application.OverlappedChildren.Count);
  276. for (var i = 0; i < iterations; i++)
  277. {
  278. Assert.Equal ((iterations - i + 1).ToString (), Application.OverlappedChildren [i].Id);
  279. }
  280. }
  281. iterations--;
  282. };
  283. Application.Run (overlapped);
  284. Assert.Empty (Application.OverlappedChildren);
  285. Assert.NotNull (Application.OverlappedTop);
  286. Assert.NotNull (Application.Top);
  287. }
  288. [Fact]
  289. [AutoInitShutdown]
  290. public void
  291. Modal_Toplevel_Can_Open_Another_Not_Modal_Toplevel_But_RequestStop_To_The_Caller_Also_Sets_Current_Running_To_False_Too ()
  292. {
  293. var overlapped = new Overlapped ();
  294. var c1 = new Toplevel ();
  295. var c2 = new Window ();
  296. var c3 = new Window ();
  297. var d1 = new Dialog ();
  298. var c4 = new Toplevel ();
  299. // OverlappedChild = c1, c2, c3, c4 = 4
  300. // d1 = 1
  301. var iterations = 5;
  302. overlapped.Ready += (s, e) =>
  303. {
  304. Assert.Empty (Application.OverlappedChildren);
  305. Application.Run (c1);
  306. };
  307. c1.Ready += (s, e) =>
  308. {
  309. Assert.Single (Application.OverlappedChildren);
  310. Application.Run (c2);
  311. };
  312. c2.Ready += (s, e) =>
  313. {
  314. Assert.Equal (2, Application.OverlappedChildren.Count);
  315. Application.Run (c3);
  316. };
  317. c3.Ready += (s, e) =>
  318. {
  319. Assert.Equal (3, Application.OverlappedChildren.Count);
  320. Application.Run (d1);
  321. };
  322. d1.Ready += (s, e) =>
  323. {
  324. Assert.Equal (3, Application.OverlappedChildren.Count);
  325. Application.Run (c4);
  326. };
  327. c4.Ready += (s, e) =>
  328. {
  329. Assert.Equal (4, Application.OverlappedChildren.Count);
  330. // Trying to close the Dialog1
  331. d1.RequestStop ();
  332. };
  333. // Now this will close the OverlappedContainer propagating through the OverlappedChildren.
  334. d1.Closed += (s, e) => { overlapped.RequestStop (); };
  335. Application.Iteration += (s, a) =>
  336. {
  337. if (iterations == 5)
  338. {
  339. // The Dialog2 still is the current top and we can't request stop to OverlappedContainer
  340. // because Dialog2 and Dialog1 must be closed first.
  341. // Using request stop here will call the Dialog again without need
  342. Assert.True (Application.Current == d1);
  343. Assert.False (Application.Current.Running);
  344. Assert.True (c4.Running);
  345. }
  346. else
  347. {
  348. Assert.Equal (iterations, Application.OverlappedChildren.Count);
  349. for (var i = 0; i < iterations; i++)
  350. {
  351. Assert.Equal (
  352. (iterations - i + (iterations == 4 && i == 0 ? 2 : 1)).ToString (),
  353. Application.OverlappedChildren [i].Id
  354. );
  355. }
  356. }
  357. iterations--;
  358. };
  359. Application.Run (overlapped);
  360. Assert.Empty (Application.OverlappedChildren);
  361. Assert.NotNull (Application.OverlappedTop);
  362. Assert.NotNull (Application.Top);
  363. }
  364. [Fact]
  365. [AutoInitShutdown]
  366. public void MoveCurrent_Returns_False_If_The_Current_And_Top_Parameter_Are_Both_With_Running_Set_To_False ()
  367. {
  368. var overlapped = new Overlapped ();
  369. var c1 = new Toplevel ();
  370. var c2 = new Window ();
  371. var c3 = new Window ();
  372. // OverlappedChild = c1, c2, c3
  373. var iterations = 3;
  374. overlapped.Ready += (s, e) =>
  375. {
  376. Assert.Empty (Application.OverlappedChildren);
  377. Application.Run (c1);
  378. };
  379. c1.Ready += (s, e) =>
  380. {
  381. Assert.Single (Application.OverlappedChildren);
  382. Application.Run (c2);
  383. };
  384. c2.Ready += (s, e) =>
  385. {
  386. Assert.Equal (2, Application.OverlappedChildren.Count);
  387. Application.Run (c3);
  388. };
  389. c3.Ready += (s, e) =>
  390. {
  391. Assert.Equal (3, Application.OverlappedChildren.Count);
  392. c3.RequestStop ();
  393. c1.RequestStop ();
  394. };
  395. // Now this will close the OverlappedContainer propagating through the OverlappedChildren.
  396. c1.Closed += (s, e) => { overlapped.RequestStop (); };
  397. Application.Iteration += (s, a) =>
  398. {
  399. if (iterations == 3)
  400. {
  401. // The Current still is c3 because Current.Running is false.
  402. Assert.True (Application.Current == c3);
  403. Assert.False (Application.Current.Running);
  404. // But the Children order were reorder by Running = false
  405. Assert.True (Application.OverlappedChildren [0] == c3);
  406. Assert.True (Application.OverlappedChildren [1] == c1);
  407. Assert.True (Application.OverlappedChildren [^1] == c2);
  408. }
  409. else if (iterations == 2)
  410. {
  411. // The Current is c1 and Current.Running is false.
  412. Assert.True (Application.Current == c1);
  413. Assert.False (Application.Current.Running);
  414. Assert.True (Application.OverlappedChildren [0] == c1);
  415. Assert.True (Application.OverlappedChildren [^1] == c2);
  416. }
  417. else if (iterations == 1)
  418. {
  419. // The Current is c2 and Current.Running is false.
  420. Assert.True (Application.Current == c2);
  421. Assert.False (Application.Current.Running);
  422. Assert.True (Application.OverlappedChildren [^1] == c2);
  423. }
  424. else
  425. {
  426. // The Current is overlapped.
  427. Assert.True (Application.Current == overlapped);
  428. Assert.Empty (Application.OverlappedChildren);
  429. }
  430. iterations--;
  431. };
  432. Application.Run (overlapped);
  433. Assert.Empty (Application.OverlappedChildren);
  434. Assert.NotNull (Application.OverlappedTop);
  435. Assert.NotNull (Application.Top);
  436. }
  437. [Fact]
  438. public void MoveToOverlappedChild_Throw_NullReferenceException_Passing_Null_Parameter ()
  439. {
  440. Assert.Throws<NullReferenceException> (delegate { Application.MoveToOverlappedChild (null); });
  441. }
  442. [Fact]
  443. [AutoInitShutdown]
  444. public void OverlappedContainer_Open_And_Close_Modal_And_Open_Not_Modal_Toplevels_Randomly ()
  445. {
  446. var overlapped = new Overlapped ();
  447. var logger = new Toplevel ();
  448. var iterations = 1; // The logger
  449. var running = true;
  450. var stageCompleted = true;
  451. var allStageClosed = false;
  452. var overlappedRequestStop = false;
  453. overlapped.Ready += (s, e) =>
  454. {
  455. Assert.Empty (Application.OverlappedChildren);
  456. Application.Run (logger);
  457. };
  458. logger.Ready += (s, e) => Assert.Single (Application.OverlappedChildren);
  459. Application.Iteration += (s, a) =>
  460. {
  461. if (stageCompleted && running)
  462. {
  463. stageCompleted = false;
  464. var stage = new Window { Modal = true };
  465. stage.Ready += (s, e) =>
  466. {
  467. Assert.Equal (iterations, Application.OverlappedChildren.Count);
  468. stage.RequestStop ();
  469. };
  470. stage.Closed += (_, _) =>
  471. {
  472. if (iterations == 11)
  473. {
  474. allStageClosed = true;
  475. }
  476. Assert.Equal (iterations, Application.OverlappedChildren.Count);
  477. if (running)
  478. {
  479. stageCompleted = true;
  480. var rpt = new Window ();
  481. rpt.Ready += (s, e) =>
  482. {
  483. iterations++;
  484. Assert.Equal (iterations, Application.OverlappedChildren.Count);
  485. };
  486. Application.Run (rpt);
  487. }
  488. };
  489. Application.Run (stage);
  490. }
  491. else if (iterations == 11 && running)
  492. {
  493. running = false;
  494. Assert.Equal (iterations, Application.OverlappedChildren.Count);
  495. }
  496. else if (!overlappedRequestStop && running && !allStageClosed)
  497. {
  498. Assert.Equal (iterations, Application.OverlappedChildren.Count);
  499. }
  500. else if (!overlappedRequestStop && !running && allStageClosed)
  501. {
  502. Assert.Equal (iterations, Application.OverlappedChildren.Count);
  503. overlappedRequestStop = true;
  504. overlapped.RequestStop ();
  505. }
  506. else
  507. {
  508. Assert.Empty (Application.OverlappedChildren);
  509. }
  510. };
  511. Application.Run (overlapped);
  512. Assert.Empty (Application.OverlappedChildren);
  513. Assert.NotNull (Application.OverlappedTop);
  514. Assert.NotNull (Application.Top);
  515. }
  516. [Fact]
  517. [AutoInitShutdown]
  518. public void OverlappedContainer_Throws_If_More_Than_One ()
  519. {
  520. var overlapped = new Overlapped ();
  521. var overlapped2 = new Overlapped ();
  522. overlapped.Ready += (s, e) =>
  523. {
  524. Assert.Throws<InvalidOperationException> (() => Application.Run (overlapped2));
  525. overlapped.RequestStop ();
  526. };
  527. Application.Run (overlapped);
  528. }
  529. [Fact]
  530. [AutoInitShutdown]
  531. public void OverlappedContainer_With_Application_RequestStop_OverlappedTop_With_Params ()
  532. {
  533. var overlapped = new Overlapped ();
  534. var c1 = new Toplevel ();
  535. var c2 = new Window ();
  536. var c3 = new Window ();
  537. var d = new Dialog ();
  538. // OverlappedChild = c1, c2, c3
  539. // d1 = 1
  540. var iterations = 4;
  541. overlapped.Ready += (s, e) =>
  542. {
  543. Assert.Empty (Application.OverlappedChildren);
  544. Application.Run (c1);
  545. };
  546. c1.Ready += (s, e) =>
  547. {
  548. Assert.Single (Application.OverlappedChildren);
  549. Application.Run (c2);
  550. };
  551. c2.Ready += (s, e) =>
  552. {
  553. Assert.Equal (2, Application.OverlappedChildren.Count);
  554. Application.Run (c3);
  555. };
  556. c3.Ready += (s, e) =>
  557. {
  558. Assert.Equal (3, Application.OverlappedChildren.Count);
  559. Application.Run (d);
  560. };
  561. // Also easy because the Overlapped Container handles all at once
  562. d.Ready += (s, e) =>
  563. {
  564. Assert.Equal (3, Application.OverlappedChildren.Count);
  565. // This will not close the OverlappedContainer because d is a modal Toplevel
  566. Application.RequestStop (overlapped);
  567. };
  568. // Now this will close the OverlappedContainer propagating through the OverlappedChildren.
  569. d.Closed += (s, e) => Application.RequestStop (overlapped);
  570. Application.Iteration += (s, a) =>
  571. {
  572. if (iterations == 4)
  573. {
  574. // The Dialog was not closed before and will be closed now.
  575. Assert.True (Application.Current == d);
  576. Assert.False (d.Running);
  577. }
  578. else
  579. {
  580. Assert.Equal (iterations, Application.OverlappedChildren.Count);
  581. for (var i = 0; i < iterations; i++)
  582. {
  583. Assert.Equal ((iterations - i + 1).ToString (), Application.OverlappedChildren [i].Id);
  584. }
  585. }
  586. iterations--;
  587. };
  588. Application.Run (overlapped);
  589. Assert.Empty (Application.OverlappedChildren);
  590. Assert.NotNull (Application.OverlappedTop);
  591. Assert.NotNull (Application.Top);
  592. }
  593. [Fact]
  594. [AutoInitShutdown]
  595. public void OverlappedContainer_With_Application_RequestStop_OverlappedTop_Without_Params ()
  596. {
  597. var overlapped = new Overlapped ();
  598. var c1 = new Toplevel ();
  599. var c2 = new Window ();
  600. var c3 = new Window ();
  601. var d = new Dialog ();
  602. // OverlappedChild = c1, c2, c3 = 3
  603. // d1 = 1
  604. var iterations = 4;
  605. overlapped.Ready += (s, e) =>
  606. {
  607. Assert.Empty (Application.OverlappedChildren);
  608. Application.Run (c1);
  609. };
  610. c1.Ready += (s, e) =>
  611. {
  612. Assert.Single (Application.OverlappedChildren);
  613. Application.Run (c2);
  614. };
  615. c2.Ready += (s, e) =>
  616. {
  617. Assert.Equal (2, Application.OverlappedChildren.Count);
  618. Application.Run (c3);
  619. };
  620. c3.Ready += (s, e) =>
  621. {
  622. Assert.Equal (3, Application.OverlappedChildren.Count);
  623. Application.Run (d);
  624. };
  625. //More harder because it's sequential.
  626. d.Ready += (s, e) =>
  627. {
  628. Assert.Equal (3, Application.OverlappedChildren.Count);
  629. // Close the Dialog
  630. Application.RequestStop ();
  631. };
  632. // Now this will close the OverlappedContainer propagating through the OverlappedChildren.
  633. d.Closed += (s, e) => Application.RequestStop (overlapped);
  634. Application.Iteration += (s, a) =>
  635. {
  636. if (iterations == 4)
  637. {
  638. // The Dialog still is the current top and we can't request stop to OverlappedContainer
  639. // because we are not using parameter calls.
  640. Assert.True (Application.Current == d);
  641. Assert.False (d.Running);
  642. }
  643. else
  644. {
  645. Assert.Equal (iterations, Application.OverlappedChildren.Count);
  646. for (var i = 0; i < iterations; i++)
  647. {
  648. Assert.Equal ((iterations - i + 1).ToString (), Application.OverlappedChildren [i].Id);
  649. }
  650. }
  651. iterations--;
  652. };
  653. Application.Run (overlapped);
  654. Assert.Empty (Application.OverlappedChildren);
  655. Assert.NotNull (Application.OverlappedTop);
  656. Assert.NotNull (Application.Top);
  657. }
  658. [Fact]
  659. [AutoInitShutdown]
  660. public void OverlappedContainer_With_Toplevel_RequestStop_Balanced ()
  661. {
  662. var overlapped = new Overlapped ();
  663. var c1 = new Toplevel ();
  664. var c2 = new Window ();
  665. var c3 = new Window ();
  666. var d = new Dialog ();
  667. // OverlappedChild = c1, c2, c3
  668. // d1 = 1
  669. var iterations = 4;
  670. overlapped.Ready += (s, e) =>
  671. {
  672. Assert.Empty (Application.OverlappedChildren);
  673. Application.Run (c1);
  674. };
  675. c1.Ready += (s, e) =>
  676. {
  677. Assert.Single (Application.OverlappedChildren);
  678. Application.Run (c2);
  679. };
  680. c2.Ready += (s, e) =>
  681. {
  682. Assert.Equal (2, Application.OverlappedChildren.Count);
  683. Application.Run (c3);
  684. };
  685. c3.Ready += (s, e) =>
  686. {
  687. Assert.Equal (3, Application.OverlappedChildren.Count);
  688. Application.Run (d);
  689. };
  690. // More easy because the Overlapped Container handles all at once
  691. d.Ready += (s, e) =>
  692. {
  693. Assert.Equal (3, Application.OverlappedChildren.Count);
  694. // This will not close the OverlappedContainer because d is a modal Toplevel and will be closed.
  695. overlapped.RequestStop ();
  696. };
  697. // Now this will close the OverlappedContainer propagating through the OverlappedChildren.
  698. d.Closed += (s, e) => { overlapped.RequestStop (); };
  699. Application.Iteration += (s, a) =>
  700. {
  701. if (iterations == 4)
  702. {
  703. // The Dialog was not closed before and will be closed now.
  704. Assert.True (Application.Current == d);
  705. Assert.False (d.Running);
  706. }
  707. else
  708. {
  709. Assert.Equal (iterations, Application.OverlappedChildren.Count);
  710. for (var i = 0; i < iterations; i++)
  711. {
  712. Assert.Equal ((iterations - i + 1).ToString (), Application.OverlappedChildren [i].Id);
  713. }
  714. }
  715. iterations--;
  716. };
  717. Application.Run (overlapped);
  718. Assert.Empty (Application.OverlappedChildren);
  719. Assert.NotNull (Application.OverlappedTop);
  720. Assert.NotNull (Application.Top);
  721. }
  722. [Fact]
  723. [AutoInitShutdown]
  724. public void Visible_False_Does_Not_Clear ()
  725. {
  726. var overlapped = new Overlapped ();
  727. var win1 = new Window { Width = 5, Height = 5, Visible = false };
  728. var win2 = new Window { X = 1, Y = 1, Width = 5, Height = 5 };
  729. ((FakeDriver)Application.Driver).SetBufferSize (10, 10);
  730. RunState rsOverlapped = Application.Begin (overlapped);
  731. // Need to fool MainLoop into thinking it's running
  732. Application.MainLoop.Running = true;
  733. // RunIteration must be call on each iteration because
  734. // it's using the Begin and not the Run method
  735. var firstIteration = false;
  736. Application.RunIteration (ref rsOverlapped, ref firstIteration);
  737. Assert.Equal (overlapped, rsOverlapped.Toplevel);
  738. Assert.Equal (Application.Top, rsOverlapped.Toplevel);
  739. Assert.Equal (Application.OverlappedTop, rsOverlapped.Toplevel);
  740. Assert.Equal (Application.Current, rsOverlapped.Toplevel);
  741. Assert.Equal (overlapped, Application.Current);
  742. RunState rsWin1 = Application.Begin (win1);
  743. Application.RunIteration (ref rsOverlapped, ref firstIteration);
  744. Assert.Equal (overlapped, rsOverlapped.Toplevel);
  745. Assert.Equal (Application.Top, rsOverlapped.Toplevel);
  746. Assert.Equal (Application.OverlappedTop, rsOverlapped.Toplevel);
  747. // The win1 Visible is false and cannot be set as the Current
  748. Assert.Equal (Application.Current, rsOverlapped.Toplevel);
  749. Assert.Equal (overlapped, Application.Current);
  750. Assert.Equal (win1, rsWin1.Toplevel);
  751. RunState rsWin2 = Application.Begin (win2);
  752. Application.RunIteration (ref rsOverlapped, ref firstIteration);
  753. // Here the Current and the rsOverlapped.Toplevel is now the win2
  754. // and not the original overlapped
  755. Assert.Equal (win2, rsOverlapped.Toplevel);
  756. Assert.Equal (Application.Top, overlapped);
  757. Assert.Equal (Application.OverlappedTop, overlapped);
  758. Assert.Equal (Application.Current, rsWin2.Toplevel);
  759. Assert.Equal (win2, Application.Current);
  760. Assert.Equal (win1, rsWin1.Toplevel);
  761. // Tests that rely on visuals are too fragile. If border style changes they break.
  762. // Instead we should just rely on the test above.
  763. Application.OnMouseEvent (new MouseEvent { X = 1, Y = 1, Flags = MouseFlags.Button1Pressed });
  764. Assert.Equal (win2.Border, Application.MouseGrabView);
  765. Application.RunIteration (ref rsOverlapped, ref firstIteration);
  766. Assert.Equal (win2, rsOverlapped.Toplevel);
  767. Assert.Equal (Application.Top, overlapped);
  768. Assert.Equal (Application.OverlappedTop, overlapped);
  769. Assert.Equal (Application.Current, rsWin2.Toplevel);
  770. Assert.Equal (win2, Application.Current);
  771. Assert.Equal (win1, rsWin1.Toplevel);
  772. Application.OnMouseEvent (new MouseEvent
  773. {
  774. X = 2,
  775. Y = 2,
  776. Flags = MouseFlags.Button1Pressed
  777. | MouseFlags.ReportMousePosition
  778. });
  779. Application.RunIteration (ref rsOverlapped, ref firstIteration);
  780. Assert.Equal (win2, rsOverlapped.Toplevel);
  781. Assert.Equal (Application.Top, overlapped);
  782. Assert.Equal (Application.OverlappedTop, overlapped);
  783. Assert.Equal (Application.Current, rsWin2.Toplevel);
  784. Assert.Equal (win2, Application.Current);
  785. Assert.Equal (win1, rsWin1.Toplevel);
  786. // Tests that rely on visuals are too fragile. If border style changes they break.
  787. // Instead we should just rely on the test above.
  788. // This will end the win2 and not the overlapped
  789. Application.End (rsOverlapped);
  790. // rsOverlapped has been disposed and Toplevel property is null
  791. // So we must use another valid RunState to iterate
  792. Application.RunIteration (ref rsWin1, ref firstIteration);
  793. #if DEBUG_IDISPOSABLE
  794. Assert.True (rsOverlapped.WasDisposed);
  795. #endif
  796. Assert.Null (rsOverlapped.Toplevel);
  797. Assert.Equal (Application.Top, overlapped);
  798. Assert.Equal (Application.OverlappedTop, overlapped);
  799. Assert.Equal (Application.Current, rsWin1.Toplevel);
  800. Assert.Equal (win1, Application.Current);
  801. Assert.Equal (win1, rsWin1.Toplevel);
  802. Application.End (rsWin1);
  803. // rsWin1 has been disposed and Toplevel property is null
  804. // So we must use another valid RunState to iterate
  805. Application.RunIteration (ref rsWin2, ref firstIteration);
  806. #if DEBUG_IDISPOSABLE
  807. Assert.True (rsOverlapped.WasDisposed);
  808. Assert.True (rsWin1.WasDisposed);
  809. #endif
  810. Assert.Null (rsOverlapped.Toplevel);
  811. Assert.Equal (Application.Top, overlapped);
  812. Assert.Equal (Application.OverlappedTop, overlapped);
  813. Assert.Equal (Application.Current, overlapped);
  814. Assert.Null (rsWin1.Toplevel);
  815. // See here that the only Toplevel that needs to End is the overlapped
  816. // which the rsWin2 now has the Toplevel set to the overlapped
  817. Assert.Equal (overlapped, rsWin2.Toplevel);
  818. Application.End (rsWin2);
  819. // There is no more RunState to iteration
  820. #if DEBUG_IDISPOSABLE
  821. Assert.True (rsOverlapped.WasDisposed);
  822. Assert.True (rsWin1.WasDisposed);
  823. Assert.True (rsWin2.WasDisposed);
  824. #endif
  825. Assert.Null (rsOverlapped.Toplevel);
  826. Assert.Equal (Application.Top, overlapped);
  827. Assert.Equal (Application.OverlappedTop, overlapped);
  828. Assert.Null (Application.Current);
  829. Assert.Null (rsWin1.Toplevel);
  830. Assert.Null (rsWin2.Toplevel);
  831. #if DEBUG_IDISPOSABLE
  832. Assert.False (win2.WasDisposed);
  833. Assert.False (win1.WasDisposed);
  834. Assert.False (overlapped.WasDisposed);
  835. #endif
  836. // Now dispose all them
  837. win2.Dispose ();
  838. win1.Dispose ();
  839. overlapped.Dispose ();
  840. Application.Shutdown ();
  841. }
  842. private class Overlapped : Toplevel
  843. {
  844. public Overlapped () { IsOverlappedContainer = true; }
  845. }
  846. }