PosTests.cs 36 KB

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