ScrollViewTests.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. using NStack;
  2. using Xunit;
  3. using Xunit.Abstractions;
  4. namespace Terminal.Gui.ViewTests {
  5. public class ScrollViewTests {
  6. readonly ITestOutputHelper output;
  7. public ScrollViewTests (ITestOutputHelper output)
  8. {
  9. this.output = output;
  10. }
  11. [Fact]
  12. public void Constructors_Defaults ()
  13. {
  14. var sv = new ScrollView ();
  15. Assert.Equal (LayoutStyle.Computed, sv.LayoutStyle);
  16. Assert.True (sv.CanFocus);
  17. Assert.Equal (new Rect (0, 0, 0, 0), sv.Frame);
  18. Assert.Equal (Rect.Empty, sv.Frame);
  19. Assert.Null (sv.X);
  20. Assert.Null (sv.Y);
  21. Assert.Null (sv.Width);
  22. Assert.Null (sv.Height);
  23. Assert.Equal (Point.Empty, sv.ContentOffset);
  24. Assert.Equal (Size.Empty, sv.ContentSize);
  25. Assert.True (sv.AutoHideScrollBars);
  26. Assert.True (sv.KeepContentAlwaysInViewport);
  27. sv = new ScrollView (new Rect (1, 2, 20, 10));
  28. Assert.Equal (LayoutStyle.Absolute, sv.LayoutStyle);
  29. Assert.True (sv.CanFocus);
  30. Assert.Equal (new Rect (1, 2, 20, 10), sv.Frame);
  31. Assert.Null (sv.X);
  32. Assert.Null (sv.Y);
  33. Assert.Null (sv.Width);
  34. Assert.Null (sv.Height);
  35. Assert.Equal (Point.Empty, sv.ContentOffset);
  36. Assert.Equal (Size.Empty, sv.ContentSize);
  37. Assert.True (sv.AutoHideScrollBars);
  38. Assert.True (sv.KeepContentAlwaysInViewport);
  39. }
  40. [Fact]
  41. public void Adding_Views ()
  42. {
  43. var sv = new ScrollView (new Rect (0, 0, 20, 10)) {
  44. ContentSize = new Size (30, 20)
  45. };
  46. sv.Add (new View () { Width = 10, Height = 5 },
  47. new View () { X = 12, Y = 7, Width = 10, Height = 5 });
  48. Assert.Equal (new Size (30, 20), sv.ContentSize);
  49. Assert.Equal (2, sv.Subviews [0].Subviews.Count);
  50. }
  51. [Fact]
  52. public void KeyBindings_Command ()
  53. {
  54. var sv = new ScrollView (new Rect (0, 0, 20, 10)) {
  55. ContentSize = new Size (40, 20)
  56. };
  57. sv.Add (new View () { Width = 20, Height = 5 },
  58. new View () { X = 22, Y = 7, Width = 10, Height = 5 });
  59. Assert.True (sv.KeepContentAlwaysInViewport);
  60. Assert.True (sv.AutoHideScrollBars);
  61. Assert.Equal (new Point (0, 0), sv.ContentOffset);
  62. Assert.False (sv.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ())));
  63. Assert.Equal (new Point (0, 0), sv.ContentOffset);
  64. Assert.True (sv.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())));
  65. Assert.Equal (new Point (0, -1), sv.ContentOffset);
  66. Assert.True (sv.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ())));
  67. Assert.Equal (new Point (0, 0), sv.ContentOffset);
  68. Assert.False (sv.ProcessKey (new KeyEvent (Key.PageUp, new KeyModifiers ())));
  69. Assert.Equal (new Point (0, 0), sv.ContentOffset);
  70. Assert.True (sv.ProcessKey (new KeyEvent (Key.PageDown, new KeyModifiers ())));
  71. Assert.Equal (new Point (0, -10), sv.ContentOffset);
  72. Assert.False (sv.ProcessKey (new KeyEvent (Key.PageDown, new KeyModifiers ())));
  73. Assert.Equal (new Point (0, -10), sv.ContentOffset);
  74. Assert.False (sv.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())));
  75. Assert.Equal (new Point (0, -10), sv.ContentOffset);
  76. Assert.True (sv.ProcessKey (new KeyEvent ((Key)'v' | Key.AltMask, new KeyModifiers ())));
  77. Assert.Equal (new Point (0, 0), sv.ContentOffset);
  78. Assert.True (sv.ProcessKey (new KeyEvent (Key.V | Key.CtrlMask, new KeyModifiers ())));
  79. Assert.Equal (new Point (0, -10), sv.ContentOffset);
  80. Assert.False (sv.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())));
  81. Assert.Equal (new Point (0, -10), sv.ContentOffset);
  82. Assert.True (sv.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())));
  83. Assert.Equal (new Point (-1, -10), sv.ContentOffset);
  84. Assert.True (sv.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())));
  85. Assert.Equal (new Point (0, -10), sv.ContentOffset);
  86. Assert.False (sv.ProcessKey (new KeyEvent (Key.PageUp | Key.CtrlMask, new KeyModifiers ())));
  87. Assert.Equal (new Point (0, -10), sv.ContentOffset);
  88. Assert.True (sv.ProcessKey (new KeyEvent (Key.PageDown | Key.CtrlMask, new KeyModifiers ())));
  89. Assert.Equal (new Point (-20, -10), sv.ContentOffset);
  90. Assert.False (sv.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())));
  91. Assert.Equal (new Point (-20, -10), sv.ContentOffset);
  92. Assert.True (sv.ProcessKey (new KeyEvent (Key.Home, new KeyModifiers ())));
  93. Assert.Equal (new Point (-20, 0), sv.ContentOffset);
  94. Assert.False (sv.ProcessKey (new KeyEvent (Key.Home, new KeyModifiers ())));
  95. Assert.Equal (new Point (-20, 0), sv.ContentOffset);
  96. Assert.True (sv.ProcessKey (new KeyEvent (Key.End, new KeyModifiers ())));
  97. Assert.Equal (new Point (-20, -10), sv.ContentOffset);
  98. Assert.False (sv.ProcessKey (new KeyEvent (Key.End, new KeyModifiers ())));
  99. Assert.Equal (new Point (-20, -10), sv.ContentOffset);
  100. Assert.True (sv.ProcessKey (new KeyEvent (Key.Home | Key.CtrlMask, new KeyModifiers ())));
  101. Assert.Equal (new Point (0, -10), sv.ContentOffset);
  102. Assert.False (sv.ProcessKey (new KeyEvent (Key.Home | Key.CtrlMask, new KeyModifiers ())));
  103. Assert.Equal (new Point (0, -10), sv.ContentOffset);
  104. Assert.True (sv.ProcessKey (new KeyEvent (Key.End | Key.CtrlMask, new KeyModifiers ())));
  105. Assert.Equal (new Point (-20, -10), sv.ContentOffset);
  106. Assert.False (sv.ProcessKey (new KeyEvent (Key.End | Key.CtrlMask, new KeyModifiers ())));
  107. Assert.Equal (new Point (-20, -10), sv.ContentOffset);
  108. Assert.True (sv.ProcessKey (new KeyEvent (Key.Home, new KeyModifiers ())));
  109. Assert.Equal (new Point (-20, 0), sv.ContentOffset);
  110. Assert.True (sv.ProcessKey (new KeyEvent (Key.Home | Key.CtrlMask, new KeyModifiers ())));
  111. Assert.Equal (new Point (0, 0), sv.ContentOffset);
  112. sv.KeepContentAlwaysInViewport = false;
  113. Assert.False (sv.KeepContentAlwaysInViewport);
  114. Assert.True (sv.AutoHideScrollBars);
  115. Assert.Equal (new Point (0, 0), sv.ContentOffset);
  116. Assert.False (sv.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ())));
  117. Assert.Equal (new Point (0, 0), sv.ContentOffset);
  118. Assert.True (sv.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())));
  119. Assert.Equal (new Point (0, -1), sv.ContentOffset);
  120. Assert.True (sv.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ())));
  121. Assert.Equal (new Point (0, 0), sv.ContentOffset);
  122. Assert.False (sv.ProcessKey (new KeyEvent (Key.PageUp, new KeyModifiers ())));
  123. Assert.Equal (new Point (0, 0), sv.ContentOffset);
  124. Assert.True (sv.ProcessKey (new KeyEvent (Key.PageDown, new KeyModifiers ())));
  125. Assert.Equal (new Point (0, -10), sv.ContentOffset);
  126. Assert.True (sv.ProcessKey (new KeyEvent (Key.PageDown, new KeyModifiers ())));
  127. Assert.Equal (new Point (0, -19), sv.ContentOffset);
  128. Assert.False (sv.ProcessKey (new KeyEvent (Key.PageDown, new KeyModifiers ())));
  129. Assert.Equal (new Point (0, -19), sv.ContentOffset);
  130. Assert.False (sv.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())));
  131. Assert.Equal (new Point (0, -19), sv.ContentOffset);
  132. Assert.True (sv.ProcessKey (new KeyEvent ((Key)'v' | Key.AltMask, new KeyModifiers ())));
  133. Assert.Equal (new Point (0, -9), sv.ContentOffset);
  134. Assert.True (sv.ProcessKey (new KeyEvent (Key.V | Key.CtrlMask, new KeyModifiers ())));
  135. Assert.Equal (new Point (0, -19), sv.ContentOffset);
  136. Assert.False (sv.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())));
  137. Assert.Equal (new Point (0, -19), sv.ContentOffset);
  138. Assert.True (sv.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())));
  139. Assert.Equal (new Point (-1, -19), sv.ContentOffset);
  140. Assert.True (sv.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())));
  141. Assert.Equal (new Point (0, -19), sv.ContentOffset);
  142. Assert.False (sv.ProcessKey (new KeyEvent (Key.PageUp | Key.CtrlMask, new KeyModifiers ())));
  143. Assert.Equal (new Point (0, -19), sv.ContentOffset);
  144. Assert.True (sv.ProcessKey (new KeyEvent (Key.PageDown | Key.CtrlMask, new KeyModifiers ())));
  145. Assert.Equal (new Point (-20, -19), sv.ContentOffset);
  146. Assert.True (sv.ProcessKey (new KeyEvent (Key.PageDown | Key.CtrlMask, new KeyModifiers ())));
  147. Assert.Equal (new Point (-39, -19), sv.ContentOffset);
  148. Assert.False (sv.ProcessKey (new KeyEvent (Key.PageDown | Key.CtrlMask, new KeyModifiers ())));
  149. Assert.Equal (new Point (-39, -19), sv.ContentOffset);
  150. Assert.False (sv.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())));
  151. Assert.Equal (new Point (-39, -19), sv.ContentOffset);
  152. Assert.True (sv.ProcessKey (new KeyEvent (Key.PageUp | Key.CtrlMask, new KeyModifiers ())));
  153. Assert.Equal (new Point (-19, -19), sv.ContentOffset);
  154. Assert.True (sv.ProcessKey (new KeyEvent (Key.Home, new KeyModifiers ())));
  155. Assert.Equal (new Point (-19, 0), sv.ContentOffset);
  156. Assert.False (sv.ProcessKey (new KeyEvent (Key.Home, new KeyModifiers ())));
  157. Assert.Equal (new Point (-19, 0), sv.ContentOffset);
  158. Assert.True (sv.ProcessKey (new KeyEvent (Key.End, new KeyModifiers ())));
  159. Assert.Equal (new Point (-19, -19), sv.ContentOffset);
  160. Assert.False (sv.ProcessKey (new KeyEvent (Key.End, new KeyModifiers ())));
  161. Assert.Equal (new Point (-19, -19), sv.ContentOffset);
  162. Assert.True (sv.ProcessKey (new KeyEvent (Key.Home | Key.CtrlMask, new KeyModifiers ())));
  163. Assert.Equal (new Point (0, -19), sv.ContentOffset);
  164. Assert.False (sv.ProcessKey (new KeyEvent (Key.Home | Key.CtrlMask, new KeyModifiers ())));
  165. Assert.Equal (new Point (0, -19), sv.ContentOffset);
  166. Assert.True (sv.ProcessKey (new KeyEvent (Key.End | Key.CtrlMask, new KeyModifiers ())));
  167. Assert.Equal (new Point (-39, -19), sv.ContentOffset);
  168. Assert.False (sv.ProcessKey (new KeyEvent (Key.End | Key.CtrlMask, new KeyModifiers ())));
  169. Assert.Equal (new Point (-39, -19), sv.ContentOffset);
  170. }
  171. [Fact, AutoInitShutdown]
  172. public void AutoHideScrollBars_ShowHorizontalScrollIndicator_ShowVerticalScrollIndicator ()
  173. {
  174. var sv = new ScrollView {
  175. Width = 10,
  176. Height = 10
  177. };
  178. Application.Top.Add (sv);
  179. Application.Begin (Application.Top);
  180. Assert.True (sv.AutoHideScrollBars);
  181. Assert.False (sv.ShowHorizontalScrollIndicator);
  182. Assert.False (sv.ShowVerticalScrollIndicator);
  183. TestHelpers.AssertDriverContentsWithFrameAre ("", output);
  184. sv.AutoHideScrollBars = false;
  185. sv.ShowHorizontalScrollIndicator = true;
  186. sv.ShowVerticalScrollIndicator = true;
  187. sv.Redraw (sv.Bounds);
  188. TestHelpers.AssertDriverContentsWithFrameAre (@"
  189. ◄├─────┤►
  190. ", output);
  191. }
  192. [Fact, AutoInitShutdown]
  193. public void ContentSize_AutoHideScrollBars_ShowHorizontalScrollIndicator_ShowVerticalScrollIndicator ()
  194. {
  195. var sv = new ScrollView {
  196. Width = 10,
  197. Height = 10,
  198. ContentSize = new Size (50, 50)
  199. };
  200. Application.Top.Add (sv);
  201. Application.Begin (Application.Top);
  202. Assert.Equal (50, sv.ContentSize.Width);
  203. Assert.Equal (50, sv.ContentSize.Height);
  204. Assert.True (sv.AutoHideScrollBars);
  205. Assert.True (sv.ShowHorizontalScrollIndicator);
  206. Assert.True (sv.ShowVerticalScrollIndicator);
  207. TestHelpers.AssertDriverContentsWithFrameAre (@"
  208. ◄├┤░░░░░►
  209. ", output);
  210. }
  211. [Fact, AutoInitShutdown]
  212. public void ContentOffset_ContentSize_AutoHideScrollBars_ShowHorizontalScrollIndicator_ShowVerticalScrollIndicator ()
  213. {
  214. var sv = new ScrollView {
  215. Width = 10,
  216. Height = 10,
  217. ContentSize = new Size (50, 50),
  218. ContentOffset = new Point (25, 25)
  219. };
  220. Application.Top.Add (sv);
  221. Application.Begin (Application.Top);
  222. Assert.Equal (-25, sv.ContentOffset.X);
  223. Assert.Equal (-25, sv.ContentOffset.Y);
  224. Assert.Equal (50, sv.ContentSize.Width);
  225. Assert.Equal (50, sv.ContentSize.Height);
  226. Assert.True (sv.AutoHideScrollBars);
  227. Assert.True (sv.ShowHorizontalScrollIndicator);
  228. Assert.True (sv.ShowVerticalScrollIndicator);
  229. TestHelpers.AssertDriverContentsWithFrameAre (@"
  230. ◄░░░├─┤░►
  231. ", output);
  232. }
  233. [Fact, AutoInitShutdown]
  234. public void Frame_And_Labels_Does_Not_Overspill_ScrollView ()
  235. {
  236. var sv = new ScrollView {
  237. X = 3,
  238. Y = 3,
  239. Width = 10,
  240. Height = 10,
  241. ContentSize = new Size (50, 50)
  242. };
  243. for (int i = 0; i < 8; i++) {
  244. sv.Add (new CustomButton ("█", $"Button {i}", 20, 3) { Y = i * 3 });
  245. }
  246. Application.Top.Add (sv);
  247. Application.Begin (Application.Top);
  248. TestHelpers.AssertDriverContentsWithFrameAre (@"
  249. █████████▲
  250. ██████But┬
  251. █████████┴
  252. ┌────────░
  253. │ But░
  254. └────────░
  255. ┌────────░
  256. │ But░
  257. └────────▼
  258. ◄├┤░░░░░► ", output);
  259. sv.ContentOffset = new Point (5, 5);
  260. Application.Refresh ();
  261. TestHelpers.AssertDriverContentsWithFrameAre (@"
  262. ─────────▲
  263. ─────────┬
  264. Button 2│
  265. ─────────┴
  266. ─────────░
  267. Button 3░
  268. ─────────░
  269. ─────────░
  270. Button 4▼
  271. ◄├─┤░░░░► ", output);
  272. }
  273. private class CustomButton : FrameView {
  274. private Label labelFill;
  275. private Label labelText;
  276. public CustomButton (string fill, ustring text, int width, int height)
  277. {
  278. Width = width;
  279. Height = height;
  280. labelFill = new Label () { AutoSize = false, Width = Dim.Fill (), Height = Dim.Fill (), Visible = false };
  281. var fillText = new System.Text.StringBuilder ();
  282. for (int i = 0; i < Bounds.Height; i++) {
  283. if (i > 0) {
  284. fillText.AppendLine ("");
  285. }
  286. for (int j = 0; j < Bounds.Width; j++) {
  287. fillText.Append (fill);
  288. }
  289. }
  290. labelFill.Text = fillText.ToString ();
  291. labelText = new Label (text) { X = Pos.Center (), Y = Pos.Center () };
  292. Add (labelFill, labelText);
  293. CanFocus = true;
  294. }
  295. public override bool OnEnter (View view)
  296. {
  297. Border.BorderStyle = BorderStyle.None;
  298. Border.DrawMarginFrame = false;
  299. labelFill.Visible = true;
  300. view = this;
  301. return base.OnEnter (view);
  302. }
  303. public override bool OnLeave (View view)
  304. {
  305. Border.BorderStyle = BorderStyle.Single;
  306. Border.DrawMarginFrame = true;
  307. labelFill.Visible = false;
  308. if (view == null)
  309. view = this;
  310. return base.OnLeave (view);
  311. }
  312. }
  313. [Fact, AutoInitShutdown]
  314. public void Clear_Window_Inside_ScrollView ()
  315. {
  316. var topLabel = new Label ("At 15,0") { X = 15 };
  317. var sv = new ScrollView {
  318. X = 3,
  319. Y = 3,
  320. Width = 10,
  321. Height = 10,
  322. ContentSize = new Size (23, 23),
  323. KeepContentAlwaysInViewport = false
  324. };
  325. var bottomLabel = new Label ("At 15,15") { X = 15, Y = 15 };
  326. Application.Top.Add (topLabel, sv, bottomLabel);
  327. Application.Begin (Application.Top);
  328. TestHelpers.AssertDriverContentsWithFrameAre (@"
  329. At 15,0
  330. ◄├┤░░░░░►
  331. At 15,15", output);
  332. var attributes = new Attribute [] {
  333. Colors.TopLevel.Normal,
  334. Colors.TopLevel.Focus,
  335. Colors.Base.Normal
  336. };
  337. TestHelpers.AssertDriverColorsAre (@"
  338. 00000000000000000000000
  339. 00000000000000000000000
  340. 00000000000000000000000
  341. 00000000000010000000000
  342. 00000000000010000000000
  343. 00000000000010000000000
  344. 00000000000010000000000
  345. 00000000000010000000000
  346. 00000000000010000000000
  347. 00000000000010000000000
  348. 00000000000010000000000
  349. 00000000000010000000000
  350. 00011111111110000000000
  351. 00000000000000000000000
  352. 00000000000000000000000
  353. 00000000000000000000000", attributes);
  354. sv.Add (new Window ("1") { X = 3, Y = 3, Width = 20, Height = 20 });
  355. Application.Refresh ();
  356. TestHelpers.AssertDriverContentsWithFrameAre (@"
  357. At 15,0
  358. ┌ 1 ──░
  359. │ ░
  360. │ ░
  361. │ ░
  362. │ ░
  363. │ ▼
  364. ◄├┤░░░░░►
  365. At 15,15", output);
  366. TestHelpers.AssertDriverColorsAre (@"
  367. 00000000000000000000000
  368. 00000000000000000000000
  369. 00000000000000000000000
  370. 00000000000010000000000
  371. 00000000000010000000000
  372. 00000000000010000000000
  373. 00000022222210000000000
  374. 00000022222210000000000
  375. 00000022222210000000000
  376. 00000022222210000000000
  377. 00000022222210000000000
  378. 00000022222210000000000
  379. 00011111111110000000000
  380. 00000000000000000000000
  381. 00000000000000000000000
  382. 00000000000000000000000", attributes);
  383. sv.ContentOffset = new Point (20, 20);
  384. Application.Refresh ();
  385. TestHelpers.AssertDriverContentsWithFrameAre (@"
  386. At 15,0
  387. │ ▲
  388. │ ░
  389. ──┘ ░
  390. ◄░░░░├─┤►
  391. At 15,15", output);
  392. TestHelpers.AssertDriverColorsAre (@"
  393. 00000000000000000000000
  394. 00000000000000000000000
  395. 00000000000000000000000
  396. 00022200000010000000000
  397. 00022200000010000000000
  398. 00022200000010000000000
  399. 00000000000010000000000
  400. 00000000000010000000000
  401. 00000000000010000000000
  402. 00000000000010000000000
  403. 00000000000010000000000
  404. 00000000000010000000000
  405. 00011111111110000000000
  406. 00000000000000000000000
  407. 00000000000000000000000
  408. 00000000000000000000000", attributes);
  409. }
  410. }
  411. }