DrawTests.cs 33 KB

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