PosTests.cs 37 KB

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