ScrollBarTests.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845
  1. using Xunit.Abstractions;
  2. using static Unix.Terminal.Delegates;
  3. namespace Terminal.Gui.ViewsTests;
  4. public class ScrollBarTests
  5. {
  6. public ScrollBarTests (ITestOutputHelper output) { _output = output; }
  7. private readonly ITestOutputHelper _output;
  8. [Fact]
  9. [AutoInitShutdown]
  10. public void AutoHideScrollBar_CheckScrollBarVisibility ()
  11. {
  12. var scrollBar = new ScrollBar { Width = 2, Height = Dim.Fill (), Size = 30 };
  13. View scrollBarSuperView = ScrollBarSuperView ();
  14. scrollBarSuperView.Add (scrollBar);
  15. Application.Begin ((scrollBarSuperView.SuperView as Toplevel)!);
  16. Assert.Equal (Orientation.Vertical, scrollBar.Orientation);
  17. //Assert.True (scrollBar.ShowScrollIndicator);
  18. Assert.True (scrollBar.Visible);
  19. Assert.Equal ("Absolute(2)", scrollBar.Width!.ToString ());
  20. Assert.Equal (2, scrollBar.Viewport.Width);
  21. Assert.Equal ("Fill(Absolute(0))", scrollBar.Height!.ToString ());
  22. Assert.Equal (25, scrollBar.Viewport.Height);
  23. scrollBar.Size = 10;
  24. //Assert.False (scrollBar.ShowScrollIndicator);
  25. Assert.False (scrollBar.Visible);
  26. scrollBar.Size = 30;
  27. //Assert.True (scrollBar.ShowScrollIndicator);
  28. Assert.True (scrollBar.Visible);
  29. scrollBar.AutoHide = false;
  30. //Assert.True (scrollBar.ShowScrollIndicator);
  31. Assert.True (scrollBar.Visible);
  32. scrollBar.Size = 10;
  33. //Assert.True (scrollBar.ShowScrollIndicator);
  34. Assert.True (scrollBar.Visible);
  35. scrollBarSuperView.SuperView!.Dispose ();
  36. }
  37. [Fact]
  38. public void Constructor_Defaults ()
  39. {
  40. var scrollBar = new ScrollBar ();
  41. Assert.False (scrollBar.CanFocus);
  42. Assert.Equal (Orientation.Vertical, scrollBar.Orientation);
  43. Assert.Equal (0, scrollBar.Size);
  44. Assert.Equal (0, scrollBar.GetSliderPosition ());
  45. Assert.True (scrollBar.AutoHide);
  46. }
  47. [Fact]
  48. public void OnOrientationChanged_Keeps_Size ()
  49. {
  50. var scroll = new ScrollBar ();
  51. scroll.Layout ();
  52. scroll.Size = 1;
  53. scroll.Orientation = Orientation.Horizontal;
  54. Assert.Equal (1, scroll.Size);
  55. }
  56. [Fact]
  57. public void OnOrientationChanged_Sets_Position_To_0 ()
  58. {
  59. View super = new View ()
  60. {
  61. Id = "super",
  62. Width = 10,
  63. Height = 10
  64. };
  65. var scrollBar = new ScrollBar ()
  66. {
  67. };
  68. super.Add (scrollBar);
  69. scrollBar.Layout ();
  70. scrollBar.ContentPosition = 1;
  71. scrollBar.Orientation = Orientation.Horizontal;
  72. Assert.Equal (0, scrollBar.GetSliderPosition ());
  73. }
  74. [Fact]
  75. public void ContentPosition_Event_Cancelables ()
  76. {
  77. var changingCount = 0;
  78. var changedCount = 0;
  79. var scrollBar = new ScrollBar { };
  80. scrollBar.Layout ();
  81. scrollBar.Size = scrollBar.Viewport.Height * 2;
  82. scrollBar.Layout ();
  83. scrollBar.ContentPositionChanging += (s, e) =>
  84. {
  85. if (changingCount == 0)
  86. {
  87. e.Cancel = true;
  88. }
  89. changingCount++;
  90. };
  91. scrollBar.ContentPositionChanged += (s, e) => changedCount++;
  92. scrollBar.ContentPosition = 1;
  93. Assert.Equal (0, scrollBar.ContentPosition);
  94. Assert.Equal (1, changingCount);
  95. Assert.Equal (0, changedCount);
  96. scrollBar.ContentPosition = 1;
  97. Assert.Equal (1, scrollBar.ContentPosition);
  98. Assert.Equal (2, changingCount);
  99. Assert.Equal (1, changedCount);
  100. }
  101. [Fact (Skip = "Disabled - Will put this feature in View")]
  102. [AutoInitShutdown]
  103. public void KeepContentInAllViewport_True_False ()
  104. {
  105. var view = new View { Width = Dim.Fill (), Height = Dim.Fill () };
  106. view.Padding.Thickness = new (0, 0, 2, 0);
  107. view.SetContentSize (new (view.Viewport.Width, 30));
  108. var scrollBar = new ScrollBar { Width = 2, Height = Dim.Fill (), Size = view.GetContentSize ().Height };
  109. scrollBar.SliderPositionChanged += (_, e) => view.Viewport = view.Viewport with { Y = e.CurrentValue };
  110. view.Padding.Add (scrollBar);
  111. var top = new Toplevel ();
  112. top.Add (view);
  113. Application.Begin (top);
  114. Assert.False (scrollBar.KeepContentInAllViewport);
  115. scrollBar.KeepContentInAllViewport = true;
  116. Assert.Equal (80, view.Padding.Viewport.Width);
  117. Assert.Equal (25, view.Padding.Viewport.Height);
  118. Assert.Equal (2, scrollBar.Viewport.Width);
  119. Assert.Equal (25, scrollBar.Viewport.Height);
  120. Assert.Equal (30, scrollBar.Size);
  121. scrollBar.KeepContentInAllViewport = false;
  122. scrollBar.ContentPosition = 50;
  123. Assert.Equal (scrollBar.GetSliderPosition (), scrollBar.Size - 1);
  124. Assert.Equal (scrollBar.GetSliderPosition (), view.Viewport.Y);
  125. Assert.Equal (29, scrollBar.GetSliderPosition ());
  126. Assert.Equal (29, view.Viewport.Y);
  127. top.Dispose ();
  128. }
  129. [Fact]
  130. public void Size_Cannot_Be_Negative ()
  131. {
  132. var scrollBar = new ScrollBar { Height = 10, Size = -1 };
  133. Assert.Equal (0, scrollBar.Size);
  134. scrollBar.Size = -10;
  135. Assert.Equal (0, scrollBar.Size);
  136. }
  137. [Fact]
  138. public void SizeChanged_Event ()
  139. {
  140. var count = 0;
  141. var scrollBar = new ScrollBar ();
  142. scrollBar.SizeChanged += (s, e) => count++;
  143. scrollBar.Size = 10;
  144. Assert.Equal (10, scrollBar.Size);
  145. Assert.Equal (1, count);
  146. }
  147. [Theory]
  148. [SetupFakeDriver]
  149. #region Vertical
  150. #region Super 10 - ScrollBar 8
  151. [InlineData (
  152. 10,
  153. 1,
  154. 10,
  155. -1,
  156. Orientation.Horizontal,
  157. @"
  158. ┌──────────┐
  159. │◄████████►│
  160. └──────────┘")]
  161. [InlineData (
  162. 10,
  163. 1,
  164. 20,
  165. -1,
  166. Orientation.Horizontal,
  167. @"
  168. ┌──────────┐
  169. │◄████░░░░►│
  170. └──────────┘")]
  171. [InlineData (
  172. 10,
  173. 1,
  174. 20,
  175. 0,
  176. Orientation.Horizontal,
  177. @"
  178. ┌──────────┐
  179. │◄████░░░░►│
  180. └──────────┘")]
  181. [InlineData (
  182. 10,
  183. 1,
  184. 20,
  185. 1,
  186. Orientation.Horizontal,
  187. @"
  188. ┌──────────┐
  189. │◄████░░░░►│
  190. └──────────┘")]
  191. [InlineData (
  192. 10,
  193. 1,
  194. 20,
  195. 2,
  196. Orientation.Horizontal,
  197. @"
  198. ┌──────────┐
  199. │◄░████░░░►│
  200. └──────────┘
  201. ")]
  202. [InlineData (
  203. 10,
  204. 1,
  205. 20,
  206. 3,
  207. Orientation.Horizontal,
  208. @"
  209. ┌──────────┐
  210. │◄░████░░░►│
  211. └──────────┘
  212. ")]
  213. [InlineData (
  214. 10,
  215. 1,
  216. 20,
  217. 4,
  218. Orientation.Horizontal,
  219. @"
  220. ┌──────────┐
  221. │◄░░████░░►│
  222. └──────────┘
  223. ")]
  224. [InlineData (
  225. 10,
  226. 1,
  227. 20,
  228. 5,
  229. Orientation.Horizontal,
  230. @"
  231. ┌──────────┐
  232. │◄░░████░░►│
  233. └──────────┘
  234. ")]
  235. [InlineData (
  236. 10,
  237. 1,
  238. 20,
  239. 6,
  240. Orientation.Horizontal,
  241. @"
  242. ┌──────────┐
  243. │◄░░░████░►│
  244. └──────────┘
  245. ")]
  246. [InlineData (
  247. 10,
  248. 1,
  249. 20,
  250. 7,
  251. Orientation.Horizontal,
  252. @"
  253. ┌──────────┐
  254. │◄░░░████░►│
  255. └──────────┘
  256. ")]
  257. [InlineData (
  258. 10,
  259. 1,
  260. 20,
  261. 8,
  262. Orientation.Horizontal,
  263. @"
  264. ┌──────────┐
  265. │◄░░░░████►│
  266. └──────────┘
  267. ")]
  268. [InlineData (
  269. 10,
  270. 1,
  271. 20,
  272. 9,
  273. Orientation.Horizontal,
  274. @"
  275. ┌──────────┐
  276. │◄░░░░████►│
  277. └──────────┘
  278. ")]
  279. [InlineData (
  280. 10,
  281. 1,
  282. 20,
  283. 10,
  284. Orientation.Horizontal,
  285. @"
  286. ┌──────────┐
  287. │◄░░░░████►│
  288. └──────────┘
  289. ")]
  290. [InlineData (
  291. 10,
  292. 1,
  293. 20,
  294. 19,
  295. Orientation.Horizontal,
  296. @"
  297. ┌──────────┐
  298. │◄░░░░████►│
  299. └──────────┘
  300. ")]
  301. [InlineData (
  302. 10,
  303. 1,
  304. 20,
  305. 20,
  306. Orientation.Horizontal,
  307. @"
  308. ┌──────────┐
  309. │◄░░░░████►│
  310. └──────────┘
  311. ")]
  312. #endregion Super 10 - ScrollBar 8
  313. #region Super 12 - ScrollBar 10
  314. [InlineData (
  315. 12,
  316. 1,
  317. 10,
  318. -1,
  319. Orientation.Horizontal,
  320. @"
  321. ┌────────────┐
  322. │◄██████████►│
  323. └────────────┘")]
  324. [InlineData (
  325. 12,
  326. 1,
  327. 20,
  328. -1,
  329. Orientation.Horizontal,
  330. @"
  331. ┌────────────┐
  332. │◄██████░░░░►│
  333. └────────────┘")]
  334. [InlineData (
  335. 12,
  336. 1,
  337. 20,
  338. 0,
  339. Orientation.Horizontal,
  340. @"
  341. ┌────────────┐
  342. │◄██████░░░░►│
  343. └────────────┘")]
  344. [InlineData (
  345. 12,
  346. 1,
  347. 20,
  348. 1,
  349. Orientation.Horizontal,
  350. @"
  351. ┌────────────┐
  352. │◄██████░░░░►│
  353. └────────────┘")]
  354. [InlineData (
  355. 12,
  356. 1,
  357. 20,
  358. 2,
  359. Orientation.Horizontal,
  360. @"
  361. ┌────────────┐
  362. │◄░██████░░░►│
  363. └────────────┘
  364. ")]
  365. [InlineData (
  366. 12,
  367. 1,
  368. 20,
  369. 3,
  370. Orientation.Horizontal,
  371. @"
  372. ┌────────────┐
  373. │◄░██████░░░►│
  374. └────────────┘
  375. ")]
  376. [InlineData (
  377. 12,
  378. 1,
  379. 20,
  380. 4,
  381. Orientation.Horizontal,
  382. @"
  383. ┌────────────┐
  384. │◄░░██████░░►│
  385. └────────────┘
  386. ")]
  387. [InlineData (
  388. 12,
  389. 1,
  390. 20,
  391. 5,
  392. Orientation.Horizontal,
  393. @"
  394. ┌────────────┐
  395. │◄░░░██████░►│
  396. └────────────┘
  397. ")]
  398. [InlineData (
  399. 12,
  400. 1,
  401. 20,
  402. 6,
  403. Orientation.Horizontal,
  404. @"
  405. ┌────────────┐
  406. │◄░░░██████░►│
  407. └────────────┘
  408. ")]
  409. [InlineData (
  410. 12,
  411. 1,
  412. 20,
  413. 7,
  414. Orientation.Horizontal,
  415. @"
  416. ┌────────────┐
  417. │◄░░░░██████►│
  418. └────────────┘
  419. ")]
  420. [InlineData (
  421. 12,
  422. 1,
  423. 20,
  424. 8,
  425. Orientation.Horizontal,
  426. @"
  427. ┌────────────┐
  428. │◄░░░░██████►│
  429. └────────────┘
  430. ")]
  431. [InlineData (
  432. 12,
  433. 1,
  434. 20,
  435. 9,
  436. Orientation.Horizontal,
  437. @"
  438. ┌────────────┐
  439. │◄░░░░██████►│
  440. └────────────┘
  441. ")]
  442. [InlineData (
  443. 12,
  444. 1,
  445. 20,
  446. 10,
  447. Orientation.Horizontal,
  448. @"
  449. ┌────────────┐
  450. │◄░░░░██████►│
  451. └────────────┘
  452. ")]
  453. [InlineData (
  454. 12,
  455. 1,
  456. 20,
  457. 19,
  458. Orientation.Horizontal,
  459. @"
  460. ┌────────────┐
  461. │◄░░░░██████►│
  462. └────────────┘
  463. ")]
  464. [InlineData (
  465. 12,
  466. 1,
  467. 20,
  468. 20,
  469. Orientation.Horizontal,
  470. @"
  471. ┌────────────┐
  472. │◄░░░░██████►│
  473. └────────────┘
  474. ")]
  475. #endregion Super 12 - ScrollBar 10
  476. [InlineData (
  477. 10,
  478. 3,
  479. 20,
  480. 2,
  481. Orientation.Horizontal,
  482. @"
  483. ┌──────────┐
  484. │ ░████░░░ │
  485. │◄░████░░░►│
  486. │ ░████░░░ │
  487. └──────────┘
  488. ")]
  489. #endregion Vertical
  490. #region Horizontal
  491. [InlineData (
  492. 1,
  493. 10,
  494. 10,
  495. -1,
  496. Orientation.Vertical,
  497. @"
  498. ┌─┐
  499. │▲│
  500. │█│
  501. │█│
  502. │█│
  503. │█│
  504. │█│
  505. │█│
  506. │█│
  507. │█│
  508. │▼│
  509. └─┘")]
  510. [InlineData (
  511. 1,
  512. 10,
  513. 10,
  514. 5,
  515. Orientation.Vertical,
  516. @"
  517. ┌─┐
  518. │▲│
  519. │█│
  520. │█│
  521. │█│
  522. │█│
  523. │█│
  524. │█│
  525. │█│
  526. │█│
  527. │▼│
  528. └─┘")]
  529. [InlineData (
  530. 1,
  531. 10,
  532. 20,
  533. 5,
  534. Orientation.Vertical,
  535. @"
  536. ┌─┐
  537. │▲│
  538. │░│
  539. │░│
  540. │█│
  541. │█│
  542. │█│
  543. │█│
  544. │░│
  545. │░│
  546. │▼│
  547. └─┘")]
  548. [InlineData (
  549. 1,
  550. 12,
  551. 20,
  552. 5,
  553. Orientation.Vertical,
  554. @"
  555. ┌─┐
  556. │▲│
  557. │░│
  558. │░│
  559. │░│
  560. │█│
  561. │█│
  562. │█│
  563. │█│
  564. │█│
  565. │█│
  566. │░│
  567. │▼│
  568. └─┘")]
  569. [InlineData (
  570. 3,
  571. 10,
  572. 20,
  573. 2,
  574. Orientation.Vertical,
  575. @"
  576. ┌───┐
  577. │ ▲ │
  578. │░░░│
  579. │███│
  580. │███│
  581. │███│
  582. │███│
  583. │░░░│
  584. │░░░│
  585. │░░░│
  586. │ ▼ │
  587. └───┘
  588. ")]
  589. #endregion
  590. public void Draws_Correctly (int superWidth, int superHeight, int contentSize, int contentPosition, Orientation orientation, string expected)
  591. {
  592. var super = new Window
  593. {
  594. Id = "super",
  595. Width = superWidth + 2,
  596. Height = superHeight + 2
  597. };
  598. var scrollBar = new ScrollBar
  599. {
  600. Orientation = orientation,
  601. };
  602. if (orientation == Orientation.Vertical)
  603. {
  604. scrollBar.Width = Dim.Fill ();
  605. }
  606. else
  607. {
  608. scrollBar.Height = Dim.Fill ();
  609. }
  610. super.Add (scrollBar);
  611. scrollBar.Size = contentSize;
  612. scrollBar.Layout ();
  613. scrollBar.ContentPosition = contentPosition;
  614. super.BeginInit ();
  615. super.EndInit ();
  616. super.Layout ();
  617. super.Draw ();
  618. _ = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  619. }
  620. private View ScrollBarSuperView ()
  621. {
  622. var view = new View
  623. {
  624. Width = Dim.Fill (),
  625. Height = Dim.Fill ()
  626. };
  627. var top = new Toplevel ();
  628. top.Add (view);
  629. return view;
  630. }
  631. [Theory]
  632. [CombinatorialData]
  633. [AutoInitShutdown]
  634. public void Mouse_Click_DecrementButton_Decrements ([CombinatorialRange (1, 3, 1)] int increment, Orientation orientation)
  635. {
  636. var top = new Toplevel ()
  637. {
  638. Id = "top",
  639. Width = 10,
  640. Height = 10
  641. };
  642. var scrollBar = new ScrollBar
  643. {
  644. Id = "scrollBar",
  645. Orientation = orientation,
  646. Size = 20,
  647. Increment = increment
  648. };
  649. top.Add (scrollBar);
  650. RunState rs = Application.Begin (top);
  651. scrollBar.ContentPosition = 5;
  652. Application.RunIteration (ref rs);
  653. Assert.Equal (5, scrollBar.GetSliderPosition ());
  654. Assert.Equal (12, scrollBar.ContentPosition);
  655. int initialPos = scrollBar.ContentPosition;
  656. Application.RaiseMouseEvent (new ()
  657. {
  658. ScreenPosition = new (0, 0),
  659. Flags = MouseFlags.Button1Clicked
  660. });
  661. Application.RunIteration (ref rs);
  662. Assert.Equal (initialPos - increment, scrollBar.ContentPosition);
  663. Application.ResetState (true);
  664. }
  665. [Theory]
  666. [CombinatorialData]
  667. [AutoInitShutdown]
  668. public void Mouse_Click_IncrementButton_Increments ([CombinatorialRange (1, 3, 1)] int increment, Orientation orientation)
  669. {
  670. var top = new Toplevel ()
  671. {
  672. Id = "top",
  673. Width = 10,
  674. Height = 10
  675. };
  676. var scrollBar = new ScrollBar
  677. {
  678. Id = "scrollBar",
  679. Orientation = orientation,
  680. Size = 20,
  681. Increment = increment
  682. };
  683. top.Add (scrollBar);
  684. RunState rs = Application.Begin (top);
  685. scrollBar.ContentPosition = 0;
  686. Application.RunIteration (ref rs);
  687. Assert.Equal (0, scrollBar.GetSliderPosition ());
  688. Assert.Equal (0, scrollBar.ContentPosition);
  689. int initialPos = scrollBar.ContentPosition;
  690. Application.RaiseMouseEvent (new ()
  691. {
  692. ScreenPosition = orientation == Orientation.Vertical ? new (0, scrollBar.Frame.Height - 1) : new (scrollBar.Frame.Width - 1, 0),
  693. Flags = MouseFlags.Button1Clicked
  694. });
  695. Application.RunIteration (ref rs);
  696. Assert.Equal (initialPos + increment, scrollBar.ContentPosition);
  697. Application.ResetState (true);
  698. }
  699. [Theory]
  700. [InlineData (1, 10, 0, 0)]
  701. [InlineData (1, 10, 5, 0)]
  702. [InlineData (1, 10, 10, 1)]
  703. [InlineData (1, 20, 0, 0)]
  704. [InlineData (1, 20, 10, 0)]
  705. [InlineData (1, 20, 20, 1)]
  706. [InlineData (2, 10, 0, 0)]
  707. [InlineData (2, 10, 5, 1)]
  708. [InlineData (2, 10, 10, 2)]
  709. [InlineData (2, 20, 0, 0)]
  710. [InlineData (2, 20, 10, 1)]
  711. [InlineData (2, 20, 20, 2)]
  712. [InlineData (3, 10, 0, 0)]
  713. [InlineData (3, 10, 5, 1)]
  714. [InlineData (3, 10, 10, 3)]
  715. [InlineData (3, 20, 0, 0)]
  716. [InlineData (3, 20, 10, 1)]
  717. [InlineData (3, 20, 20, 3)]
  718. [InlineData (4, 10, 0, 0)]
  719. [InlineData (4, 10, 5, 2)]
  720. [InlineData (4, 10, 10, 4)]
  721. [InlineData (4, 20, 0, 0)]
  722. [InlineData (4, 20, 10, 2)]
  723. [InlineData (4, 20, 20, 4)]
  724. [InlineData (5, 10, 0, 0)]
  725. [InlineData (5, 10, 5, 2)]
  726. [InlineData (5, 10, 10, 5)]
  727. [InlineData (5, 20, 0, 0)]
  728. [InlineData (5, 20, 10, 2)]
  729. [InlineData (5, 20, 20, 5)]
  730. public void ScrollBar_CombinatorialTests (int width, int size, int contentPosition, int expectedSliderPosition)
  731. {
  732. // Arrange
  733. var scrollBar = new ScrollBar
  734. {
  735. Width = width,
  736. Size = size,
  737. ContentPosition = contentPosition
  738. };
  739. scrollBar.Layout ();
  740. // Act
  741. var sliderPosition = scrollBar.GetSliderPosition ();
  742. // Assert
  743. Assert.Equal (expectedSliderPosition, sliderPosition);
  744. }
  745. }