ScrollTests.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. using Microsoft.VisualStudio.TestPlatform.Utilities;
  2. using Xunit.Abstractions;
  3. namespace Terminal.Gui.ViewsTests;
  4. public class ScrollTests
  5. {
  6. public ScrollTests (ITestOutputHelper output) { _output = output; }
  7. private readonly ITestOutputHelper _output;
  8. [Fact]
  9. public void OnOrientationChanged_Keeps_Size ()
  10. {
  11. var scroll = new Scroll ();
  12. scroll.Layout ();
  13. scroll.Size = 1;
  14. scroll.Orientation = Orientation.Horizontal;
  15. Assert.Equal (1, scroll.Size);
  16. }
  17. [Fact]
  18. public void OnOrientationChanged_Sets_ContentPosition_To_0 ()
  19. {
  20. View super = new View ()
  21. {
  22. Id = "super",
  23. Width = 10,
  24. Height = 10
  25. };
  26. var scroll = new Scroll ()
  27. {
  28. };
  29. super.Add (scroll);
  30. scroll.Layout ();
  31. scroll.ContentPosition = 1;
  32. scroll.Orientation = Orientation.Horizontal;
  33. Assert.Equal (0, scroll.ContentPosition);
  34. }
  35. // [Theory]
  36. // [AutoInitShutdown]
  37. // [InlineData (
  38. // 20,
  39. // @"
  40. //█
  41. //█
  42. //█
  43. //█
  44. //█
  45. //░
  46. //░
  47. //░
  48. //░
  49. //░",
  50. // @"
  51. //░
  52. //░
  53. //█
  54. //█
  55. //█
  56. //█
  57. //█
  58. //░
  59. //░
  60. //░",
  61. // @"
  62. //░
  63. //░
  64. //░
  65. //░
  66. //░
  67. //█
  68. //█
  69. //█
  70. //█
  71. //█",
  72. // @"
  73. //░
  74. //░
  75. //█
  76. //█
  77. //█
  78. //░
  79. //░
  80. //░
  81. //░
  82. //░",
  83. // @"
  84. //█████░░░░░",
  85. // @"
  86. //░░█████░░░",
  87. // @"
  88. //░░░░░█████",
  89. // @"
  90. //░░███░░░░░")]
  91. // [InlineData (
  92. // 40,
  93. // @"
  94. //█
  95. //█
  96. //█
  97. //░
  98. //░
  99. //░
  100. //░
  101. //░
  102. //░
  103. //░",
  104. // @"
  105. //░
  106. //█
  107. //█
  108. //█
  109. //░
  110. //░
  111. //░
  112. //░
  113. //░
  114. //░",
  115. // @"
  116. //░
  117. //░
  118. //█
  119. //█
  120. //█
  121. //░
  122. //░
  123. //░
  124. //░
  125. //░",
  126. // @"
  127. //░
  128. //█
  129. //█
  130. //░
  131. //░
  132. //░
  133. //░
  134. //░
  135. //░
  136. //░",
  137. // @"
  138. //███░░░░░░░",
  139. // @"
  140. //░███░░░░░░",
  141. // @"
  142. //░░███░░░░░",
  143. // @"
  144. //░██░░░░░░░")]
  145. // public void Changing_Position_Size_Orientation_Draws_Correctly_KeepContentInAllViewport_True (
  146. // int size,
  147. // string firstVertExpected,
  148. // string middleVertExpected,
  149. // string endVertExpected,
  150. // string sizeVertExpected,
  151. // string firstHoriExpected,
  152. // string middleHoriExpected,
  153. // string endHoriExpected,
  154. // string sizeHoriExpected
  155. // )
  156. // {
  157. // var scroll = new Scroll
  158. // {
  159. // Orientation = Orientation.Vertical,
  160. // Size = size,
  161. // Height = 10,
  162. // KeepContentInAllViewport = true
  163. // };
  164. // var top = new Toplevel ();
  165. // top.Add (scroll);
  166. // RunState rs = Application.Begin (top);
  167. // Application.RunIteration (ref rs);
  168. // _ = TestHelpers.AssertDriverContentsWithFrameAre (firstVertExpected, _output);
  169. // scroll.Position = 4;
  170. // Application.RunIteration (ref rs);
  171. // _ = TestHelpers.AssertDriverContentsWithFrameAre (middleVertExpected, _output);
  172. // scroll.Position = 10;
  173. // Application.RunIteration (ref rs);
  174. // _ = TestHelpers.AssertDriverContentsWithFrameAre (endVertExpected, _output);
  175. // scroll.Size = size * 2;
  176. // Application.RunIteration (ref rs);
  177. // _ = TestHelpers.AssertDriverContentsWithFrameAre (sizeVertExpected, _output);
  178. // scroll.Orientation = Orientation.Horizontal;
  179. // scroll.Width = 10;
  180. // scroll.Height = 1;
  181. // scroll.Position = 0;
  182. // scroll.Size = size;
  183. // Application.RunIteration (ref rs);
  184. // _ = TestHelpers.AssertDriverContentsWithFrameAre (firstHoriExpected, _output);
  185. // scroll.Position = 4;
  186. // Application.RunIteration (ref rs);
  187. // _ = TestHelpers.AssertDriverContentsWithFrameAre (middleHoriExpected, _output);
  188. // scroll.Position = 10;
  189. // Application.RunIteration (ref rs);
  190. // _ = TestHelpers.AssertDriverContentsWithFrameAre (endHoriExpected, _output);
  191. // scroll.Size = size * 2;
  192. // Application.RunIteration (ref rs);
  193. // _ = TestHelpers.AssertDriverContentsWithFrameAre (sizeHoriExpected, _output);
  194. // }
  195. [Fact]
  196. public void Constructor_Defaults ()
  197. {
  198. var scroll = new Scroll ();
  199. Assert.False (scroll.CanFocus);
  200. Assert.Equal (Orientation.Vertical, scroll.Orientation);
  201. Assert.Equal (0, scroll.Size);
  202. Assert.Equal (0, scroll.GetSliderPosition ());
  203. }
  204. //[Fact]
  205. //[AutoInitShutdown]
  206. //public void KeepContentInAllViewport_True_False_KeepContentInAllViewport_True ()
  207. //{
  208. // var view = new View { Width = Dim.Fill (), Height = Dim.Fill () };
  209. // view.Padding.Thickness = new (0, 0, 2, 0);
  210. // view.SetContentSize (new (view.Viewport.Width, 30));
  211. // var scroll = new Scroll { Width = 2, Height = Dim.Fill (), Size = view.GetContentSize ().Height, KeepContentInAllViewport = true };
  212. // scroll.PositionChanged += (_, e) => view.Viewport = view.Viewport with { Y = e.CurrentValue };
  213. // view.Padding.Add (scroll);
  214. // var top = new Toplevel ();
  215. // top.Add (view);
  216. // Application.Begin (top);
  217. // Assert.True (scroll.KeepContentInAllViewport);
  218. // Assert.Equal (80, view.Padding.Viewport.Width);
  219. // Assert.Equal (25, view.Padding.Viewport.Height);
  220. // Assert.Equal (2, scroll.Viewport.Width);
  221. // Assert.Equal (25, scroll.Viewport.Height);
  222. // Assert.Equal (30, scroll.Size);
  223. // scroll.KeepContentInAllViewport = false;
  224. // scroll.Position = 50;
  225. // Assert.Equal (scroll.Position, scroll.Size - 1);
  226. // Assert.Equal (scroll.Position, view.Viewport.Y);
  227. // Assert.Equal (29, scroll.Position);
  228. // Assert.Equal (29, view.Viewport.Y);
  229. // top.Dispose ();
  230. //}
  231. //[Theory]
  232. //[AutoInitShutdown]
  233. //[InlineData (Orientation.Vertical)]
  234. //[InlineData (Orientation.Horizontal)]
  235. //public void Moving_Mouse_Outside_Host_Ensures_Correct_Location_KeepContentInAllViewport_True (Orientation orientation)
  236. //{
  237. // var scroll = new Scroll
  238. // {
  239. // X = 10, Y = 10, Width = orientation == Orientation.Vertical ? 1 : 10, Height = orientation == Orientation.Vertical ? 10 : 1, Size = 20,
  240. // SliderPosition = 5, Orientation = orientation
  241. // };
  242. // var top = new Toplevel ();
  243. // top.Add (scroll);
  244. // RunState rs = Application.Begin (top);
  245. // Rectangle scrollSliderFrame = scroll.Subviews.FirstOrDefault (x => x.Id == "scrollSlider")!.Frame;
  246. // Assert.Equal (scrollSliderFrame, orientation == Orientation.Vertical ? new (0, 2, 1, 5) : new (2, 0, 5, 1));
  247. // Application.RaiseMouseEvent (new () { ScreenPosition = orientation == Orientation.Vertical ? new (10, 12) : new (12, 10), Flags = MouseFlags.Button1Pressed });
  248. // Application.RunIteration (ref rs);
  249. // Application.RaiseMouseEvent (
  250. // new ()
  251. // {
  252. // ScreenPosition = orientation == Orientation.Vertical ? new (10, 0) : new (0, 10),
  253. // Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
  254. // });
  255. // Application.RunIteration (ref rs);
  256. // Assert.Equal (new (0, 0), scroll.Subviews.FirstOrDefault (x => x.Id == "scrollSlider")!.Frame.Location);
  257. // Application.RaiseMouseEvent (
  258. // new ()
  259. // {
  260. // ScreenPosition = orientation == Orientation.Vertical ? new (0, 25) : new (80, 0),
  261. // Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
  262. // });
  263. // Application.RunIteration (ref rs);
  264. // Assert.Equal (
  265. // orientation == Orientation.Vertical ? new (0, 5) : new (5, 0),
  266. // scroll.Subviews.FirstOrDefault (x => x.Id == "scrollSlider")!.Frame.Location);
  267. //}
  268. [Theory]
  269. [CombinatorialData]
  270. [AutoInitShutdown]
  271. public void Mouse_Wheel_Increments_Position ([CombinatorialRange (1, 3, 1)] int increment, Orientation orientation)
  272. {
  273. var top = new Toplevel ()
  274. {
  275. Id = "top",
  276. Width = 10,
  277. Height = 10
  278. };
  279. var scroll = new Scroll
  280. {
  281. Id = "scroll",
  282. Orientation = orientation,
  283. Size = 20,
  284. Increment = increment
  285. };
  286. top.Add (scroll);
  287. RunState rs = Application.Begin (top);
  288. Assert.Equal (0, scroll.GetSliderPosition ());
  289. Assert.Equal (0, scroll.ContentPosition);
  290. Application.RaiseMouseEvent (new ()
  291. {
  292. ScreenPosition = new (0, 0),
  293. Flags = orientation == Orientation.Vertical ? MouseFlags.WheeledDown : MouseFlags.WheeledRight
  294. });
  295. Application.RunIteration (ref rs);
  296. Assert.Equal (increment, scroll.ContentPosition);
  297. Application.RaiseMouseEvent (new ()
  298. {
  299. ScreenPosition = new (0, 0),
  300. Flags = orientation == Orientation.Vertical ? MouseFlags.WheeledDown : MouseFlags.WheeledRight
  301. });
  302. Application.RunIteration (ref rs);
  303. Assert.Equal (increment * 2, scroll.ContentPosition);
  304. Application.RaiseMouseEvent (new ()
  305. {
  306. ScreenPosition = new (0, 0),
  307. Flags = orientation == Orientation.Vertical ? MouseFlags.WheeledUp : MouseFlags.WheeledLeft
  308. });
  309. Application.RunIteration (ref rs);
  310. Assert.Equal (increment, scroll.ContentPosition);
  311. Application.ResetState (true);
  312. }
  313. [Theory]
  314. [CombinatorialData]
  315. [AutoInitShutdown]
  316. public void Mouse_Click_Outside_Slider_Moves (Orientation orientation)
  317. {
  318. var top = new Toplevel ()
  319. {
  320. Id = "top",
  321. Width = 10,
  322. Height = 10
  323. };
  324. var scroll = new Scroll
  325. {
  326. Id = "scroll",
  327. Orientation = orientation,
  328. Size = 20,
  329. };
  330. top.Add (scroll);
  331. RunState rs = Application.Begin (top);
  332. scroll.ContentPosition = 5;
  333. Application.RunIteration (ref rs);
  334. Assert.Equal (5, scroll.GetSliderPosition ());
  335. Assert.Equal (10, scroll.ContentPosition);
  336. Application.RaiseMouseEvent (new ()
  337. {
  338. ScreenPosition = new (0, 0),
  339. Flags = MouseFlags.Button1Clicked
  340. });
  341. Application.RunIteration (ref rs);
  342. Assert.Equal (0, scroll.GetSliderPosition ());
  343. Assert.Equal (0, scroll.ContentPosition);
  344. Application.ResetState (true);
  345. }
  346. [Theory]
  347. [CombinatorialData]
  348. public void Position_Clamps_To_Size (
  349. [CombinatorialRange (1, 6, 1)] int scrollSize,
  350. [CombinatorialRange (-1, 6, 1)] int scrollPosition,
  351. Orientation orientation
  352. )
  353. {
  354. var super = new View
  355. {
  356. Id = "super",
  357. Width = 5,
  358. Height = 5
  359. };
  360. var scroll = new Scroll
  361. {
  362. Orientation = orientation,
  363. Width = Dim.Fill (),
  364. Height = Dim.Fill ()
  365. };
  366. super.Add (scroll);
  367. scroll.Size = scrollSize;
  368. super.Layout ();
  369. scroll.ContentPosition = scrollPosition;
  370. super.Layout ();
  371. Assert.True (scroll.GetSliderPosition () <= scrollSize);
  372. }
  373. [Fact]
  374. public void PositionChanging_PositionChanged_Events_Only_Raises_Once_If_Position_Was_Really_Changed ()
  375. {
  376. var changing = 0;
  377. var cancel = false;
  378. var changed = 0;
  379. var scroll = new Scroll { Height = 10, Size = 20 };
  380. scroll.SliderPositionChanged += Scroll_PositionChanged;
  381. Assert.Equal (Orientation.Vertical, scroll.Orientation);
  382. scroll.Layout ();
  383. Assert.Equal (new (0, 0, 1, 10), scroll.Viewport);
  384. Assert.Equal (0, scroll.GetSliderPosition ());
  385. Assert.Equal (0, changing);
  386. Assert.Equal (0, changed);
  387. scroll.ContentPosition = 0;
  388. Assert.Equal (0, scroll.GetSliderPosition ());
  389. Assert.Equal (0, changing);
  390. Assert.Equal (0, changed);
  391. scroll.ContentPosition = 1;
  392. Assert.Equal (1, scroll.GetSliderPosition ());
  393. Assert.Equal (1, changing);
  394. Assert.Equal (1, changed);
  395. Reset ();
  396. cancel = true;
  397. scroll.ContentPosition = 2;
  398. Assert.Equal (1, scroll.GetSliderPosition ());
  399. Assert.Equal (1, changing);
  400. Assert.Equal (0, changed);
  401. Reset ();
  402. scroll.ContentPosition = 10;
  403. Assert.Equal (5, scroll.GetSliderPosition ());
  404. Assert.Equal (1, changing);
  405. Assert.Equal (1, changed);
  406. Reset ();
  407. scroll.ContentPosition = 11;
  408. Assert.Equal (5, scroll.GetSliderPosition ());
  409. Assert.Equal (1, changing);
  410. Assert.Equal (1, changed);
  411. Reset ();
  412. scroll.ContentPosition = 0;
  413. Assert.Equal (0, scroll.GetSliderPosition ());
  414. Assert.Equal (1, changing);
  415. Assert.Equal (1, changed);
  416. scroll.SliderPositionChanged -= Scroll_PositionChanged;
  417. void Scroll_PositionChanged (object sender, EventArgs<int> e) { changed++; }
  418. void Reset ()
  419. {
  420. changing = 0;
  421. cancel = false;
  422. changed = 0;
  423. }
  424. }
  425. [Fact]
  426. public void Size_Cannot_Be_Negative ()
  427. {
  428. var scroll = new Scroll { Height = 10, Size = -1 };
  429. Assert.Equal (0, scroll.Size);
  430. scroll.Size = -10;
  431. Assert.Equal (0, scroll.Size);
  432. }
  433. [Fact]
  434. public void SizeChanged_Event ()
  435. {
  436. var count = 0;
  437. var scroll = new Scroll ();
  438. scroll.Layout ();
  439. scroll.SizeChanged += (s, e) => count++;
  440. scroll.Size = 10;
  441. Assert.Equal (10, scroll.Size);
  442. Assert.Equal (1, count);
  443. }
  444. [Theory]
  445. [SetupFakeDriver]
  446. [InlineData (
  447. 10,
  448. 1,
  449. 20,
  450. 0,
  451. Orientation.Horizontal,
  452. @"
  453. ┌──────────┐
  454. │█████░░░░░│
  455. └──────────┘")]
  456. [InlineData (
  457. 10,
  458. 3,
  459. 20,
  460. 1,
  461. Orientation.Horizontal,
  462. @"
  463. ┌──────────┐
  464. │░█████░░░░│
  465. │░█████░░░░│
  466. │░█████░░░░│
  467. └──────────┘")]
  468. [InlineData (
  469. 3,
  470. 10,
  471. 20,
  472. 0,
  473. Orientation.Vertical,
  474. @"
  475. ┌───┐
  476. │███│
  477. │███│
  478. │███│
  479. │███│
  480. │███│
  481. │░░░│
  482. │░░░│
  483. │░░░│
  484. │░░░│
  485. │░░░│
  486. └───┘")]
  487. public void Draws_Correctly (int superViewportWidth, int superViewportHeight, int sliderSize, int sliderPosition, Orientation orientation, string expected)
  488. {
  489. var super = new Window
  490. {
  491. Id = "super",
  492. Width = superViewportWidth + 2,
  493. Height = superViewportHeight + 2
  494. };
  495. var scroll = new Scroll
  496. {
  497. Orientation = orientation,
  498. };
  499. if (orientation == Orientation.Vertical)
  500. {
  501. scroll.Width = Dim.Fill ();
  502. }
  503. else
  504. {
  505. scroll.Height = Dim.Fill ();
  506. }
  507. super.Add (scroll);
  508. scroll.Size = sliderSize;
  509. scroll.Layout ();
  510. scroll.ContentPosition = sliderPosition;
  511. super.BeginInit ();
  512. super.EndInit ();
  513. super.Layout ();
  514. super.Draw ();
  515. _ = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  516. }
  517. }