ScrollViewTests.cs 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137
  1. using System.Text;
  2. using Xunit.Abstractions;
  3. namespace Terminal.Gui.ViewsTests;
  4. public class ScrollViewTests
  5. {
  6. private readonly ITestOutputHelper _output;
  7. public ScrollViewTests (ITestOutputHelper output) { _output = output; }
  8. [Fact]
  9. public void Adding_Views ()
  10. {
  11. var sv = new ScrollView { Width = 20, Height = 10, ContentSize = new (30, 20) };
  12. sv.Add (
  13. new View { Width = 10, Height = 5 },
  14. new View { X = 12, Y = 7, Width = 10, Height = 5 }
  15. );
  16. Assert.Equal (new (30, 20), sv.ContentSize);
  17. Assert.Equal (2, sv.Subviews [0].Subviews.Count);
  18. }
  19. [Fact]
  20. [AutoInitShutdown]
  21. public void AutoHideScrollBars_False_ShowHorizontalScrollIndicator_ShowVerticalScrollIndicator ()
  22. {
  23. var sv = new ScrollView { Width = 10, Height = 10, AutoHideScrollBars = false };
  24. sv.ShowHorizontalScrollIndicator = true;
  25. sv.ShowVerticalScrollIndicator = true;
  26. var top = new Toplevel ();
  27. top.Add (sv);
  28. Application.Begin (top);
  29. Assert.Equal (new Rectangle (0, 0, 10, 10), sv.Viewport);
  30. Assert.False (sv.AutoHideScrollBars);
  31. Assert.True (sv.ShowHorizontalScrollIndicator);
  32. Assert.True (sv.ShowVerticalScrollIndicator);
  33. sv.Draw ();
  34. TestHelpers.AssertDriverContentsAre (
  35. @"
  36. ◄├─────┤►
  37. ",
  38. _output
  39. );
  40. sv.ShowHorizontalScrollIndicator = false;
  41. Assert.Equal (new Rectangle (0, 0, 10, 10), sv.Viewport);
  42. sv.ShowVerticalScrollIndicator = true;
  43. Assert.Equal (new Rectangle (0, 0, 10, 10), sv.Viewport);
  44. Assert.False (sv.AutoHideScrollBars);
  45. Assert.False (sv.ShowHorizontalScrollIndicator);
  46. Assert.True (sv.ShowVerticalScrollIndicator);
  47. sv.Draw ();
  48. TestHelpers.AssertDriverContentsAre (
  49. @"
  50. ",
  51. _output
  52. );
  53. sv.ShowHorizontalScrollIndicator = true;
  54. sv.ShowVerticalScrollIndicator = false;
  55. Assert.False (sv.AutoHideScrollBars);
  56. Assert.True (sv.ShowHorizontalScrollIndicator);
  57. Assert.False (sv.ShowVerticalScrollIndicator);
  58. sv.Draw ();
  59. TestHelpers.AssertDriverContentsAre (
  60. @"
  61. ◄├──────┤►
  62. ",
  63. _output
  64. );
  65. sv.ShowHorizontalScrollIndicator = false;
  66. sv.ShowVerticalScrollIndicator = false;
  67. Assert.False (sv.AutoHideScrollBars);
  68. Assert.False (sv.ShowHorizontalScrollIndicator);
  69. Assert.False (sv.ShowVerticalScrollIndicator);
  70. sv.Draw ();
  71. TestHelpers.AssertDriverContentsAre (
  72. @"
  73. ",
  74. _output
  75. );
  76. }
  77. [Fact]
  78. [AutoInitShutdown]
  79. public void AutoHideScrollBars_ShowHorizontalScrollIndicator_ShowVerticalScrollIndicator ()
  80. {
  81. var sv = new ScrollView { Width = 10, Height = 10 };
  82. var top = new Toplevel ();
  83. top.Add (sv);
  84. Application.Begin (top);
  85. Assert.True (sv.AutoHideScrollBars);
  86. Assert.False (sv.ShowHorizontalScrollIndicator);
  87. Assert.False (sv.ShowVerticalScrollIndicator);
  88. TestHelpers.AssertDriverContentsWithFrameAre ("", _output);
  89. sv.AutoHideScrollBars = false;
  90. sv.ShowHorizontalScrollIndicator = true;
  91. sv.ShowVerticalScrollIndicator = true;
  92. sv.LayoutSubviews ();
  93. sv.Draw ();
  94. TestHelpers.AssertDriverContentsWithFrameAre (
  95. @"
  96. ◄├─────┤►
  97. ",
  98. _output
  99. );
  100. }
  101. // There are still issue with the lower right corner of the scroll view
  102. [Fact]
  103. [AutoInitShutdown]
  104. public void Clear_Window_Inside_ScrollView ()
  105. {
  106. var topLabel = new Label { X = 15, Text = "At 15,0" };
  107. var sv = new ScrollView
  108. {
  109. X = 3,
  110. Y = 3,
  111. Width = 10,
  112. Height = 10,
  113. ContentSize = new (23, 23),
  114. KeepContentAlwaysInViewport = false
  115. };
  116. var bottomLabel = new Label { X = 15, Y = 15, Text = "At 15,15" };
  117. var top = new Toplevel ();
  118. top.Add (topLabel, sv, bottomLabel);
  119. Application.Begin (top);
  120. TestHelpers.AssertDriverContentsWithFrameAre (
  121. @"
  122. At 15,0
  123. ◄├┤░░░░░►
  124. At 15,15",
  125. _output
  126. );
  127. Attribute [] attributes =
  128. {
  129. Colors.ColorSchemes ["TopLevel"].Normal,
  130. Colors.ColorSchemes ["TopLevel"].Focus,
  131. Colors.ColorSchemes ["Base"].Normal
  132. };
  133. TestHelpers.AssertDriverAttributesAre (
  134. @"
  135. 00000000000000000000000
  136. 00000000000000000000000
  137. 00000000000000000000000
  138. 00000000000010000000000
  139. 00000000000010000000000
  140. 00000000000010000000000
  141. 00000000000010000000000
  142. 00000000000010000000000
  143. 00000000000010000000000
  144. 00000000000010000000000
  145. 00000000000010000000000
  146. 00000000000010000000000
  147. 00011111111110000000000
  148. 00000000000000000000000
  149. 00000000000000000000000
  150. 00000000000000000000000",
  151. null,
  152. attributes
  153. );
  154. sv.Add (new Window { X = 3, Y = 3, Width = 20, Height = 20 });
  155. Application.Refresh ();
  156. TestHelpers.AssertDriverContentsWithFrameAre (
  157. @"
  158. At 15,0
  159. ┌─────░
  160. │ ░
  161. │ ░
  162. │ ░
  163. │ ░
  164. │ ▼
  165. ◄├┤░░░░░►
  166. At 15,15",
  167. _output
  168. );
  169. TestHelpers.AssertDriverAttributesAre (
  170. @"
  171. 00000000000000000000000
  172. 00000000000000000000000
  173. 00000000000000000000000
  174. 00000000000010000000000
  175. 00000000000010000000000
  176. 00000000000010000000000
  177. 00000022222210000000000
  178. 00000022222210000000000
  179. 00000022222210000000000
  180. 00000022222210000000000
  181. 00000022222210000000000
  182. 00000022222210000000000
  183. 00011111111110000000000
  184. 00000000000000000000000
  185. 00000000000000000000000
  186. 00000000000000000000000",
  187. null,
  188. attributes
  189. );
  190. sv.ContentOffset = new Point (20, 20);
  191. Application.Refresh ();
  192. TestHelpers.AssertDriverContentsWithFrameAre (
  193. @"
  194. At 15,0
  195. │ ▲
  196. │ ░
  197. ──┘ ░
  198. ◄░░░░├─┤►
  199. At 15,15",
  200. _output
  201. );
  202. TestHelpers.AssertDriverAttributesAre (
  203. @"
  204. 00000000000000000000000
  205. 00000000000000000000000
  206. 00000000000000000000000
  207. 00022200000010000000000
  208. 00022200000010000000000
  209. 00022200000010000000000
  210. 00000000000010000000000
  211. 00000000000010000000000
  212. 00000000000010000000000
  213. 00000000000010000000000
  214. 00000000000010000000000
  215. 00000000000010000000000
  216. 00011111111110000000000
  217. 00000000000000000000000
  218. 00000000000000000000000
  219. 00000000000000000000000",
  220. null,
  221. attributes
  222. );
  223. }
  224. [Fact]
  225. public void Constructors_Defaults ()
  226. {
  227. var sv = new ScrollView ();
  228. Assert.Equal (LayoutStyle.Absolute, sv.LayoutStyle);
  229. Assert.True (sv.CanFocus);
  230. Assert.Equal (new Rectangle (0, 0, 0, 0), sv.Frame);
  231. Assert.Equal (Rectangle.Empty, sv.Frame);
  232. Assert.Equal (Point.Empty, sv.ContentOffset);
  233. Assert.Equal (Size.Empty, sv.ContentSize);
  234. Assert.True (sv.AutoHideScrollBars);
  235. Assert.True (sv.KeepContentAlwaysInViewport);
  236. sv = new ScrollView { X = 1, Y = 2, Width = 20, Height = 10 };
  237. Assert.Equal (LayoutStyle.Absolute, sv.LayoutStyle);
  238. Assert.True (sv.CanFocus);
  239. Assert.Equal (new Rectangle (1, 2, 20, 10), sv.Frame);
  240. Assert.Equal (Point.Empty, sv.ContentOffset);
  241. Assert.Equal (sv.Viewport.Size, sv.ContentSize);
  242. Assert.True (sv.AutoHideScrollBars);
  243. Assert.True (sv.KeepContentAlwaysInViewport);
  244. }
  245. [Fact]
  246. [SetupFakeDriver]
  247. public void ContentBottomRightCorner_Draw ()
  248. {
  249. ((FakeDriver)Application.Driver).SetBufferSize (30, 30);
  250. var top = new View { Width = 30, Height = 30, ColorScheme = new ColorScheme { Normal = Attribute.Default } };
  251. Size size = new (20, 10);
  252. var sv = new ScrollView
  253. {
  254. X = 1,
  255. Y = 1,
  256. Width = 10,
  257. Height = 5,
  258. ContentSize = size,
  259. ColorScheme = new ColorScheme { Normal = new Attribute (Color.Red, Color.Green) }
  260. };
  261. string text = null;
  262. for (var i = 0; i < size.Height; i++)
  263. {
  264. text += "*".Repeat (size.Width);
  265. if (i < size.Height)
  266. {
  267. text += '\n';
  268. }
  269. }
  270. var view = new View
  271. {
  272. Width = size.Width,
  273. Height = size.Height,
  274. ColorScheme = new ColorScheme { Normal = new Attribute (Color.Blue, Color.Yellow) },
  275. AutoSize = true,
  276. Text = text
  277. };
  278. sv.Add (view);
  279. top.Add (sv);
  280. top.BeginInit ();
  281. top.EndInit ();
  282. top.LayoutSubviews ();
  283. top.Draw ();
  284. View contentBottomRightCorner = sv.Subviews.First (v => v is ScrollBarView.ContentBottomRightCorner);
  285. Assert.True (contentBottomRightCorner is ScrollBarView.ContentBottomRightCorner);
  286. Assert.True (contentBottomRightCorner.Visible);
  287. TestHelpers.AssertDriverContentsWithFrameAre (
  288. @"
  289. *********▲
  290. *********┬
  291. *********┴
  292. *********▼
  293. ◄├──┤░░░► ",
  294. _output
  295. );
  296. Attribute [] attrs = { Attribute.Default, new (Color.Red, Color.Green), new (Color.Blue, Color.Yellow) };
  297. TestHelpers.AssertDriverAttributesAre (
  298. @"
  299. 000000000000
  300. 022222222210
  301. 022222222210
  302. 022222222210
  303. 022222222210
  304. 011111111110
  305. 000000000000",
  306. null,
  307. attrs
  308. );
  309. }
  310. [Fact]
  311. [AutoInitShutdown]
  312. public void
  313. ContentOffset_ContentSize_AutoHideScrollBars_ShowHorizontalScrollIndicator_ShowVerticalScrollIndicator ()
  314. {
  315. var sv = new ScrollView
  316. {
  317. Width = 10, Height = 10, ContentSize = new (50, 50), ContentOffset = new (25, 25)
  318. };
  319. var top = new Toplevel ();
  320. top.Add (sv);
  321. Application.Begin (top);
  322. Assert.Equal(new(-25,-25),sv.ContentOffset);
  323. Assert.Equal(new(50,50),sv.ContentSize);
  324. Assert.True (sv.AutoHideScrollBars);
  325. Assert.True (sv.ShowHorizontalScrollIndicator);
  326. Assert.True (sv.ShowVerticalScrollIndicator);
  327. TestHelpers.AssertDriverContentsWithFrameAre (
  328. @"
  329. ◄░░░├─┤░►
  330. ",
  331. _output
  332. );
  333. }
  334. [Fact]
  335. [AutoInitShutdown]
  336. public void ContentSize_AutoHideScrollBars_ShowHorizontalScrollIndicator_ShowVerticalScrollIndicator ()
  337. {
  338. var sv = new ScrollView { Width = 10, Height = 10, ContentSize = new (50, 50) };
  339. var top = new Toplevel ();
  340. top.Add (sv);
  341. Application.Begin (top);
  342. Assert.Equal (50, sv.ContentSize.Width);
  343. Assert.Equal (50, sv.ContentSize.Height);
  344. Assert.True (sv.AutoHideScrollBars);
  345. Assert.True (sv.ShowHorizontalScrollIndicator);
  346. Assert.True (sv.ShowVerticalScrollIndicator);
  347. TestHelpers.AssertDriverContentsWithFrameAre (
  348. @"
  349. ◄├┤░░░░░►
  350. ",
  351. _output
  352. );
  353. }
  354. [Fact]
  355. [AutoInitShutdown]
  356. public void DrawTextFormatter_Respects_The_Clip_Bounds ()
  357. {
  358. var rule = "0123456789";
  359. Size size = new (40, 40);
  360. var view = new View { Frame = new (Point.Empty, size) };
  361. view.Add (
  362. new Label
  363. {
  364. AutoSize = false, Width = Dim.Fill (), Height = 1, Text = rule.Repeat (size.Width / rule.Length)
  365. }
  366. );
  367. view.Add (
  368. new Label
  369. {
  370. AutoSize = false,
  371. Height = Dim.Fill (),
  372. Width = 1,
  373. Text = rule.Repeat (size.Height / rule.Length),
  374. TextDirection = TextDirection.TopBottom_LeftRight
  375. }
  376. );
  377. view.Add (new Label { X = 1, Y = 1, Text = "[ Press me! ]" });
  378. var scrollView = new ScrollView
  379. {
  380. X = 1,
  381. Y = 1,
  382. Width = 15,
  383. Height = 10,
  384. ContentSize = size,
  385. ShowHorizontalScrollIndicator = true,
  386. ShowVerticalScrollIndicator = true
  387. };
  388. scrollView.Add (view);
  389. var win = new Window { X = 1, Y = 1, Width = 20, Height = 14 };
  390. win.Add (scrollView);
  391. var top = new Toplevel ();
  392. top.Add (win);
  393. Application.Begin (top);
  394. var expected = @"
  395. ┌──────────────────┐
  396. │ │
  397. │ 01234567890123▲ │
  398. │ 1[ Press me! ]┬ │
  399. │ 2 │ │
  400. │ 3 ┴ │
  401. │ 4 ░ │
  402. │ 5 ░ │
  403. │ 6 ░ │
  404. │ 7 ░ │
  405. │ 8 ▼ │
  406. │ ◄├───┤░░░░░░░► │
  407. │ │
  408. └──────────────────┘
  409. "
  410. ;
  411. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  412. Assert.Equal (new Rectangle (1, 1, 21, 14), pos);
  413. Assert.True (scrollView.OnKeyDown (Key.CursorRight));
  414. top.Draw ();
  415. expected = @"
  416. ┌──────────────────┐
  417. │ │
  418. │ 12345678901234▲ │
  419. │ [ Press me! ] ┬ │
  420. │ │ │
  421. │ ┴ │
  422. │ ░ │
  423. │ ░ │
  424. │ ░ │
  425. │ ░ │
  426. │ ▼ │
  427. │ ◄├───┤░░░░░░░► │
  428. │ │
  429. └──────────────────┘
  430. "
  431. ;
  432. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  433. Assert.Equal (new Rectangle (1, 1, 21, 14), pos);
  434. Assert.True (scrollView.OnKeyDown (Key.CursorRight));
  435. top.Draw ();
  436. expected = @"
  437. ┌──────────────────┐
  438. │ │
  439. │ 23456789012345▲ │
  440. │ Press me! ] ┬ │
  441. │ │ │
  442. │ ┴ │
  443. │ ░ │
  444. │ ░ │
  445. │ ░ │
  446. │ ░ │
  447. │ ▼ │
  448. │ ◄├────┤░░░░░░► │
  449. │ │
  450. └──────────────────┘
  451. "
  452. ;
  453. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  454. Assert.Equal (new Rectangle (1, 1, 21, 14), pos);
  455. Assert.True (scrollView.OnKeyDown (Key.CursorRight));
  456. top.Draw ();
  457. expected = @"
  458. ┌──────────────────┐
  459. │ │
  460. │ 34567890123456▲ │
  461. │ Press me! ] ┬ │
  462. │ │ │
  463. │ ┴ │
  464. │ ░ │
  465. │ ░ │
  466. │ ░ │
  467. │ ░ │
  468. │ ▼ │
  469. │ ◄├────┤░░░░░░► │
  470. │ │
  471. └──────────────────┘
  472. "
  473. ;
  474. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  475. Assert.Equal (new Rectangle (1, 1, 21, 14), pos);
  476. Assert.True (scrollView.OnKeyDown (Key.CursorRight));
  477. top.Draw ();
  478. expected = @"
  479. ┌──────────────────┐
  480. │ │
  481. │ 45678901234567▲ │
  482. │ ress me! ] ┬ │
  483. │ │ │
  484. │ ┴ │
  485. │ ░ │
  486. │ ░ │
  487. │ ░ │
  488. │ ░ │
  489. │ ▼ │
  490. │ ◄░├───┤░░░░░░► │
  491. │ │
  492. └──────────────────┘
  493. "
  494. ;
  495. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  496. Assert.Equal (new Rectangle (1, 1, 21, 14), pos);
  497. Assert.True (scrollView.OnKeyDown (Key.CursorRight));
  498. top.Draw ();
  499. expected = @"
  500. ┌──────────────────┐
  501. │ │
  502. │ 56789012345678▲ │
  503. │ ess me! ] ┬ │
  504. │ │ │
  505. │ ┴ │
  506. │ ░ │
  507. │ ░ │
  508. │ ░ │
  509. │ ░ │
  510. │ ▼ │
  511. │ ◄░├────┤░░░░░► │
  512. │ │
  513. └──────────────────┘
  514. "
  515. ;
  516. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  517. Assert.Equal (new Rectangle (1, 1, 21, 14), pos);
  518. Assert.True (scrollView.OnKeyDown (Key.CursorRight));
  519. top.Draw ();
  520. expected = @"
  521. ┌──────────────────┐
  522. │ │
  523. │ 67890123456789▲ │
  524. │ ss me! ] ┬ │
  525. │ │ │
  526. │ ┴ │
  527. │ ░ │
  528. │ ░ │
  529. │ ░ │
  530. │ ░ │
  531. │ ▼ │
  532. │ ◄░├────┤░░░░░► │
  533. │ │
  534. └──────────────────┘
  535. "
  536. ;
  537. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  538. Assert.Equal (new Rectangle (1, 1, 21, 14), pos);
  539. Assert.True (scrollView.OnKeyDown (Key.CursorRight));
  540. top.Draw ();
  541. expected = @"
  542. ┌──────────────────┐
  543. │ │
  544. │ 78901234567890▲ │
  545. │ s me! ] ┬ │
  546. │ │ │
  547. │ ┴ │
  548. │ ░ │
  549. │ ░ │
  550. │ ░ │
  551. │ ░ │
  552. │ ▼ │
  553. │ ◄░░├───┤░░░░░► │
  554. │ │
  555. └──────────────────┘
  556. ";
  557. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  558. Assert.Equal (new Rectangle (1, 1, 21, 14), pos);
  559. Assert.True (scrollView.OnKeyDown (Key.End.WithCtrl));
  560. top.Draw ();
  561. expected = @"
  562. ┌──────────────────┐
  563. │ │
  564. │ 67890123456789▲ │
  565. │ ┬ │
  566. │ │ │
  567. │ ┴ │
  568. │ ░ │
  569. │ ░ │
  570. │ ░ │
  571. │ ░ │
  572. │ ▼ │
  573. │ ◄░░░░░░░├───┤► │
  574. │ │
  575. └──────────────────┘
  576. ";
  577. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  578. Assert.Equal (new Rectangle (1, 1, 21, 14), pos);
  579. Assert.True (scrollView.OnKeyDown (Key.Home.WithCtrl));
  580. Assert.True (scrollView.OnKeyDown (Key.CursorDown));
  581. top.Draw ();
  582. expected = @"
  583. ┌──────────────────┐
  584. │ │
  585. │ 1[ Press me! ]▲ │
  586. │ 2 ┬ │
  587. │ 3 │ │
  588. │ 4 ┴ │
  589. │ 5 ░ │
  590. │ 6 ░ │
  591. │ 7 ░ │
  592. │ 8 ░ │
  593. │ 9 ▼ │
  594. │ ◄├───┤░░░░░░░► │
  595. │ │
  596. └──────────────────┘
  597. ";
  598. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  599. Assert.Equal (new Rectangle (1, 1, 21, 14), pos);
  600. Assert.True (scrollView.OnKeyDown (Key.CursorDown));
  601. top.Draw ();
  602. expected = @"
  603. ┌──────────────────┐
  604. │ │
  605. │ 2 ▲ │
  606. │ 3 ┬ │
  607. │ 4 │ │
  608. │ 5 ┴ │
  609. │ 6 ░ │
  610. │ 7 ░ │
  611. │ 8 ░ │
  612. │ 9 ░ │
  613. │ 0 ▼ │
  614. │ ◄├───┤░░░░░░░► │
  615. │ │
  616. └──────────────────┘
  617. ";
  618. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  619. Assert.Equal (new Rectangle (1, 1, 21, 14), pos);
  620. Assert.True (scrollView.OnKeyDown (Key.CursorDown));
  621. top.Draw ();
  622. expected = @"
  623. ┌──────────────────┐
  624. │ │
  625. │ 3 ▲ │
  626. │ 4 ┬ │
  627. │ 5 │ │
  628. │ 6 ┴ │
  629. │ 7 ░ │
  630. │ 8 ░ │
  631. │ 9 ░ │
  632. │ 0 ░ │
  633. │ 1 ▼ │
  634. │ ◄├───┤░░░░░░░► │
  635. │ │
  636. └──────────────────┘
  637. ";
  638. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  639. Assert.Equal (new Rectangle (1, 1, 21, 14), pos);
  640. Assert.True (scrollView.OnKeyDown (Key.End));
  641. top.Draw ();
  642. expected = @"
  643. ┌──────────────────┐
  644. │ │
  645. │ 1 ▲ │
  646. │ 2 ░ │
  647. │ 3 ░ │
  648. │ 4 ░ │
  649. │ 5 ░ │
  650. │ 6 ░ │
  651. │ 7 ┬ │
  652. │ 8 ┴ │
  653. │ 9 ▼ │
  654. │ ◄├───┤░░░░░░░► │
  655. │ │
  656. └──────────────────┘
  657. ";
  658. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  659. Assert.Equal (new Rectangle (1, 1, 21, 14), pos);
  660. }
  661. // There still have an issue with lower right corner of the scroll view
  662. [Fact]
  663. [AutoInitShutdown]
  664. public void Frame_And_Labels_Does_Not_Overspill_ScrollView ()
  665. {
  666. var sv = new ScrollView
  667. {
  668. X = 3,
  669. Y = 3,
  670. Width = 10,
  671. Height = 10,
  672. ContentSize = new (50, 50)
  673. };
  674. for (var i = 0; i < 8; i++)
  675. {
  676. sv.Add (new CustomButton ("█", $"Button {i}", 20, 3) { Y = i * 3 });
  677. }
  678. var top = new Toplevel ();
  679. top.Add (sv);
  680. Application.Begin (top);
  681. TestHelpers.AssertDriverContentsWithFrameAre (
  682. @"
  683. █████████▲
  684. ██████But┬
  685. █████████┴
  686. ┌────────░
  687. │ But░
  688. └────────░
  689. ┌────────░
  690. │ But░
  691. └────────▼
  692. ◄├┤░░░░░► ",
  693. _output
  694. );
  695. sv.ContentOffset = new Point (5, 5);
  696. sv.LayoutSubviews ();
  697. Application.Refresh ();
  698. TestHelpers.AssertDriverContentsWithFrameAre (
  699. @"
  700. ─────────▲
  701. ─────────┬
  702. Button 2│
  703. ─────────┴
  704. ─────────░
  705. Button 3░
  706. ─────────░
  707. ─────────░
  708. Button 4▼
  709. ◄├─┤░░░░► ",
  710. _output
  711. );
  712. }
  713. [Fact]
  714. public void KeyBindings_Command ()
  715. {
  716. var sv = new ScrollView { Width = 20, Height = 10, ContentSize = new (40, 20) };
  717. sv.Add (
  718. new View { Width = 20, Height = 5 },
  719. new View { X = 22, Y = 7, Width = 10, Height = 5 }
  720. );
  721. sv.BeginInit ();
  722. sv.EndInit ();
  723. Assert.True (sv.KeepContentAlwaysInViewport);
  724. Assert.True (sv.AutoHideScrollBars);
  725. Assert.Equal (Point.Empty, sv.ContentOffset);
  726. Assert.False (sv.OnKeyDown (Key.CursorUp));
  727. Assert.Equal (Point.Empty, sv.ContentOffset);
  728. Assert.True (sv.OnKeyDown (Key.CursorDown));
  729. Assert.Equal (new (0, -1), sv.ContentOffset);
  730. Assert.True (sv.OnKeyDown (Key.CursorUp));
  731. Assert.Equal (Point.Empty, sv.ContentOffset);
  732. Assert.False (sv.OnKeyDown (Key.PageUp));
  733. Assert.Equal (Point.Empty, sv.ContentOffset);
  734. Assert.True (sv.OnKeyDown (Key.PageDown));
  735. Point point0xMinus10 = new (0, -10);
  736. Assert.Equal (point0xMinus10, sv.ContentOffset);
  737. Assert.False (sv.OnKeyDown (Key.PageDown));
  738. Assert.Equal (point0xMinus10, sv.ContentOffset);
  739. Assert.False (sv.OnKeyDown (Key.CursorDown));
  740. Assert.Equal (point0xMinus10, sv.ContentOffset);
  741. Assert.True (sv.OnKeyDown (Key.V.WithAlt));
  742. Assert.Equal (Point.Empty, sv.ContentOffset);
  743. Assert.True (sv.OnKeyDown (Key.V.WithCtrl));
  744. Assert.Equal (point0xMinus10, sv.ContentOffset);
  745. Assert.False (sv.OnKeyDown (Key.CursorLeft));
  746. Assert.Equal (point0xMinus10, sv.ContentOffset);
  747. Assert.True (sv.OnKeyDown (Key.CursorRight));
  748. Assert.Equal (new (-1, -10), sv.ContentOffset);
  749. Assert.True (sv.OnKeyDown (Key.CursorLeft));
  750. Assert.Equal (point0xMinus10, sv.ContentOffset);
  751. Assert.False (sv.OnKeyDown (Key.PageUp.WithCtrl));
  752. Assert.Equal (point0xMinus10, sv.ContentOffset);
  753. Assert.True (sv.OnKeyDown (Key.PageDown.WithCtrl));
  754. Point pointMinus20xMinus10 = new (-20, -10);
  755. Assert.Equal (pointMinus20xMinus10, sv.ContentOffset);
  756. Assert.False (sv.OnKeyDown (Key.CursorRight));
  757. Assert.Equal (pointMinus20xMinus10, sv.ContentOffset);
  758. Assert.True (sv.OnKeyDown (Key.Home));
  759. Point pointMinus20x0 = new (-20, 0);
  760. Assert.Equal (pointMinus20x0, sv.ContentOffset);
  761. Assert.False (sv.OnKeyDown (Key.Home));
  762. Assert.Equal (pointMinus20x0, sv.ContentOffset);
  763. Assert.True (sv.OnKeyDown (Key.End));
  764. Assert.Equal (pointMinus20xMinus10, sv.ContentOffset);
  765. Assert.False (sv.OnKeyDown (Key.End));
  766. Assert.Equal (pointMinus20xMinus10, sv.ContentOffset);
  767. Assert.True (sv.OnKeyDown (Key.Home.WithCtrl));
  768. Assert.Equal (point0xMinus10, sv.ContentOffset);
  769. Assert.False (sv.OnKeyDown (Key.Home.WithCtrl));
  770. Assert.Equal (point0xMinus10, sv.ContentOffset);
  771. Assert.True (sv.OnKeyDown (Key.End.WithCtrl));
  772. Assert.Equal (pointMinus20xMinus10, sv.ContentOffset);
  773. Assert.False (sv.OnKeyDown (Key.End.WithCtrl));
  774. Assert.Equal (pointMinus20xMinus10, sv.ContentOffset);
  775. Assert.True (sv.OnKeyDown (Key.Home));
  776. Assert.Equal (pointMinus20x0, sv.ContentOffset);
  777. Assert.True (sv.OnKeyDown (Key.Home.WithCtrl));
  778. Assert.Equal (Point.Empty, sv.ContentOffset);
  779. sv.KeepContentAlwaysInViewport = false;
  780. Assert.False (sv.KeepContentAlwaysInViewport);
  781. Assert.True (sv.AutoHideScrollBars);
  782. Assert.Equal (Point.Empty, sv.ContentOffset);
  783. Assert.False (sv.OnKeyDown (Key.CursorUp));
  784. Assert.Equal (Point.Empty, sv.ContentOffset);
  785. Assert.True (sv.OnKeyDown (Key.CursorDown));
  786. Assert.Equal (new (0, -1), sv.ContentOffset);
  787. Assert.True (sv.OnKeyDown (Key.CursorUp));
  788. Assert.Equal (Point.Empty, sv.ContentOffset);
  789. Assert.False (sv.OnKeyDown (Key.PageUp));
  790. Assert.Equal (Point.Empty, sv.ContentOffset);
  791. Assert.True (sv.OnKeyDown (Key.PageDown));
  792. Assert.Equal (point0xMinus10, sv.ContentOffset);
  793. Assert.True (sv.OnKeyDown (Key.PageDown));
  794. Point point0xMinus19 = new (0, -19);
  795. Assert.Equal (point0xMinus19, sv.ContentOffset);
  796. Assert.False (sv.OnKeyDown (Key.PageDown));
  797. Assert.Equal (point0xMinus19, sv.ContentOffset);
  798. Assert.False (sv.OnKeyDown (Key.CursorDown));
  799. Assert.Equal (point0xMinus19, sv.ContentOffset);
  800. Assert.True (sv.OnKeyDown (Key.V.WithAlt));
  801. Assert.Equal (new (0, -9), sv.ContentOffset);
  802. Assert.True (sv.OnKeyDown (Key.V.WithCtrl));
  803. Assert.Equal (point0xMinus19, sv.ContentOffset);
  804. Assert.False (sv.OnKeyDown (Key.CursorLeft));
  805. Assert.Equal (point0xMinus19, sv.ContentOffset);
  806. Assert.True (sv.OnKeyDown (Key.CursorRight));
  807. Assert.Equal (new (-1, -19), sv.ContentOffset);
  808. Assert.True (sv.OnKeyDown (Key.CursorLeft));
  809. Assert.Equal (point0xMinus19, sv.ContentOffset);
  810. Assert.False (sv.OnKeyDown (Key.PageUp.WithCtrl));
  811. Assert.Equal (point0xMinus19, sv.ContentOffset);
  812. Assert.True (sv.OnKeyDown (Key.PageDown.WithCtrl));
  813. Assert.Equal (new (-20, -19), sv.ContentOffset);
  814. Assert.True (sv.OnKeyDown (Key.PageDown.WithCtrl));
  815. Point pointMinus39xMinus19 = new (-39, -19);
  816. Assert.Equal (pointMinus39xMinus19, sv.ContentOffset);
  817. Assert.False (sv.OnKeyDown (Key.PageDown.WithCtrl));
  818. Assert.Equal (pointMinus39xMinus19, sv.ContentOffset);
  819. Assert.False (sv.OnKeyDown (Key.CursorRight));
  820. Assert.Equal (pointMinus39xMinus19, sv.ContentOffset);
  821. Assert.True (sv.OnKeyDown (Key.PageUp.WithCtrl));
  822. Point pointMinus19xMinus19 = new Point (-19, -19);
  823. Assert.Equal (pointMinus19xMinus19, sv.ContentOffset);
  824. Assert.True (sv.OnKeyDown (Key.Home));
  825. Assert.Equal (new (-19, 0), sv.ContentOffset);
  826. Assert.False (sv.OnKeyDown (Key.Home));
  827. Assert.Equal (new (-19, 0), sv.ContentOffset);
  828. Assert.True (sv.OnKeyDown (Key.End));
  829. Assert.Equal (pointMinus19xMinus19, sv.ContentOffset);
  830. Assert.False (sv.OnKeyDown (Key.End));
  831. Assert.Equal (pointMinus19xMinus19, sv.ContentOffset);
  832. Assert.True (sv.OnKeyDown (Key.Home.WithCtrl));
  833. Assert.Equal (point0xMinus19, sv.ContentOffset);
  834. Assert.False (sv.OnKeyDown (Key.Home.WithCtrl));
  835. Assert.Equal (point0xMinus19, sv.ContentOffset);
  836. Assert.True (sv.OnKeyDown (Key.End.WithCtrl));
  837. Assert.Equal (pointMinus39xMinus19, sv.ContentOffset);
  838. Assert.False (sv.OnKeyDown (Key.End.WithCtrl));
  839. Assert.Equal (pointMinus39xMinus19, sv.ContentOffset);
  840. }
  841. [Fact]
  842. [AutoInitShutdown]
  843. public void Remove_Added_View_Is_Allowed ()
  844. {
  845. var sv = new ScrollView { Width = 20, Height = 20, ContentSize = new (100, 100) };
  846. sv.Add (
  847. new View { Width = Dim.Fill (), Height = Dim.Fill (50), Id = "View1" },
  848. new View { Y = 51, Width = Dim.Fill (), Height = Dim.Fill (), Id = "View2" }
  849. );
  850. var top = new Toplevel ();
  851. top.Add (sv);
  852. Application.Begin (top);
  853. Assert.Equal (4, sv.Subviews.Count);
  854. Assert.Equal (2, sv.Subviews [0].Subviews.Count);
  855. sv.Remove (sv.Subviews [0].Subviews [1]);
  856. Assert.Equal (4, sv.Subviews.Count);
  857. Assert.Single (sv.Subviews [0].Subviews);
  858. Assert.Equal ("View1", sv.Subviews [0].Subviews [0].Id);
  859. }
  860. private class CustomButton : FrameView
  861. {
  862. private readonly Label labelFill;
  863. private readonly Label labelText;
  864. public CustomButton (string fill, string text, int width, int height)
  865. {
  866. Width = width;
  867. Height = height;
  868. //labelFill = new Label { AutoSize = false, X = Pos.Center (), Y = Pos.Center (), Width = Dim.Fill (), Height = Dim.Fill (), Visible = false };
  869. labelFill = new Label { AutoSize = false, Width = Dim.Fill (), Height = Dim.Fill (), Visible = false };
  870. labelFill.LayoutComplete += (s, e) =>
  871. {
  872. var fillText = new StringBuilder ();
  873. for (var i = 0; i < labelFill.Viewport.Height; i++)
  874. {
  875. if (i > 0)
  876. {
  877. fillText.AppendLine ("");
  878. }
  879. for (var j = 0; j < labelFill.Viewport.Width; j++)
  880. {
  881. fillText.Append (fill);
  882. }
  883. }
  884. labelFill.Text = fillText.ToString ();
  885. };
  886. labelText = new Label { X = Pos.Center (), Y = Pos.Center (), Text = text };
  887. Add (labelFill, labelText);
  888. CanFocus = true;
  889. }
  890. public override bool OnEnter (View view)
  891. {
  892. Border.LineStyle = LineStyle.None;
  893. Border.Thickness = new Thickness (0);
  894. labelFill.Visible = true;
  895. view = this;
  896. return base.OnEnter (view);
  897. }
  898. public override bool OnLeave (View view)
  899. {
  900. Border.LineStyle = LineStyle.Single;
  901. Border.Thickness = new Thickness (1);
  902. labelFill.Visible = false;
  903. if (view == null)
  904. {
  905. view = this;
  906. }
  907. return base.OnLeave (view);
  908. }
  909. }
  910. }