DrawTests.cs 32 KB

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