AdornmentTests.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. namespace Terminal.Gui.ViewTests;
  2. [Collection ("Global Test Setup")]
  3. public class AdornmentTests
  4. {
  5. [Fact]
  6. public void Viewport_Location_Always_Empty_Size_Correct ()
  7. {
  8. var view = new View
  9. {
  10. X = 1,
  11. Y = 2,
  12. Width = 20,
  13. Height = 20
  14. };
  15. view.BeginInit ();
  16. view.EndInit ();
  17. Assert.Equal (new (1, 2, 20, 20), view.Frame);
  18. Assert.Equal (new (0, 0, 20, 20), view.Viewport);
  19. var marginThickness = 1;
  20. view.Margin.Thickness = new (marginThickness);
  21. Assert.Equal (new (0, 0, 18, 18), view.Viewport);
  22. var borderThickness = 2;
  23. view.Border.Thickness = new (borderThickness);
  24. Assert.Equal (new (0, 0, 14, 14), view.Viewport);
  25. var paddingThickness = 3;
  26. view.Padding.Thickness = new (paddingThickness);
  27. Assert.Equal (new (0, 0, 8, 8), view.Viewport);
  28. Assert.Equal (new (0, 0, view.Margin.Frame.Width, view.Margin.Frame.Height), view.Margin.Viewport);
  29. Assert.Equal (new (0, 0, view.Border.Frame.Width, view.Border.Frame.Height), view.Border.Viewport);
  30. Assert.Equal (new (0, 0, view.Padding.Frame.Width, view.Padding.Frame.Height), view.Padding.Viewport);
  31. }
  32. // Test that Adornment.Viewport_get override returns Frame.Size minus Thickness
  33. [Theory]
  34. [InlineData (0, 0, 0, 0, 0)]
  35. [InlineData (0, 0, 0, 1, 1)]
  36. [InlineData (0, 0, 0, 1, 0)]
  37. [InlineData (0, 0, 0, 0, 1)]
  38. [InlineData (1, 0, 0, 0, 0)]
  39. [InlineData (1, 0, 0, 1, 1)]
  40. [InlineData (1, 0, 0, 1, 0)]
  41. [InlineData (1, 0, 0, 0, 1)]
  42. [InlineData (1, 0, 0, 4, 4)]
  43. [InlineData (1, 0, 0, 4, 0)]
  44. [InlineData (1, 0, 0, 0, 4)]
  45. [InlineData (0, 1, 0, 0, 0)]
  46. [InlineData (0, 1, 0, 1, 1)]
  47. [InlineData (0, 1, 0, 1, 0)]
  48. [InlineData (0, 1, 0, 0, 1)]
  49. [InlineData (1, 1, 0, 0, 0)]
  50. [InlineData (1, 1, 0, 1, 1)]
  51. [InlineData (1, 1, 0, 1, 0)]
  52. [InlineData (1, 1, 0, 0, 1)]
  53. [InlineData (1, 1, 0, 4, 4)]
  54. [InlineData (1, 1, 0, 4, 0)]
  55. [InlineData (1, 1, 0, 0, 4)]
  56. [InlineData (0, 1, 1, 0, 0)]
  57. [InlineData (0, 1, 1, 1, 1)]
  58. [InlineData (0, 1, 1, 1, 0)]
  59. [InlineData (0, 1, 1, 0, 1)]
  60. [InlineData (1, 1, 1, 0, 0)]
  61. [InlineData (1, 1, 1, 1, 1)]
  62. [InlineData (1, 1, 1, 1, 0)]
  63. [InlineData (1, 1, 1, 0, 1)]
  64. [InlineData (1, 1, 1, 4, 4)]
  65. [InlineData (1, 1, 1, 4, 0)]
  66. [InlineData (1, 1, 1, 0, 4)]
  67. public void Viewport_Width_Is_Frame_Width (int thickness, int x, int y, int w, int h)
  68. {
  69. var adornment = new Adornment (null);
  70. adornment.Thickness = new (thickness);
  71. adornment.Frame = new (x, y, w, h);
  72. Assert.Equal (new (x, y, w, h), adornment.Frame);
  73. var expectedBounds = new Rectangle (0, 0, w, h);
  74. Assert.Equal (expectedBounds, adornment.Viewport);
  75. }
  76. // Test that Adornment.Viewport_get override uses Parent not SuperView
  77. [Fact]
  78. public void BoundsToScreen_Uses_Parent_Not_SuperView ()
  79. {
  80. var parent = new View { X = 1, Y = 2, Width = 10, Height = 10 };
  81. parent.BeginInit ();
  82. parent.EndInit ();
  83. Assert.Equal (new (1, 2, 10, 10), parent.Frame);
  84. Assert.Equal (new (0, 0, 10, 10), parent.Viewport);
  85. Assert.Equal (new (0, 0, 10, 10), parent.Margin.Frame);
  86. Assert.Equal (new (0, 0, 10, 10), parent.Margin.Viewport);
  87. Assert.Null (parent.Margin.SuperView);
  88. Rectangle boundsAsScreen = parent.Margin.ViewportToScreen (new Rectangle (1, 2, 5, 5));
  89. Assert.Equal (new (2, 4, 5, 5), boundsAsScreen);
  90. }
  91. [Fact]
  92. public void SetAdornmentFrames_Sets_Frames_Correctly ()
  93. {
  94. var parent = new View { X = 1, Y = 2, Width = 10, Height = 20 };
  95. parent.SetAdornmentFrames ();
  96. Assert.Equal (new (1, 2, 10, 20), parent.Frame);
  97. Assert.Equal (new (0, 0, 10, 20), parent.Viewport);
  98. Assert.Equal (new (0, 0, 10, 20), parent.Margin.Frame);
  99. Assert.Equal (new (0, 0, 10, 20), parent.Margin.Viewport);
  100. }
  101. [Fact]
  102. public void Frames_are_Parent_SuperView_Relative ()
  103. {
  104. var view = new View
  105. {
  106. X = 1,
  107. Y = 2,
  108. Width = 20,
  109. Height = 31
  110. };
  111. var marginThickness = 1;
  112. view.Margin.Thickness = new (marginThickness);
  113. var borderThickness = 2;
  114. view.Border.Thickness = new (borderThickness);
  115. var paddingThickness = 3;
  116. view.Padding.Thickness = new (paddingThickness);
  117. view.BeginInit ();
  118. view.EndInit ();
  119. Assert.Equal (new (1, 2, 20, 31), view.Frame);
  120. Assert.Equal (new (0, 0, 8, 19), view.Viewport);
  121. // Margin.Frame is always the same as the view frame
  122. Assert.Equal (new (0, 0, 20, 31), view.Margin.Frame);
  123. // Border.Frame is View.Frame minus the Margin thickness
  124. Assert.Equal (
  125. new (marginThickness, marginThickness, view.Frame.Width - marginThickness * 2, view.Frame.Height - marginThickness * 2),
  126. view.Border.Frame);
  127. // Padding.Frame is View.Frame minus the Border thickness plus Margin thickness
  128. Assert.Equal (
  129. new (
  130. marginThickness + borderThickness,
  131. marginThickness + borderThickness,
  132. view.Frame.Width - (marginThickness + borderThickness) * 2,
  133. view.Frame.Height - (marginThickness + borderThickness) * 2),
  134. view.Padding.Frame);
  135. }
  136. // Test that Adornment.FrameToScreen override retains Frame.Size
  137. [Theory]
  138. [InlineData (0, 0, 0)]
  139. [InlineData (0, 1, 1)]
  140. [InlineData (0, 10, 10)]
  141. [InlineData (1, 0, 0)]
  142. [InlineData (1, 1, 1)]
  143. [InlineData (1, 10, 10)]
  144. public void FrameToScreen_Retains_Frame_Size (int marginThickness, int w, int h)
  145. {
  146. var parent = new View { X = 1, Y = 2, Width = w, Height = h };
  147. parent.Margin.Thickness = new (marginThickness);
  148. parent.BeginInit ();
  149. parent.EndInit ();
  150. Assert.Equal (new (1, 2, w, h), parent.Frame);
  151. Assert.Equal (new (0, 0, w, h), parent.Margin.Frame);
  152. Assert.Equal (parent.Frame, parent.Margin.FrameToScreen ());
  153. }
  154. // Test that Adornment.FrameToScreen override returns Frame if Parent is null
  155. [Fact]
  156. public void FrameToScreen_Returns_Frame_If_Parent_Is_Null ()
  157. {
  158. var a = new Adornment
  159. {
  160. X = 1,
  161. Y = 2,
  162. Width = 3,
  163. Height = 4
  164. };
  165. Assert.Null (a.Parent);
  166. Assert.Equal (a.Frame, a.FrameToScreen ());
  167. }
  168. // Test that Adornment.FrameToScreen override returns correct location
  169. [Theory]
  170. [InlineData (0, 0, 0, 0)]
  171. [InlineData (0, 0, 1, 1)]
  172. [InlineData (0, 0, 10, 10)]
  173. [InlineData (1, 0, 0, 0)]
  174. [InlineData (1, 0, 1, 1)]
  175. [InlineData (1, 0, 10, 10)]
  176. [InlineData (0, 1, 0, 0)]
  177. [InlineData (0, 1, 1, 1)]
  178. [InlineData (0, 1, 10, 10)]
  179. [InlineData (1, 1, 0, 0)]
  180. [InlineData (1, 1, 1, 1)]
  181. [InlineData (1, 1, 10, 10)]
  182. public void FrameToScreen_Returns_Screen_Location (int marginThickness, int borderThickness, int x, int y)
  183. {
  184. var superView = new View
  185. {
  186. X = 1,
  187. Y = 1,
  188. Width = 20,
  189. Height = 20
  190. };
  191. superView.Margin.Thickness = new (marginThickness);
  192. superView.Border.Thickness = new (borderThickness);
  193. var view = new View { X = x, Y = y, Width = 1, Height = 1 };
  194. superView.Add (view);
  195. superView.BeginInit ();
  196. superView.EndInit ();
  197. Assert.Equal (new (x, y, 1, 1), view.Frame);
  198. Assert.Equal (new (0, 0, 20, 20), superView.Margin.Frame);
  199. Assert.Equal (
  200. new (marginThickness, marginThickness, 20 - marginThickness * 2, 20 - marginThickness * 2),
  201. superView.Border.Frame
  202. );
  203. Assert.Equal (
  204. new (superView.Frame.X + marginThickness, superView.Frame.Y + marginThickness, 20 - marginThickness * 2, 20 - marginThickness * 2),
  205. superView.Border.FrameToScreen ()
  206. );
  207. }
  208. // Test that Adornment.FrameToScreen override uses Parent not SuperView
  209. [Fact]
  210. public void FrameToScreen_Uses_Parent_Not_SuperView ()
  211. {
  212. var parent = new View { X = 1, Y = 2, Width = 10, Height = 10 };
  213. parent.BeginInit ();
  214. parent.EndInit ();
  215. Assert.Equal (new (1, 2, 10, 10), parent.Frame);
  216. Assert.Equal (new (0, 0, 10, 10), parent.Viewport);
  217. Assert.Equal (new (0, 0, 10, 10), parent.Margin.Frame);
  218. Assert.Equal (new (0, 0, 10, 10), parent.Margin.Viewport);
  219. Assert.Null (parent.Margin.SuperView);
  220. Assert.Equal (new (1, 2, 10, 10), parent.Margin.FrameToScreen ());
  221. }
  222. [Fact]
  223. public void GetAdornmentsThickness ()
  224. {
  225. var view = new View ();
  226. Assert.Equal (Thickness.Empty, view.GetAdornmentsThickness ());
  227. view.Margin.Thickness = new (1);
  228. Assert.Equal (new (1), view.GetAdornmentsThickness ());
  229. view.Border.Thickness = new (1);
  230. Assert.Equal (new (2), view.GetAdornmentsThickness ());
  231. view.Padding.Thickness = new (1);
  232. Assert.Equal (new (3), view.GetAdornmentsThickness ());
  233. view.Padding.Thickness = new (2);
  234. Assert.Equal (new (4), view.GetAdornmentsThickness ());
  235. view.Padding.Thickness = new (1, 2, 3, 4);
  236. Assert.Equal (new (3, 4, 5, 6), view.GetAdornmentsThickness ());
  237. view.Margin.Thickness = new (1, 2, 3, 4);
  238. Assert.Equal (new (3, 5, 7, 9), view.GetAdornmentsThickness ());
  239. view.Dispose ();
  240. }
  241. [Fact]
  242. public void Setting_Viewport_Throws ()
  243. {
  244. var adornment = new Adornment (null);
  245. Assert.Throws<InvalidOperationException> (() => adornment.Viewport = new (1, 2, 3, 4));
  246. }
  247. [Fact]
  248. public void Setting_SuperViewRendersLineCanvas_Throws ()
  249. {
  250. var adornment = new Adornment (null);
  251. Assert.Throws<InvalidOperationException> (() => adornment.SuperViewRendersLineCanvas = true);
  252. }
  253. [Fact]
  254. public void Setting_Thickness_Changes_Parent_Bounds ()
  255. {
  256. var parent = new View { Width = 10, Height = 10 };
  257. parent.BeginInit ();
  258. parent.EndInit ();
  259. Assert.Equal (new (0, 0, 10, 10), parent.Frame);
  260. Assert.Equal (new (0, 0, 10, 10), parent.Viewport);
  261. parent.Margin.Thickness = new (1);
  262. Assert.Equal (new (0, 0, 10, 10), parent.Frame);
  263. Assert.Equal (new (0, 0, 8, 8), parent.Viewport);
  264. }
  265. [Fact]
  266. public void Setting_Thickness_Raises_ThicknessChanged ()
  267. {
  268. var adornment = new Adornment (null);
  269. var super = new View ();
  270. var raised = false;
  271. adornment.ThicknessChanged += (s, e) =>
  272. {
  273. raised = true;
  274. Assert.Equal (new (1, 2, 3, 4), adornment.Thickness);
  275. };
  276. adornment.Thickness = new (1, 2, 3, 4);
  277. Assert.True (raised);
  278. }
  279. [Fact]
  280. public void Setting_Thickness_Causes_Parent_Layout ()
  281. {
  282. var parent = new View ();
  283. var raised = false;
  284. parent.BeginInit ();
  285. parent.EndInit ();
  286. parent.SubViewLayout += LayoutStarted;
  287. parent.Margin.Thickness = new (1, 2, 3, 4);
  288. Assert.True (parent.NeedsLayout);
  289. Assert.True (parent.Margin.NeedsLayout);
  290. parent.Layout ();
  291. Assert.True (raised);
  292. return;
  293. void LayoutStarted (object sender, LayoutEventArgs e) { raised = true; }
  294. }
  295. [Fact]
  296. public void Setting_Thickness_Causes_Adornment_Layout ()
  297. {
  298. var parent = new View ();
  299. var raised = false;
  300. parent.BeginInit ();
  301. parent.EndInit ();
  302. parent.Margin.SubViewLayout += LayoutStarted;
  303. parent.Margin.Thickness = new (1, 2, 3, 4);
  304. Assert.True (parent.NeedsLayout);
  305. Assert.True (parent.Margin.NeedsLayout);
  306. parent.Layout ();
  307. Assert.True (raised);
  308. return;
  309. void LayoutStarted (object sender, LayoutEventArgs e) { raised = true; }
  310. }
  311. [Fact]
  312. public void Set_Viewport_Throws ()
  313. {
  314. View view = new ();
  315. view.BeginInit ();
  316. view.EndInit ();
  317. view.Padding.Thickness = new (2, 2, 2, 2);
  318. Assert.Throws<InvalidOperationException> (() => view.Padding.Viewport = view.Padding.Viewport with { Location = new (1, 1) });
  319. }
  320. // Contains tests
  321. [Theory]
  322. [InlineData (0, 0, 0, 0, 0, 0, false)]
  323. [InlineData (0, 0, 0, 1, 0, 0, false)]
  324. [InlineData (0, 0, 1, 0, 0, 0, false)]
  325. [InlineData (0, 0, 1, 1, 0, 0, true)]
  326. [InlineData (0, 0, 1, 2, 0, 0, true)]
  327. [InlineData (1, 1, 0, 0, 0, 0, false)]
  328. [InlineData (1, 1, 0, 1, 0, 0, false)]
  329. [InlineData (1, 1, 1, 0, 0, 0, false)]
  330. [InlineData (1, 1, 1, 0, 0, 1, false)]
  331. [InlineData (1, 1, 1, 1, 1, 0, false)]
  332. [InlineData (1, 1, 1, 1, 0, 0, false)]
  333. [InlineData (1, 1, 1, 1, 1, 1, true)]
  334. [InlineData (1, 1, 1, 2, 1, 1, true)]
  335. public void Contains_Left_Only (int x, int y, int width, int height, int pointX, int pointY, bool expected)
  336. {
  337. Adornment adornment = new () { Id = "adornment" };
  338. adornment.Parent = new() { Id = "parent" };
  339. adornment.Parent.Frame = new (x, y, width, height);
  340. adornment.Thickness = new (1, 0, 0, 0);
  341. adornment.Frame = adornment.Parent.Frame with { Location = Point.Empty };
  342. bool result = adornment.Contains (new (pointX, pointY));
  343. Assert.Equal (expected, result);
  344. }
  345. [Theory]
  346. [InlineData (0, 0, 0, 0, 0, 0, false)]
  347. [InlineData (0, 0, 0, 1, 0, 0, false)]
  348. [InlineData (0, 0, 1, 0, 0, 0, false)]
  349. [InlineData (0, 0, 1, 1, 0, 0, true)]
  350. [InlineData (0, 0, 1, 2, 0, 0, true)]
  351. [InlineData (1, 1, 0, 0, 0, 0, false)]
  352. [InlineData (1, 1, 0, 1, 0, 0, false)]
  353. [InlineData (1, 1, 1, 0, 0, 0, false)]
  354. [InlineData (1, 1, 1, 0, 0, 1, false)]
  355. [InlineData (1, 1, 1, 1, 1, 0, false)]
  356. [InlineData (1, 1, 1, 1, 0, 0, false)]
  357. [InlineData (1, 1, 1, 1, 1, 1, true)]
  358. [InlineData (1, 1, 1, 2, 1, 1, true)]
  359. public void Contains_Right_Only (int x, int y, int width, int height, int pointX, int pointY, bool expected)
  360. {
  361. Adornment adornment = new () { Id = "adornment" };
  362. adornment.Parent = new() { Id = "parent" };
  363. adornment.Parent.Frame = new (x, y, width, height);
  364. adornment.Thickness = new (0, 0, 1, 0);
  365. adornment.Frame = adornment.Parent.Frame with { Location = Point.Empty };
  366. bool result = adornment.Contains (new (pointX, pointY));
  367. Assert.Equal (expected, result);
  368. }
  369. [Theory]
  370. [InlineData (0, 0, 0, 0, 0, 0, false)]
  371. [InlineData (0, 0, 0, 1, 0, 0, false)]
  372. [InlineData (0, 0, 1, 0, 0, 0, false)]
  373. [InlineData (0, 0, 1, 1, 0, 0, true)]
  374. [InlineData (0, 0, 1, 2, 0, 0, true)]
  375. [InlineData (1, 1, 0, 0, 0, 0, false)]
  376. [InlineData (1, 1, 0, 1, 0, 0, false)]
  377. [InlineData (1, 1, 1, 0, 0, 0, false)]
  378. [InlineData (1, 1, 1, 0, 0, 1, false)]
  379. [InlineData (1, 1, 1, 1, 1, 0, false)]
  380. [InlineData (1, 1, 1, 1, 0, 0, false)]
  381. [InlineData (1, 1, 1, 1, 1, 1, true)]
  382. [InlineData (1, 1, 1, 2, 1, 1, true)]
  383. public void Contains_Top_Only (int x, int y, int width, int height, int pointX, int pointY, bool expected)
  384. {
  385. Adornment adornment = new () { Id = "adornment" };
  386. adornment.Parent = new() { Id = "parent" };
  387. adornment.Parent.Frame = new (x, y, width, height);
  388. adornment.Thickness = new (0, 1, 0, 0);
  389. adornment.Frame = adornment.Parent.Frame with { Location = Point.Empty };
  390. bool result = adornment.Contains (new (pointX, pointY));
  391. Assert.Equal (expected, result);
  392. }
  393. [Theory]
  394. [InlineData (0, 0, 0, 0, 0, 0, false)]
  395. [InlineData (0, 0, 0, 1, 0, 0, false)]
  396. [InlineData (0, 0, 1, 0, 0, 0, false)]
  397. [InlineData (0, 0, 1, 1, 0, 0, true)]
  398. [InlineData (0, 0, 1, 2, 0, 0, true)]
  399. [InlineData (1, 1, 0, 0, 0, 0, false)]
  400. [InlineData (1, 1, 0, 1, 0, 0, false)]
  401. [InlineData (1, 1, 1, 0, 0, 0, false)]
  402. [InlineData (1, 1, 1, 0, 0, 1, false)]
  403. [InlineData (1, 1, 1, 1, 1, 0, false)]
  404. [InlineData (1, 1, 1, 1, 0, 0, false)]
  405. [InlineData (1, 1, 1, 1, 1, 1, true)]
  406. [InlineData (1, 1, 1, 2, 1, 1, true)]
  407. public void Contains_TopLeft_Only (int x, int y, int width, int height, int pointX, int pointY, bool expected)
  408. {
  409. Adornment adornment = new () { Id = "adornment" };
  410. adornment.Parent = new() { Id = "parent" };
  411. adornment.Parent.Frame = new (x, y, width, height);
  412. adornment.Thickness = new (1, 1, 0, 0);
  413. adornment.Frame = adornment.Parent.Frame with { Location = Point.Empty };
  414. bool result = adornment.Contains (new (pointX, pointY));
  415. Assert.Equal (expected, result);
  416. }
  417. }