PosTests.cs 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126
  1. using System;
  2. using System.Collections.Generic;
  3. using Xunit;
  4. using Xunit.Abstractions;
  5. // Alias Console to MockConsole so we don't accidentally use Console
  6. namespace Terminal.Gui.ViewTests;
  7. public class PosTests {
  8. readonly ITestOutputHelper _output;
  9. public PosTests (ITestOutputHelper output) => _output = output;
  10. [Fact]
  11. public void New_Works ()
  12. {
  13. var pos = new Pos ();
  14. Assert.Equal ("Terminal.Gui.Pos", pos.ToString ());
  15. }
  16. [Fact]
  17. public void AnchorEnd_SetsValue ()
  18. {
  19. int n = 0;
  20. var pos = Pos.AnchorEnd ();
  21. Assert.Equal ($"AnchorEnd({n})", pos.ToString ());
  22. n = 5;
  23. pos = Pos.AnchorEnd (n);
  24. Assert.Equal ($"AnchorEnd({n})", pos.ToString ());
  25. }
  26. [Fact]
  27. public void AnchorEnd_Equal ()
  28. {
  29. int n1 = 0;
  30. int n2 = 0;
  31. var pos1 = Pos.AnchorEnd (n1);
  32. var pos2 = Pos.AnchorEnd (n2);
  33. Assert.Equal (pos1, pos2);
  34. // Test inequality
  35. n2 = 5;
  36. pos2 = Pos.AnchorEnd (n2);
  37. Assert.NotEqual (pos1, pos2);
  38. }
  39. [Fact]
  40. [AutoInitShutdown]
  41. public void AnchorEnd_Equal_Inside_Window ()
  42. {
  43. int viewWidth = 10;
  44. int viewHeight = 1;
  45. var tv = new TextView () {
  46. X = Pos.AnchorEnd (viewWidth),
  47. Y = Pos.AnchorEnd (viewHeight),
  48. Width = viewWidth,
  49. Height = viewHeight
  50. };
  51. var win = new Window ();
  52. win.Add (tv);
  53. var top = Application.Top;
  54. top.Add (win);
  55. var rs = Application.Begin (top);
  56. Assert.Equal (new Rect (0, 0, 80, 25), top.Frame);
  57. Assert.Equal (new Rect (0, 0, 80, 25), win.Frame);
  58. Assert.Equal (new Rect (68, 22, 10, 1), tv.Frame);
  59. Application.End (rs);
  60. }
  61. [Fact]
  62. [AutoInitShutdown]
  63. public void AnchorEnd_Equal_Inside_Window_With_MenuBar_And_StatusBar_On_Toplevel ()
  64. {
  65. int viewWidth = 10;
  66. int viewHeight = 1;
  67. var tv = new TextView () {
  68. X = Pos.AnchorEnd (viewWidth),
  69. Y = Pos.AnchorEnd (viewHeight),
  70. Width = viewWidth,
  71. Height = viewHeight
  72. };
  73. var win = new Window ();
  74. win.Add (tv);
  75. var menu = new MenuBar ();
  76. var status = new StatusBar ();
  77. var top = Application.Top;
  78. top.Add (win, menu, status);
  79. var rs = Application.Begin (top);
  80. Assert.Equal (new Rect (0, 0, 80, 25), top.Frame);
  81. Assert.Equal (new Rect (0, 0, 80, 1), menu.Frame);
  82. Assert.Equal (new Rect (0, 24, 80, 1), status.Frame);
  83. Assert.Equal (new Rect (0, 1, 80, 23), win.Frame);
  84. Assert.Equal (new Rect (68, 20, 10, 1), tv.Frame);
  85. Application.End (rs);
  86. }
  87. [Fact]
  88. [AutoInitShutdown]
  89. public void Bottom_Equal_Inside_Window ()
  90. {
  91. var win = new Window ();
  92. var label = new Label ("This should be the last line.") {
  93. TextAlignment = TextAlignment.Centered,
  94. ColorScheme = Colors.Menu,
  95. Width = Dim.Fill (),
  96. X = Pos.Center (),
  97. Y = Pos.Bottom (win) - 3 // two lines top and bottom borders more one line above the bottom border
  98. };
  99. win.Add (label);
  100. var top = Application.Top;
  101. top.Add (win);
  102. var rs = Application.Begin (top);
  103. ((FakeDriver)Application.Driver).SetBufferSize (40, 10);
  104. Assert.True (label.AutoSize);
  105. Assert.Equal (new Rect (0, 0, 40, 10), top.Frame);
  106. Assert.Equal (new Rect (0, 0, 40, 10), win.Frame);
  107. Assert.Equal (new Rect (0, 7, 38, 1), label.Frame);
  108. string expected = @"
  109. ┌──────────────────────────────────────┐
  110. │ │
  111. │ │
  112. │ │
  113. │ │
  114. │ │
  115. │ │
  116. │ │
  117. │ This should be the last line. │
  118. └──────────────────────────────────────┘
  119. ";
  120. TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  121. Application.End (rs);
  122. }
  123. [Fact]
  124. [AutoInitShutdown]
  125. public void AnchorEnd_Better_Than_Bottom_Equal_Inside_Window ()
  126. {
  127. var win = new Window ();
  128. var label = new Label ("This should be the last line.") {
  129. TextAlignment = TextAlignment.Centered,
  130. ColorScheme = Colors.Menu,
  131. Width = Dim.Fill (),
  132. X = Pos.Center (),
  133. Y = Pos.AnchorEnd (1)
  134. };
  135. win.Add (label);
  136. var top = Application.Top;
  137. top.Add (win);
  138. var rs = Application.Begin (top);
  139. ((FakeDriver)Application.Driver).SetBufferSize (40, 10);
  140. Assert.True (label.AutoSize);
  141. Assert.Equal (29, label.Text.Length);
  142. Assert.Equal (new Rect (0, 0, 40, 10), top.Frame);
  143. Assert.Equal (new Rect (0, 0, 40, 10), win.Frame);
  144. Assert.Equal (new Rect (0, 7, 38, 1), label.Frame);
  145. string expected = @"
  146. ┌──────────────────────────────────────┐
  147. │ │
  148. │ │
  149. │ │
  150. │ │
  151. │ │
  152. │ │
  153. │ │
  154. │ This should be the last line. │
  155. └──────────────────────────────────────┘
  156. ";
  157. TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  158. Application.End (rs);
  159. }
  160. [Fact]
  161. [AutoInitShutdown]
  162. public void Bottom_Equal_Inside_Window_With_MenuBar_And_StatusBar_On_Toplevel ()
  163. {
  164. var win = new Window ();
  165. var label = new Label ("This should be the last line.") {
  166. TextAlignment = TextAlignment.Centered,
  167. ColorScheme = Colors.Menu,
  168. Width = Dim.Fill (),
  169. X = Pos.Center (),
  170. Y = Pos.Bottom (win) - 4 // two lines top and bottom borders more two lines above border
  171. };
  172. win.Add (label);
  173. var menu = new MenuBar (new MenuBarItem [] { new ("Menu", "", null) });
  174. var status = new StatusBar (new StatusItem [] { new (KeyCode.F1, "~F1~ Help", null) });
  175. var top = Application.Top;
  176. top.Add (win, menu, status);
  177. var rs = Application.Begin (top);
  178. Assert.True (label.AutoSize);
  179. Assert.Equal (new Rect (0, 0, 80, 25), top.Frame);
  180. Assert.Equal (new Rect (0, 0, 80, 1), menu.Frame);
  181. Assert.Equal (new Rect (0, 24, 80, 1), status.Frame);
  182. Assert.Equal (new Rect (0, 1, 80, 23), win.Frame);
  183. Assert.Equal (new Rect (0, 20, 78, 1), label.Frame);
  184. string expected = @"
  185. Menu
  186. ┌──────────────────────────────────────────────────────────────────────────────┐
  187. │ │
  188. │ │
  189. │ │
  190. │ │
  191. │ │
  192. │ │
  193. │ │
  194. │ │
  195. │ │
  196. │ │
  197. │ │
  198. │ │
  199. │ │
  200. │ │
  201. │ │
  202. │ │
  203. │ │
  204. │ │
  205. │ │
  206. │ │
  207. │ This should be the last line. │
  208. └──────────────────────────────────────────────────────────────────────────────┘
  209. F1 Help
  210. ";
  211. TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  212. Application.End (rs);
  213. }
  214. [Fact]
  215. [AutoInitShutdown]
  216. public void AnchorEnd_Better_Than_Bottom_Equal_Inside_Window_With_MenuBar_And_StatusBar_On_Toplevel ()
  217. {
  218. var win = new Window ();
  219. var label = new Label ("This should be the last line.") {
  220. TextAlignment = TextAlignment.Centered,
  221. ColorScheme = Colors.Menu,
  222. Width = Dim.Fill (),
  223. X = Pos.Center (),
  224. Y = Pos.AnchorEnd (1)
  225. };
  226. win.Add (label);
  227. var menu = new MenuBar (new MenuBarItem [] { new ("Menu", "", null) });
  228. var status = new StatusBar (new StatusItem [] { new (KeyCode.F1, "~F1~ Help", null) });
  229. var top = Application.Top;
  230. top.Add (win, menu, status);
  231. var rs = Application.Begin (top);
  232. Assert.True (label.AutoSize);
  233. Assert.Equal (new Rect (0, 0, 80, 25), top.Frame);
  234. Assert.Equal (new Rect (0, 0, 80, 1), menu.Frame);
  235. Assert.Equal (new Rect (0, 24, 80, 1), status.Frame);
  236. Assert.Equal (new Rect (0, 1, 80, 23), win.Frame);
  237. Assert.Equal (new Rect (0, 20, 78, 1), label.Frame);
  238. string expected = @"
  239. Menu
  240. ┌──────────────────────────────────────────────────────────────────────────────┐
  241. │ │
  242. │ │
  243. │ │
  244. │ │
  245. │ │
  246. │ │
  247. │ │
  248. │ │
  249. │ │
  250. │ │
  251. │ │
  252. │ │
  253. │ │
  254. │ │
  255. │ │
  256. │ │
  257. │ │
  258. │ │
  259. │ │
  260. │ │
  261. │ This should be the last line. │
  262. └──────────────────────────────────────────────────────────────────────────────┘
  263. F1 Help
  264. ";
  265. TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  266. Application.End (rs);
  267. }
  268. [Fact]
  269. public void AnchorEnd_Negative_Throws ()
  270. {
  271. Pos pos;
  272. int n = -1;
  273. Assert.Throws<ArgumentException> (() => pos = Pos.AnchorEnd (n));
  274. }
  275. [Fact]
  276. public void At_SetsValue ()
  277. {
  278. var pos = Pos.At (0);
  279. Assert.Equal ("Absolute(0)", pos.ToString ());
  280. pos = Pos.At (5);
  281. Assert.Equal ("Absolute(5)", pos.ToString ());
  282. pos = Pos.At (-1);
  283. Assert.Equal ("Absolute(-1)", pos.ToString ());
  284. }
  285. [Fact]
  286. public void At_Equal ()
  287. {
  288. int n1 = 0;
  289. int n2 = 0;
  290. var pos1 = Pos.At (n1);
  291. var pos2 = Pos.At (n2);
  292. Assert.Equal (pos1, pos2);
  293. }
  294. [Fact]
  295. public void SetSide_Null_Throws ()
  296. {
  297. var pos = Pos.Left (null);
  298. Assert.Throws<NullReferenceException> (() => pos.ToString ());
  299. pos = Pos.X (null);
  300. Assert.Throws<NullReferenceException> (() => pos.ToString ());
  301. pos = Pos.Top (null);
  302. Assert.Throws<NullReferenceException> (() => pos.ToString ());
  303. pos = Pos.Y (null);
  304. Assert.Throws<NullReferenceException> (() => pos.ToString ());
  305. pos = Pos.Bottom (null);
  306. Assert.Throws<NullReferenceException> (() => pos.ToString ());
  307. pos = Pos.Right (null);
  308. Assert.Throws<NullReferenceException> (() => pos.ToString ());
  309. }
  310. // TODO: Test Left, Top, Right bottom Equal
  311. /// <summary>
  312. /// Tests Pos.Left, Pos.X, Pos.Top, Pos.Y, Pos.Right, and Pos.Bottom set operations
  313. /// </summary>
  314. [Fact]
  315. [TestRespondersDisposed]
  316. public void PosSide_SetsValue ()
  317. {
  318. string side; // used in format string
  319. var testRect = Rect.Empty;
  320. int testInt = 0;
  321. Pos pos;
  322. // Pos.Left
  323. side = "x";
  324. testInt = 0;
  325. testRect = Rect.Empty;
  326. pos = Pos.Left (new View ());
  327. Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
  328. pos = Pos.Left (new View (testRect));
  329. Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
  330. testRect = new Rect (1, 2, 3, 4);
  331. pos = Pos.Left (new View (testRect));
  332. Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
  333. // Pos.Left(win) + 0
  334. pos = Pos.Left (new View (testRect)) + testInt;
  335. Assert.Equal ($"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
  336. testInt = 1;
  337. // Pos.Left(win) +1
  338. pos = Pos.Left (new View (testRect)) + testInt;
  339. Assert.Equal ($"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
  340. testInt = -1;
  341. // Pos.Left(win) -1
  342. pos = Pos.Left (new View (testRect)) - testInt;
  343. Assert.Equal ($"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
  344. // Pos.X
  345. side = "x";
  346. testInt = 0;
  347. testRect = Rect.Empty;
  348. pos = Pos.X (new View ());
  349. Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
  350. pos = Pos.X (new View (testRect));
  351. Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
  352. testRect = new Rect (1, 2, 3, 4);
  353. pos = Pos.X (new View (testRect));
  354. Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
  355. // Pos.X(win) + 0
  356. pos = Pos.X (new View (testRect)) + testInt;
  357. Assert.Equal ($"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
  358. testInt = 1;
  359. // Pos.X(win) +1
  360. pos = Pos.X (new View (testRect)) + testInt;
  361. Assert.Equal ($"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
  362. testInt = -1;
  363. // Pos.X(win) -1
  364. pos = Pos.X (new View (testRect)) - testInt;
  365. Assert.Equal ($"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
  366. // Pos.Top
  367. side = "y";
  368. testInt = 0;
  369. testRect = Rect.Empty;
  370. pos = Pos.Top (new View ());
  371. Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
  372. pos = Pos.Top (new View (testRect));
  373. Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
  374. testRect = new Rect (1, 2, 3, 4);
  375. pos = Pos.Top (new View (testRect));
  376. Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
  377. // Pos.Top(win) + 0
  378. pos = Pos.Top (new View (testRect)) + testInt;
  379. Assert.Equal ($"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
  380. testInt = 1;
  381. // Pos.Top(win) +1
  382. pos = Pos.Top (new View (testRect)) + testInt;
  383. Assert.Equal ($"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
  384. testInt = -1;
  385. // Pos.Top(win) -1
  386. pos = Pos.Top (new View (testRect)) - testInt;
  387. Assert.Equal ($"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
  388. // Pos.Y
  389. side = "y";
  390. testInt = 0;
  391. testRect = Rect.Empty;
  392. pos = Pos.Y (new View ());
  393. Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
  394. pos = Pos.Y (new View (testRect));
  395. Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
  396. testRect = new Rect (1, 2, 3, 4);
  397. pos = Pos.Y (new View (testRect));
  398. Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
  399. // Pos.Y(win) + 0
  400. pos = Pos.Y (new View (testRect)) + testInt;
  401. Assert.Equal ($"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
  402. testInt = 1;
  403. // Pos.Y(win) +1
  404. pos = Pos.Y (new View (testRect)) + testInt;
  405. Assert.Equal ($"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
  406. testInt = -1;
  407. // Pos.Y(win) -1
  408. pos = Pos.Y (new View (testRect)) - testInt;
  409. Assert.Equal ($"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
  410. // Pos.Bottom
  411. side = "bottom";
  412. testRect = Rect.Empty;
  413. testInt = 0;
  414. pos = Pos.Bottom (new View ());
  415. Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
  416. pos = Pos.Bottom (new View (testRect));
  417. Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
  418. testRect = new Rect (1, 2, 3, 4);
  419. pos = Pos.Bottom (new View (testRect));
  420. Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
  421. // Pos.Bottom(win) + 0
  422. pos = Pos.Bottom (new View (testRect)) + testInt;
  423. Assert.Equal ($"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
  424. testInt = 1;
  425. // Pos.Bottom(win) +1
  426. pos = Pos.Bottom (new View (testRect)) + testInt;
  427. Assert.Equal ($"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
  428. testInt = -1;
  429. // Pos.Bottom(win) -1
  430. pos = Pos.Bottom (new View (testRect)) - testInt;
  431. Assert.Equal ($"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
  432. #if DEBUG_IDISPOSABLE
  433. // HACK: Force clean up of Responders to avoid having to Dispose all the Views created above.
  434. Responder.Instances.Clear ();
  435. #endif
  436. }
  437. // See: https://github.com/gui-cs/Terminal.Gui/issues/504
  438. [Fact]
  439. [TestRespondersDisposed]
  440. public void LeftTopBottomRight_Win_ShouldNotThrow ()
  441. {
  442. // Setup Fake driver
  443. (Window win, Button button) setup ()
  444. {
  445. Application.Init (new FakeDriver ());
  446. Application.Iteration += (s, a) => {
  447. Application.RequestStop ();
  448. };
  449. var win = new Window () {
  450. X = 0,
  451. Y = 0,
  452. Width = Dim.Fill (),
  453. Height = Dim.Fill ()
  454. };
  455. Application.Top.Add (win);
  456. var button = new Button ("button") {
  457. X = Pos.Center ()
  458. };
  459. win.Add (button);
  460. return (win, button);
  461. }
  462. RunState rs;
  463. void cleanup (RunState rs)
  464. {
  465. // Cleanup
  466. Application.End (rs);
  467. // Shutdown must be called to safely clean up Application if Init has been called
  468. Application.Shutdown ();
  469. }
  470. // Test cases:
  471. var app = setup ();
  472. app.button.Y = Pos.Left (app.win);
  473. rs = Application.Begin (Application.Top);
  474. // If Application.RunState is used then we must use Application.RunLoop with the rs parameter
  475. Application.RunLoop (rs);
  476. cleanup (rs);
  477. app = setup ();
  478. app.button.Y = Pos.X (app.win);
  479. rs = Application.Begin (Application.Top);
  480. // If Application.RunState is used then we must use Application.RunLoop with the rs parameter
  481. Application.RunLoop (rs);
  482. cleanup (rs);
  483. app = setup ();
  484. app.button.Y = Pos.Top (app.win);
  485. rs = Application.Begin (Application.Top);
  486. // If Application.RunState is used then we must use Application.RunLoop with the rs parameter
  487. Application.RunLoop (rs);
  488. cleanup (rs);
  489. app = setup ();
  490. app.button.Y = Pos.Y (app.win);
  491. rs = Application.Begin (Application.Top);
  492. // If Application.RunState is used then we must use Application.RunLoop with the rs parameter
  493. Application.RunLoop (rs);
  494. cleanup (rs);
  495. app = setup ();
  496. app.button.Y = Pos.Bottom (app.win);
  497. rs = Application.Begin (Application.Top);
  498. // If Application.RunState is used then we must use Application.RunLoop with the rs parameter
  499. Application.RunLoop (rs);
  500. cleanup (rs);
  501. app = setup ();
  502. app.button.Y = Pos.Right (app.win);
  503. rs = Application.Begin (Application.Top);
  504. // If Application.RunState is used then we must use Application.RunLoop with the rs parameter
  505. Application.RunLoop (rs);
  506. cleanup (rs);
  507. }
  508. [Fact]
  509. public void Center_SetsValue ()
  510. {
  511. var pos = Pos.Center ();
  512. Assert.Equal ("Center", pos.ToString ());
  513. }
  514. [Fact]
  515. public void Percent_SetsValue ()
  516. {
  517. float f = 0;
  518. var pos = Pos.Percent (f);
  519. Assert.Equal ($"Factor({f / 100:0.###})", pos.ToString ());
  520. f = 0.5F;
  521. pos = Pos.Percent (f);
  522. Assert.Equal ($"Factor({f / 100:0.###})", pos.ToString ());
  523. f = 100;
  524. pos = Pos.Percent (f);
  525. Assert.Equal ($"Factor({f / 100:0.###})", pos.ToString ());
  526. }
  527. [Fact]
  528. public void Percent_Equal ()
  529. {
  530. float n1 = 0;
  531. float n2 = 0;
  532. var pos1 = Pos.Percent (n1);
  533. var pos2 = Pos.Percent (n2);
  534. Assert.Equal (pos1, pos2);
  535. n1 = n2 = 1;
  536. pos1 = Pos.Percent (n1);
  537. pos2 = Pos.Percent (n2);
  538. Assert.Equal (pos1, pos2);
  539. n1 = n2 = 0.5f;
  540. pos1 = Pos.Percent (n1);
  541. pos2 = Pos.Percent (n2);
  542. Assert.Equal (pos1, pos2);
  543. n1 = n2 = 100f;
  544. pos1 = Pos.Percent (n1);
  545. pos2 = Pos.Percent (n2);
  546. Assert.Equal (pos1, pos2);
  547. n1 = 0;
  548. n2 = 1;
  549. pos1 = Pos.Percent (n1);
  550. pos2 = Pos.Percent (n2);
  551. Assert.NotEqual (pos1, pos2);
  552. n1 = 0.5f;
  553. n2 = 1.5f;
  554. pos1 = Pos.Percent (n1);
  555. pos2 = Pos.Percent (n2);
  556. Assert.NotEqual (pos1, pos2);
  557. }
  558. [Fact]
  559. public void Percent_ThrowsOnIvalid ()
  560. {
  561. var pos = Pos.Percent (0);
  562. Assert.Throws<ArgumentException> (() => pos = Pos.Percent (-1));
  563. Assert.Throws<ArgumentException> (() => pos = Pos.Percent (101));
  564. Assert.Throws<ArgumentException> (() => pos = Pos.Percent (100.0001F));
  565. Assert.Throws<ArgumentException> (() => pos = Pos.Percent (1000001));
  566. }
  567. [Fact]
  568. public void ForceValidatePosDim_True_Pos_Validation_Throws_If_NewValue_Is_PosAbsolute_And_OldValue_Is_Another_Type ()
  569. {
  570. Application.Init (new FakeDriver ());
  571. var t = Application.Top;
  572. var w = new Window () {
  573. X = Pos.Left (t) + 2,
  574. Y = Pos.At (2)
  575. };
  576. var v = new View () {
  577. X = Pos.Center (),
  578. Y = Pos.Percent (10),
  579. ValidatePosDim = true
  580. };
  581. w.Add (v);
  582. t.Add (w);
  583. t.Ready += (s, e) => {
  584. Assert.Equal (2, w.X = 2);
  585. Assert.Equal (2, w.Y = 2);
  586. Assert.Throws<ArgumentException> (() => v.X = 2);
  587. Assert.Throws<ArgumentException> (() => v.Y = 2);
  588. };
  589. Application.Iteration += (s, a) => Application.RequestStop ();
  590. Application.Run ();
  591. Application.Shutdown ();
  592. }
  593. [Fact]
  594. public void Pos_Validation_Do_Not_Throws_If_NewValue_Is_PosAbsolute_And_OldValue_Is_Null ()
  595. {
  596. Application.Init (new FakeDriver ());
  597. var t = Application.Top;
  598. var w = new Window (new Rect (1, 2, 4, 5));
  599. t.Add (w);
  600. t.Ready += (s, e) => {
  601. Assert.Equal (2, w.X = 2);
  602. Assert.Equal (2, w.Y = 2);
  603. };
  604. Application.Iteration += (s, a) => Application.RequestStop ();
  605. Application.Run ();
  606. Application.Shutdown ();
  607. }
  608. [Fact]
  609. public void Pos_Validation_Do_Not_Throws_If_NewValue_Is_PosAbsolute_And_OldValue_Is_Another_Type_After_Sets_To_LayoutStyle_Absolute ()
  610. {
  611. Application.Init (new FakeDriver ());
  612. var t = Application.Top;
  613. var w = new Window () {
  614. X = Pos.Left (t) + 2,
  615. Y = Pos.At (2)
  616. };
  617. var v = new View () {
  618. X = Pos.Center (),
  619. Y = Pos.Percent (10)
  620. };
  621. w.Add (v);
  622. t.Add (w);
  623. t.Ready += (s, e) => {
  624. v.LayoutStyle = LayoutStyle.Absolute;
  625. Assert.Equal (2, v.X = 2);
  626. Assert.Equal (2, v.Y = 2);
  627. };
  628. Application.Iteration += (s, a) => Application.RequestStop ();
  629. Application.Run ();
  630. Application.Shutdown ();
  631. }
  632. // DONE: Test PosCombine
  633. // DONE: Test operators
  634. // BUGBUG: v2 - This test is bogus. v1 and references it's superview's (f) superview (w).
  635. //[Fact]
  636. //public void PosCombine_Do_Not_Throws ()
  637. //{
  638. // Application.Init (new FakeDriver ());
  639. // var w = new Window () {
  640. // X = Pos.Left (Application.Top) + 2,
  641. // Y = Pos.Top (Application.Top) + 2
  642. // };
  643. // var f = new FrameView ();
  644. // var v1 = new View () {
  645. // X = Pos.Left (w) + 2,
  646. // Y = Pos.Top (w) + 2
  647. // };
  648. // var v2 = new View () {
  649. // X = Pos.Left (v1) + 2,
  650. // Y = Pos.Top (v1) + 2
  651. // };
  652. // f.Add (v1, v2);
  653. // w.Add (f);
  654. // Application.Top.Add (w);
  655. // f.X = Pos.X (Application.Top) + Pos.X (v2) - Pos.X (v1);
  656. // f.Y = Pos.Y (Application.Top) + Pos.Y (v2) - Pos.Y (v1);
  657. // Application.Top.LayoutComplete += (s, e) => {
  658. // Assert.Equal (0, Application.Top.Frame.X);
  659. // Assert.Equal (0, Application.Top.Frame.Y);
  660. // Assert.Equal (2, w.Frame.X);
  661. // Assert.Equal (2, w.Frame.Y);
  662. // Assert.Equal (2, f.Frame.X);
  663. // Assert.Equal (2, f.Frame.Y);
  664. // Assert.Equal (4, v1.Frame.X);
  665. // Assert.Equal (4, v1.Frame.Y);
  666. // Assert.Equal (6, v2.Frame.X);
  667. // Assert.Equal (6, v2.Frame.Y);
  668. // };
  669. // Application.Iteration += (s, a) => Application.RequestStop ();
  670. // Application.Run ();
  671. // Application.Shutdown ();
  672. //}
  673. [Fact]
  674. [TestRespondersDisposed]
  675. public void PosCombine_Will_Throws ()
  676. {
  677. Application.Init (new FakeDriver ());
  678. var t = Application.Top;
  679. var w = new Window () {
  680. X = Pos.Left (t) + 2,
  681. Y = Pos.Top (t) + 2
  682. };
  683. var f = new FrameView ();
  684. var v1 = new View () {
  685. X = Pos.Left (w) + 2,
  686. Y = Pos.Top (w) + 2
  687. };
  688. var v2 = new View () {
  689. X = Pos.Left (v1) + 2,
  690. Y = Pos.Top (v1) + 2
  691. };
  692. f.Add (v1); // v2 not added
  693. w.Add (f);
  694. t.Add (w);
  695. f.X = Pos.X (v2) - Pos.X (v1);
  696. f.Y = Pos.Y (v2) - Pos.Y (v1);
  697. Assert.Throws<InvalidOperationException> (() => Application.Run ());
  698. Application.Shutdown ();
  699. v2.Dispose ();
  700. }
  701. [Fact]
  702. [TestRespondersDisposed]
  703. public void Pos_Add_Operator ()
  704. {
  705. Application.Init (new FakeDriver ());
  706. var top = Application.Top;
  707. var view = new View () { X = 0, Y = 0, Width = 20, Height = 20 };
  708. var field = new TextField () { X = 0, Y = 0, Width = 20 };
  709. int count = 0;
  710. field.KeyDown += (s, k) => {
  711. if (k.KeyCode == KeyCode.Enter) {
  712. field.Text = $"Label {count}";
  713. var label = new Label (field.Text) { X = 0, Y = field.Y, Width = 20 };
  714. view.Add (label);
  715. Assert.Equal ($"Label {count}", label.Text);
  716. Assert.Equal ($"Absolute({count})", label.Y.ToString ());
  717. Assert.Equal ($"Absolute({count})", field.Y.ToString ());
  718. field.Y += 1;
  719. count++;
  720. Assert.Equal ($"Absolute({count})", field.Y.ToString ());
  721. }
  722. };
  723. Application.Iteration += (s, a) => {
  724. while (count < 20) {
  725. field.NewKeyDownEvent (new Key (KeyCode.Enter));
  726. }
  727. Application.RequestStop ();
  728. };
  729. var win = new Window ();
  730. win.Add (view);
  731. win.Add (field);
  732. top.Add (win);
  733. Application.Run (top);
  734. Assert.Equal (20, count);
  735. // Shutdown must be called to safely clean up Application if Init has been called
  736. Application.Shutdown ();
  737. }
  738. [Fact]
  739. [TestRespondersDisposed]
  740. public void Pos_Subtract_Operator ()
  741. {
  742. Application.Init (new FakeDriver ());
  743. var top = Application.Top;
  744. var view = new View () { X = 0, Y = 0, Width = 20, Height = 20 };
  745. var field = new TextField () { X = 0, Y = 0, Width = 20 };
  746. int count = 20;
  747. var listLabels = new List<Label> ();
  748. for (int i = 0; i < count; i++) {
  749. field.Text = $"Label {i}";
  750. var label = new Label (field.Text) { X = 0, Y = field.Y, Width = 20 };
  751. view.Add (label);
  752. Assert.Equal ($"Label {i}", label.Text);
  753. Assert.Equal ($"Absolute({i})", field.Y.ToString ());
  754. listLabels.Add (label);
  755. Assert.Equal ($"Absolute({i})", field.Y.ToString ());
  756. field.Y += 1;
  757. Assert.Equal ($"Absolute({i + 1})", field.Y.ToString ());
  758. }
  759. field.KeyDown += (s, k) => {
  760. if (k.KeyCode == KeyCode.Enter) {
  761. Assert.Equal ($"Label {count - 1}", listLabels [count - 1].Text);
  762. view.Remove (listLabels [count - 1]);
  763. listLabels [count - 1].Dispose ();
  764. Assert.Equal ($"Absolute({count})", field.Y.ToString ());
  765. field.Y -= 1;
  766. count--;
  767. Assert.Equal ($"Absolute({count})", field.Y.ToString ());
  768. }
  769. };
  770. Application.Iteration += (s, a) => {
  771. while (count > 0) {
  772. field.NewKeyDownEvent (new Key (KeyCode.Enter));
  773. }
  774. Application.RequestStop ();
  775. };
  776. var win = new Window ();
  777. win.Add (view);
  778. win.Add (field);
  779. top.Add (win);
  780. Application.Run (top);
  781. Assert.Equal (0, count);
  782. // Shutdown must be called to safely clean up Application if Init has been called
  783. Application.Shutdown ();
  784. }
  785. [Fact]
  786. [TestRespondersDisposed]
  787. public void Internal_Tests ()
  788. {
  789. var posFactor = new Pos.PosFactor (0.10F);
  790. Assert.Equal (10, posFactor.Anchor (100));
  791. var posAnchorEnd = new Pos.PosAnchorEnd (1);
  792. Assert.Equal (99, posAnchorEnd.Anchor (100));
  793. var posCenter = new Pos.PosCenter ();
  794. Assert.Equal (50, posCenter.Anchor (100));
  795. var posAbsolute = new Pos.PosAbsolute (10);
  796. Assert.Equal (10, posAbsolute.Anchor (0));
  797. var posCombine = new Pos.PosCombine (true, posFactor, posAbsolute);
  798. Assert.Equal (posCombine._left, posFactor);
  799. Assert.Equal (posCombine._right, posAbsolute);
  800. Assert.Equal (20, posCombine.Anchor (100));
  801. posCombine = new Pos.PosCombine (true, posAbsolute, posFactor);
  802. Assert.Equal (posCombine._left, posAbsolute);
  803. Assert.Equal (posCombine._right, posFactor);
  804. Assert.Equal (20, posCombine.Anchor (100));
  805. var view = new View (new Rect (20, 10, 20, 1));
  806. var posViewX = new Pos.PosView (view, 0);
  807. Assert.Equal (20, posViewX.Anchor (0));
  808. var posViewY = new Pos.PosView (view, 1);
  809. Assert.Equal (10, posViewY.Anchor (0));
  810. var posRight = new Pos.PosView (view, 2);
  811. Assert.Equal (40, posRight.Anchor (0));
  812. var posViewBottom = new Pos.PosView (view, 3);
  813. Assert.Equal (11, posViewBottom.Anchor (0));
  814. view.Dispose ();
  815. }
  816. [Fact]
  817. public void Function_SetsValue ()
  818. {
  819. string text = "Test";
  820. var pos = Pos.Function (() => text.Length);
  821. Assert.Equal ("PosFunc(4)", pos.ToString ());
  822. text = "New Test";
  823. Assert.Equal ("PosFunc(8)", pos.ToString ());
  824. text = "";
  825. Assert.Equal ("PosFunc(0)", pos.ToString ());
  826. }
  827. [Fact]
  828. public void Function_Equal ()
  829. {
  830. var f1 = () => 0;
  831. var f2 = () => 0;
  832. var pos1 = Pos.Function (f1);
  833. var pos2 = Pos.Function (f2);
  834. Assert.Equal (pos1, pos2);
  835. f2 = () => 1;
  836. pos2 = Pos.Function (f2);
  837. Assert.NotEqual (pos1, pos2);
  838. }
  839. [Theory]
  840. [AutoInitShutdown]
  841. [InlineData (true)]
  842. [InlineData (false)]
  843. public void PosPercentPlusOne (bool testHorizontal)
  844. {
  845. var container = new View {
  846. Width = 100,
  847. Height = 100
  848. };
  849. var label = new Label {
  850. X = testHorizontal ? Pos.Percent (50) + Pos.Percent (10) + 1 : 1,
  851. Y = testHorizontal ? 1 : Pos.Percent (50) + Pos.Percent (10) + 1,
  852. Width = 10,
  853. Height = 10
  854. };
  855. container.Add (label);
  856. Application.Top.Add (container);
  857. Application.Top.LayoutSubviews ();
  858. Assert.Equal (100, container.Frame.Width);
  859. Assert.Equal (100, container.Frame.Height);
  860. if (testHorizontal) {
  861. Assert.Equal (61, label.Frame.X);
  862. Assert.Equal (1, label.Frame.Y);
  863. } else {
  864. Assert.Equal (1, label.Frame.X);
  865. Assert.Equal (61, label.Frame.Y);
  866. }
  867. }
  868. [Fact]
  869. public void PosCombine_Referencing_Same_View ()
  870. {
  871. var super = new View ("super") {
  872. Width = 10,
  873. Height = 10
  874. };
  875. var view1 = new View ("view1") {
  876. Width = 2,
  877. Height = 2
  878. };
  879. var view2 = new View ("view2") {
  880. Width = 2,
  881. Height = 2
  882. };
  883. view2.X = Pos.AnchorEnd () - (Pos.Right (view2) - Pos.Left (view2));
  884. super.Add (view1, view2);
  885. super.BeginInit ();
  886. super.EndInit ();
  887. var exception = Record.Exception (super.LayoutSubviews);
  888. Assert.Null (exception);
  889. Assert.Equal (new Rect (0, 0, 10, 10), super.Frame);
  890. Assert.Equal (new Rect (0, 0, 2, 2), view1.Frame);
  891. Assert.Equal (new Rect (8, 0, 2, 2), view2.Frame);
  892. super.Dispose ();
  893. }
  894. [Fact]
  895. public void DoNotReturnPosCombine ()
  896. {
  897. var v = new View () { Id = "V" };
  898. var pos = Pos.Left (v);
  899. Assert.Equal (
  900. "View(side=x,target=View(V)(0,0,0,0))",
  901. pos.ToString ());
  902. pos = Pos.X (v);
  903. Assert.Equal (
  904. "View(side=x,target=View(V)(0,0,0,0))",
  905. pos.ToString ());
  906. pos = Pos.Top (v);
  907. Assert.Equal (
  908. "View(side=y,target=View(V)(0,0,0,0))",
  909. pos.ToString ());
  910. pos = Pos.Y (v);
  911. Assert.Equal (
  912. "View(side=y,target=View(V)(0,0,0,0))",
  913. pos.ToString ());
  914. pos = Pos.Right (v);
  915. Assert.Equal (
  916. "View(side=right,target=View(V)(0,0,0,0))",
  917. pos.ToString ());
  918. pos = Pos.Bottom (v);
  919. Assert.Equal (
  920. "View(side=bottom,target=View(V)(0,0,0,0))",
  921. pos.ToString ());
  922. }
  923. }