ScrollBarTests.cs 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289
  1. using Xunit.Abstractions;
  2. using static Unix.Terminal.Delegates;
  3. namespace Terminal.Gui.ViewsTests;
  4. public class ScrollBarTests (ITestOutputHelper output)
  5. {
  6. [Fact]
  7. public void Constructor_Defaults ()
  8. {
  9. var scrollBar = new ScrollBar ();
  10. Assert.False (scrollBar.CanFocus);
  11. Assert.Equal (Orientation.Vertical, scrollBar.Orientation);
  12. Assert.Equal (0, scrollBar.ScrollableContentSize);
  13. Assert.Equal (0, scrollBar.VisibleContentSize);
  14. Assert.Equal (0, scrollBar.GetSliderPosition ());
  15. Assert.Equal (0, scrollBar.Position);
  16. Assert.True (scrollBar.AutoHide);
  17. }
  18. #region AutoHide
  19. [Fact]
  20. [AutoInitShutdown]
  21. public void AutoHide_True_Is_Default_CorrectlyHidesAndShows ()
  22. {
  23. var super = new Toplevel ()
  24. {
  25. Id = "super",
  26. Width = 1,
  27. Height = 20
  28. };
  29. var scrollBar = new ScrollBar
  30. {
  31. ScrollableContentSize = 20,
  32. };
  33. super.Add (scrollBar);
  34. Assert.True (scrollBar.AutoHide);
  35. Assert.True (scrollBar.Visible); // Before Init
  36. RunState rs = Application.Begin (super);
  37. // Should Show
  38. scrollBar.ScrollableContentSize = 21;
  39. Application.RunIteration (ref rs);
  40. Assert.True (scrollBar.Visible);
  41. // Should Hide
  42. scrollBar.ScrollableContentSize = 10;
  43. Assert.False (scrollBar.Visible);
  44. super.Dispose ();
  45. }
  46. [Fact]
  47. [AutoInitShutdown]
  48. public void AutoHide_False_CorrectlyHidesAndShows ()
  49. {
  50. var super = new Toplevel ()
  51. {
  52. Id = "super",
  53. Width = 1,
  54. Height = 20
  55. };
  56. var scrollBar = new ScrollBar
  57. {
  58. ScrollableContentSize = 20,
  59. AutoHide = false
  60. };
  61. super.Add (scrollBar);
  62. Assert.False (scrollBar.AutoHide);
  63. Assert.True (scrollBar.Visible);
  64. RunState rs = Application.Begin (super);
  65. // Should Hide if AutoSize = true, but should not hide if AutoSize = false
  66. scrollBar.ScrollableContentSize = 10;
  67. Assert.True (scrollBar.Visible);
  68. super.Dispose ();
  69. }
  70. [Fact]
  71. [AutoInitShutdown]
  72. public void AutoHide_Change_AutoSize_CorrectlyHidesAndShows ()
  73. {
  74. var super = new Toplevel ()
  75. {
  76. Id = "super",
  77. Width = 1,
  78. Height = 20
  79. };
  80. var scrollBar = new ScrollBar
  81. {
  82. ScrollableContentSize = 20,
  83. };
  84. super.Add (scrollBar);
  85. Assert.True (scrollBar.AutoHide);
  86. Assert.True (scrollBar.Visible); // Before Init
  87. RunState rs = Application.Begin (super);
  88. Assert.False (scrollBar.Visible);
  89. Assert.Equal (1, scrollBar.Frame.Width);
  90. Assert.Equal (20, scrollBar.Frame.Height);
  91. scrollBar.ScrollableContentSize = 10;
  92. Application.RunIteration (ref rs);
  93. Assert.False (scrollBar.Visible);
  94. scrollBar.ScrollableContentSize = 30;
  95. Assert.True (scrollBar.Visible);
  96. scrollBar.AutoHide = false;
  97. Assert.True (scrollBar.Visible);
  98. scrollBar.ScrollableContentSize = 10;
  99. Assert.True (scrollBar.Visible);
  100. super.Dispose ();
  101. }
  102. [Fact]
  103. [AutoInitShutdown]
  104. public void AutoHide_Change_Size_CorrectlyHidesAndShows ()
  105. {
  106. var super = new Toplevel ()
  107. {
  108. Id = "super",
  109. Width = 1,
  110. Height = 20
  111. };
  112. var scrollBar = new ScrollBar
  113. {
  114. ScrollableContentSize = 20,
  115. };
  116. super.Add (scrollBar);
  117. RunState rs = Application.Begin (super);
  118. Assert.Equal (Orientation.Vertical, scrollBar.Orientation);
  119. Assert.Equal (20, scrollBar.VisibleContentSize);
  120. //Assert.True (scrollBar.ShowScrollIndicator);
  121. Assert.False (scrollBar.Visible);
  122. Assert.Equal (1, scrollBar.Frame.Width);
  123. Assert.Equal (20, scrollBar.Frame.Height);
  124. scrollBar.ScrollableContentSize = 10;
  125. Application.RunIteration (ref rs);
  126. //Assert.False (scrollBar.ShowScrollIndicator);
  127. Assert.False (scrollBar.Visible);
  128. scrollBar.ScrollableContentSize = 30;
  129. //Assert.True (scrollBar.ShowScrollIndicator);
  130. Assert.True (scrollBar.Visible);
  131. scrollBar.ScrollableContentSize = 10;
  132. Application.RunIteration (ref rs);
  133. //Assert.False (scrollBar.ShowScrollIndicator);
  134. Assert.False (scrollBar.Visible);
  135. scrollBar.ScrollableContentSize = 21;
  136. //Assert.True (scrollBar.ShowScrollIndicator);
  137. Assert.True (scrollBar.Visible);
  138. scrollBar.AutoHide = false;
  139. //Assert.True (scrollBar.ShowScrollIndicator);
  140. Assert.True (scrollBar.Visible);
  141. scrollBar.ScrollableContentSize = 10;
  142. //Assert.True (scrollBar.ShowScrollIndicator);
  143. Assert.True (scrollBar.Visible);
  144. super.Dispose ();
  145. }
  146. #endregion AutoHide
  147. #region Orientation
  148. [Fact]
  149. public void OnOrientationChanged_Keeps_Size ()
  150. {
  151. var scroll = new ScrollBar ();
  152. scroll.Layout ();
  153. scroll.ScrollableContentSize = 1;
  154. scroll.Orientation = Orientation.Horizontal;
  155. Assert.Equal (1, scroll.ScrollableContentSize);
  156. }
  157. [Fact]
  158. public void OnOrientationChanged_Sets_Position_To_0 ()
  159. {
  160. View super = new View ()
  161. {
  162. Id = "super",
  163. Width = 10,
  164. Height = 10
  165. };
  166. var scrollBar = new ScrollBar ()
  167. {
  168. };
  169. super.Add (scrollBar);
  170. scrollBar.Layout ();
  171. scrollBar.Position = 1;
  172. scrollBar.Orientation = Orientation.Horizontal;
  173. Assert.Equal (0, scrollBar.GetSliderPosition ());
  174. }
  175. #endregion Orientation
  176. #region Slider
  177. [Theory]
  178. [InlineData (-1, 10, 1)]
  179. [InlineData (0, 10, 1)]
  180. [InlineData (10, 15, 5)]
  181. [InlineData (10, 5, 8)]
  182. [InlineData (10, 3, 8)]
  183. [InlineData (10, 2, 8)]
  184. [InlineData (10, 1, 8)]
  185. [InlineData (10, 0, 8)]
  186. [InlineData (10, 10, 8)]
  187. [InlineData (10, 20, 4)]
  188. [InlineData (10, 100, 1)]
  189. [InlineData (15, 0, 13)]
  190. [InlineData (15, 1, 13)]
  191. [InlineData (15, 2, 13)]
  192. [InlineData (15, 3, 13)]
  193. [InlineData (15, 5, 13)]
  194. [InlineData (15, 10, 13)]
  195. [InlineData (15, 14, 13)]
  196. [InlineData (15, 15, 13)]
  197. [InlineData (15, 16, 12)]
  198. [InlineData (20, 10, 18)]
  199. [InlineData (100, 10, 98)]
  200. public void CalculateSliderSize_Width_Is_VisibleContentSize_CalculatesCorrectly (int visibleContentSize, int scrollableContentSize, int expectedSliderSize)
  201. {
  202. // Arrange
  203. var scrollBar = new ScrollBar
  204. {
  205. VisibleContentSize = visibleContentSize,
  206. ScrollableContentSize = scrollableContentSize,
  207. Orientation = Orientation.Horizontal // Assuming horizontal for simplicity
  208. };
  209. scrollBar.Width = visibleContentSize;
  210. // Act
  211. var sliderSize = scrollBar.CalculateSliderSize ();
  212. // Assert
  213. Assert.Equal (expectedSliderSize, sliderSize);
  214. }
  215. [Theory]
  216. // 0123456789
  217. // -
  218. // **********
  219. // ◄███►
  220. [InlineData (5, 10, 1, 3)]
  221. // 01234567890
  222. // ----------
  223. // **********
  224. // ◄██░►
  225. [InlineData (5, 10, 11, 2)]
  226. [InlineData (20, 10, 1, 18)]
  227. //// ◄█░░░░░░░►
  228. //[InlineData (1, 10, 1)]
  229. //// ---------
  230. //// ◄████░░░░►
  231. //[InlineData (5, 10, 4)]
  232. //// ----------
  233. //// ◄███░░░░░►
  234. //[InlineData (5, 11, 3)]
  235. //[InlineData (5, 12, 3)]
  236. //[InlineData (5, 13, 3)]
  237. //// 012345678901234
  238. //// --------------
  239. //// ◄██░░░░░░►
  240. //[InlineData (5, 14, 2)]
  241. //[InlineData (5, 15, 2)]
  242. //[InlineData (5, 16, 2)]
  243. //// 012345678901234567890
  244. //// ----------------
  245. //// ◄██░░░░░░►
  246. //[InlineData (5, 18, 2)]
  247. //[InlineData (5, 19, 2)]
  248. //[InlineData (5, 20, 2)]
  249. //// 012345678901234567890
  250. //// --------------------
  251. //// ◄█░░░░░░░►
  252. //[InlineData (5, 21, 1)]
  253. //[InlineData (5, 22, 1)]
  254. //[InlineData (5, 23, 1)]
  255. public void CalculateSliderSize_Width_Is_LT_VisibleContentSize_CalculatesCorrectly (int width, int visibleContentSize, int scrollableContentSize, int expectedSliderSize)
  256. {
  257. // Arrange
  258. var scrollBar = new ScrollBar
  259. {
  260. VisibleContentSize = visibleContentSize,
  261. ScrollableContentSize = scrollableContentSize,
  262. Orientation = Orientation.Horizontal // Assuming horizontal for simplicity
  263. };
  264. scrollBar.Width = width;
  265. // Act
  266. var sliderSize = scrollBar.CalculateSliderSize ();
  267. // Assert
  268. Assert.Equal (expectedSliderSize, sliderSize);
  269. }
  270. [Theory]
  271. // 0123456789
  272. // ---------
  273. // ◄█░░░░░░░►
  274. [InlineData (0, 10, 1)]
  275. // ◄█░░░░░░░►
  276. [InlineData (1, 10, 1)]
  277. // ---------
  278. // ◄████░░░░►
  279. [InlineData (5, 10, 4)]
  280. // ----------
  281. // ◄███░░░░░►
  282. [InlineData (5, 11, 3)]
  283. [InlineData (5, 12, 3)]
  284. [InlineData (5, 13, 3)]
  285. // 012345678901234
  286. // --------------
  287. // ◄██░░░░░░►
  288. [InlineData (5, 14, 2)]
  289. [InlineData (5, 15, 2)]
  290. [InlineData (5, 16, 2)]
  291. // 012345678901234567890
  292. // ----------------
  293. // ◄██░░░░░░►
  294. [InlineData (5, 18, 2)]
  295. [InlineData (5, 19, 2)]
  296. [InlineData (5, 20, 2)]
  297. // 012345678901234567890
  298. // --------------------
  299. // ◄█░░░░░░░►
  300. [InlineData (5, 21, 1)]
  301. [InlineData (5, 22, 1)]
  302. [InlineData (5, 23, 1)]
  303. public void CalculateSliderSize_Width_Is_GT_VisibleContentSize_CalculatesCorrectly (int visibleContentSize, int scrollableContentSize, int expectedSliderSize)
  304. {
  305. // Arrange
  306. var scrollBar = new ScrollBar
  307. {
  308. VisibleContentSize = visibleContentSize,
  309. ScrollableContentSize = scrollableContentSize,
  310. Orientation = Orientation.Horizontal // Assuming horizontal for simplicity
  311. };
  312. scrollBar.Width = 10;
  313. // Act
  314. var sliderSize = scrollBar.CalculateSliderSize ();
  315. // Assert
  316. Assert.Equal (expectedSliderSize, sliderSize);
  317. }
  318. [Theory]
  319. // 0123456789
  320. // ---------
  321. // ◄█►
  322. [InlineData (3, 3, 0, 0)]
  323. [InlineData (3, 3, 1, 0)]
  324. [InlineData (3, 3, 2, 0)]
  325. // 0123456789
  326. // ---------
  327. // ◄██►
  328. [InlineData (4, 4, 0, 0)]
  329. [InlineData (4, 4, 1, 0)]
  330. [InlineData (4, 4, 2, 0)]
  331. [InlineData (4, 4, 3, 0)]
  332. [InlineData (4, 4, 4, 0)]
  333. // 012345
  334. // ^----
  335. // ◄█░►
  336. [InlineData (4, 5, 0, 0)]
  337. // -^---
  338. // ◄█░►
  339. [InlineData (4, 5, 1, 0)]
  340. // --^--
  341. // ◄░█►
  342. [InlineData (4, 5, 2, 1)]
  343. // ---^-
  344. // ◄░█►
  345. [InlineData (4, 5, 3, 1)]
  346. // ----^
  347. // ◄░█►
  348. [InlineData (4, 5, 4, 1)]
  349. // 01234
  350. // ^---------
  351. // ◄█░░►
  352. [InlineData (5, 10, 0, 0)]
  353. // -^--------
  354. // ◄█░░►
  355. [InlineData (5, 10, 1, 0)]
  356. // --^-------
  357. // ◄█░░►
  358. [InlineData (5, 10, 2, 0)]
  359. // ---^------
  360. // ◄█░░►
  361. [InlineData (5, 10, 3, 0)]
  362. // ----^----
  363. // ◄░█░►
  364. [InlineData (5, 10, 4, 1)]
  365. // -----^---
  366. // ◄░█░►
  367. [InlineData (5, 10, 5, 1)]
  368. // ------^--
  369. // ◄░░█►
  370. [InlineData (5, 10, 6, 2)]
  371. // ------^--
  372. // ◄░░█►
  373. [InlineData (5, 10, 7, 2)]
  374. // -------^-
  375. // ◄░░█►
  376. [InlineData (5, 10, 8, 2)]
  377. // --------^
  378. // ◄░░█►
  379. [InlineData (5, 10, 9, 2)]
  380. [InlineData (10, 20, 0, 0)]
  381. [InlineData (10, 20, 1, 0)]
  382. [InlineData (10, 20, 2, 0)]
  383. [InlineData (10, 20, 3, 1)]
  384. [InlineData (10, 20, 4, 2)]
  385. [InlineData (10, 20, 5, 2)]
  386. [InlineData (10, 20, 6, 3)]
  387. [InlineData (10, 20, 7, 4)]
  388. [InlineData (10, 20, 8, 4)]
  389. public void CalculateSliderPosition_Calculates_Correctly (int visibleContentSize, int scrollableContentSize, int contentPosition, int expectedSliderPosition)
  390. {
  391. // Arrange
  392. var scrollBar = new ScrollBar
  393. {
  394. ScrollableContentSize = scrollableContentSize,
  395. VisibleContentSize = visibleContentSize,
  396. Orientation = Orientation.Horizontal // Assuming horizontal for simplicity
  397. };
  398. scrollBar.Width = visibleContentSize;
  399. // Act
  400. var sliderPosition= scrollBar.CalculateSliderPositionFromContentPosition (contentPosition, NavigationDirection.Forward);
  401. // Assert
  402. Assert.Equal (expectedSliderPosition, sliderPosition);
  403. }
  404. #endregion Slider
  405. #region Size
  406. // TODO: Add tests.
  407. #endregion Size
  408. #region Position
  409. // 012345678901
  410. // ◄█░░░░░░░░░►
  411. [Theory]
  412. // ◄█►
  413. [InlineData (3, 3, -1, 0)]
  414. [InlineData (3, 3, 0, 0)]
  415. // 012
  416. // ---
  417. // ◄█►
  418. [InlineData (3, 3, 1, 0)]
  419. [InlineData (3, 3, 2, 0)]
  420. // ◄██►
  421. [InlineData (4, 2, 1, 0)]
  422. [InlineData (4, 2, 2, 0)]
  423. // 0123
  424. // ---
  425. // ◄██►
  426. [InlineData (4, 3, 0, 0)] // scrollBarWidth/VisibleContentSize > size - scrolling doesn't make sense. Size should clamp to scrollSlider.Size.
  427. // ◄██►
  428. [InlineData (4, 3, 1, 0)]
  429. // ◄██►
  430. [InlineData (4, 3, 2, 0)]
  431. // 01234
  432. // ----
  433. // ◄██►
  434. [InlineData (4, 4, 0, 0)] // scrollBarWidth/VisibleContentSize == size - scrolling doesn't make sense. Size should clamp to scrollSlider.Size.
  435. // ◄██►
  436. [InlineData (4, 4, 1, 0)]
  437. // ◄██►
  438. [InlineData (4, 4, 2, 0)]
  439. // 012345
  440. // ◄███►
  441. // -----
  442. [InlineData (5, 5, 3, 0)]
  443. [InlineData (5, 5, 4, 0)]
  444. // 0123456
  445. // ◄██░►
  446. // ^-----
  447. [InlineData (5, 6, 0, 0)]
  448. // ◄░██►
  449. // -^----
  450. [InlineData (5, 6, 1, 1)]
  451. [InlineData (5, 6, 2, 1)]
  452. // 012346789
  453. // ◄█░░►
  454. // ^--------
  455. [InlineData (5, 10, -1, 0)]
  456. [InlineData (5, 10, 0, 0)]
  457. // 0123456789
  458. // ◄░█░►
  459. // --^-------
  460. [InlineData (5, 10, 1, 3)]
  461. // ◄░░█►
  462. // ----^----
  463. [InlineData (5, 10, 2, 5)]
  464. // ◄░░█►
  465. // ------^---
  466. [InlineData (5, 10, 4, 5)]
  467. // ◄░████░░░►
  468. // --------------------
  469. [InlineData (10, 20, 0, 0)]
  470. public void CalculatePosition_Calculates (int visibleContentSize, int scrollableContentSize, int sliderPosition, int expectedContentPosition)
  471. {
  472. // Arrange
  473. var scrollBar = new ScrollBar
  474. {
  475. VisibleContentSize = visibleContentSize,
  476. ScrollableContentSize = scrollableContentSize,
  477. Orientation = Orientation.Horizontal // Use Horizontal because it's easier to visualize
  478. };
  479. scrollBar.Frame = new (0, 0, visibleContentSize, 0);
  480. // Act
  481. var contentPosition = scrollBar.CalculatePositionFromSliderPosition (sliderPosition);
  482. // Assert
  483. Assert.Equal (expectedContentPosition, contentPosition);
  484. }
  485. [Fact]
  486. public void Position_Event_Cancelables ()
  487. {
  488. var changingCount = 0;
  489. var changedCount = 0;
  490. var scrollBar = new ScrollBar { };
  491. scrollBar.ScrollableContentSize = 5;
  492. scrollBar.Frame = new Rectangle (0, 0, 1, 4); // Needs to be at least 4 for slider to move
  493. scrollBar.PositionChanging += (s, e) =>
  494. {
  495. if (changingCount == 0)
  496. {
  497. e.Cancel = true;
  498. }
  499. changingCount++;
  500. };
  501. scrollBar.PositionChanged += (s, e) => changedCount++;
  502. scrollBar.Position = 1;
  503. Assert.Equal (0, scrollBar.Position);
  504. Assert.Equal (1, changingCount);
  505. Assert.Equal (0, changedCount);
  506. scrollBar.Position = 1;
  507. Assert.Equal (1, scrollBar.Position);
  508. Assert.Equal (2, changingCount);
  509. Assert.Equal (1, changedCount);
  510. }
  511. #endregion Position
  512. [Fact]
  513. public void ScrollableContentSize_Cannot_Be_Negative ()
  514. {
  515. var scrollBar = new ScrollBar { Height = 10, ScrollableContentSize = -1 };
  516. Assert.Equal (0, scrollBar.ScrollableContentSize);
  517. scrollBar.ScrollableContentSize = -10;
  518. Assert.Equal (0, scrollBar.ScrollableContentSize);
  519. }
  520. [Fact]
  521. public void ScrollableContentSizeChanged_Event ()
  522. {
  523. var count = 0;
  524. var scrollBar = new ScrollBar ();
  525. scrollBar.ScrollableContentSizeChanged += (s, e) => count++;
  526. scrollBar.ScrollableContentSize = 10;
  527. Assert.Equal (10, scrollBar.ScrollableContentSize);
  528. Assert.Equal (1, count);
  529. }
  530. [Theory]
  531. [SetupFakeDriver]
  532. #region Draw
  533. #region Horizontal
  534. #region Super 10 - ScrollBar 8
  535. [InlineData (
  536. 10,
  537. 1,
  538. 10,
  539. -1,
  540. Orientation.Horizontal,
  541. @"
  542. ┌──────────┐
  543. │◄████████►│
  544. └──────────┘")]
  545. [InlineData (
  546. 10,
  547. 1,
  548. 20,
  549. -1,
  550. Orientation.Horizontal,
  551. @"
  552. ┌──────────┐
  553. │◄████░░░░►│
  554. └──────────┘")]
  555. [InlineData (
  556. 10,
  557. 1,
  558. 20,
  559. 0,
  560. Orientation.Horizontal,
  561. @"
  562. ┌──────────┐
  563. │◄████░░░░►│
  564. └──────────┘")]
  565. [InlineData (
  566. 10,
  567. 1,
  568. 20,
  569. 1,
  570. Orientation.Horizontal,
  571. @"
  572. ┌──────────┐
  573. │◄████░░░░►│
  574. └──────────┘")]
  575. [InlineData (
  576. 10,
  577. 1,
  578. 20,
  579. 2,
  580. Orientation.Horizontal,
  581. @"
  582. ┌──────────┐
  583. │◄████░░░░►│
  584. └──────────┘
  585. ")]
  586. [InlineData (
  587. 10,
  588. 1,
  589. 20,
  590. 3,
  591. Orientation.Horizontal,
  592. @"
  593. ┌──────────┐
  594. │◄░████░░░►│
  595. └──────────┘
  596. ")]
  597. [InlineData (
  598. 10,
  599. 1,
  600. 20,
  601. 4,
  602. Orientation.Horizontal,
  603. @"
  604. ┌──────────┐
  605. │◄░░████░░►│
  606. └──────────┘
  607. ")]
  608. [InlineData (
  609. 10,
  610. 1,
  611. 20,
  612. 5,
  613. Orientation.Horizontal,
  614. @"
  615. ┌──────────┐
  616. │◄░░████░░►│
  617. └──────────┘
  618. ")]
  619. [InlineData (
  620. 10,
  621. 1,
  622. 20,
  623. 6,
  624. Orientation.Horizontal,
  625. @"
  626. ┌──────────┐
  627. │◄░░░████░►│
  628. └──────────┘
  629. ")]
  630. [InlineData (
  631. 10,
  632. 1,
  633. 20,
  634. 7,
  635. Orientation.Horizontal,
  636. @"
  637. ┌──────────┐
  638. │◄░░░████░►│
  639. └──────────┘
  640. ")]
  641. [InlineData (
  642. 10,
  643. 1,
  644. 20,
  645. 8,
  646. Orientation.Horizontal,
  647. @"
  648. ┌──────────┐
  649. │◄░░░░████►│
  650. └──────────┘
  651. ")]
  652. [InlineData (
  653. 10,
  654. 1,
  655. 20,
  656. 9,
  657. Orientation.Horizontal,
  658. @"
  659. ┌──────────┐
  660. │◄░░░░████►│
  661. └──────────┘
  662. ")]
  663. [InlineData (
  664. 10,
  665. 1,
  666. 20,
  667. 10,
  668. Orientation.Horizontal,
  669. @"
  670. ┌──────────┐
  671. │◄░░░░████►│
  672. └──────────┘
  673. ")]
  674. [InlineData (
  675. 10,
  676. 1,
  677. 20,
  678. 19,
  679. Orientation.Horizontal,
  680. @"
  681. ┌──────────┐
  682. │◄░░░░████►│
  683. └──────────┘
  684. ")]
  685. [InlineData (
  686. 10,
  687. 1,
  688. 20,
  689. 20,
  690. Orientation.Horizontal,
  691. @"
  692. ┌──────────┐
  693. │◄░░░░████►│
  694. └──────────┘
  695. ")]
  696. #endregion Super 10 - ScrollBar 8
  697. #region Super 12 - ScrollBar 10
  698. [InlineData (
  699. 12,
  700. 1,
  701. 10,
  702. -1,
  703. Orientation.Horizontal,
  704. @"
  705. ┌────────────┐
  706. │◄██████████►│
  707. └────────────┘")]
  708. [InlineData (
  709. 12,
  710. 1,
  711. 20,
  712. -1,
  713. Orientation.Horizontal,
  714. @"
  715. ┌────────────┐
  716. │◄██████░░░░►│
  717. └────────────┘")]
  718. [InlineData (
  719. 12,
  720. 1,
  721. 20,
  722. 0,
  723. Orientation.Horizontal,
  724. @"
  725. ┌────────────┐
  726. │◄██████░░░░►│
  727. └────────────┘")]
  728. [InlineData (
  729. 12,
  730. 1,
  731. 20,
  732. 1,
  733. Orientation.Horizontal,
  734. @"
  735. ┌────────────┐
  736. │◄██████░░░░►│
  737. └────────────┘")]
  738. [InlineData (
  739. 12,
  740. 1,
  741. 20,
  742. 2,
  743. Orientation.Horizontal,
  744. @"
  745. ┌────────────┐
  746. │◄░██████░░░►│
  747. └────────────┘
  748. ")]
  749. [InlineData (
  750. 12,
  751. 1,
  752. 20,
  753. 3,
  754. Orientation.Horizontal,
  755. @"
  756. ┌────────────┐
  757. │◄░██████░░░►│
  758. └────────────┘
  759. ")]
  760. [InlineData (
  761. 12,
  762. 1,
  763. 20,
  764. 4,
  765. Orientation.Horizontal,
  766. @"
  767. ┌────────────┐
  768. │◄░░██████░░►│
  769. └────────────┘
  770. ")]
  771. [InlineData (
  772. 12,
  773. 1,
  774. 20,
  775. 5,
  776. Orientation.Horizontal,
  777. @"
  778. ┌────────────┐
  779. │◄░░░██████░►│
  780. └────────────┘
  781. ")]
  782. [InlineData (
  783. 12,
  784. 1,
  785. 20,
  786. 6,
  787. Orientation.Horizontal,
  788. @"
  789. ┌────────────┐
  790. │◄░░░██████░►│
  791. └────────────┘
  792. ")]
  793. [InlineData (
  794. 12,
  795. 1,
  796. 20,
  797. 7,
  798. Orientation.Horizontal,
  799. @"
  800. ┌────────────┐
  801. │◄░░░░██████►│
  802. └────────────┘
  803. ")]
  804. [InlineData (
  805. 12,
  806. 1,
  807. 20,
  808. 8,
  809. Orientation.Horizontal,
  810. @"
  811. ┌────────────┐
  812. │◄░░░░██████►│
  813. └────────────┘
  814. ")]
  815. [InlineData (
  816. 12,
  817. 1,
  818. 20,
  819. 9,
  820. Orientation.Horizontal,
  821. @"
  822. ┌────────────┐
  823. │◄░░░░██████►│
  824. └────────────┘
  825. ")]
  826. [InlineData (
  827. 12,
  828. 1,
  829. 20,
  830. 10,
  831. Orientation.Horizontal,
  832. @"
  833. ┌────────────┐
  834. │◄░░░░██████►│
  835. └────────────┘
  836. ")]
  837. [InlineData (
  838. 12,
  839. 1,
  840. 20,
  841. 19,
  842. Orientation.Horizontal,
  843. @"
  844. ┌────────────┐
  845. │◄░░░░██████►│
  846. └────────────┘
  847. ")]
  848. [InlineData (
  849. 12,
  850. 1,
  851. 20,
  852. 20,
  853. Orientation.Horizontal,
  854. @"
  855. ┌────────────┐
  856. │◄░░░░██████►│
  857. └────────────┘
  858. ")]
  859. #endregion Super 12 - ScrollBar 10
  860. [InlineData (
  861. 10,
  862. 3,
  863. 20,
  864. 2,
  865. Orientation.Horizontal,
  866. @"
  867. ┌──────────┐
  868. │ ░████░░░ │
  869. │◄░████░░░►│
  870. │ ░████░░░ │
  871. └──────────┘
  872. ")]
  873. #endregion Horizontal
  874. #region Vertical
  875. [InlineData (
  876. 1,
  877. 10,
  878. 10,
  879. -1,
  880. Orientation.Vertical,
  881. @"
  882. ┌─┐
  883. │▲│
  884. │█│
  885. │█│
  886. │█│
  887. │█│
  888. │█│
  889. │█│
  890. │█│
  891. │█│
  892. │▼│
  893. └─┘")]
  894. [InlineData (
  895. 1,
  896. 10,
  897. 10,
  898. 5,
  899. Orientation.Vertical,
  900. @"
  901. ┌─┐
  902. │▲│
  903. │█│
  904. │█│
  905. │█│
  906. │█│
  907. │█│
  908. │█│
  909. │█│
  910. │█│
  911. │▼│
  912. └─┘")]
  913. [InlineData (
  914. 1,
  915. 10,
  916. 20,
  917. 5,
  918. Orientation.Vertical,
  919. @"
  920. ┌─┐
  921. │▲│
  922. │░│
  923. │░│
  924. │█│
  925. │█│
  926. │█│
  927. │█│
  928. │░│
  929. │░│
  930. │▼│
  931. └─┘")]
  932. [InlineData (
  933. 1,
  934. 12,
  935. 20,
  936. 5,
  937. Orientation.Vertical,
  938. @"
  939. ┌─┐
  940. │▲│
  941. │░│
  942. │░│
  943. │░│
  944. │█│
  945. │█│
  946. │█│
  947. │█│
  948. │█│
  949. │█│
  950. │░│
  951. │▼│
  952. └─┘")]
  953. [InlineData (
  954. 3,
  955. 10,
  956. 20,
  957. 2,
  958. Orientation.Vertical,
  959. @"
  960. ┌───┐
  961. │ ▲ │
  962. │░░░│
  963. │███│
  964. │███│
  965. │███│
  966. │███│
  967. │░░░│
  968. │░░░│
  969. │░░░│
  970. │ ▼ │
  971. └───┘
  972. ")]
  973. #endregion Vertical
  974. public void Draws_Correctly (int width, int height, int contentSize, int contentPosition, Orientation orientation, string expected)
  975. {
  976. var super = new Window
  977. {
  978. Id = "super",
  979. Width = width + 2,
  980. Height = height + 2
  981. };
  982. var scrollBar = new ScrollBar
  983. {
  984. Orientation = orientation,
  985. };
  986. if (orientation == Orientation.Vertical)
  987. {
  988. scrollBar.Width = 1;
  989. scrollBar.Height = height;
  990. }
  991. else
  992. {
  993. scrollBar.Width = width;
  994. scrollBar.Height = 1;
  995. }
  996. super.Add (scrollBar);
  997. scrollBar.ScrollableContentSize = contentSize;
  998. scrollBar.Position = contentPosition;
  999. int sliderPos = scrollBar.CalculateSliderPositionFromContentPosition (contentPosition, NavigationDirection.Forward);
  1000. super.BeginInit ();
  1001. super.EndInit ();
  1002. super.Layout ();
  1003. super.Draw ();
  1004. _ = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  1005. }
  1006. #endregion Draw
  1007. #region Mouse
  1008. [Theory]
  1009. [CombinatorialData]
  1010. [AutoInitShutdown]
  1011. public void Mouse_Click_DecrementButton_Decrements ([CombinatorialRange (1, 3, 1)] int increment, Orientation orientation)
  1012. {
  1013. var top = new Toplevel ()
  1014. {
  1015. Id = "top",
  1016. Width = 10,
  1017. Height = 10
  1018. };
  1019. var scrollBar = new ScrollBar
  1020. {
  1021. Id = "scrollBar",
  1022. Orientation = orientation,
  1023. ScrollableContentSize = 20,
  1024. Increment = increment
  1025. };
  1026. top.Add (scrollBar);
  1027. RunState rs = Application.Begin (top);
  1028. // Scroll to end
  1029. scrollBar.Position = 20;
  1030. Assert.Equal (10, scrollBar.Position);
  1031. Application.RunIteration (ref rs);
  1032. Assert.Equal (4, scrollBar.GetSliderPosition ());
  1033. Assert.Equal (10, scrollBar.Position);
  1034. int initialPos = scrollBar.Position;
  1035. Application.RaiseMouseEvent (new ()
  1036. {
  1037. ScreenPosition = new (0, 0),
  1038. Flags = MouseFlags.Button1Clicked
  1039. });
  1040. Application.RunIteration (ref rs);
  1041. Assert.Equal (initialPos - increment, scrollBar.Position);
  1042. Application.ResetState (true);
  1043. }
  1044. [Theory]
  1045. [CombinatorialData]
  1046. [AutoInitShutdown]
  1047. public void Mouse_Click_IncrementButton_Increments ([CombinatorialRange (1, 3, 1)] int increment, Orientation orientation)
  1048. {
  1049. var top = new Toplevel ()
  1050. {
  1051. Id = "top",
  1052. Width = 10,
  1053. Height = 10
  1054. };
  1055. var scrollBar = new ScrollBar
  1056. {
  1057. Id = "scrollBar",
  1058. Orientation = orientation,
  1059. ScrollableContentSize = 20,
  1060. Increment = increment
  1061. };
  1062. top.Add (scrollBar);
  1063. RunState rs = Application.Begin (top);
  1064. // Scroll to top
  1065. scrollBar.Position = 0;
  1066. Application.RunIteration (ref rs);
  1067. Assert.Equal (0, scrollBar.GetSliderPosition ());
  1068. Assert.Equal (0, scrollBar.Position);
  1069. int initialPos = scrollBar.Position;
  1070. Application.RaiseMouseEvent (new ()
  1071. {
  1072. ScreenPosition = orientation == Orientation.Vertical ? new (0, scrollBar.Frame.Height - 1) : new (scrollBar.Frame.Width - 1, 0),
  1073. Flags = MouseFlags.Button1Clicked
  1074. });
  1075. Application.RunIteration (ref rs);
  1076. Assert.Equal (initialPos + increment, scrollBar.Position);
  1077. Application.ResetState (true);
  1078. }
  1079. #endregion Mouse
  1080. [Fact (Skip = "Disabled - Will put this feature in View")]
  1081. [AutoInitShutdown]
  1082. public void KeepContentInAllViewport_True_False ()
  1083. {
  1084. var view = new View { Width = Dim.Fill (), Height = Dim.Fill () };
  1085. view.Padding.Thickness = new (0, 0, 2, 0);
  1086. view.SetContentSize (new (view.Viewport.Width, 30));
  1087. var scrollBar = new ScrollBar { Width = 2, Height = Dim.Fill (), ScrollableContentSize = view.GetContentSize ().Height };
  1088. scrollBar.SliderPositionChanged += (_, e) => view.Viewport = view.Viewport with { Y = e.CurrentValue };
  1089. view.Padding.Add (scrollBar);
  1090. var top = new Toplevel ();
  1091. top.Add (view);
  1092. Application.Begin (top);
  1093. Assert.False (scrollBar.KeepContentInAllViewport);
  1094. scrollBar.KeepContentInAllViewport = true;
  1095. Assert.Equal (80, view.Padding.Viewport.Width);
  1096. Assert.Equal (25, view.Padding.Viewport.Height);
  1097. Assert.Equal (2, scrollBar.Viewport.Width);
  1098. Assert.Equal (25, scrollBar.Viewport.Height);
  1099. Assert.Equal (30, scrollBar.ScrollableContentSize);
  1100. scrollBar.KeepContentInAllViewport = false;
  1101. scrollBar.Position = 50;
  1102. Assert.Equal (scrollBar.GetSliderPosition (), scrollBar.ScrollableContentSize - 1);
  1103. Assert.Equal (scrollBar.GetSliderPosition (), view.Viewport.Y);
  1104. Assert.Equal (29, scrollBar.GetSliderPosition ());
  1105. Assert.Equal (29, view.Viewport.Y);
  1106. top.Dispose ();
  1107. }
  1108. }