DimAutoTests.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  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. ValidatePosDim = true,
  161. };
  162. superView.BeginInit ();
  163. superView.EndInit ();
  164. Assert.Throws<InvalidOperationException> (() => superView.Add (subView));
  165. subView.Width = 10;
  166. superView.Add (subView);
  167. superView.BeginInit ();
  168. superView.EndInit ();
  169. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  170. superView.LayoutSubviews (); // no throw
  171. subView.Width = Dim.Fill ();
  172. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rect (0, 0, 0, 0)));
  173. subView.Width = 10;
  174. subView.Height = Dim.Fill ();
  175. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rect (0, 0, 0, 0)));
  176. subView.Height = 10;
  177. subView.Height = Dim.Percent (50);
  178. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rect (0, 0, 0, 0)));
  179. subView.Height = 10;
  180. subView.X = Pos.Center ();
  181. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rect (0, 0, 0, 0)));
  182. subView.X = 0;
  183. subView.Y = Pos.Center ();
  184. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rect (0, 0, 0, 0)));
  185. subView.Y = 0;
  186. subView.Width = 10;
  187. subView.Height = 10;
  188. subView.X = 0;
  189. subView.Y = 0;
  190. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  191. superView.LayoutSubviews ();
  192. }
  193. // Test validation
  194. [Fact]
  195. public void ValidatePosDim_True_Throws_When_SubView_Uses_SuperView_Dims_Combine ()
  196. {
  197. var superView = new View () {
  198. X = 0,
  199. Y = 0,
  200. Width = Dim.Auto (),
  201. Height = Dim.Auto (),
  202. ValidatePosDim = true,
  203. };
  204. var subView = new View () {
  205. X = 0,
  206. Y = 0,
  207. Width = 10,
  208. Height = 10
  209. };
  210. var subView2 = new View () {
  211. X = 0,
  212. Y = 0,
  213. Width = 10,
  214. Height = 10
  215. };
  216. superView.Add (subView, subView2);
  217. superView.BeginInit ();
  218. superView.EndInit ();
  219. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  220. superView.LayoutSubviews (); // no throw
  221. subView.Height = Dim.Fill () + 3;
  222. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rect (0, 0, 0, 0)));
  223. subView.Height = 0;
  224. subView.Height = 3 + Dim.Fill ();
  225. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rect (0, 0, 0, 0)));
  226. subView.Height = 0;
  227. subView.Height = 3 + 5 + Dim.Fill ();
  228. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rect (0, 0, 0, 0)));
  229. subView.Height = 0;
  230. subView.Height = 3 + 5 + Dim.Percent (10);
  231. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rect (0, 0, 0, 0)));
  232. subView.Height = 0;
  233. // Tests nested Combine
  234. subView.Height = 5 + new Dim.DimCombine (true, 3, new Dim.DimCombine (true, Dim.Percent (10), 9));
  235. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rect (0, 0, 0, 0)));
  236. }
  237. [Fact]
  238. public void ValidatePosDim_True_Throws_When_SubView_Uses_SuperView_Pos_Combine ()
  239. {
  240. var superView = new View () {
  241. X = 0,
  242. Y = 0,
  243. Width = Dim.Auto (),
  244. Height = Dim.Auto (),
  245. ValidatePosDim = true,
  246. };
  247. var subView = new View () {
  248. X = 0,
  249. Y = 0,
  250. Width = 10,
  251. Height = 10
  252. };
  253. var subView2 = new View () {
  254. X = 0,
  255. Y = 0,
  256. Width = 10,
  257. Height = 10
  258. };
  259. superView.Add (subView, subView2);
  260. superView.BeginInit ();
  261. superView.EndInit ();
  262. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  263. superView.LayoutSubviews (); // no throw
  264. subView.X = Pos.Right (subView2);
  265. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  266. superView.LayoutSubviews (); // no throw
  267. subView.X = Pos.Right (subView2) + 3;
  268. superView.SetRelativeLayout (new Rect (0, 0, 0, 0)); // no throw
  269. superView.LayoutSubviews (); // no throw
  270. subView.X = new Pos.PosCombine (true, Pos.Right (subView2), new Pos.PosCombine (true, 7, 9));
  271. superView.SetRelativeLayout (new Rect (0, 0, 0, 0)); // no throw
  272. subView.X = Pos.Center () + 3;
  273. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rect (0, 0, 0, 0)));
  274. subView.X = 0;
  275. subView.X = 3 + Pos.Center ();
  276. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rect (0, 0, 0, 0)));
  277. subView.X = 0;
  278. subView.X = 3 + 5 + Pos.Center ();
  279. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rect (0, 0, 0, 0)));
  280. subView.X = 0;
  281. subView.X = 3 + 5 + Pos.Percent (10);
  282. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rect (0, 0, 0, 0)));
  283. subView.X = 0;
  284. subView.X = Pos.Percent (10) + Pos.Center ();
  285. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rect (0, 0, 0, 0)));
  286. subView.X = 0;
  287. // Tests nested Combine
  288. subView.X = 5 + new Pos.PosCombine (true, Pos.Right (subView2), new Pos.PosCombine (true, Pos.Center (), 9));
  289. Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rect (0, 0, 0, 0)));
  290. subView.X = 0;
  291. }
  292. // Test min - ensure that if min is specified in the DimAuto constructor it is honored
  293. [Fact]
  294. public void DimAuto_Min ()
  295. {
  296. var superView = new View () {
  297. X = 0,
  298. Y = 0,
  299. Width = Dim.Auto (min: 10),
  300. Height = Dim.Auto (min: 10),
  301. ValidatePosDim = true,
  302. };
  303. var subView = new View () {
  304. X = 0,
  305. Y = 0,
  306. Width = 5,
  307. Height = 5
  308. };
  309. superView.Add (subView);
  310. superView.BeginInit ();
  311. superView.EndInit ();
  312. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  313. superView.LayoutSubviews (); // no throw
  314. Assert.Equal (10, superView.Frame.Width);
  315. Assert.Equal (10, superView.Frame.Height);
  316. }
  317. [Fact]
  318. public void DimAuto_Min_Resets_If_Subview_Shrinks ()
  319. {
  320. var superView = new View () {
  321. X = 0,
  322. Y = 0,
  323. Width = Dim.Auto (min: 10),
  324. Height = Dim.Auto (min: 10),
  325. ValidatePosDim = true,
  326. };
  327. var subView = new View () {
  328. X = 0,
  329. Y = 0,
  330. Width = 5,
  331. Height = 5
  332. };
  333. superView.Add (subView);
  334. superView.BeginInit ();
  335. superView.EndInit ();
  336. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  337. superView.LayoutSubviews (); // no throw
  338. Assert.Equal (10, superView.Frame.Width);
  339. Assert.Equal (10, superView.Frame.Height);
  340. subView.Width = 3;
  341. subView.Height = 3;
  342. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  343. superView.LayoutSubviews (); // no throw
  344. Assert.Equal (3, subView.Frame.Width);
  345. Assert.Equal (3, subView.Frame.Height);
  346. Assert.Equal (10, superView.Frame.Width);
  347. Assert.Equal (10, superView.Frame.Height);
  348. }
  349. // what happens if DimAuto (min: 10) and the subview moves to a negative coord?
  350. [Fact]
  351. public void DimAuto_Min_Resets_If_Subview_Moves_Negative ()
  352. {
  353. var superView = new View () {
  354. X = 0,
  355. Y = 0,
  356. Width = Dim.Auto (min: 10),
  357. Height = Dim.Auto (min: 10),
  358. ValidatePosDim = true,
  359. };
  360. var subView = new View () {
  361. X = 0,
  362. Y = 0,
  363. Width = 5,
  364. Height = 5
  365. };
  366. superView.Add (subView);
  367. superView.BeginInit ();
  368. superView.EndInit ();
  369. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  370. superView.LayoutSubviews (); // no throw
  371. Assert.Equal (10, superView.Frame.Width);
  372. Assert.Equal (10, superView.Frame.Height);
  373. subView.X = -1;
  374. subView.Y = -1;
  375. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  376. superView.LayoutSubviews (); // no throw
  377. Assert.Equal (5, subView.Frame.Width);
  378. Assert.Equal (5, subView.Frame.Height);
  379. Assert.Equal (10, superView.Frame.Width);
  380. Assert.Equal (10, superView.Frame.Height);
  381. }
  382. // Test variations of Frame
  383. }