DimAutoTests.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. using System;
  2. using System.Globalization;
  3. using System.Threading;
  4. using Xunit;
  5. using Xunit.Abstractions;
  6. // Alias Console to MockConsole so we don't accidentally use Console
  7. using Console = Terminal.Gui.FakeConsole;
  8. namespace Terminal.Gui.ViewTests;
  9. public class DimAutoTests {
  10. readonly ITestOutputHelper _output;
  11. public DimAutoTests (ITestOutputHelper output)
  12. {
  13. _output = output;
  14. Console.OutputEncoding = System.Text.Encoding.Default;
  15. // Change current culture
  16. var culture = CultureInfo.CreateSpecificCulture ("en-US");
  17. Thread.CurrentThread.CurrentCulture = culture;
  18. Thread.CurrentThread.CurrentUICulture = culture;
  19. }
  20. [Fact]
  21. public void NoSubViews_Does_Nothing ()
  22. {
  23. var superView = new View () {
  24. X = 0,
  25. Y = 0,
  26. Width = Dim.Auto (),
  27. Height = Dim.Auto (),
  28. ValidatePosDim = true,
  29. };
  30. superView.BeginInit ();
  31. superView.EndInit ();
  32. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  33. Assert.Equal (new Rect (0, 0, 0, 0), superView.Frame);
  34. superView.SetRelativeLayout (new Rect (0, 0, 10, 10));
  35. Assert.Equal (new Rect (0, 0, 0, 0), superView.Frame);
  36. superView.SetRelativeLayout (new Rect (10, 10, 10, 10));
  37. Assert.Equal (new Rect (0, 0, 0, 0), superView.Frame);
  38. }
  39. [Theory]
  40. [InlineData (0, 0, 0, 0, 0, 0)]
  41. [InlineData (0, 0, 5, 0, 5, 0)]
  42. [InlineData (0, 0, 0, 5, 0, 5)]
  43. [InlineData (0, 0, 5, 5, 5, 5)]
  44. [InlineData (1, 0, 5, 0, 6, 0)]
  45. [InlineData (1, 0, 0, 5, 1, 5)]
  46. [InlineData (1, 0, 5, 5, 6, 5)]
  47. [InlineData (1, 1, 5, 5, 6, 6)]
  48. [InlineData (-1, 0, 5, 0, 4, 0)]
  49. [InlineData (-1, 0, 0, 5, 0, 5)]
  50. [InlineData (-1, 0, 5, 5, 4, 5)]
  51. [InlineData (-1, -1, 5, 5, 4, 4)]
  52. public void SubView_ChangesSuperViewSize (int subX, int subY, int subWidth, int subHeight, int expectedWidth, int expectedHeight)
  53. {
  54. var superView = new View () {
  55. X = 0,
  56. Y = 0,
  57. Width = Dim.Auto (),
  58. Height = Dim.Auto (),
  59. ValidatePosDim = true,
  60. };
  61. var subView = new View () {
  62. X = subX,
  63. Y = subY,
  64. Width = subWidth,
  65. Height = subHeight,
  66. ValidatePosDim = true,
  67. };
  68. superView.Add (subView);
  69. superView.BeginInit ();
  70. superView.EndInit ();
  71. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  72. Assert.Equal (new Rect (0, 0, expectedWidth, expectedHeight), superView.Frame);
  73. }
  74. [Theory]
  75. [InlineData (0, 0, 0, 0, 0)]
  76. [InlineData (0, 0, 5, 0, 5)]
  77. [InlineData (0, 0, 0, 5, 0)]
  78. [InlineData (0, 0, 5, 5, 5)]
  79. [InlineData (1, 0, 5, 0, 6)]
  80. [InlineData (1, 0, 0, 5, 1)]
  81. [InlineData (1, 0, 5, 5, 6)]
  82. [InlineData (1, 1, 5, 5, 6)]
  83. [InlineData (-1, 0, 5, 0, 4)]
  84. [InlineData (-1, 0, 0, 5, 0)]
  85. [InlineData (-1, 0, 5, 5, 4)]
  86. [InlineData (-1, -1, 5, 5, 4)]
  87. public void Width_Auto_Height_NotChanged (int subX, int subY, int subWidth, int subHeight, int expectedWidth)
  88. {
  89. var superView = new View () {
  90. X = 0,
  91. Y = 0,
  92. Width = Dim.Auto (),
  93. Height = 10,
  94. ValidatePosDim = true,
  95. };
  96. var subView = new View () {
  97. X = subX,
  98. Y = subY,
  99. Width = subWidth,
  100. Height = subHeight,
  101. ValidatePosDim = true,
  102. };
  103. superView.Add (subView);
  104. superView.BeginInit ();
  105. superView.EndInit ();
  106. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  107. Assert.Equal (new Rect (0, 0, expectedWidth, 10), superView.Frame);
  108. }
  109. [Theory]
  110. [InlineData (0, 0, 0, 0, 0)]
  111. [InlineData (0, 0, 5, 0, 0)]
  112. [InlineData (0, 0, 0, 5, 5)]
  113. [InlineData (0, 0, 5, 5, 5)]
  114. [InlineData (1, 0, 5, 0, 0)]
  115. [InlineData (1, 0, 0, 5, 5)]
  116. [InlineData (1, 0, 5, 5, 5)]
  117. [InlineData (1, 1, 5, 5, 6)]
  118. [InlineData (-1, 0, 5, 0, 0)]
  119. [InlineData (-1, 0, 0, 5, 5)]
  120. [InlineData (-1, 0, 5, 5, 5)]
  121. [InlineData (-1, -1, 5, 5, 4)]
  122. public void Height_Auto_Width_NotChanged (int subX, int subY, int subWidth, int subHeight, int expectedHeight)
  123. {
  124. var superView = new View () {
  125. X = 0,
  126. Y = 0,
  127. Width = 10,
  128. Height = Dim.Auto (),
  129. ValidatePosDim = true,
  130. };
  131. var subView = new View () {
  132. X = subX,
  133. Y = subY,
  134. Width = subWidth,
  135. Height = subHeight,
  136. ValidatePosDim = true,
  137. };
  138. superView.Add (subView);
  139. superView.BeginInit ();
  140. superView.EndInit ();
  141. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  142. Assert.Equal (new Rect (0, 0, 10, expectedHeight), superView.Frame);
  143. }
  144. // Test validation
  145. [Fact]
  146. public void ValidatePosDim_True_Throws_When_SubView_Uses_SuperView_Dims ()
  147. {
  148. var superView = new View () {
  149. X = 0,
  150. Y = 0,
  151. Width = Dim.Auto (),
  152. Height = Dim.Auto (),
  153. ValidatePosDim = true,
  154. };
  155. var subView = new View () {
  156. X = 0,
  157. Y = 0,
  158. Width = Dim.Fill (),
  159. Height = 10
  160. };
  161. Assert.Throws<InvalidOperationException> (() => superView.Add (subView));
  162. subView.Width = 10;
  163. superView.Add (subView);
  164. superView.BeginInit ();
  165. superView.EndInit ();
  166. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  167. superView.LayoutSubviews (); // no throw
  168. Assert.Throws<InvalidOperationException> (() => subView.Width = Dim.Fill ());
  169. subView.Width = 10;
  170. Assert.Throws<InvalidOperationException> (() => subView.Height = Dim.Fill ());
  171. subView.Height = 10;
  172. Assert.Throws<InvalidOperationException> (() => subView.Height = Dim.Percent (50));
  173. subView.Height = 10;
  174. Assert.Throws<InvalidOperationException> (() => subView.X = Pos.Center ());
  175. subView.X = 0;
  176. Assert.Throws<InvalidOperationException> (() => subView.Y = Pos.Center ());
  177. subView.Y = 0;
  178. subView.Width = 10;
  179. subView.Height = 10;
  180. subView.X = 0;
  181. subView.Y = 0;
  182. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  183. superView.LayoutSubviews ();
  184. }
  185. // Test validation
  186. [Fact]
  187. public void ValidatePosDim_True_Throws_When_SubView_Uses_SuperView_Dims_Combine ()
  188. {
  189. var superView = new View () {
  190. X = 0,
  191. Y = 0,
  192. Width = Dim.Auto (),
  193. Height = Dim.Auto (),
  194. ValidatePosDim = true,
  195. };
  196. var subView = new View () {
  197. X = 0,
  198. Y = 0,
  199. Width = 10,
  200. Height = 10
  201. };
  202. var subView2 = new View () {
  203. X = 0,
  204. Y = 0,
  205. Width = 10,
  206. Height = 10
  207. };
  208. superView.Add (subView, subView2);
  209. superView.BeginInit ();
  210. superView.EndInit ();
  211. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  212. superView.LayoutSubviews (); // no throw
  213. Assert.Throws<InvalidOperationException> (() => subView.Height = Dim.Fill () + 3);
  214. subView.Height = 0;
  215. Assert.Throws<InvalidOperationException> (() => subView.Height = 3 + Dim.Fill ());
  216. subView.Height = 0;
  217. Assert.Throws<InvalidOperationException> (() => subView.Height = 3 + 5 + Dim.Fill ());
  218. subView.Height = 0;
  219. Assert.Throws<InvalidOperationException> (() => subView.Height = 3 + 5 + Dim.Percent (10));
  220. subView.Height = 0;
  221. // Tests nested Combine
  222. Assert.Throws<InvalidOperationException> (() => subView.Height = 5 + new Dim.DimCombine (true, 3, new Dim.DimCombine (true, Dim.Percent (10), 9)));
  223. }
  224. [Fact]
  225. public void ValidatePosDim_True_Throws_When_SubView_Uses_SuperView_Pos_Combine ()
  226. {
  227. var superView = new View () {
  228. X = 0,
  229. Y = 0,
  230. Width = Dim.Auto (),
  231. Height = Dim.Auto (),
  232. ValidatePosDim = true,
  233. };
  234. var subView = new View () {
  235. X = 0,
  236. Y = 0,
  237. Width = 10,
  238. Height = 10
  239. };
  240. var subView2 = new View () {
  241. X = 0,
  242. Y = 0,
  243. Width = 10,
  244. Height = 10
  245. };
  246. superView.Add (subView, subView2);
  247. superView.BeginInit ();
  248. superView.EndInit ();
  249. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  250. superView.LayoutSubviews (); // no throw
  251. subView.X = Pos.Right (subView2);
  252. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  253. superView.LayoutSubviews (); // no throw
  254. subView.X = Pos.Right (subView2) + 3;
  255. superView.SetRelativeLayout (new Rect (0, 0, 0, 0)); // no throw
  256. superView.LayoutSubviews (); // no throw
  257. subView.X = new Pos.PosCombine (true, Pos.Right (subView2), new Pos.PosCombine (true, 7, 9));
  258. superView.SetRelativeLayout (new Rect (0, 0, 0, 0)); // no throw
  259. Assert.Throws<InvalidOperationException> (() => subView.X = Pos.Center () + 3);
  260. subView.X = 0;
  261. Assert.Throws<InvalidOperationException> (() => subView.X = 3 + Pos.Center ());
  262. subView.X = 0;
  263. Assert.Throws<InvalidOperationException> (() => subView.X = 3 + 5 + Pos.Center ());
  264. subView.X = 0;
  265. Assert.Throws<InvalidOperationException> (() => subView.X = 3 + 5 + Pos.Percent (10));
  266. subView.X = 0;
  267. Assert.Throws<InvalidOperationException> (() => subView.X = Pos.Percent (10) + Pos.Center ());
  268. subView.X = 0;
  269. // Tests nested Combine
  270. Assert.Throws<InvalidOperationException> (() => subView.X = 5 + new Pos.PosCombine (true, Pos.Right (subView2), new Pos.PosCombine (true, Pos.Center (), 9)));
  271. subView.X = 0;
  272. }
  273. // Test min - ensure that if min is specified in the DimAuto constructor it is honored
  274. [Fact]
  275. public void DimAuto_Min ()
  276. {
  277. var superView = new View () {
  278. X = 0,
  279. Y = 0,
  280. Width = Dim.Auto (min: 10),
  281. Height = Dim.Auto (min: 10),
  282. ValidatePosDim = true,
  283. };
  284. var subView = new View () {
  285. X = 0,
  286. Y = 0,
  287. Width = 5,
  288. Height = 5
  289. };
  290. superView.Add (subView);
  291. superView.BeginInit ();
  292. superView.EndInit ();
  293. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  294. superView.LayoutSubviews (); // no throw
  295. Assert.Equal (10, superView.Frame.Width);
  296. Assert.Equal (10, superView.Frame.Height);
  297. }
  298. [Fact]
  299. public void DimAuto_Min_Resets_If_Subview_Shrinks ()
  300. {
  301. var superView = new View () {
  302. X = 0,
  303. Y = 0,
  304. Width = Dim.Auto (min: 10),
  305. Height = Dim.Auto (min: 10),
  306. ValidatePosDim = true,
  307. };
  308. var subView = new View () {
  309. X = 0,
  310. Y = 0,
  311. Width = 5,
  312. Height = 5
  313. };
  314. superView.Add (subView);
  315. superView.BeginInit ();
  316. superView.EndInit ();
  317. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  318. superView.LayoutSubviews (); // no throw
  319. Assert.Equal (10, superView.Frame.Width);
  320. Assert.Equal (10, superView.Frame.Height);
  321. subView.Width = 3;
  322. subView.Height = 3;
  323. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  324. superView.LayoutSubviews (); // no throw
  325. Assert.Equal (3, subView.Frame.Width);
  326. Assert.Equal (3, subView.Frame.Height);
  327. Assert.Equal (10, superView.Frame.Width);
  328. Assert.Equal (10, superView.Frame.Height);
  329. }
  330. // what happens if DimAuto (min: 10) and the subview moves to a negative coord?
  331. [Fact]
  332. public void DimAuto_Min_Resets_If_Subview_Moves_Negative ()
  333. {
  334. var superView = new View () {
  335. X = 0,
  336. Y = 0,
  337. Width = Dim.Auto (min: 10),
  338. Height = Dim.Auto (min: 10),
  339. ValidatePosDim = true,
  340. };
  341. var subView = new View () {
  342. X = 0,
  343. Y = 0,
  344. Width = 5,
  345. Height = 5
  346. };
  347. superView.Add (subView);
  348. superView.BeginInit ();
  349. superView.EndInit ();
  350. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  351. superView.LayoutSubviews (); // no throw
  352. Assert.Equal (10, superView.Frame.Width);
  353. Assert.Equal (10, superView.Frame.Height);
  354. subView.X = -1;
  355. subView.Y = -1;
  356. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  357. superView.LayoutSubviews (); // no throw
  358. Assert.Equal (5, subView.Frame.Width);
  359. Assert.Equal (5, subView.Frame.Height);
  360. Assert.Equal (10, superView.Frame.Width);
  361. Assert.Equal (10, superView.Frame.Height);
  362. }
  363. // Test variations of Frame
  364. }