DrawTests.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963
  1. #nullable enable
  2. using System.Text;
  3. using UnitTests;
  4. using Xunit.Abstractions;
  5. namespace UnitTests.ViewBaseTests;
  6. [Trait ("Category", "Output")]
  7. public class DrawTests (ITestOutputHelper output)
  8. {
  9. [Fact]
  10. [AutoInitShutdown]
  11. [Trait ("Category", "Unicode")]
  12. public void CJK_Compatibility_Ideographs_ConsoleWidth_ColumnWidth_Equal_Two ()
  13. {
  14. const string s = "\U0000f900";
  15. var r = (Rune)0xf900;
  16. Assert.Equal ("豈", s);
  17. Assert.Equal ("豈", r.ToString ());
  18. Assert.Equal (s, r.ToString ());
  19. Assert.Equal (2, s.GetColumns ());
  20. Assert.Equal (2, r.GetColumns ());
  21. var win = new Window { Title = s };
  22. var view = new View { Text = r.ToString (), Height = Dim.Fill (), Width = Dim.Fill () };
  23. var tf = new TextField { Text = s, Y = 1, Width = 3 };
  24. win.Add (view, tf);
  25. Runnable top = new ();
  26. top.Add (win);
  27. Application.Begin (top);
  28. Application.Driver!.SetScreenSize (10, 4);
  29. Application.LayoutAndDraw ();
  30. const string expectedOutput = """
  31. ┌┤豈├────┐
  32. │豈 │
  33. │豈 │
  34. └────────┘
  35. """;
  36. DriverAssert.AssertDriverContentsWithFrameAre (expectedOutput, output);
  37. DriverAssert.AssertDriverContentsAre (expectedOutput, output);
  38. // This test has nothing to do with color - removing as it is not relevant and fragile
  39. top.Dispose ();
  40. }
  41. [Fact]
  42. [AutoInitShutdown]
  43. [Trait ("Category", "Output")]
  44. public void Colors_On_TextAlignment_Right_And_Bottom ()
  45. {
  46. var viewRight = new View
  47. {
  48. Text = "Test",
  49. Width = 6,
  50. Height = 1,
  51. TextAlignment = Alignment.End,
  52. };
  53. var viewBottom = new View
  54. {
  55. Text = "Test",
  56. TextDirection = TextDirection.TopBottom_LeftRight,
  57. Y = 1,
  58. Width = 1,
  59. Height = 6,
  60. VerticalTextAlignment = Alignment.End,
  61. };
  62. Runnable top = new ();
  63. top.Add (viewRight, viewBottom);
  64. var rs = Application.Begin (top);
  65. Application.Driver!.SetScreenSize (7, 7);
  66. AutoInitShutdownAttribute.RunIteration ();
  67. DriverAssert.AssertDriverContentsWithFrameAre (
  68. """
  69. Test
  70. T
  71. e
  72. s
  73. t
  74. """,
  75. output
  76. );
  77. DriverAssert.AssertDriverAttributesAre (
  78. """
  79. 000000
  80. 0
  81. 0
  82. 0
  83. 0
  84. 0
  85. 0
  86. """,
  87. output,
  88. Application.Driver,
  89. SchemeManager.GetSchemes () ["Base"]!.Normal
  90. );
  91. top.Dispose ();
  92. }
  93. [Fact]
  94. [SetupFakeApplication]
  95. public void Draw_Minimum_Full_Border_With_Empty_Viewport ()
  96. {
  97. var view = new View
  98. {
  99. App = ApplicationImpl.Instance,
  100. Width = 2, Height = 2, BorderStyle = LineStyle.Single
  101. };
  102. Assert.True (view.NeedsLayout);
  103. Assert.True (view.NeedsDraw);
  104. view.Layout ();
  105. Assert.Equal (new (0, 0, 2, 2), view.Frame);
  106. Assert.Equal (Rectangle.Empty, view.Viewport);
  107. Assert.True (view.NeedsDraw);
  108. view.Draw ();
  109. DriverAssert.AssertDriverContentsWithFrameAre (
  110. """
  111. ┌┐
  112. └┘
  113. """,
  114. output
  115. );
  116. }
  117. [Fact]
  118. [SetupFakeApplication]
  119. public void Draw_Minimum_Full_Border_With_Empty_Viewport_Without_Bottom ()
  120. {
  121. var view = new View
  122. {
  123. App = ApplicationImpl.Instance,
  124. Width = 2, Height = 1, BorderStyle = LineStyle.Single
  125. };
  126. view.Border!.Thickness = new (1, 1, 1, 0);
  127. view.BeginInit ();
  128. view.EndInit ();
  129. view.SetRelativeLayout (Application.Screen.Size);
  130. Assert.Equal (new (0, 0, 2, 1), view.Frame);
  131. Assert.Equal (Rectangle.Empty, view.Viewport);
  132. view.Draw ();
  133. DriverAssert.AssertDriverContentsWithFrameAre ("──", output);
  134. }
  135. [Fact]
  136. [SetupFakeApplication]
  137. public void Draw_Minimum_Full_Border_With_Empty_Viewport_Without_Left ()
  138. {
  139. var view = new View
  140. {
  141. App = ApplicationImpl.Instance,
  142. Width = 1, Height = 2, BorderStyle = LineStyle.Single
  143. };
  144. view.Border!.Thickness = new (0, 1, 1, 1);
  145. view.BeginInit ();
  146. view.EndInit ();
  147. view.SetRelativeLayout (Application.Screen.Size);
  148. Assert.Equal (new (0, 0, 1, 2), view.Frame);
  149. Assert.Equal (Rectangle.Empty, view.Viewport);
  150. view.Draw ();
  151. DriverAssert.AssertDriverContentsWithFrameAre (
  152. """
  153. """,
  154. output
  155. );
  156. }
  157. [Fact]
  158. [SetupFakeApplication]
  159. public void Draw_Minimum_Full_Border_With_Empty_Viewport_Without_Right ()
  160. {
  161. var view = new View
  162. {
  163. App = ApplicationImpl.Instance,
  164. Width = 1, Height = 2, BorderStyle = LineStyle.Single
  165. };
  166. view.Border!.Thickness = new (1, 1, 0, 1);
  167. view.BeginInit ();
  168. view.EndInit ();
  169. view.SetRelativeLayout (Application.Screen.Size);
  170. Assert.Equal (new (0, 0, 1, 2), view.Frame);
  171. Assert.Equal (Rectangle.Empty, view.Viewport);
  172. view.Draw ();
  173. DriverAssert.AssertDriverContentsWithFrameAre (
  174. """
  175. """,
  176. output
  177. );
  178. }
  179. [Fact]
  180. [SetupFakeApplication]
  181. public void Draw_Minimum_Full_Border_With_Empty_Viewport_Without_Top ()
  182. {
  183. var view = new View
  184. {
  185. App = ApplicationImpl.Instance,
  186. Width = 2, Height = 1, BorderStyle = LineStyle.Single
  187. };
  188. view.Border!.Thickness = new (1, 0, 1, 1);
  189. view.BeginInit ();
  190. view.EndInit ();
  191. view.SetRelativeLayout (Application.Screen.Size);
  192. Assert.Equal (new (0, 0, 2, 1), view.Frame);
  193. Assert.Equal (Rectangle.Empty, view.Viewport);
  194. view.Draw ();
  195. DriverAssert.AssertDriverContentsWithFrameAre (
  196. "││",
  197. output
  198. );
  199. }
  200. [Fact]
  201. [AutoInitShutdown]
  202. public void Draw_Negative_Viewport_Horizontal_With_New_Lines ()
  203. {
  204. var subView = new View
  205. {
  206. Id = "subView",
  207. X = 1,
  208. Width = 1,
  209. Height = 7,
  210. Text = """
  211. s
  212. u
  213. b
  214. V
  215. i
  216. e
  217. w
  218. """
  219. };
  220. var view = new View
  221. {
  222. Id = "view", Width = 2, Height = 20, Text = """
  223. 0
  224. 1
  225. 2
  226. 3
  227. 4
  228. 5
  229. 6
  230. 7
  231. 8
  232. 9
  233. 0
  234. 1
  235. 2
  236. 3
  237. 4
  238. 5
  239. 6
  240. 7
  241. 8
  242. 9
  243. """
  244. };
  245. view.Add (subView);
  246. var content = new View { Id = "content", Width = 20, Height = 20 };
  247. content.Add (view);
  248. var container = new View
  249. {
  250. Id = "container",
  251. X = 1,
  252. Y = 1,
  253. Width = 5,
  254. Height = 5
  255. };
  256. container.Add (content);
  257. Runnable top = new ();
  258. top.Add (container);
  259. var rs = Application.Begin (top);
  260. top.Draw ();
  261. DriverAssert.AssertDriverContentsWithFrameAre (
  262. """
  263. 0s
  264. 1u
  265. 2b
  266. 3V
  267. 4i
  268. """,
  269. output
  270. );
  271. content.X = -1;
  272. AutoInitShutdownAttribute.RunIteration ();
  273. DriverAssert.AssertDriverContentsWithFrameAre (
  274. """
  275. s
  276. u
  277. b
  278. V
  279. i
  280. """,
  281. output
  282. );
  283. content.X = -2;
  284. AutoInitShutdownAttribute.RunIteration ();
  285. DriverAssert.AssertDriverContentsWithFrameAre (@"", output);
  286. content.X = 0;
  287. content.Y = -1;
  288. AutoInitShutdownAttribute.RunIteration ();
  289. DriverAssert.AssertDriverContentsWithFrameAre (
  290. """
  291. 1u
  292. 2b
  293. 3V
  294. 4i
  295. 5e
  296. """,
  297. output
  298. );
  299. content.Y = -6;
  300. AutoInitShutdownAttribute.RunIteration ();
  301. DriverAssert.AssertDriverContentsWithFrameAre (
  302. """
  303. 6w
  304. 7
  305. 8
  306. 9
  307. 0
  308. """,
  309. output
  310. );
  311. content.Y = -19;
  312. AutoInitShutdownAttribute.RunIteration ();
  313. DriverAssert.AssertDriverContentsWithFrameAre (
  314. """
  315. 9
  316. """,
  317. output
  318. );
  319. content.Y = -20;
  320. AutoInitShutdownAttribute.RunIteration ();
  321. DriverAssert.AssertDriverContentsWithFrameAre ("", output);
  322. content.X = -2;
  323. content.Y = 0;
  324. AutoInitShutdownAttribute.RunIteration ();
  325. DriverAssert.AssertDriverContentsWithFrameAre ("", output);
  326. top.Dispose ();
  327. }
  328. [Fact]
  329. [AutoInitShutdown]
  330. public void Draw_Negative_Viewport_Horizontal_Without_New_Lines ()
  331. {
  332. // BUGBUG: This previously assumed the default height of a View was 1.
  333. var subView = new View
  334. {
  335. Id = "subView",
  336. Y = 1,
  337. Width = 7,
  338. Height = 1,
  339. Text = "subView"
  340. };
  341. var view = new View { Id = "view", Width = 20, Height = 2, Text = "01234567890123456789" };
  342. view.Add (subView);
  343. var content = new View { Id = "content", Width = 20, Height = 20 };
  344. content.Add (view);
  345. var container = new View
  346. {
  347. Id = "container",
  348. X = 1,
  349. Y = 1,
  350. Width = 5,
  351. Height = 5
  352. };
  353. container.Add (content);
  354. Runnable top = new ();
  355. top.Add (container);
  356. // BUGBUG: v2 - it's bogus to reference .Frame before BeginInit. And why is the clip being set anyway???
  357. top.SubViewsLaidOut += Top_LayoutComplete;
  358. Application.Begin (top);
  359. AutoInitShutdownAttribute.RunIteration ();
  360. DriverAssert.AssertDriverContentsWithFrameAre (
  361. """
  362. 01234
  363. subVi
  364. """,
  365. output
  366. );
  367. content.X = -1;
  368. AutoInitShutdownAttribute.RunIteration ();
  369. DriverAssert.AssertDriverContentsWithFrameAre (
  370. """
  371. 12345
  372. ubVie
  373. """,
  374. output
  375. );
  376. content.Y = -1;
  377. AutoInitShutdownAttribute.RunIteration ();
  378. DriverAssert.AssertDriverContentsWithFrameAre (
  379. """
  380. ubVie
  381. """,
  382. output
  383. );
  384. content.Y = -2;
  385. AutoInitShutdownAttribute.RunIteration ();
  386. DriverAssert.AssertDriverContentsWithFrameAre ("", output);
  387. content.X = -20;
  388. content.Y = 0;
  389. AutoInitShutdownAttribute.RunIteration ();
  390. DriverAssert.AssertDriverContentsWithFrameAre ("", output);
  391. top.Dispose ();
  392. return;
  393. void Top_LayoutComplete (object? sender, LayoutEventArgs e) { Application.Driver!.Clip = new (container.Frame); }
  394. }
  395. [Fact]
  396. [AutoInitShutdown]
  397. public void Draw_Negative_Viewport_Vertical ()
  398. {
  399. var subView = new View
  400. {
  401. Id = "subView",
  402. X = 1,
  403. Width = 1,
  404. Height = 7,
  405. Text = "subView",
  406. TextDirection = TextDirection.TopBottom_LeftRight
  407. };
  408. var view = new View
  409. {
  410. Id = "view",
  411. Width = 2,
  412. Height = 20,
  413. Text = "01234567890123456789",
  414. TextDirection = TextDirection.TopBottom_LeftRight
  415. };
  416. view.Add (subView);
  417. var content = new View { Id = "content", Width = 20, Height = 20 };
  418. content.Add (view);
  419. var container = new View
  420. {
  421. Id = "container",
  422. X = 1,
  423. Y = 1,
  424. Width = 5,
  425. Height = 5
  426. };
  427. container.Add (content);
  428. Runnable top = new ();
  429. top.Add (container);
  430. Application.Begin (top);
  431. AutoInitShutdownAttribute.RunIteration ();
  432. DriverAssert.AssertDriverContentsWithFrameAre (
  433. """
  434. 0s
  435. 1u
  436. 2b
  437. 3V
  438. 4i
  439. """,
  440. output
  441. );
  442. content.X = -1;
  443. AutoInitShutdownAttribute.RunIteration ();
  444. DriverAssert.AssertDriverContentsWithFrameAre (
  445. """
  446. s
  447. u
  448. b
  449. V
  450. i
  451. """,
  452. output
  453. );
  454. content.X = -2;
  455. AutoInitShutdownAttribute.RunIteration ();
  456. DriverAssert.AssertDriverContentsWithFrameAre (@"", output);
  457. content.X = 0;
  458. content.Y = -1;
  459. AutoInitShutdownAttribute.RunIteration ();
  460. DriverAssert.AssertDriverContentsWithFrameAre (
  461. """
  462. 1u
  463. 2b
  464. 3V
  465. 4i
  466. 5e
  467. """,
  468. output
  469. );
  470. content.Y = -6;
  471. AutoInitShutdownAttribute.RunIteration ();
  472. DriverAssert.AssertDriverContentsWithFrameAre (
  473. """
  474. 6w
  475. 7
  476. 8
  477. 9
  478. 0
  479. """,
  480. output
  481. );
  482. content.Y = -19;
  483. AutoInitShutdownAttribute.RunIteration ();
  484. DriverAssert.AssertDriverContentsWithFrameAre (
  485. """
  486. 9
  487. """,
  488. output
  489. );
  490. content.Y = -20;
  491. AutoInitShutdownAttribute.RunIteration ();
  492. DriverAssert.AssertDriverContentsWithFrameAre ("", output);
  493. content.X = -2;
  494. content.Y = 0;
  495. AutoInitShutdownAttribute.RunIteration ();
  496. DriverAssert.AssertDriverContentsWithFrameAre ("", output);
  497. top.Dispose ();
  498. }
  499. [Theory]
  500. [SetupFakeApplication]
  501. [InlineData ("𝔽𝕆𝕆𝔹𝔸R")]
  502. [InlineData ("a𐐀b")]
  503. public void DrawHotString_NonBmp (string expected)
  504. {
  505. var view = new View
  506. {
  507. App = ApplicationImpl.Instance,
  508. Width = 10, Height = 1
  509. };
  510. view.DrawHotString (expected, Attribute.Default, Attribute.Default);
  511. DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
  512. }
  513. // TODO: The tests below that use Label should use View instead.
  514. [Fact]
  515. [AutoInitShutdown]
  516. public void Non_Bmp_ConsoleWidth_ColumnWidth_Equal_Two ()
  517. {
  518. var us = "\U0001d539";
  519. var r = (Rune)0x1d539;
  520. Assert.Equal ("𝔹", us);
  521. Assert.Equal ("𝔹", r.ToString ());
  522. Assert.Equal (us, r.ToString ());
  523. Assert.Equal (1, us.GetColumns ());
  524. Assert.Equal (1, r.GetColumns ());
  525. var win = new Window { Title = us };
  526. var view = new Label { Text = r.ToString () };
  527. var tf = new TextField { Text = us, Y = 1, Width = 3 };
  528. win.Add (view, tf);
  529. Runnable top = new ();
  530. top.Add (win);
  531. Application.Begin (top);
  532. Application.Driver!.SetScreenSize (10, 4);
  533. Application.LayoutAndDraw ();
  534. var expected = """
  535. ┌┤𝔹├─────┐
  536. │𝔹 │
  537. │𝔹 │
  538. └────────┘
  539. """;
  540. DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
  541. DriverAssert.AssertDriverContentsAre (expected, output);
  542. top.Dispose ();
  543. // This test has nothing to do with color - removing as it is not relevant and fragile
  544. }
  545. [Fact]
  546. [AutoInitShutdown]
  547. public void Draw_Throws_IndexOutOfRangeException_With_Negative_Bounds ()
  548. {
  549. Runnable top = new ();
  550. var view = new View { X = -2, Text = "view" };
  551. top.Add (view);
  552. Application.Iteration += OnApplicationOnIteration;
  553. try
  554. {
  555. Application.Run (top);
  556. }
  557. catch (IndexOutOfRangeException ex)
  558. {
  559. // After the fix this exception will not be caught.
  560. Assert.IsType<IndexOutOfRangeException> (ex);
  561. }
  562. finally
  563. {
  564. Application.Iteration -= OnApplicationOnIteration;
  565. }
  566. top.Dispose ();
  567. // Shutdown must be called to safely clean up Application if Init has been called
  568. Application.Shutdown ();
  569. return;
  570. void OnApplicationOnIteration (object? s, EventArgs<IApplication?> a)
  571. {
  572. Assert.Equal (-2, view.X);
  573. Application.RequestStop ();
  574. }
  575. }
  576. [Fact]
  577. [AutoInitShutdown]
  578. public void Correct_Redraw_Viewport_NeedDisplay_On_Shrink_And_Move_Down_Right_Using_Frame ()
  579. {
  580. var label = new Label { Text = "At 0,0" };
  581. var view = new DerivedView
  582. {
  583. X = 2,
  584. Y = 2,
  585. Width = 30,
  586. Height = 2,
  587. Text = "A text with some long width\n and also with two lines."
  588. };
  589. Runnable top = new ();
  590. top.Add (label, view);
  591. SessionToken sessionToken = Application.Begin (top);
  592. AutoInitShutdownAttribute.RunIteration ();
  593. DriverAssert.AssertDriverContentsWithFrameAre (
  594. @"
  595. At 0,0
  596. A text with some long width
  597. and also with two lines. "
  598. ,
  599. output
  600. );
  601. view.Frame = new (3, 3, 10, 1);
  602. Assert.Equal (new (3, 3, 10, 1), view.Frame);
  603. Assert.Equal (new (0, 0, 10, 1), view.Viewport);
  604. Assert.Equal (new (0, 0, 10, 1), view.NeedsDrawRect);
  605. //Application.Refresh();
  606. top.Draw ();
  607. DriverAssert.AssertDriverContentsWithFrameAre (
  608. @"
  609. At 0,0
  610. A text wit",
  611. output
  612. );
  613. Application.End (sessionToken);
  614. top.Dispose ();
  615. }
  616. [Fact]
  617. [AutoInitShutdown]
  618. public void Correct_Redraw_Viewport_NeedDisplay_On_Shrink_And_Move_Down_Right_Using_Pos_Dim ()
  619. {
  620. var label = new Label { Text = "At 0,0" };
  621. var view = new DerivedView
  622. {
  623. X = 2,
  624. Y = 2,
  625. Width = 30,
  626. Height = 2,
  627. Text = "A text with some long width\n and also with two lines."
  628. };
  629. Runnable top = new ();
  630. top.Add (label, view);
  631. SessionToken sessionToken = Application.Begin (top);
  632. top.Draw ();
  633. DriverAssert.AssertDriverContentsWithFrameAre (
  634. @"
  635. At 0,0
  636. A text with some long width
  637. and also with two lines. "
  638. ,
  639. output
  640. );
  641. view.X = 3;
  642. view.Y = 3;
  643. view.Width = 10;
  644. view.Height = 1;
  645. Assert.Equal (new (3, 3, 10, 1), view.Frame);
  646. Assert.Equal (new (0, 0, 10, 1), view.Viewport);
  647. Assert.Equal (new (0, 0, 10, 1), view.NeedsDrawRect);
  648. view.SetClipToScreen ();
  649. top.Draw ();
  650. DriverAssert.AssertDriverContentsWithFrameAre (
  651. @"
  652. At 0,0
  653. A text wit"
  654. ,
  655. output
  656. );
  657. Application.End (sessionToken);
  658. top.Dispose ();
  659. }
  660. [Fact]
  661. [AutoInitShutdown]
  662. public void Correct_Redraw_Viewport_NeedDisplay_On_Shrink_And_Move_Up_Left_Using_Frame ()
  663. {
  664. var label = new Label { Text = "At 0,0" };
  665. var view = new DerivedView
  666. {
  667. X = 2,
  668. Y = 2,
  669. Width = 30,
  670. Height = 2,
  671. Text = "A text with some long width\n and also with two lines."
  672. };
  673. Runnable top = new ();
  674. top.Add (label, view);
  675. SessionToken sessionToken = Application.Begin (top);
  676. AutoInitShutdownAttribute.RunIteration ();
  677. DriverAssert.AssertDriverContentsWithFrameAre (
  678. @"
  679. At 0,0
  680. A text with some long width
  681. and also with two lines. "
  682. ,
  683. output
  684. );
  685. view.Frame = new (1, 1, 10, 1);
  686. Assert.Equal (new (1, 1, 10, 1), view.Frame);
  687. Assert.Equal (new (0, 0, 10, 1), view.Viewport);
  688. Assert.Equal (new (0, 0, 10, 1), view.NeedsDrawRect);
  689. top.Draw ();
  690. DriverAssert.AssertDriverContentsWithFrameAre (
  691. @"
  692. At 0,0
  693. A text wit"
  694. ,
  695. output
  696. );
  697. Application.End (sessionToken);
  698. top.Dispose ();
  699. }
  700. [Fact]
  701. [AutoInitShutdown]
  702. public void Correct_Redraw_Viewport_NeedDisplay_On_Shrink_And_Move_Up_Left_Using_Pos_Dim ()
  703. {
  704. var label = new Label { Text = "At 0,0" };
  705. var view = new DerivedView
  706. {
  707. X = 2,
  708. Y = 2,
  709. Width = 30,
  710. Height = 2,
  711. Text = "A text with some long width\n and also with two lines."
  712. };
  713. Runnable top = new ();
  714. top.Add (label, view);
  715. SessionToken sessionToken = Application.Begin (top);
  716. top.Draw ();
  717. DriverAssert.AssertDriverContentsWithFrameAre (
  718. @"
  719. At 0,0
  720. A text with some long width
  721. and also with two lines. "
  722. ,
  723. output
  724. );
  725. view.X = 1;
  726. view.Y = 1;
  727. view.Width = 10;
  728. view.Height = 1;
  729. Assert.Equal (new (1, 1, 10, 1), view.Frame);
  730. Assert.Equal (new (0, 0, 10, 1), view.Viewport);
  731. Assert.Equal (new (0, 0, 10, 1), view.NeedsDrawRect);
  732. view.SetClipToScreen ();
  733. top.Draw ();
  734. DriverAssert.AssertDriverContentsWithFrameAre (
  735. @"
  736. At 0,0
  737. A text wit"
  738. ,
  739. output
  740. );
  741. Application.End (sessionToken);
  742. top.Dispose ();
  743. }
  744. public class DerivedView : View
  745. {
  746. public DerivedView () { CanFocus = true; }
  747. public bool IsKeyDown { get; set; }
  748. public bool IsKeyPress { get; set; }
  749. public bool IsKeyUp { get; set; }
  750. public override string Text { get; set; } = null!;
  751. protected override bool OnDrawingContent (DrawContext? context)
  752. {
  753. var idx = 0;
  754. // BUGBUG: v2 - this should use Viewport, not Frame
  755. for (var r = 0; r < Frame.Height; r++)
  756. {
  757. for (var c = 0; c < Frame.Width; c++)
  758. {
  759. if (idx < Text.Length)
  760. {
  761. char rune = Text [idx];
  762. if (rune != '\n')
  763. {
  764. AddRune (c, r, (Rune)Text [idx]);
  765. }
  766. idx++;
  767. if (rune == '\n')
  768. {
  769. break;
  770. }
  771. }
  772. }
  773. }
  774. ClearNeedsDraw ();
  775. return true;
  776. }
  777. protected override bool OnKeyDown (Key keyEvent)
  778. {
  779. IsKeyDown = true;
  780. return true;
  781. }
  782. public override bool OnKeyUp (Key keyEvent)
  783. {
  784. IsKeyUp = true;
  785. return true;
  786. }
  787. protected override bool OnKeyDownNotHandled (Key keyEvent)
  788. {
  789. IsKeyPress = true;
  790. return true;
  791. }
  792. }
  793. }