PosTests.cs 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070
  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 ($"Pos.AnchorEnd(margin={n})", pos.ToString ());
  31. n = 5;
  32. pos = Pos.AnchorEnd (n);
  33. Assert.Equal ($"Pos.AnchorEnd(margin={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 = Terminal.Gui.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 = Terminal.Gui.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 = Terminal.Gui.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 = Terminal.Gui.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 ("Pos.Absolute(0)", pos.ToString ());
  310. pos = Pos.At (5);
  311. Assert.Equal ("Pos.Absolute(5)", pos.ToString ());
  312. pos = Pos.At (-1);
  313. Assert.Equal ("Pos.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 ($"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 ());
  357. pos = Pos.Left (new View (testRect));
  358. 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 ());
  359. testRect = new Rect (1, 2, 3, 4);
  360. pos = Pos.Left (new View (testRect));
  361. 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 ());
  362. // Pos.Left(win) + 0
  363. pos = Pos.Left (new View (testRect)) + testInt;
  364. 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 ());
  365. testInt = 1;
  366. // Pos.Left(win) +1
  367. pos = Pos.Left (new View (testRect)) + testInt;
  368. 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 ());
  369. testInt = -1;
  370. // Pos.Left(win) -1
  371. pos = Pos.Left (new View (testRect)) - testInt;
  372. 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 ());
  373. // Pos.X
  374. side = "x";
  375. testInt = 0;
  376. testRect = Rect.Empty;
  377. pos = Pos.X (new View ());
  378. 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 ());
  379. pos = Pos.X (new View (testRect));
  380. 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 ());
  381. testRect = new Rect (1, 2, 3, 4);
  382. pos = Pos.X (new View (testRect));
  383. 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 ());
  384. // Pos.X(win) + 0
  385. pos = Pos.X (new View (testRect)) + testInt;
  386. 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 ());
  387. testInt = 1;
  388. // Pos.X(win) +1
  389. pos = Pos.X (new View (testRect)) + testInt;
  390. 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 ());
  391. testInt = -1;
  392. // Pos.X(win) -1
  393. pos = Pos.X (new View (testRect)) - testInt;
  394. 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 ());
  395. // Pos.Top
  396. side = "y";
  397. testInt = 0;
  398. testRect = Rect.Empty;
  399. pos = Pos.Top (new View ());
  400. 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 ());
  401. pos = Pos.Top (new View (testRect));
  402. 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 ());
  403. testRect = new Rect (1, 2, 3, 4);
  404. pos = Pos.Top (new View (testRect));
  405. 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 ());
  406. // Pos.Top(win) + 0
  407. pos = Pos.Top (new View (testRect)) + testInt;
  408. 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 ());
  409. testInt = 1;
  410. // Pos.Top(win) +1
  411. pos = Pos.Top (new View (testRect)) + testInt;
  412. 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 ());
  413. testInt = -1;
  414. // Pos.Top(win) -1
  415. pos = Pos.Top (new View (testRect)) - testInt;
  416. 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 ());
  417. // Pos.Y
  418. side = "y";
  419. testInt = 0;
  420. testRect = Rect.Empty;
  421. pos = Pos.Y (new View ());
  422. 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 ());
  423. pos = Pos.Y (new View (testRect));
  424. 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 ());
  425. testRect = new Rect (1, 2, 3, 4);
  426. pos = Pos.Y (new View (testRect));
  427. 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 ());
  428. // Pos.Y(win) + 0
  429. pos = Pos.Y (new View (testRect)) + testInt;
  430. 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 ());
  431. testInt = 1;
  432. // Pos.Y(win) +1
  433. pos = Pos.Y (new View (testRect)) + testInt;
  434. 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 ());
  435. testInt = -1;
  436. // Pos.Y(win) -1
  437. pos = Pos.Y (new View (testRect)) - testInt;
  438. 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 ());
  439. // Pos.Bottom
  440. side = "bottom";
  441. testRect = Rect.Empty;
  442. testInt = 0;
  443. pos = Pos.Bottom (new View ());
  444. 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 ());
  445. pos = Pos.Bottom (new View (testRect));
  446. 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 ());
  447. testRect = new Rect (1, 2, 3, 4);
  448. pos = Pos.Bottom (new View (testRect));
  449. 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 ());
  450. // Pos.Bottom(win) + 0
  451. pos = Pos.Bottom (new View (testRect)) + testInt;
  452. 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 ());
  453. testInt = 1;
  454. // Pos.Bottom(win) +1
  455. pos = Pos.Bottom (new View (testRect)) + testInt;
  456. 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 ());
  457. testInt = -1;
  458. // Pos.Bottom(win) -1
  459. pos = Pos.Bottom (new View (testRect)) - testInt;
  460. 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 ());
  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 ("Pos.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 ($"Pos.Factor({f / 100:0.###})", pos.ToString ());
  544. f = 0.5F;
  545. pos = Pos.Percent (f);
  546. Assert.Equal ($"Pos.Factor({f / 100:0.###})", pos.ToString ());
  547. f = 100;
  548. pos = Pos.Percent (f);
  549. Assert.Equal ($"Pos.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 ($"Pos.Absolute({count})", label.Y.ToString ());
  738. Assert.Equal ($"Pos.Absolute({count})", field.Y.ToString ());
  739. field.Y += 1;
  740. count++;
  741. Assert.Equal ($"Pos.Absolute({count})", field.Y.ToString ());
  742. }
  743. };
  744. Application.Iteration += () => {
  745. while (count < 20) {
  746. field.OnKeyDown (new KeyEvent (Key.Enter, new KeyModifiers ()));
  747. }
  748. Application.RequestStop ();
  749. };
  750. var win = new Window ();
  751. win.Add (view);
  752. win.Add (field);
  753. top.Add (win);
  754. Application.Run (top);
  755. Assert.Equal (20, count);
  756. // Shutdown must be called to safely clean up Application if Init has been called
  757. Application.Shutdown ();
  758. }
  759. [Fact]
  760. public void Pos_Subtract_Operator ()
  761. {
  762. Application.Init (new FakeDriver ());
  763. var top = Application.Top;
  764. var view = new View () { X = 0, Y = 0, Width = 20, Height = 20 };
  765. var field = new TextField () { X = 0, Y = 0, Width = 20 };
  766. var count = 20;
  767. var listLabels = new List<Label> ();
  768. for (int i = 0; i < count; i++) {
  769. field.Text = $"Label {i}";
  770. var label = new Label (field.Text) { X = 0, Y = field.Y, Width = 20 };
  771. view.Add (label);
  772. Assert.Equal ($"Label {i}", label.Text);
  773. Assert.Equal ($"Pos.Absolute({i})", field.Y.ToString ());
  774. listLabels.Add (label);
  775. Assert.Equal ($"Pos.Absolute({i})", field.Y.ToString ());
  776. field.Y += 1;
  777. Assert.Equal ($"Pos.Absolute({i + 1})", field.Y.ToString ());
  778. }
  779. field.KeyDown += (k) => {
  780. if (k.KeyEvent.Key == Key.Enter) {
  781. Assert.Equal ($"Label {count - 1}", listLabels [count - 1].Text);
  782. view.Remove (listLabels [count - 1]);
  783. Assert.Equal ($"Pos.Absolute({count})", field.Y.ToString ());
  784. field.Y -= 1;
  785. count--;
  786. Assert.Equal ($"Pos.Absolute({count})", field.Y.ToString ());
  787. }
  788. };
  789. Application.Iteration += () => {
  790. while (count > 0) {
  791. field.OnKeyDown (new KeyEvent (Key.Enter, new KeyModifiers ()));
  792. }
  793. Application.RequestStop ();
  794. };
  795. var win = new Window ();
  796. win.Add (view);
  797. win.Add (field);
  798. top.Add (win);
  799. Application.Run (top);
  800. Assert.Equal (0, count);
  801. // Shutdown must be called to safely clean up Application if Init has been called
  802. Application.Shutdown ();
  803. }
  804. [Fact]
  805. public void Internal_Tests ()
  806. {
  807. var posFactor = new Pos.PosFactor (0.10F);
  808. Assert.Equal (10, posFactor.Anchor (100));
  809. var posAnchorEnd = new Pos.PosAnchorEnd (1);
  810. Assert.Equal (99, posAnchorEnd.Anchor (100));
  811. var posCenter = new Pos.PosCenter ();
  812. Assert.Equal (50, posCenter.Anchor (100));
  813. var posAbsolute = new Pos.PosAbsolute (10);
  814. Assert.Equal (10, posAbsolute.Anchor (0));
  815. var posCombine = new Pos.PosCombine (true, posFactor, posAbsolute);
  816. Assert.Equal (posCombine.left, posFactor);
  817. Assert.Equal (posCombine.right, posAbsolute);
  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 ("Pos.PosFunc(4)", pos.ToString ());
  835. text = "New Test";
  836. Assert.Equal ("Pos.PosFunc(8)", pos.ToString ());
  837. text = "";
  838. Assert.Equal ("Pos.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. }