DrawTests.cs 34 KB

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