AdornmentTests.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. using Xunit.Abstractions;
  2. namespace Terminal.Gui.ViewTests;
  3. public class AdornmentTests (ITestOutputHelper output)
  4. {
  5. private readonly ITestOutputHelper _output = output;
  6. [Fact]
  7. public void Viewport_Location_Always_Empty_Size_Correct ()
  8. {
  9. var view = new View
  10. {
  11. X = 1,
  12. Y = 2,
  13. Width = 20,
  14. Height = 20
  15. };
  16. view.BeginInit ();
  17. view.EndInit ();
  18. Assert.Equal (new (1, 2, 20, 20), view.Frame);
  19. Assert.Equal (new (0, 0, 20, 20), view.Viewport);
  20. var marginThickness = 1;
  21. view.Margin.Thickness = new (marginThickness);
  22. Assert.Equal (new (0, 0, 18, 18), view.Viewport);
  23. var borderThickness = 2;
  24. view.Border.Thickness = new (borderThickness);
  25. Assert.Equal (new (0, 0, 14, 14), view.Viewport);
  26. var paddingThickness = 3;
  27. view.Padding.Thickness = new Thickness (paddingThickness);
  28. Assert.Equal (new (0, 0, 8, 8), view.Viewport);
  29. Assert.Equal (new (0, 0, view.Margin.Frame.Width, view.Margin.Frame.Height), view.Margin.Viewport);
  30. Assert.Equal (new (0, 0, view.Border.Frame.Width, view.Border.Frame.Height), view.Border.Viewport);
  31. Assert.Equal (new (0, 0, view.Padding.Frame.Width, view.Padding.Frame.Height), view.Padding.Viewport);
  32. }
  33. // Test that Adornment.Viewport_get override returns Frame.Size minus Thickness
  34. [Theory]
  35. [InlineData (0, 0, 0, 0, 0)]
  36. [InlineData (0, 0, 0, 1, 1)]
  37. [InlineData (0, 0, 0, 1, 0)]
  38. [InlineData (0, 0, 0, 0, 1)]
  39. [InlineData (1, 0, 0, 0, 0)]
  40. [InlineData (1, 0, 0, 1, 1)]
  41. [InlineData (1, 0, 0, 1, 0)]
  42. [InlineData (1, 0, 0, 0, 1)]
  43. [InlineData (1, 0, 0, 4, 4)]
  44. [InlineData (1, 0, 0, 4, 0)]
  45. [InlineData (1, 0, 0, 0, 4)]
  46. [InlineData (0, 1, 0, 0, 0)]
  47. [InlineData (0, 1, 0, 1, 1)]
  48. [InlineData (0, 1, 0, 1, 0)]
  49. [InlineData (0, 1, 0, 0, 1)]
  50. [InlineData (1, 1, 0, 0, 0)]
  51. [InlineData (1, 1, 0, 1, 1)]
  52. [InlineData (1, 1, 0, 1, 0)]
  53. [InlineData (1, 1, 0, 0, 1)]
  54. [InlineData (1, 1, 0, 4, 4)]
  55. [InlineData (1, 1, 0, 4, 0)]
  56. [InlineData (1, 1, 0, 0, 4)]
  57. [InlineData (0, 1, 1, 0, 0)]
  58. [InlineData (0, 1, 1, 1, 1)]
  59. [InlineData (0, 1, 1, 1, 0)]
  60. [InlineData (0, 1, 1, 0, 1)]
  61. [InlineData (1, 1, 1, 0, 0)]
  62. [InlineData (1, 1, 1, 1, 1)]
  63. [InlineData (1, 1, 1, 1, 0)]
  64. [InlineData (1, 1, 1, 0, 1)]
  65. [InlineData (1, 1, 1, 4, 4)]
  66. [InlineData (1, 1, 1, 4, 0)]
  67. [InlineData (1, 1, 1, 0, 4)]
  68. public void Viewport_Width_Is_Frame_Width (int thickness, int x, int y, int w, int h)
  69. {
  70. var adornment = new Adornment (null);
  71. adornment.Thickness = new Thickness (thickness);
  72. adornment.Frame = new Rectangle (x, y, w, h);
  73. Assert.Equal (new Rectangle (x, y, w, h), adornment.Frame);
  74. var expectedBounds = new Rectangle (0, 0, w, h);
  75. Assert.Equal (expectedBounds, adornment.Viewport);
  76. }
  77. // Test that Adornment.Viewport_get override uses Parent not SuperView
  78. [Fact]
  79. public void BoundsToScreen_Uses_Parent_Not_SuperView ()
  80. {
  81. var parent = new View { X = 1, Y = 2, Width = 10, Height = 10 };
  82. parent.BeginInit ();
  83. parent.EndInit ();
  84. Assert.Equal (new Rectangle (1, 2, 10, 10), parent.Frame);
  85. Assert.Equal (new Rectangle (0, 0, 10, 10), parent.Viewport);
  86. Assert.Equal (new Rectangle (0, 0, 10, 10), parent.Margin.Frame);
  87. Assert.Equal (new Rectangle (0, 0, 10, 10), parent.Margin.Viewport);
  88. Assert.Null (parent.Margin.SuperView);
  89. Rectangle boundsAsScreen = parent.Margin.ViewportToScreen (new Rectangle (1, 2, 5, 5));
  90. Assert.Equal (new Rectangle (2, 4, 5, 5), boundsAsScreen);
  91. }
  92. [Fact]
  93. public void Frames_are_Parent_SuperView_Relative ()
  94. {
  95. var view = new View
  96. {
  97. X = 1,
  98. Y = 2,
  99. Width = 20,
  100. Height = 31
  101. };
  102. var marginThickness = 1;
  103. view.Margin.Thickness = new Thickness (marginThickness);
  104. var borderThickness = 2;
  105. view.Border.Thickness = new Thickness (borderThickness);
  106. var paddingThickness = 3;
  107. view.Padding.Thickness = new Thickness (paddingThickness);
  108. view.BeginInit ();
  109. view.EndInit ();
  110. Assert.Equal (new Rectangle (1, 2, 20, 31), view.Frame);
  111. Assert.Equal (new Rectangle (0, 0, 8, 19), view.Viewport);
  112. // Margin.Frame is always the same as the view frame
  113. Assert.Equal (new Rectangle (0, 0, 20, 31), view.Margin.Frame);
  114. // Border.Frame is View.Frame minus the Margin thickness
  115. Assert.Equal (
  116. new Rectangle (marginThickness, marginThickness, view.Frame.Width - marginThickness * 2, view.Frame.Height - marginThickness * 2),
  117. view.Border.Frame);
  118. // Padding.Frame is View.Frame minus the Border thickness plus Margin thickness
  119. Assert.Equal (
  120. new Rectangle (
  121. marginThickness + borderThickness,
  122. marginThickness + borderThickness,
  123. view.Frame.Width - (marginThickness + borderThickness) * 2,
  124. view.Frame.Height - (marginThickness + borderThickness) * 2),
  125. view.Padding.Frame);
  126. }
  127. // Test that Adornment.FrameToScreen override retains Frame.Size
  128. [Theory]
  129. [InlineData (0, 0, 0)]
  130. [InlineData (0, 1, 1)]
  131. [InlineData (0, 10, 10)]
  132. [InlineData (1, 0, 0)]
  133. [InlineData (1, 1, 1)]
  134. [InlineData (1, 10, 10)]
  135. public void FrameToScreen_Retains_Frame_Size (int marginThickness, int w, int h)
  136. {
  137. var parent = new View { X = 1, Y = 2, Width = w, Height = h };
  138. parent.Margin.Thickness = new Thickness (marginThickness);
  139. parent.BeginInit ();
  140. parent.EndInit ();
  141. Assert.Equal (new Rectangle (1, 2, w, h), parent.Frame);
  142. Assert.Equal (new Rectangle (0, 0, w, h), parent.Margin.Frame);
  143. Assert.Equal (parent.Frame, parent.Margin.FrameToScreen ());
  144. }
  145. // Test that Adornment.FrameToScreen override returns Frame if Parent is null
  146. [Fact]
  147. public void FrameToScreen_Returns_Frame_If_Parent_Is_Null ()
  148. {
  149. var a = new Adornment
  150. {
  151. X = 1,
  152. Y = 2,
  153. Width = 3,
  154. Height = 4
  155. };
  156. Assert.Null (a.Parent);
  157. Assert.Equal (a.Frame, a.FrameToScreen ());
  158. }
  159. // Test that Adornment.FrameToScreen override returns correct location
  160. [Theory]
  161. [InlineData (0, 0, 0, 0)]
  162. [InlineData (0, 0, 1, 1)]
  163. [InlineData (0, 0, 10, 10)]
  164. [InlineData (1, 0, 0, 0)]
  165. [InlineData (1, 0, 1, 1)]
  166. [InlineData (1, 0, 10, 10)]
  167. [InlineData (0, 1, 0, 0)]
  168. [InlineData (0, 1, 1, 1)]
  169. [InlineData (0, 1, 10, 10)]
  170. [InlineData (1, 1, 0, 0)]
  171. [InlineData (1, 1, 1, 1)]
  172. [InlineData (1, 1, 10, 10)]
  173. public void FrameToScreen_Returns_Screen_Location (int marginThickness, int borderThickness, int x, int y)
  174. {
  175. var superView = new View
  176. {
  177. X = 1,
  178. Y = 1,
  179. Width = 20,
  180. Height = 20
  181. };
  182. superView.Margin.Thickness = new Thickness (marginThickness);
  183. superView.Border.Thickness = new Thickness (borderThickness);
  184. var view = new View { X = x, Y = y, Width = 1, Height = 1 };
  185. superView.Add (view);
  186. superView.BeginInit ();
  187. superView.EndInit ();
  188. Assert.Equal (new Rectangle (x, y, 1, 1), view.Frame);
  189. Assert.Equal (new Rectangle (0, 0, 20, 20), superView.Margin.Frame);
  190. Assert.Equal (
  191. new Rectangle (marginThickness, marginThickness, 20 - marginThickness * 2, 20 - marginThickness * 2),
  192. superView.Border.Frame
  193. );
  194. Assert.Equal (
  195. new Rectangle (superView.Frame.X + marginThickness, superView.Frame.Y + marginThickness, 20 - marginThickness * 2, 20 - marginThickness * 2),
  196. superView.Border.FrameToScreen ()
  197. );
  198. }
  199. // Test that Adornment.FrameToScreen override uses Parent not SuperView
  200. [Fact]
  201. public void FrameToScreen_Uses_Parent_Not_SuperView ()
  202. {
  203. var parent = new View { X = 1, Y = 2, Width = 10, Height = 10 };
  204. parent.BeginInit ();
  205. parent.EndInit ();
  206. Assert.Equal (new Rectangle (1, 2, 10, 10), parent.Frame);
  207. Assert.Equal (new Rectangle (0, 0, 10, 10), parent.Viewport);
  208. Assert.Equal (new Rectangle (0, 0, 10, 10), parent.Margin.Frame);
  209. Assert.Equal (new Rectangle (0, 0, 10, 10), parent.Margin.Viewport);
  210. Assert.Null (parent.Margin.SuperView);
  211. Assert.Equal (new Rectangle (1, 2, 10, 10), parent.Margin.FrameToScreen ());
  212. }
  213. [Fact]
  214. public void GetAdornmentsThickness ()
  215. {
  216. var view = new View ();
  217. Assert.Equal (Thickness.Empty, view.GetAdornmentsThickness ());
  218. view.Margin.Thickness = new Thickness (1);
  219. Assert.Equal (new Thickness (1), view.GetAdornmentsThickness ());
  220. view.Border.Thickness = new Thickness (1);
  221. Assert.Equal (new Thickness (2), view.GetAdornmentsThickness ());
  222. view.Padding.Thickness = new Thickness (1);
  223. Assert.Equal (new Thickness (3), view.GetAdornmentsThickness ());
  224. view.Padding.Thickness = new Thickness (2);
  225. Assert.Equal (new Thickness (4), view.GetAdornmentsThickness ());
  226. view.Padding.Thickness = new Thickness (1, 2, 3, 4);
  227. Assert.Equal (new Thickness (3, 4, 5, 6), view.GetAdornmentsThickness ());
  228. view.Margin.Thickness = new Thickness (1, 2, 3, 4);
  229. Assert.Equal (new Thickness (3, 5, 7, 9), view.GetAdornmentsThickness ());
  230. view.Dispose ();
  231. }
  232. [Fact]
  233. public void Setting_Viewport_Throws ()
  234. {
  235. var adornment = new Adornment (null);
  236. Assert.Throws<InvalidOperationException> (() => adornment.Viewport = new Rectangle (1, 2, 3, 4));
  237. }
  238. [Fact]
  239. public void Setting_SuperView_Throws ()
  240. {
  241. var adornment = new Adornment (null);
  242. Assert.Throws<InvalidOperationException> (() => adornment.SuperView = new View ());
  243. }
  244. [Fact]
  245. public void Setting_SuperViewRendersLineCanvas_Throws ()
  246. {
  247. var adornment = new Adornment (null);
  248. Assert.Throws<InvalidOperationException> (() => adornment.SuperViewRendersLineCanvas = true);
  249. }
  250. [Fact]
  251. public void Setting_Thickness_Changes_Parent_Bounds ()
  252. {
  253. var parent = new View { Width = 10, Height = 10 };
  254. parent.BeginInit ();
  255. parent.EndInit ();
  256. Assert.Equal (new Rectangle (0, 0, 10, 10), parent.Frame);
  257. Assert.Equal (new Rectangle (0, 0, 10, 10), parent.Viewport);
  258. parent.Margin.Thickness = new Thickness (1);
  259. Assert.Equal (new Rectangle (0, 0, 10, 10), parent.Frame);
  260. Assert.Equal (new Rectangle (0, 0, 8, 8), parent.Viewport);
  261. }
  262. [Fact]
  263. public void Setting_Thickness_Raises_ThicknessChanged ()
  264. {
  265. var adornment = new Adornment (null);
  266. var super = new View ();
  267. var raised = false;
  268. adornment.ThicknessChanged += (s, e) =>
  269. {
  270. raised = true;
  271. Assert.Equal (new Thickness (1, 2, 3, 4), adornment.Thickness);
  272. };
  273. adornment.Thickness = new Thickness (1, 2, 3, 4);
  274. Assert.True (raised);
  275. }
  276. [Fact]
  277. public void Setting_Thickness_Causes_Parent_Layout ()
  278. {
  279. var view = new View ();
  280. var raised = false;
  281. view.BeginInit ();
  282. view.EndInit ();
  283. view.LayoutStarted += LayoutStarted;
  284. view.Margin.Thickness = new Thickness (1, 2, 3, 4);
  285. Assert.True (raised);
  286. return;
  287. void LayoutStarted (object sender, LayoutEventArgs e)
  288. {
  289. raised = true;
  290. }
  291. }
  292. [Fact]
  293. public void Setting_Thickness_Causes_Adornment_Layout ()
  294. {
  295. var view = new View ();
  296. var raised = false;
  297. view.BeginInit ();
  298. view.EndInit ();
  299. view.Margin.LayoutStarted += LayoutStarted;
  300. view.Margin.Thickness = new Thickness (1, 2, 3, 4);
  301. Assert.True (raised);
  302. return;
  303. void LayoutStarted (object sender, LayoutEventArgs e)
  304. {
  305. raised = true;
  306. }
  307. }
  308. [Fact]
  309. public void Set_Viewport_Throws ()
  310. {
  311. View view = new ();
  312. view.BeginInit ();
  313. view.EndInit ();
  314. view.Padding.Thickness = new (2, 2, 2, 2);
  315. Assert.Throws<InvalidOperationException> (() => view.Padding.Viewport = view.Padding.Viewport with { Location = new (1, 1) });
  316. }
  317. }