ScrollViewTests.cs 38 KB

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