AdornmentTests.cs 17 KB

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