ScrollBarViewTests.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Reflection;
  5. using Xunit;
  6. using Xunit.Abstractions;
  7. namespace Terminal.Gui.Views {
  8. public class ScrollBarViewTests {
  9. readonly ITestOutputHelper output;
  10. public ScrollBarViewTests (ITestOutputHelper output)
  11. {
  12. this.output = output;
  13. }
  14. // This class enables test functions annotated with the [InitShutdown] attribute
  15. // to have a function called before the test function is called and after.
  16. //
  17. // This is necessary because a) Application is a singleton and Init/Shutdown must be called
  18. // as a pair, and b) all unit test functions should be atomic.
  19. [AttributeUsage (AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
  20. public class InitShutdownAttribute : Xunit.Sdk.BeforeAfterTestAttribute {
  21. public override void Before (MethodInfo methodUnderTest)
  22. {
  23. Debug.WriteLine ($"Before: {methodUnderTest.Name}");
  24. if (_hostView != null) {
  25. throw new InvalidOperationException ("After did not run.");
  26. }
  27. Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
  28. var top = Application.Top;
  29. ScrollBarViewTests._hostView = new HostView () {
  30. Width = Dim.Fill (),
  31. Height = Dim.Fill (),
  32. Top = 0,
  33. Lines = 30,
  34. Left = 0,
  35. Cols = 100
  36. };
  37. top.Add (ScrollBarViewTests._hostView);
  38. }
  39. public override void After (MethodInfo methodUnderTest)
  40. {
  41. Debug.WriteLine ($"After: {methodUnderTest.Name}");
  42. ScrollBarViewTests._hostView = null;
  43. Application.Shutdown ();
  44. }
  45. }
  46. public class HostView : View {
  47. public int Top { get; set; }
  48. public int Lines { get; set; }
  49. public int Left { get; set; }
  50. public int Cols { get; set; }
  51. }
  52. private static HostView _hostView;
  53. private ScrollBarView _scrollBar;
  54. private bool _added;
  55. private void AddHandlers ()
  56. {
  57. if (!_added) {
  58. _hostView.DrawContent += _hostView_DrawContent;
  59. _scrollBar.ChangedPosition += _scrollBar_ChangedPosition;
  60. _scrollBar.OtherScrollBarView.ChangedPosition += _scrollBar_OtherScrollBarView_ChangedPosition;
  61. }
  62. _added = true;
  63. }
  64. private void RemoveHandlers ()
  65. {
  66. if (_added) {
  67. _hostView.DrawContent -= _hostView_DrawContent;
  68. _scrollBar.ChangedPosition -= _scrollBar_ChangedPosition;
  69. _scrollBar.OtherScrollBarView.ChangedPosition -= _scrollBar_OtherScrollBarView_ChangedPosition;
  70. }
  71. _added = false;
  72. }
  73. private void _hostView_DrawContent (Rect obj)
  74. {
  75. _scrollBar.Size = _hostView.Lines;
  76. _scrollBar.Position = _hostView.Top;
  77. _scrollBar.OtherScrollBarView.Size = _hostView.Cols;
  78. _scrollBar.OtherScrollBarView.Position = _hostView.Left;
  79. _scrollBar.Refresh ();
  80. }
  81. private void _scrollBar_ChangedPosition ()
  82. {
  83. _hostView.Top = _scrollBar.Position;
  84. if (_hostView.Top != _scrollBar.Position) {
  85. _scrollBar.Position = _hostView.Top;
  86. }
  87. _hostView.SetNeedsDisplay ();
  88. }
  89. private void _scrollBar_OtherScrollBarView_ChangedPosition ()
  90. {
  91. _hostView.Left = _scrollBar.OtherScrollBarView.Position;
  92. if (_hostView.Left != _scrollBar.OtherScrollBarView.Position) {
  93. _scrollBar.OtherScrollBarView.Position = _hostView.Left;
  94. }
  95. _hostView.SetNeedsDisplay ();
  96. }
  97. [Fact]
  98. [InitShutdown]
  99. public void Hosting_A_Null_View_To_A_ScrollBarView_Throws_ArgumentNullException ()
  100. {
  101. Assert.Throws<ArgumentNullException> ("The host parameter can't be null.",
  102. () => new ScrollBarView (null, true));
  103. Assert.Throws<ArgumentNullException> ("The host parameter can't be null.",
  104. () => new ScrollBarView (null, false));
  105. }
  106. [Fact]
  107. [InitShutdown]
  108. public void Hosting_A_Null_SuperView_View_To_A_ScrollBarView_Throws_ArgumentNullException ()
  109. {
  110. Assert.Throws<ArgumentNullException> ("The host SuperView parameter can't be null.",
  111. () => new ScrollBarView (new View (), true));
  112. Assert.Throws<ArgumentNullException> ("The host SuperView parameter can't be null.",
  113. () => new ScrollBarView (new View (), false));
  114. }
  115. [Fact]
  116. [InitShutdown]
  117. public void Hosting_Two_Vertical_ScrollBarView_Throws_ArgumentException ()
  118. {
  119. var top = new Toplevel ();
  120. var host = new View ();
  121. top.Add (host);
  122. var v = new ScrollBarView (host, true);
  123. var h = new ScrollBarView (host, true);
  124. Assert.Throws<ArgumentException> (() => v.OtherScrollBarView = h);
  125. Assert.Throws<ArgumentException> (() => h.OtherScrollBarView = v);
  126. }
  127. [Fact]
  128. [InitShutdown]
  129. public void Hosting_Two_Horizontal_ScrollBarView_Throws_ArgumentException ()
  130. {
  131. var top = new Toplevel ();
  132. var host = new View ();
  133. top.Add (host);
  134. var v = new ScrollBarView (host, false);
  135. var h = new ScrollBarView (host, false);
  136. Assert.Throws<ArgumentException> (() => v.OtherScrollBarView = h);
  137. Assert.Throws<ArgumentException> (() => h.OtherScrollBarView = v);
  138. }
  139. [Fact]
  140. [InitShutdown]
  141. public void Scrolling_With_Default_Constructor_Do_Not_Scroll ()
  142. {
  143. var sbv = new ScrollBarView {
  144. Position = 1
  145. };
  146. Assert.NotEqual (1, sbv.Position);
  147. Assert.Equal (0, sbv.Position);
  148. }
  149. [Fact]
  150. [InitShutdown]
  151. public void Hosting_A_View_To_A_ScrollBarView ()
  152. {
  153. RemoveHandlers ();
  154. _scrollBar = new ScrollBarView (_hostView, true);
  155. Assert.True (_scrollBar.IsVertical);
  156. Assert.False (_scrollBar.OtherScrollBarView.IsVertical);
  157. Assert.Equal (_scrollBar.Position, _hostView.Top);
  158. Assert.NotEqual (_scrollBar.Size, _hostView.Lines);
  159. Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left);
  160. Assert.NotEqual (_scrollBar.OtherScrollBarView.Size, _hostView.Cols);
  161. AddHandlers ();
  162. _hostView.SuperView.LayoutSubviews ();
  163. _hostView.Redraw (_hostView.Bounds);
  164. Assert.Equal (_scrollBar.Position, _hostView.Top);
  165. Assert.Equal (_scrollBar.Size, _hostView.Lines);
  166. Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left);
  167. Assert.Equal (_scrollBar.OtherScrollBarView.Size, _hostView.Cols);
  168. }
  169. [Fact]
  170. [InitShutdown]
  171. public void ChangedPosition_Update_The_Hosted_View ()
  172. {
  173. Hosting_A_View_To_A_ScrollBarView ();
  174. AddHandlers ();
  175. _scrollBar.Position = 2;
  176. Assert.Equal (_scrollBar.Position, _hostView.Top);
  177. _scrollBar.OtherScrollBarView.Position = 5;
  178. Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left);
  179. }
  180. [Fact]
  181. [InitShutdown]
  182. public void ChangedPosition_Scrolling ()
  183. {
  184. Hosting_A_View_To_A_ScrollBarView ();
  185. AddHandlers ();
  186. for (int i = 0; i < _scrollBar.Size; i++) {
  187. _scrollBar.Position += 1;
  188. Assert.Equal (_scrollBar.Position, _hostView.Top);
  189. }
  190. for (int i = _scrollBar.Size - 1; i >= 0; i--) {
  191. _scrollBar.Position -= 1;
  192. Assert.Equal (_scrollBar.Position, _hostView.Top);
  193. }
  194. for (int i = 0; i < _scrollBar.OtherScrollBarView.Size; i++) {
  195. _scrollBar.OtherScrollBarView.Position += i;
  196. Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left);
  197. }
  198. for (int i = _scrollBar.OtherScrollBarView.Size - 1; i >= 0; i--) {
  199. _scrollBar.OtherScrollBarView.Position -= 1;
  200. Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left);
  201. }
  202. }
  203. [Fact]
  204. [InitShutdown]
  205. public void ChangedPosition_Negative_Value ()
  206. {
  207. Hosting_A_View_To_A_ScrollBarView ();
  208. AddHandlers ();
  209. _scrollBar.Position = -20;
  210. Assert.Equal (0, _scrollBar.Position);
  211. Assert.Equal (_scrollBar.Position, _hostView.Top);
  212. _scrollBar.OtherScrollBarView.Position = -50;
  213. Assert.Equal (0, _scrollBar.OtherScrollBarView.Position);
  214. Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left);
  215. }
  216. [Fact]
  217. [InitShutdown]
  218. public void DrawContent_Update_The_ScrollBarView_Position ()
  219. {
  220. Hosting_A_View_To_A_ScrollBarView ();
  221. AddHandlers ();
  222. _hostView.Top = 3;
  223. _hostView.Redraw (_hostView.Bounds);
  224. Assert.Equal (_scrollBar.Position, _hostView.Top);
  225. _hostView.Left = 6;
  226. _hostView.Redraw (_hostView.Bounds);
  227. Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left);
  228. }
  229. [Fact]
  230. [InitShutdown]
  231. public void OtherScrollBarView_Not_Null ()
  232. {
  233. Hosting_A_View_To_A_ScrollBarView ();
  234. AddHandlers ();
  235. Assert.NotNull (_scrollBar.OtherScrollBarView);
  236. Assert.NotEqual (_scrollBar, _scrollBar.OtherScrollBarView);
  237. Assert.Equal (_scrollBar.OtherScrollBarView.OtherScrollBarView, _scrollBar);
  238. }
  239. [Fact]
  240. [InitShutdown]
  241. public void ShowScrollIndicator_Check ()
  242. {
  243. Hosting_A_View_To_A_ScrollBarView ();
  244. AddHandlers ();
  245. Assert.True (_scrollBar.ShowScrollIndicator);
  246. Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
  247. }
  248. [Fact]
  249. [InitShutdown]
  250. public void KeepContentAlwaysInViewport_True ()
  251. {
  252. Hosting_A_View_To_A_ScrollBarView ();
  253. AddHandlers ();
  254. Assert.Equal (80, _hostView.Bounds.Width);
  255. Assert.Equal (25, _hostView.Bounds.Height);
  256. Assert.Equal (79, _scrollBar.OtherScrollBarView.Bounds.Width);
  257. Assert.Equal (24, _scrollBar.Bounds.Height);
  258. Assert.Equal (30, _scrollBar.Size);
  259. Assert.Equal (100, _scrollBar.OtherScrollBarView.Size);
  260. Assert.True (_scrollBar.ShowScrollIndicator);
  261. Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
  262. Assert.True (_scrollBar.Visible);
  263. Assert.True (_scrollBar.OtherScrollBarView.Visible);
  264. _scrollBar.Position = 50;
  265. Assert.Equal (_scrollBar.Position, _scrollBar.Size - _scrollBar.Bounds.Height);
  266. Assert.Equal (_scrollBar.Position, _hostView.Top);
  267. Assert.Equal (6, _scrollBar.Position);
  268. Assert.Equal (6, _hostView.Top);
  269. Assert.True (_scrollBar.ShowScrollIndicator);
  270. Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
  271. Assert.True (_scrollBar.Visible);
  272. Assert.True (_scrollBar.OtherScrollBarView.Visible);
  273. _scrollBar.OtherScrollBarView.Position = 150;
  274. Assert.Equal (_scrollBar.OtherScrollBarView.Position, _scrollBar.OtherScrollBarView.Size - _scrollBar.OtherScrollBarView.Bounds.Width);
  275. Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left);
  276. Assert.Equal (21, _scrollBar.OtherScrollBarView.Position);
  277. Assert.Equal (21, _hostView.Left);
  278. Assert.True (_scrollBar.ShowScrollIndicator);
  279. Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
  280. Assert.True (_scrollBar.Visible);
  281. Assert.True (_scrollBar.OtherScrollBarView.Visible);
  282. }
  283. [Fact]
  284. [InitShutdown]
  285. public void KeepContentAlwaysInViewport_False ()
  286. {
  287. Hosting_A_View_To_A_ScrollBarView ();
  288. AddHandlers ();
  289. _scrollBar.KeepContentAlwaysInViewport = false;
  290. _scrollBar.Position = 50;
  291. Assert.Equal (_scrollBar.Position, _scrollBar.Size - 1);
  292. Assert.Equal (_scrollBar.Position, _hostView.Top);
  293. Assert.Equal (29, _scrollBar.Position);
  294. Assert.Equal (29, _hostView.Top);
  295. _scrollBar.OtherScrollBarView.Position = 150;
  296. Assert.Equal (_scrollBar.OtherScrollBarView.Position, _scrollBar.OtherScrollBarView.Size - 1);
  297. Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left);
  298. Assert.Equal (99, _scrollBar.OtherScrollBarView.Position);
  299. Assert.Equal (99, _hostView.Left);
  300. }
  301. [Fact]
  302. [InitShutdown]
  303. public void AutoHideScrollBars_Check ()
  304. {
  305. Hosting_A_View_To_A_ScrollBarView ();
  306. AddHandlers ();
  307. _hostView.Redraw (_hostView.Bounds);
  308. Assert.True (_scrollBar.ShowScrollIndicator);
  309. Assert.True (_scrollBar.Visible);
  310. Assert.Equal ("Dim.Absolute(1)", _scrollBar.Width.ToString ());
  311. Assert.Equal (1, _scrollBar.Bounds.Width);
  312. Assert.Equal ("Dim.Combine(DimView(side=Height, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(1))",
  313. _scrollBar.Height.ToString ());
  314. Assert.Equal (24, _scrollBar.Bounds.Height);
  315. Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
  316. Assert.True (_scrollBar.OtherScrollBarView.Visible);
  317. Assert.Equal ("Dim.Combine(DimView(side=Width, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(1))",
  318. _scrollBar.OtherScrollBarView.Width.ToString ());
  319. Assert.Equal (79, _scrollBar.OtherScrollBarView.Bounds.Width);
  320. Assert.Equal ("Dim.Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
  321. Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height);
  322. _hostView.Lines = 10;
  323. _hostView.Redraw (_hostView.Bounds);
  324. Assert.False (_scrollBar.ShowScrollIndicator);
  325. Assert.False (_scrollBar.Visible);
  326. Assert.Equal ("Dim.Absolute(1)", _scrollBar.Width.ToString ());
  327. Assert.Equal (1, _scrollBar.Bounds.Width);
  328. Assert.Equal ("Dim.Combine(DimView(side=Height, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(1))",
  329. _scrollBar.Height.ToString ());
  330. Assert.Equal (24, _scrollBar.Bounds.Height);
  331. Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
  332. Assert.True (_scrollBar.OtherScrollBarView.Visible);
  333. Assert.Equal ("Dim.Combine(DimView(side=Width, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(0))",
  334. _scrollBar.OtherScrollBarView.Width.ToString ());
  335. Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width);
  336. Assert.Equal ("Dim.Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
  337. Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height);
  338. _hostView.Cols = 60;
  339. _hostView.Redraw (_hostView.Bounds);
  340. Assert.False (_scrollBar.ShowScrollIndicator);
  341. Assert.False (_scrollBar.Visible);
  342. Assert.Equal ("Dim.Absolute(1)", _scrollBar.Width.ToString ());
  343. Assert.Equal (1, _scrollBar.Bounds.Width);
  344. Assert.Equal ("Dim.Combine(DimView(side=Height, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(1))",
  345. _scrollBar.Height.ToString ());
  346. Assert.Equal (24, _scrollBar.Bounds.Height);
  347. Assert.False (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
  348. Assert.False (_scrollBar.OtherScrollBarView.Visible);
  349. Assert.Equal ("Dim.Combine(DimView(side=Width, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(0))",
  350. _scrollBar.OtherScrollBarView.Width.ToString ());
  351. Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width);
  352. Assert.Equal ("Dim.Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
  353. Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height);
  354. _hostView.Lines = 40;
  355. _hostView.Redraw (_hostView.Bounds);
  356. Assert.True (_scrollBar.ShowScrollIndicator);
  357. Assert.True (_scrollBar.Visible);
  358. Assert.Equal ("Dim.Absolute(1)", _scrollBar.Width.ToString ());
  359. Assert.Equal (1, _scrollBar.Bounds.Width);
  360. Assert.Equal ("Dim.Combine(DimView(side=Height, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(0))",
  361. _scrollBar.Height.ToString ());
  362. Assert.Equal (25, _scrollBar.Bounds.Height);
  363. Assert.False (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
  364. Assert.False (_scrollBar.OtherScrollBarView.Visible);
  365. Assert.Equal ("Dim.Combine(DimView(side=Width, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(0))",
  366. _scrollBar.OtherScrollBarView.Width.ToString ());
  367. Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width);
  368. Assert.Equal ("Dim.Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
  369. Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height);
  370. _hostView.Cols = 120;
  371. _hostView.Redraw (_hostView.Bounds);
  372. Assert.True (_scrollBar.ShowScrollIndicator);
  373. Assert.True (_scrollBar.Visible);
  374. Assert.Equal ("Dim.Absolute(1)", _scrollBar.Width.ToString ());
  375. Assert.Equal (1, _scrollBar.Bounds.Width);
  376. Assert.Equal ("Dim.Combine(DimView(side=Height, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(1))",
  377. _scrollBar.Height.ToString ());
  378. Assert.Equal (24, _scrollBar.Bounds.Height);
  379. Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
  380. Assert.True (_scrollBar.OtherScrollBarView.Visible);
  381. Assert.Equal ("Dim.Combine(DimView(side=Width, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(1))",
  382. _scrollBar.OtherScrollBarView.Width.ToString ());
  383. Assert.Equal (79, _scrollBar.OtherScrollBarView.Bounds.Width);
  384. Assert.Equal ("Dim.Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
  385. Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height);
  386. }
  387. [Fact]
  388. public void Constructor_ShowBothScrollIndicator_False_And_IsVertical_True_Refresh_Does_Not_Throws_An_Object_Null_Exception ()
  389. {
  390. var exception = Record.Exception (() => {
  391. Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
  392. var top = Application.Top;
  393. var win = new Window () {
  394. X = 0,
  395. Y = 0,
  396. Width = Dim.Fill (),
  397. Height = Dim.Fill ()
  398. };
  399. List<string> source = new List<string> ();
  400. for (int i = 0; i < 50; i++) {
  401. source.Add ($"item {i}");
  402. }
  403. var listView = new ListView (source) {
  404. X = 0,
  405. Y = 0,
  406. Width = Dim.Fill (),
  407. Height = Dim.Fill ()
  408. };
  409. win.Add (listView);
  410. var newScrollBarView = new ScrollBarView (listView, true, false) {
  411. KeepContentAlwaysInViewport = true
  412. };
  413. win.Add (newScrollBarView);
  414. newScrollBarView.ChangedPosition += () => {
  415. listView.TopItem = newScrollBarView.Position;
  416. if (listView.TopItem != newScrollBarView.Position) {
  417. newScrollBarView.Position = listView.TopItem;
  418. }
  419. Assert.Equal (newScrollBarView.Position, listView.TopItem);
  420. listView.SetNeedsDisplay ();
  421. };
  422. listView.DrawContent += (e) => {
  423. newScrollBarView.Size = listView.Source.Count;
  424. Assert.Equal (newScrollBarView.Size, listView.Source.Count);
  425. newScrollBarView.Position = listView.TopItem;
  426. Assert.Equal (newScrollBarView.Position, listView.TopItem);
  427. newScrollBarView.Refresh ();
  428. };
  429. top.Ready += () => {
  430. newScrollBarView.Position = 45;
  431. Assert.Equal (newScrollBarView.Position, newScrollBarView.Size - listView.TopItem + (listView.TopItem - listView.Bounds.Height));
  432. Assert.Equal (newScrollBarView.Position, listView.TopItem);
  433. Assert.Equal (27, newScrollBarView.Position);
  434. Assert.Equal (27, listView.TopItem);
  435. Application.RequestStop ();
  436. };
  437. top.Add (win);
  438. Application.Run ();
  439. Application.Shutdown ();
  440. });
  441. Assert.Null (exception);
  442. }
  443. [Fact]
  444. public void Constructor_ShowBothScrollIndicator_False_And_IsVertical_False_Refresh_Does_Not_Throws_An_Object_Null_Exception ()
  445. {
  446. var exception = Record.Exception (() => {
  447. Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
  448. var top = Application.Top;
  449. var win = new Window () {
  450. X = 0,
  451. Y = 0,
  452. Width = Dim.Fill (),
  453. Height = Dim.Fill ()
  454. };
  455. List<string> source = new List<string> ();
  456. for (int i = 0; i < 50; i++) {
  457. var text = $"item {i} - ";
  458. for (int j = 0; j < 160; j++) {
  459. var col = j.ToString ();
  460. text += col.Length == 1 ? col [0] : col [1];
  461. }
  462. source.Add (text);
  463. }
  464. var listView = new ListView (source) {
  465. X = 0,
  466. Y = 0,
  467. Width = Dim.Fill (),
  468. Height = Dim.Fill ()
  469. };
  470. win.Add (listView);
  471. var newScrollBarView = new ScrollBarView (listView, false, false) {
  472. KeepContentAlwaysInViewport = true
  473. };
  474. win.Add (newScrollBarView);
  475. newScrollBarView.ChangedPosition += () => {
  476. listView.LeftItem = newScrollBarView.Position;
  477. if (listView.LeftItem != newScrollBarView.Position) {
  478. newScrollBarView.Position = listView.LeftItem;
  479. }
  480. Assert.Equal (newScrollBarView.Position, listView.LeftItem);
  481. listView.SetNeedsDisplay ();
  482. };
  483. listView.DrawContent += (e) => {
  484. newScrollBarView.Size = listView.Maxlength;
  485. Assert.Equal (newScrollBarView.Size, listView.Maxlength);
  486. newScrollBarView.Position = listView.LeftItem;
  487. Assert.Equal (newScrollBarView.Position, listView.LeftItem);
  488. newScrollBarView.Refresh ();
  489. };
  490. top.Ready += () => {
  491. newScrollBarView.Position = 100;
  492. Assert.Equal (newScrollBarView.Position, newScrollBarView.Size - listView.LeftItem + (listView.LeftItem - listView.Bounds.Width));
  493. Assert.Equal (newScrollBarView.Position, listView.LeftItem);
  494. Assert.Equal (92, newScrollBarView.Position);
  495. Assert.Equal (92, listView.LeftItem);
  496. Application.RequestStop ();
  497. };
  498. top.Add (win);
  499. Application.Run ();
  500. Application.Shutdown ();
  501. });
  502. Assert.Null (exception);
  503. }
  504. [Fact]
  505. [AutoInitShutdown]
  506. public void Internal_Tests ()
  507. {
  508. var top = Application.Top;
  509. Assert.Equal (new Rect (0, 0, 80, 25), top.Bounds);
  510. var view = new View () { Width = Dim.Fill (), Height = Dim.Fill () };
  511. top.Add (view);
  512. var sbv = new ScrollBarView (view, true);
  513. top.Add (sbv);
  514. Assert.Equal (view, sbv.Host);
  515. sbv.Size = 40;
  516. sbv.Position = 0;
  517. sbv.OtherScrollBarView.Size = 100;
  518. sbv.OtherScrollBarView.Position = 0;
  519. // Host bounds is empty.
  520. Assert.False (sbv.CanScroll (10, out int max, sbv.IsVertical));
  521. Assert.Equal (0, max);
  522. Assert.False (sbv.OtherScrollBarView.CanScroll (10, out max, sbv.OtherScrollBarView.IsVertical));
  523. Assert.Equal (0, max);
  524. // They aren't visible so they aren't drawn.
  525. Assert.False (sbv.Visible);
  526. Assert.False (sbv.OtherScrollBarView.Visible);
  527. top.LayoutSubviews ();
  528. // Now the host bounds is not empty.
  529. Assert.True (sbv.CanScroll (10, out max, sbv.IsVertical));
  530. Assert.Equal (10, max);
  531. Assert.True (sbv.OtherScrollBarView.CanScroll (10, out max, sbv.OtherScrollBarView.IsVertical));
  532. Assert.Equal (10, max);
  533. Assert.True (sbv.CanScroll (50, out max, sbv.IsVertical));
  534. Assert.Equal (40, sbv.Size);
  535. Assert.Equal (15, max); // 15+25=40
  536. Assert.True (sbv.OtherScrollBarView.CanScroll (150, out max, sbv.OtherScrollBarView.IsVertical));
  537. Assert.Equal (100, sbv.OtherScrollBarView.Size);
  538. Assert.Equal (20, max); // 20+80=100
  539. Assert.False (sbv.Visible);
  540. Assert.False (sbv.OtherScrollBarView.Visible);
  541. sbv.KeepContentAlwaysInViewport = false;
  542. sbv.OtherScrollBarView.KeepContentAlwaysInViewport = false;
  543. Assert.True (sbv.CanScroll (50, out max, sbv.IsVertical));
  544. Assert.Equal (39, max);
  545. Assert.True (sbv.OtherScrollBarView.CanScroll (150, out max, sbv.OtherScrollBarView.IsVertical));
  546. Assert.Equal (99, max);
  547. Assert.True (sbv.Visible);
  548. Assert.True (sbv.OtherScrollBarView.Visible);
  549. }
  550. [Fact, AutoInitShutdown]
  551. public void Hosting_ShowBothScrollIndicator_Invisible ()
  552. {
  553. var textView = new TextView () {
  554. Width = Dim.Fill (),
  555. Height = Dim.Fill (),
  556. Text = "This is the help text for the Second Step.\n\nPress the button to see a message box.\n\nEnter name too."
  557. };
  558. var win = new Window ("Test") {
  559. Width = Dim.Fill (),
  560. Height = Dim.Fill ()
  561. };
  562. win.Add (textView);
  563. var scrollBar = new ScrollBarView (textView, true);
  564. scrollBar.ChangedPosition += () => {
  565. textView.TopRow = scrollBar.Position;
  566. if (textView.TopRow != scrollBar.Position) {
  567. scrollBar.Position = textView.TopRow;
  568. }
  569. textView.SetNeedsDisplay ();
  570. };
  571. scrollBar.OtherScrollBarView.ChangedPosition += () => {
  572. textView.LeftColumn = scrollBar.OtherScrollBarView.Position;
  573. if (textView.LeftColumn != scrollBar.OtherScrollBarView.Position) {
  574. scrollBar.OtherScrollBarView.Position = textView.LeftColumn;
  575. }
  576. textView.SetNeedsDisplay ();
  577. };
  578. scrollBar.VisibleChanged += () => {
  579. if (scrollBar.Visible && textView.RightOffset == 0) {
  580. textView.RightOffset = 1;
  581. } else if (!scrollBar.Visible && textView.RightOffset == 1) {
  582. textView.RightOffset = 0;
  583. }
  584. };
  585. scrollBar.OtherScrollBarView.VisibleChanged += () => {
  586. if (scrollBar.OtherScrollBarView.Visible && textView.BottomOffset == 0) {
  587. textView.BottomOffset = 1;
  588. } else if (!scrollBar.OtherScrollBarView.Visible && textView.BottomOffset == 1) {
  589. textView.BottomOffset = 0;
  590. }
  591. };
  592. textView.DrawContent += (e) => {
  593. scrollBar.Size = textView.Lines;
  594. scrollBar.Position = textView.TopRow;
  595. if (scrollBar.OtherScrollBarView != null) {
  596. scrollBar.OtherScrollBarView.Size = textView.Maxlength;
  597. scrollBar.OtherScrollBarView.Position = textView.LeftColumn;
  598. }
  599. scrollBar.LayoutSubviews ();
  600. scrollBar.Refresh ();
  601. };
  602. Application.Top.Add (win);
  603. Application.Begin (Application.Top);
  604. ((FakeDriver)Application.Driver).SetBufferSize (45, 20);
  605. Assert.True (scrollBar.AutoHideScrollBars);
  606. Assert.Equal (5, textView.Lines);
  607. Assert.Equal (42, textView.Maxlength);
  608. Assert.Equal (0, textView.LeftColumn);
  609. Assert.Equal (0, scrollBar.Position);
  610. Assert.Equal (0, scrollBar.OtherScrollBarView.Position);
  611. var expected = @"
  612. ┌ Test ─────────────────────────────────────┐
  613. │This is the help text for the Second Step. │
  614. │ │
  615. │Press the button to see a message box. │
  616. │ │
  617. │Enter name too. │
  618. │ │
  619. │ │
  620. │ │
  621. │ │
  622. │ │
  623. │ │
  624. │ │
  625. │ │
  626. │ │
  627. │ │
  628. │ │
  629. │ │
  630. │ │
  631. └───────────────────────────────────────────┘
  632. ";
  633. var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output);
  634. Assert.Equal (new Rect (0, 0, 45, 20), pos);
  635. textView.WordWrap = true;
  636. ((FakeDriver)Application.Driver).SetBufferSize (26, 20);
  637. Application.Refresh ();
  638. Assert.True (textView.WordWrap);
  639. Assert.True (scrollBar.AutoHideScrollBars);
  640. Assert.Equal (7, textView.Lines);
  641. Assert.Equal (22, textView.Maxlength);
  642. Assert.Equal (0, textView.LeftColumn);
  643. Assert.Equal (0, scrollBar.Position);
  644. Assert.Equal (0, scrollBar.OtherScrollBarView.Position);
  645. expected = @"
  646. ┌ Test ──────────────────┐
  647. │This is the help text │
  648. │for the Second Step. │
  649. │ │
  650. │Press the button to │
  651. │see a message box. │
  652. │ │
  653. │Enter name too. │
  654. │ │
  655. │ │
  656. │ │
  657. │ │
  658. │ │
  659. │ │
  660. │ │
  661. │ │
  662. │ │
  663. │ │
  664. │ │
  665. └────────────────────────┘
  666. ";
  667. pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output);
  668. Assert.Equal (new Rect (0, 0, 26, 20), pos);
  669. ((FakeDriver)Application.Driver).SetBufferSize (10, 10);
  670. Application.Refresh ();
  671. Assert.True (textView.WordWrap);
  672. Assert.True (scrollBar.AutoHideScrollBars);
  673. Assert.Equal (20, textView.Lines);
  674. Assert.Equal (7, textView.Maxlength);
  675. Assert.Equal (0, textView.LeftColumn);
  676. Assert.Equal (0, scrollBar.Position);
  677. Assert.Equal (0, scrollBar.OtherScrollBarView.Position);
  678. expected = @"
  679. ┌ Test ──┐
  680. │This ▲│
  681. │is the ┬│
  682. │help ││
  683. │text ┴│
  684. │for ░│
  685. │the ░│
  686. │Second ░│
  687. │Step. ▼│
  688. └────────┘
  689. ";
  690. pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output);
  691. Assert.Equal (new Rect (0, 0, 10, 10), pos);
  692. }
  693. [Fact, AutoInitShutdown]
  694. public void ContentBottomRightCorner_Not_Redraw_If_Both_Size_Equal_To_Zero ()
  695. {
  696. var text = "This is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test";
  697. var label = new Label (text);
  698. Application.Top.Add (label);
  699. var sbv = new ScrollBarView (label, true, true) {
  700. Size = 100,
  701. };
  702. sbv.OtherScrollBarView.Size = 100;
  703. Application.Begin (Application.Top);
  704. Assert.Equal (100, sbv.Size);
  705. Assert.Equal (100, sbv.OtherScrollBarView.Size);
  706. Assert.True (sbv.ShowScrollIndicator);
  707. Assert.True (sbv.OtherScrollBarView.ShowScrollIndicator);
  708. Assert.True (sbv.Visible);
  709. Assert.True (sbv.OtherScrollBarView.Visible);
  710. GraphViewTests.AssertDriverContentsWithFrameAre (@"
  711. This is a tes▲
  712. This is a tes┬
  713. This is a tes┴
  714. This is a tes░
  715. This is a tes▼
  716. ◄├─┤░░░░░░░░►
  717. ", output);
  718. sbv.Size = 0;
  719. sbv.OtherScrollBarView.Size = 0;
  720. Assert.Equal (0, sbv.Size);
  721. Assert.Equal (0, sbv.OtherScrollBarView.Size);
  722. Assert.False (sbv.ShowScrollIndicator);
  723. Assert.False (sbv.OtherScrollBarView.ShowScrollIndicator);
  724. Assert.False (sbv.Visible);
  725. Assert.False (sbv.OtherScrollBarView.Visible);
  726. Application.Top.Redraw (Application.Top.Bounds);
  727. GraphViewTests.AssertDriverContentsWithFrameAre (@"
  728. This is a test
  729. This is a test
  730. This is a test
  731. This is a test
  732. This is a test
  733. This is a test
  734. ", output);
  735. sbv.Size = 50;
  736. sbv.OtherScrollBarView.Size = 50;
  737. Assert.Equal (50, sbv.Size);
  738. Assert.Equal (50, sbv.OtherScrollBarView.Size);
  739. Assert.True (sbv.ShowScrollIndicator);
  740. Assert.True (sbv.OtherScrollBarView.ShowScrollIndicator);
  741. Assert.True (sbv.Visible);
  742. Assert.True (sbv.OtherScrollBarView.Visible);
  743. Application.Top.Redraw (Application.Top.Bounds);
  744. GraphViewTests.AssertDriverContentsWithFrameAre (@"
  745. This is a tes▲
  746. This is a tes┬
  747. This is a tes┴
  748. This is a tes░
  749. This is a tes▼
  750. ◄├──┤░░░░░░░►
  751. ", output);
  752. }
  753. [Fact, AutoInitShutdown]
  754. public void ContentBottomRightCorner_Not_Redraw_If_One_Size_Equal_To_Zero ()
  755. {
  756. var text = "This is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test";
  757. var label = new Label (text);
  758. Application.Top.Add (label);
  759. var sbv = new ScrollBarView (label, true, false) {
  760. Size = 100,
  761. };
  762. Application.Begin (Application.Top);
  763. Assert.Equal (100, sbv.Size);
  764. Assert.Null (sbv.OtherScrollBarView);
  765. Assert.True (sbv.ShowScrollIndicator);
  766. Assert.True (sbv.Visible);
  767. GraphViewTests.AssertDriverContentsWithFrameAre (@"
  768. This is a tes▲
  769. This is a tes┬
  770. This is a tes┴
  771. This is a tes░
  772. This is a tes░
  773. This is a tes▼
  774. ", output);
  775. sbv.Size = 0;
  776. Assert.Equal (0, sbv.Size);
  777. Assert.False (sbv.ShowScrollIndicator);
  778. Assert.False (sbv.Visible);
  779. Application.Top.Redraw (Application.Top.Bounds);
  780. GraphViewTests.AssertDriverContentsWithFrameAre (@"
  781. This is a test
  782. This is a test
  783. This is a test
  784. This is a test
  785. This is a test
  786. This is a test
  787. ", output);
  788. }
  789. [Fact, AutoInitShutdown]
  790. public void ShowScrollIndicator_False_Must_Also_Set_Visible_To_False_To_Not_Respond_To_Events ()
  791. {
  792. var clicked = false;
  793. var text = "This is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test";
  794. var label = new Label (text) { Width = 14, Height = 5 };
  795. var btn = new Button (14, 0, "Click Me!");
  796. btn.Clicked += () => clicked = true;
  797. Application.Top.Add (label, btn);
  798. var sbv = new ScrollBarView (label, true, false) {
  799. Size = 5,
  800. };
  801. Application.Begin (Application.Top);
  802. Assert.Equal (5, sbv.Size);
  803. Assert.Null (sbv.OtherScrollBarView);
  804. Assert.False (sbv.ShowScrollIndicator);
  805. Assert.False (sbv.Visible);
  806. GraphViewTests.AssertDriverContentsWithFrameAre (@"
  807. This is a test[ Click Me! ]
  808. This is a test
  809. This is a test
  810. This is a test
  811. This is a test
  812. ", output);
  813. ReflectionTools.InvokePrivate (
  814. typeof (Application),
  815. "ProcessMouseEvent",
  816. new MouseEvent () {
  817. X = 15,
  818. Y = 0,
  819. Flags = MouseFlags.Button1Clicked
  820. });
  821. Assert.Null (Application.MouseGrabView);
  822. Assert.True (clicked);
  823. clicked = false;
  824. sbv.Visible = true;
  825. Assert.Equal (5, sbv.Size);
  826. Assert.False (sbv.ShowScrollIndicator);
  827. Assert.True (sbv.Visible);
  828. Application.Top.Redraw (Application.Top.Bounds);
  829. GraphViewTests.AssertDriverContentsWithFrameAre (@"
  830. This is a test[ Click Me! ]
  831. This is a test
  832. This is a test
  833. This is a test
  834. This is a test
  835. ", output);
  836. ReflectionTools.InvokePrivate (
  837. typeof (Application),
  838. "ProcessMouseEvent",
  839. new MouseEvent () {
  840. X = 15,
  841. Y = 0,
  842. Flags = MouseFlags.Button1Clicked
  843. });
  844. Assert.Null (Application.MouseGrabView);
  845. Assert.True (clicked);
  846. Assert.Equal (5, sbv.Size);
  847. Assert.False (sbv.ShowScrollIndicator);
  848. Assert.False (sbv.Visible);
  849. }
  850. }
  851. }