DimAutoTests.cs 11 KB

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