TextTests.cs 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362
  1. using System.Runtime.CompilerServices;
  2. using System.Text;
  3. using Xunit.Abstractions;
  4. namespace Terminal.Gui.ViewTests;
  5. /// <summary>
  6. /// Tests of the <see cref="View.Text"/> and <see cref="View.TextFormatter"/> properties (independent of
  7. /// AutoSize).
  8. /// </summary>
  9. public class TextTests (ITestOutputHelper output)
  10. {
  11. private readonly ITestOutputHelper _output = output;
  12. [Fact]
  13. [SetupFakeDriver]
  14. public void Setting_With_Height_Horizontal ()
  15. {
  16. var top = new View { Width = 25, Height = 25 };
  17. var label = new Label { Text = "Hello", /* Width = 10, Height = 2, */ ValidatePosDim = true };
  18. var viewX = new View { Text = "X", X = Pos.Right (label), Width = 1, Height = 1 };
  19. var viewY = new View { Text = "Y", Y = Pos.Bottom (label), Width = 1, Height = 1 };
  20. top.Add (label, viewX, viewY);
  21. top.BeginInit ();
  22. top.EndInit ();
  23. Assert.Equal (new (0, 0, 5, 1), label.Frame);
  24. top.LayoutSubviews ();
  25. top.Draw ();
  26. var expected = @"
  27. HelloX
  28. Y
  29. ";
  30. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  31. label.Width = 10;
  32. label.Height = 2;
  33. Assert.Equal (new (0, 0, 10, 2), label.Frame);
  34. top.LayoutSubviews ();
  35. top.Draw ();
  36. expected = @"
  37. Hello X
  38. Y
  39. ";
  40. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  41. }
  42. [Fact]
  43. [AutoInitShutdown]
  44. public void Setting_With_Height_Vertical ()
  45. {
  46. // BUGBUG: Label is Width = Dim.Auto (), Height = Dim.Auto (), so Width & Height are ignored
  47. var label = new Label
  48. { /*Width = 2, Height = 10, */
  49. TextDirection = TextDirection.TopBottom_LeftRight, ValidatePosDim = true
  50. };
  51. var viewX = new View { Text = "X", X = Pos.Right (label), Width = 1, Height = 1 };
  52. var viewY = new View { Text = "Y", Y = Pos.Bottom (label), Width = 1, Height = 1 };
  53. var top = new Toplevel ();
  54. top.Add (label, viewX, viewY);
  55. RunState rs = Application.Begin (top);
  56. label.Text = "Hello";
  57. Application.Refresh ();
  58. Assert.Equal (new (0, 0, 1, 5), label.Frame);
  59. var expected = @"
  60. HX
  61. e
  62. l
  63. l
  64. o
  65. Y
  66. ";
  67. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  68. label.Width = 2;
  69. label.Height = 10;
  70. Application.Refresh ();
  71. Assert.Equal (new (0, 0, 2, 10), label.Frame);
  72. expected = @"
  73. H X
  74. e
  75. l
  76. l
  77. o
  78. Y
  79. "
  80. ;
  81. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  82. Application.End (rs);
  83. }
  84. [Fact]
  85. [AutoInitShutdown]
  86. public void TextDirection_Toggle ()
  87. {
  88. var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () };
  89. var view = new View ();
  90. win.Add (view);
  91. var top = new Toplevel ();
  92. top.Add (win);
  93. RunState rs = Application.Begin (top);
  94. ((FakeDriver)Application.Driver).SetBufferSize (15, 15);
  95. Assert.Equal (new Rectangle (0, 0, 15, 15), win.Frame);
  96. Assert.Equal (new Rectangle (0, 0, 15, 15), win.Margin.Frame);
  97. Assert.Equal (new Rectangle (0, 0, 15, 15), win.Border.Frame);
  98. Assert.Equal (new Rectangle (1, 1, 13, 13), win.Padding.Frame);
  99. Assert.Equal (TextDirection.LeftRight_TopBottom, view.TextDirection);
  100. Assert.Equal (Rectangle.Empty, view.Frame);
  101. Assert.Equal ("Absolute(0)", view.X.ToString ());
  102. Assert.Equal ("Absolute(0)", view.Y.ToString ());
  103. Assert.Equal ("Absolute(0)", view.Width.ToString ());
  104. Assert.Equal ("Absolute(0)", view.Height.ToString ());
  105. var expected = @"
  106. ┌─────────────┐
  107. │ │
  108. │ │
  109. │ │
  110. │ │
  111. │ │
  112. │ │
  113. │ │
  114. │ │
  115. │ │
  116. │ │
  117. │ │
  118. │ │
  119. │ │
  120. └─────────────┘
  121. ";
  122. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  123. view.Text = "Hello World";
  124. view.Width = 11;
  125. view.Height = 1;
  126. win.LayoutSubviews ();
  127. Application.Refresh ();
  128. Assert.Equal (new Rectangle (0, 0, 11, 1), view.Frame);
  129. Assert.Equal ("Absolute(0)", view.X.ToString ());
  130. Assert.Equal ("Absolute(0)", view.Y.ToString ());
  131. Assert.Equal ("Absolute(11)", view.Width.ToString ());
  132. Assert.Equal ("Absolute(1)", view.Height.ToString ());
  133. expected = @"
  134. ┌─────────────┐
  135. │Hello World │
  136. │ │
  137. │ │
  138. │ │
  139. │ │
  140. │ │
  141. │ │
  142. │ │
  143. │ │
  144. │ │
  145. │ │
  146. │ │
  147. │ │
  148. └─────────────┘
  149. ";
  150. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  151. view.Width = Dim.Auto ();
  152. view.Height = Dim.Auto ();
  153. view.Text = "Hello Worlds";
  154. Application.Refresh ();
  155. int len = "Hello Worlds".Length;
  156. Assert.Equal (12, len);
  157. Assert.Equal (new Rectangle (0, 0, len, 1), view.Frame);
  158. expected = @"
  159. ┌─────────────┐
  160. │Hello Worlds │
  161. │ │
  162. │ │
  163. │ │
  164. │ │
  165. │ │
  166. │ │
  167. │ │
  168. │ │
  169. │ │
  170. │ │
  171. │ │
  172. │ │
  173. └─────────────┘
  174. ";
  175. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  176. view.TextDirection = TextDirection.TopBottom_LeftRight;
  177. Application.Refresh ();
  178. Assert.Equal (new Rectangle (0, 0, 1, 12), view.Frame);
  179. Assert.Equal (new Rectangle (0, 0, 1, 12), view.Frame);
  180. expected = @"
  181. ┌─────────────┐
  182. │H │
  183. │e │
  184. │l │
  185. │l │
  186. │o │
  187. │ │
  188. │W │
  189. │o │
  190. │r │
  191. │l │
  192. │d │
  193. │s │
  194. │ │
  195. └─────────────┘
  196. ";
  197. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  198. // Setting to false causes Width and Height to be set to the current ContentSize
  199. view.Width = 1;
  200. view.Height = 12;
  201. Assert.Equal (new Rectangle (0, 0, 1, 12), view.Frame);
  202. view.Width = 12;
  203. view.Height = 1;
  204. view.TextFormatter.Size = new (12, 1);
  205. win.LayoutSubviews ();
  206. Assert.Equal (new Size (12, 1), view.TextFormatter.Size);
  207. Assert.Equal (new Rectangle (0, 0, 12, 1), view.Frame);
  208. top.Clear ();
  209. view.Draw ();
  210. expected = @" HelloWorlds";
  211. TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  212. Application.Refresh ();
  213. // TextDirection.TopBottom_LeftRight - Height of 1 and Width of 12 means
  214. // that the text will be spread "vertically" across 1 line.
  215. // Hence no space.
  216. expected = @"
  217. ┌─────────────┐
  218. │HelloWorlds │
  219. │ │
  220. │ │
  221. │ │
  222. │ │
  223. │ │
  224. │ │
  225. │ │
  226. │ │
  227. │ │
  228. │ │
  229. │ │
  230. │ │
  231. └─────────────┘
  232. ";
  233. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  234. view.PreserveTrailingSpaces = true;
  235. Application.Refresh ();
  236. Assert.Equal (new Rectangle (0, 0, 12, 1), view.Frame);
  237. expected = @"
  238. ┌─────────────┐
  239. │Hello Worlds │
  240. │ │
  241. │ │
  242. │ │
  243. │ │
  244. │ │
  245. │ │
  246. │ │
  247. │ │
  248. │ │
  249. │ │
  250. │ │
  251. │ │
  252. └─────────────┘
  253. ";
  254. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  255. view.PreserveTrailingSpaces = false;
  256. Rectangle f = view.Frame;
  257. view.Width = f.Height;
  258. view.Height = f.Width;
  259. view.TextDirection = TextDirection.TopBottom_LeftRight;
  260. Application.Refresh ();
  261. Assert.Equal (new Rectangle (0, 0, 1, 12), view.Frame);
  262. expected = @"
  263. ┌─────────────┐
  264. │H │
  265. │e │
  266. │l │
  267. │l │
  268. │o │
  269. │ │
  270. │W │
  271. │o │
  272. │r │
  273. │l │
  274. │d │
  275. │s │
  276. │ │
  277. └─────────────┘
  278. ";
  279. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  280. view.Width = Dim.Auto ();
  281. view.Height = Dim.Auto ();
  282. Application.Refresh ();
  283. Assert.Equal (new Rectangle (0, 0, 1, 12), view.Frame);
  284. expected = @"
  285. ┌─────────────┐
  286. │H │
  287. │e │
  288. │l │
  289. │l │
  290. │o │
  291. │ │
  292. │W │
  293. │o │
  294. │r │
  295. │l │
  296. │d │
  297. │s │
  298. │ │
  299. └─────────────┘
  300. ";
  301. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  302. Application.End (rs);
  303. }
  304. [Fact]
  305. [AutoInitShutdown]
  306. public void AutoSize_True_View_IsEmpty_False_Minimum_Width ()
  307. {
  308. var text = "Views";
  309. var view = new View
  310. {
  311. TextDirection = TextDirection.TopBottom_LeftRight,
  312. Height = Dim.Fill () - text.Length,
  313. Text = text,
  314. };
  315. view.Width = Dim.Auto ();
  316. view.Height = Dim.Auto ();
  317. var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () };
  318. win.Add (view);
  319. var top = new Toplevel ();
  320. top.Add (win);
  321. Application.Begin (top);
  322. ((FakeDriver)Application.Driver).SetBufferSize (4, 10);
  323. Assert.Equal (5, text.Length);
  324. Assert.Equal (new (0, 0, 1, 5), view.Frame);
  325. Assert.Equal (new (1, 5), view.TextFormatter.Size);
  326. Assert.Equal (new List<string> { "Views" }, view.TextFormatter.GetLines ());
  327. Assert.Equal (new (0, 0, 4, 10), win.Frame);
  328. Assert.Equal (new (0, 0, 4, 10), Application.Top.Frame);
  329. var expected = @"
  330. ┌──┐
  331. │V │
  332. │i │
  333. │e │
  334. │w │
  335. │s │
  336. │ │
  337. │ │
  338. │ │
  339. └──┘
  340. ";
  341. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  342. Assert.Equal (new (0, 0, 4, 10), pos);
  343. text = "0123456789";
  344. Assert.Equal (10, text.Length);
  345. //view.Height = Dim.Fill () - text.Length;
  346. Application.Refresh ();
  347. Assert.Equal (new (0, 0, 1, 5), view.Frame);
  348. Assert.Equal (new (1, 5), view.TextFormatter.Size);
  349. Exception exception = Record.Exception (() => Assert.Single (view.TextFormatter.GetLines ()));
  350. Assert.Null (exception);
  351. expected = @"
  352. ┌──┐
  353. │V │
  354. │i │
  355. │e │
  356. │w │
  357. │s │
  358. │ │
  359. │ │
  360. │ │
  361. └──┘
  362. ";
  363. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  364. Assert.Equal (new Rectangle (0, 0, 4, 10), pos);
  365. }
  366. [Fact]
  367. [AutoInitShutdown]
  368. public void AutoSize_True_View_IsEmpty_False_Minimum_Width_Wide_Rune ()
  369. {
  370. var text = "界View";
  371. var view = new View
  372. {
  373. TextDirection = TextDirection.TopBottom_LeftRight,
  374. Text = text,
  375. Width = Dim.Auto (),
  376. Height = Dim.Auto ()
  377. };
  378. var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () };
  379. win.Add (view);
  380. var top = new Toplevel ();
  381. top.Add (win);
  382. Application.Begin (top);
  383. ((FakeDriver)Application.Driver).SetBufferSize (4, 10);
  384. Assert.Equal (5, text.Length);
  385. Assert.Equal (new (0, 0, 2, 5), view.Frame);
  386. Assert.Equal (new (2, 5), view.TextFormatter.Size);
  387. Assert.Equal (new List<string> { "界View" }, view.TextFormatter.GetLines ());
  388. Assert.Equal (new (0, 0, 4, 10), win.Frame);
  389. Assert.Equal (new (0, 0, 4, 10), Application.Top.Frame);
  390. var expected = @"
  391. ┌──┐
  392. │界│
  393. │V │
  394. │i │
  395. │e │
  396. │w │
  397. │ │
  398. │ │
  399. │ │
  400. └──┘
  401. ";
  402. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  403. Assert.Equal (new (0, 0, 4, 10), pos);
  404. text = "0123456789";
  405. Assert.Equal (10, text.Length);
  406. //view.Height = Dim.Fill () - text.Length;
  407. Application.Refresh ();
  408. Assert.Equal (new (0, 0, 2, 5), view.Frame);
  409. Assert.Equal (new (2, 5), view.TextFormatter.Size);
  410. Exception exception = Record.Exception (
  411. () => Assert.Equal (
  412. new List<string> { "界View" },
  413. view.TextFormatter.GetLines ()
  414. )
  415. );
  416. Assert.Null (exception);
  417. expected = @"
  418. ┌──┐
  419. │界│
  420. │V │
  421. │i │
  422. │e │
  423. │w │
  424. │ │
  425. │ │
  426. │ │
  427. └──┘
  428. ";
  429. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  430. Assert.Equal (new Rectangle (0, 0, 4, 10), pos);
  431. }
  432. [Fact]
  433. [AutoInitShutdown]
  434. public void AutoSize_True_Width_Height_SetMinWidthHeight_Narrow_Wide_Runes ()
  435. {
  436. var text = $"0123456789{Environment.NewLine}01234567891";
  437. var horizontalView = new View
  438. {
  439. Width = Dim.Auto (),
  440. Height = Dim.Auto (),
  441. Text = text
  442. };
  443. var verticalView = new View
  444. {
  445. Width = Dim.Auto (),
  446. Height = Dim.Auto (),
  447. Y = 3,
  448. //Height = 11,
  449. //Width = 2,
  450. Text = text,
  451. TextDirection = TextDirection.TopBottom_LeftRight
  452. };
  453. var win = new Window
  454. {
  455. Width = Dim.Fill (),
  456. Height = Dim.Fill (),
  457. Text = "Window"
  458. };
  459. win.Add (horizontalView, verticalView);
  460. var top = new Toplevel ();
  461. top.Add (win);
  462. RunState rs = Application.Begin (top);
  463. ((FakeDriver)Application.Driver).SetBufferSize (20, 20);
  464. Assert.Equal (new Rectangle (0, 0, 11, 2), horizontalView.Frame);
  465. Assert.Equal (new Rectangle (0, 3, 2, 11), verticalView.Frame);
  466. var expected = @"
  467. ┌──────────────────┐
  468. │0123456789 │
  469. │01234567891 │
  470. │ │
  471. │00 │
  472. │11 │
  473. │22 │
  474. │33 │
  475. │44 │
  476. │55 │
  477. │66 │
  478. │77 │
  479. │88 │
  480. │99 │
  481. │ 1 │
  482. │ │
  483. │ │
  484. │ │
  485. │ │
  486. └──────────────────┘
  487. ";
  488. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  489. verticalView.Text = $"最初の行{Environment.NewLine}二行目";
  490. Application.Top.Draw ();
  491. Assert.Equal (new Rectangle (0, 3, 4, 4), verticalView.Frame);
  492. expected = @"
  493. ┌──────────────────┐
  494. │0123456789 │
  495. │01234567891 │
  496. │ │
  497. │最二 │
  498. │初行 │
  499. │の目 │
  500. │行 │
  501. │ │
  502. │ │
  503. │ │
  504. │ │
  505. │ │
  506. │ │
  507. │ │
  508. │ │
  509. │ │
  510. │ │
  511. │ │
  512. └──────────────────┘
  513. ";
  514. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  515. Application.End (rs);
  516. }
  517. [Fact]
  518. [AutoInitShutdown]
  519. public void AutoSize_True_Width_Height_Stay_True_If_TextFormatter_Size_Fit ()
  520. {
  521. var text = "Finish 終";
  522. var horizontalView = new View
  523. {
  524. Id = "horizontalView",
  525. Width = Dim.Auto (), Height = Dim.Auto (), Text = text
  526. };
  527. var verticalView = new View
  528. {
  529. Id = "verticalView",
  530. Y = 3,
  531. Width = Dim.Auto (),
  532. Height = Dim.Auto (),
  533. Text = text,
  534. TextDirection = TextDirection.TopBottom_LeftRight
  535. };
  536. var win = new Window { Id = "win", Width = Dim.Fill (), Height = Dim.Fill (), Text = "Window" };
  537. win.Add (horizontalView, verticalView);
  538. var top = new Toplevel ();
  539. top.Add (win);
  540. RunState rs = Application.Begin (top);
  541. ((FakeDriver)Application.Driver).SetBufferSize (22, 22);
  542. Assert.Equal (new (text.GetColumns (), 1), horizontalView.TextFormatter.Size);
  543. Assert.Equal (new (2, 8), verticalView.TextFormatter.Size);
  544. //Assert.Equal (new (0, 0, 10, 1), horizontalView.Frame);
  545. //Assert.Equal (new (0, 3, 10, 9), verticalView.Frame);
  546. var expected = @"
  547. ┌────────────────────┐
  548. │Finish 終 │
  549. │ │
  550. │ │
  551. │F │
  552. │i │
  553. │n │
  554. │i │
  555. │s │
  556. │h │
  557. │ │
  558. │終 │
  559. │ │
  560. │ │
  561. │ │
  562. │ │
  563. │ │
  564. │ │
  565. │ │
  566. │ │
  567. │ │
  568. └────────────────────┘
  569. ";
  570. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  571. verticalView.Text = "最初の行二行目";
  572. Application.Top.Draw ();
  573. // height was initialized with 8 and can only grow or keep initial value
  574. Assert.Equal (new Rectangle (0, 3, 2, 7), verticalView.Frame);
  575. expected = @"
  576. ┌────────────────────┐
  577. │Finish 終 │
  578. │ │
  579. │ │
  580. │最 │
  581. │初 │
  582. │の │
  583. │行 │
  584. │二 │
  585. │行 │
  586. │目 │
  587. │ │
  588. │ │
  589. │ │
  590. │ │
  591. │ │
  592. │ │
  593. │ │
  594. │ │
  595. │ │
  596. │ │
  597. └────────────────────┘
  598. ";
  599. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  600. Application.End (rs);
  601. }
  602. [Fact]
  603. [AutoInitShutdown]
  604. public void Excess_Text_Is_Erased_When_The_Width_Is_Reduced ()
  605. {
  606. var lbl = new Label { Text = "123" };
  607. var top = new Toplevel ();
  608. top.Add (lbl);
  609. RunState rs = Application.Begin (top);
  610. Assert.Equal ("123 ", GetContents ());
  611. lbl.Text = "12";
  612. Assert.Equal (new Rectangle (0, 0, 2, 1), lbl.Frame);
  613. Assert.Equal (new Rectangle (0, 0, 3, 1), lbl._needsDisplayRect);
  614. Assert.Equal (new Rectangle (0, 0, 0, 0), lbl.SuperView._needsDisplayRect);
  615. Assert.True (lbl.SuperView.LayoutNeeded);
  616. lbl.SuperView.Draw ();
  617. Assert.Equal ("12 ", GetContents ());
  618. string GetContents ()
  619. {
  620. var text = "";
  621. for (var i = 0; i < 4; i++)
  622. {
  623. text += Application.Driver.Contents [0, i].Rune;
  624. }
  625. return text;
  626. }
  627. Application.End (rs);
  628. }
  629. [Fact]
  630. [AutoInitShutdown]
  631. public void GetTextFormatterBoundsSize_GetSizeNeededForText_HotKeySpecifier ()
  632. {
  633. var text = "Say Hello 你";
  634. // Frame: 0, 0, 12, 1
  635. var horizontalView = new View
  636. {
  637. Width = Dim.Auto (), Height = Dim.Auto ()
  638. };
  639. horizontalView.TextFormatter.HotKeySpecifier = (Rune)'_';
  640. horizontalView.Text = text;
  641. // Frame: 0, 0, 1, 12
  642. var verticalView = new View
  643. {
  644. Width = Dim.Auto (), Height = Dim.Auto (), TextDirection = TextDirection.TopBottom_LeftRight
  645. };
  646. verticalView.Text = text;
  647. verticalView.TextFormatter.HotKeySpecifier = (Rune)'_';
  648. var top = new Toplevel ();
  649. top.Add (horizontalView, verticalView);
  650. Application.Begin (top);
  651. ((FakeDriver)Application.Driver).SetBufferSize (50, 50);
  652. Assert.Equal (new (0, 0, 12, 1), horizontalView.Frame);
  653. Assert.Equal (new (12, 1), horizontalView.GetSizeNeededForTextWithoutHotKey ());
  654. Assert.Equal (horizontalView.Frame.Size, horizontalView.GetSizeNeededForTextWithoutHotKey ());
  655. Assert.Equal (new (0, 0, 2, 11), verticalView.Frame);
  656. Assert.Equal (new (2, 11), verticalView.GetSizeNeededForTextWithoutHotKey ());
  657. Assert.Equal (verticalView.Frame.Size, verticalView.GetSizeNeededForTextWithoutHotKey ());
  658. text = "012345678你";
  659. horizontalView.Text = text;
  660. verticalView.Text = text;
  661. Assert.Equal (new (0, 0, 11, 1), horizontalView.Frame);
  662. Assert.Equal (new (11, 1), horizontalView.GetSizeNeededForTextWithoutHotKey ());
  663. Assert.Equal (horizontalView.Frame.Size, horizontalView.GetSizeNeededForTextWithoutHotKey ());
  664. Assert.Equal (new (0, 0, 2, 10), verticalView.Frame);
  665. Assert.Equal (new (2, 10), verticalView.GetSizeNeededForTextWithoutHotKey ());
  666. Assert.Equal (verticalView.Frame.Size, verticalView.GetSizeNeededForTextWithoutHotKey ());
  667. }
  668. [Theory]
  669. [AutoInitShutdown]
  670. [InlineData (true)]
  671. [InlineData (false)]
  672. public void View_Draw_Horizontal_Simple_TextAlignments (bool autoSize)
  673. {
  674. var text = "Hello World";
  675. var width = 20;
  676. var lblLeft = new View
  677. {
  678. Text = text,
  679. Width = width,
  680. Height = 1,
  681. };
  682. if (autoSize)
  683. {
  684. lblLeft.Width = Dim.Auto ();
  685. lblLeft.Height = Dim.Auto ();
  686. }
  687. var lblCenter = new View
  688. {
  689. Text = text,
  690. Y = 1,
  691. Width = width,
  692. Height = 1,
  693. TextAlignment = TextAlignment.Centered,
  694. };
  695. if (autoSize)
  696. {
  697. lblCenter.Width = Dim.Auto ();
  698. lblCenter.Height = Dim.Auto ();
  699. }
  700. var lblRight = new View
  701. {
  702. Text = text,
  703. Y = 2,
  704. Width = width,
  705. Height = 1,
  706. TextAlignment = TextAlignment.Right,
  707. };
  708. if (autoSize)
  709. {
  710. lblRight.Width = Dim.Auto ();
  711. lblRight.Height = Dim.Auto ();
  712. }
  713. var lblJust = new View
  714. {
  715. Text = text,
  716. Y = 3,
  717. Width = width,
  718. Height = 1,
  719. TextAlignment = TextAlignment.Justified,
  720. };
  721. if (autoSize)
  722. {
  723. lblJust.Width = Dim.Auto ();
  724. lblJust.Height = Dim.Auto ();
  725. }
  726. var frame = new FrameView { Width = Dim.Fill (), Height = Dim.Fill () };
  727. frame.Add (lblLeft, lblCenter, lblRight, lblJust);
  728. var top = new Toplevel ();
  729. top.Add (frame);
  730. Application.Begin (top);
  731. ((FakeDriver)Application.Driver).SetBufferSize (width + 2, 6);
  732. if (autoSize)
  733. {
  734. Size expectedSize = new (11, 1);
  735. Assert.Equal (expectedSize, lblLeft.TextFormatter.Size);
  736. Assert.Equal (expectedSize, lblCenter.TextFormatter.Size);
  737. Assert.Equal (expectedSize, lblRight.TextFormatter.Size);
  738. Assert.Equal (expectedSize, lblJust.TextFormatter.Size);
  739. }
  740. else
  741. {
  742. Size expectedSize = new (width, 1);
  743. Assert.Equal (expectedSize, lblLeft.TextFormatter.Size);
  744. Assert.Equal (expectedSize, lblCenter.TextFormatter.Size);
  745. Assert.Equal (expectedSize, lblRight.TextFormatter.Size);
  746. Assert.Equal (expectedSize, lblJust.TextFormatter.Size);
  747. }
  748. Assert.Equal (new (0, 0, width + 2, 6), frame.Frame);
  749. string expected;
  750. if (autoSize)
  751. {
  752. expected = @"
  753. ┌────────────────────┐
  754. │Hello World │
  755. │Hello World │
  756. │Hello World │
  757. │Hello World │
  758. └────────────────────┘
  759. ";
  760. }
  761. else
  762. {
  763. expected = @"
  764. ┌────────────────────┐
  765. │Hello World │
  766. │ Hello World │
  767. │ Hello World│
  768. │Hello World│
  769. └────────────────────┘
  770. ";
  771. }
  772. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  773. Assert.Equal (new (0, 0, width + 2, 6), pos);
  774. }
  775. [Theory]
  776. [AutoInitShutdown]
  777. [InlineData (true)]
  778. [InlineData (false)]
  779. public void View_Draw_Vertical_Simple_TextAlignments (bool autoSize)
  780. {
  781. var text = "Hello World";
  782. var height = 20;
  783. var lblLeft = new View
  784. {
  785. Text = text,
  786. Width = 1,
  787. Height = height,
  788. TextDirection = TextDirection.TopBottom_LeftRight,
  789. };
  790. if (autoSize)
  791. {
  792. lblLeft.Width = Dim.Auto ();
  793. lblLeft.Height = Dim.Auto ();
  794. }
  795. var lblCenter = new View
  796. {
  797. Text = text,
  798. X = 2,
  799. Width = 1,
  800. Height = height,
  801. TextDirection = TextDirection.TopBottom_LeftRight,
  802. VerticalTextAlignment = VerticalTextAlignment.Middle
  803. };
  804. if (autoSize)
  805. {
  806. lblCenter.Width = Dim.Auto ();
  807. lblCenter.Height = Dim.Auto ();
  808. }
  809. var lblRight = new View
  810. {
  811. Text = text,
  812. X = 4,
  813. Width = 1,
  814. Height = height,
  815. TextDirection = TextDirection.TopBottom_LeftRight,
  816. VerticalTextAlignment = VerticalTextAlignment.Bottom
  817. };
  818. if (autoSize)
  819. {
  820. lblRight.Width = Dim.Auto ();
  821. lblRight.Height = Dim.Auto ();
  822. }
  823. var lblJust = new View
  824. {
  825. Text = text,
  826. X = 6,
  827. Width = 1,
  828. Height = height,
  829. TextDirection = TextDirection.TopBottom_LeftRight,
  830. VerticalTextAlignment = VerticalTextAlignment.Justified
  831. };
  832. if (autoSize)
  833. {
  834. lblJust.Width = Dim.Auto ();
  835. lblJust.Height = Dim.Auto ();
  836. }
  837. var frame = new FrameView { Width = Dim.Fill (), Height = Dim.Fill () };
  838. frame.Add (lblLeft, lblCenter, lblRight, lblJust);
  839. var top = new Toplevel ();
  840. top.Add (frame);
  841. Application.Begin (top);
  842. ((FakeDriver)Application.Driver).SetBufferSize (9, height + 2);
  843. if (autoSize)
  844. {
  845. Assert.Equal (new (1, 11), lblLeft.TextFormatter.Size);
  846. Assert.Equal (new (1, 11), lblCenter.TextFormatter.Size);
  847. Assert.Equal (new (1, 11), lblRight.TextFormatter.Size);
  848. Assert.Equal (new (1, 11), lblJust.TextFormatter.Size);
  849. Assert.Equal (new (0, 0, 9, height + 2), frame.Frame);
  850. }
  851. else
  852. {
  853. Assert.Equal (new (1, height), lblLeft.TextFormatter.Size);
  854. Assert.Equal (new (1, height), lblCenter.TextFormatter.Size);
  855. Assert.Equal (new (1, height), lblRight.TextFormatter.Size);
  856. Assert.Equal (new (1, height), lblJust.TextFormatter.Size);
  857. Assert.Equal (new (0, 0, 9, height + 2), frame.Frame);
  858. }
  859. string expected;
  860. if (autoSize)
  861. {
  862. expected = @"
  863. ┌───────┐
  864. │H H H H│
  865. │e e e e│
  866. │l l l l│
  867. │l l l l│
  868. │o o o o│
  869. │ │
  870. │W W W W│
  871. │o o o o│
  872. │r r r r│
  873. │l l l l│
  874. │d d d d│
  875. │ │
  876. │ │
  877. │ │
  878. │ │
  879. │ │
  880. │ │
  881. │ │
  882. │ │
  883. │ │
  884. └───────┘
  885. ";
  886. }
  887. else
  888. {
  889. expected = @"
  890. ┌───────┐
  891. │H H│
  892. │e e│
  893. │l l│
  894. │l l│
  895. │o H o│
  896. │ e │
  897. │W l │
  898. │o l │
  899. │r o │
  900. │l H │
  901. │d W e │
  902. │ o l │
  903. │ r l │
  904. │ l o │
  905. │ d │
  906. │ W W│
  907. │ o o│
  908. │ r r│
  909. │ l l│
  910. │ d d│
  911. └───────┘
  912. ";
  913. }
  914. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  915. Assert.Equal (new (0, 0, 9, height + 2), pos);
  916. }
  917. // Test that View.PreserveTrailingSpaces removes trailing spaces
  918. [Fact]
  919. public void PreserveTrailingSpaces_Removes_Trailing_Spaces ()
  920. {
  921. var view = new View { Text = "Hello World " };
  922. Assert.Equal ("Hello World ", view.TextFormatter.Text);
  923. view.TextFormatter.WordWrap = true;
  924. view.TextFormatter.Size = new (5, 3);
  925. view.PreserveTrailingSpaces = false;
  926. Assert.Equal ($"Hello{Environment.NewLine}World", view.TextFormatter.Format ());
  927. view.PreserveTrailingSpaces = true;
  928. Assert.Equal ($"Hello{Environment.NewLine} {Environment.NewLine}World", view.TextFormatter.Format ());
  929. }
  930. // View.PreserveTrailingSpaces Gets or sets whether trailing spaces at the end of word-wrapped lines are preserved
  931. // or not when <see cref="TextFormatter.WordWrap"/> is enabled.
  932. // If <see langword="true"/> trailing spaces at the end of wrapped lines will be removed when
  933. // <see cref = "Text" / > is formatted for display.The default is <see langword = "false" / >.
  934. [Fact]
  935. public void PreserveTrailingSpaces_Set_Get ()
  936. {
  937. var view = new View { Text = "Hello World" };
  938. Assert.False (view.PreserveTrailingSpaces);
  939. view.PreserveTrailingSpaces = true;
  940. Assert.True (view.PreserveTrailingSpaces);
  941. }
  942. // Setting TextFormatter DOES NOT update Text
  943. [Fact]
  944. public void SettingTextFormatterDoesNotUpdateText ()
  945. {
  946. var view = new View ();
  947. view.TextFormatter.Text = "Hello World";
  948. Assert.True (string.IsNullOrEmpty (view.Text));
  949. }
  950. // Setting Text updates TextFormatter
  951. [Fact]
  952. public void SettingTextUpdatesTextFormatter ()
  953. {
  954. var view = new View { Text = "Hello World" };
  955. Assert.Equal ("Hello World", view.Text);
  956. Assert.Equal ("Hello World", view.TextFormatter.Text);
  957. }
  958. // Setting Text does NOT set the HotKey
  959. [Fact]
  960. public void Text_Does_Not_Set_HotKey ()
  961. {
  962. var view = new View { HotKeySpecifier = (Rune)'_', Text = "_Hello World" };
  963. Assert.NotEqual (Key.H, view.HotKey);
  964. }
  965. // Test that TextFormatter is init only
  966. [Fact]
  967. public void TextFormatterIsInitOnly ()
  968. {
  969. var view = new View ();
  970. // Use reflection to ensure the TextFormatter property is `init` only
  971. Assert.Contains (
  972. typeof (IsExternalInit),
  973. typeof (View).GetMethod ("set_TextFormatter")
  974. .ReturnParameter.GetRequiredCustomModifiers ());
  975. }
  976. // Test that the Text property is set correctly.
  977. [Fact]
  978. public void TextProperty ()
  979. {
  980. var view = new View { Text = "Hello World" };
  981. Assert.Equal ("Hello World", view.Text);
  982. }
  983. // Test view.UpdateTextFormatterText overridden in a subclass updates TextFormatter.Text
  984. [Fact]
  985. public void UpdateTextFormatterText_Overridden ()
  986. {
  987. var view = new TestView { Text = "Hello World" };
  988. Assert.Equal ("Hello World", view.Text);
  989. Assert.Equal (">Hello World<", view.TextFormatter.Text);
  990. }
  991. private class TestView : View
  992. {
  993. protected override void UpdateTextFormatterText () { TextFormatter.Text = $">{Text}<"; }
  994. }
  995. [Fact]
  996. public void TextDirection_Horizontal_Dims_Correct ()
  997. {
  998. // Initializes a view with a vertical direction
  999. var view = new View
  1000. {
  1001. Text = "01234",
  1002. TextDirection = TextDirection.LeftRight_TopBottom,
  1003. Width = Dim.Auto (Dim.DimAutoStyle.Text),
  1004. Height = Dim.Auto (Dim.DimAutoStyle.Text)
  1005. };
  1006. Assert.Equal (new Rectangle (0, 0, 5, 1), view.Frame);
  1007. Assert.Equal (new Rectangle (0, 0, 5, 1), view.Viewport);
  1008. view.BeginInit ();
  1009. view.EndInit ();
  1010. Assert.Equal (new Rectangle (0, 0, 5, 1), view.Frame);
  1011. Assert.Equal (new Rectangle (0, 0, 5, 1), view.Viewport);
  1012. }
  1013. // BUGBUG: this is a temporary test that helped identify #3469 - It needs to be expanded upon (and renamed)
  1014. [Fact]
  1015. public void TextDirection_Horizontal_Dims_Correct_WidthAbsolute ()
  1016. {
  1017. var view = new View
  1018. {
  1019. Text = "01234",
  1020. TextDirection = TextDirection.LeftRight_TopBottom,
  1021. TextAlignment = TextAlignment.Centered,
  1022. Width = 10,
  1023. Height = Dim.Auto (Dim.DimAutoStyle.Text)
  1024. };
  1025. view.BeginInit ();
  1026. view.EndInit ();
  1027. Assert.Equal (new Rectangle (0, 0, 10, 1), view.Frame);
  1028. Assert.Equal (new Rectangle (0, 0, 10, 1), view.Viewport);
  1029. Assert.Equal (new (10, 1), view.TextFormatter.Size);
  1030. }
  1031. [Fact]
  1032. public void TextDirection_Vertical_Dims_Correct ()
  1033. {
  1034. // Initializes a view with a vertical direction
  1035. var view = new View
  1036. {
  1037. TextDirection = TextDirection.TopBottom_LeftRight,
  1038. Text = "01234",
  1039. Width = Dim.Auto (Dim.DimAutoStyle.Text),
  1040. Height = Dim.Auto (Dim.DimAutoStyle.Text),
  1041. };
  1042. Assert.Equal (new Rectangle (0, 0, 1, 5), view.Frame);
  1043. Assert.Equal (new Rectangle (0, 0, 1, 5), view.Viewport);
  1044. view.BeginInit ();
  1045. Assert.Equal (new Rectangle (0, 0, 1, 5), view.Frame);
  1046. view.EndInit ();
  1047. Assert.Equal (new Rectangle (0, 0, 1, 5), view.Frame);
  1048. Assert.Equal (new Rectangle (0, 0, 1, 5), view.Viewport);
  1049. }
  1050. [Fact]
  1051. [SetupFakeDriver]
  1052. public void Width_Height_SetMinWidthHeight_Narrow_Wide_Runes ()
  1053. {
  1054. ((FakeDriver)Application.Driver).SetBufferSize (32, 32);
  1055. var top = new View { Width = 32, Height = 32 };
  1056. var text = $"First line{Environment.NewLine}Second line";
  1057. var horizontalView = new View { Width = 20, Height = 1, Text = text };
  1058. // Autosize is off, so we have to explicitly set TextFormatter.Size
  1059. horizontalView.TextFormatter.Size = new (20, 1);
  1060. var verticalView = new View
  1061. {
  1062. Y = 3,
  1063. Height = 20,
  1064. Width = 1,
  1065. Text = text,
  1066. TextDirection = TextDirection.TopBottom_LeftRight
  1067. };
  1068. // Autosize is off, so we have to explicitly set TextFormatter.Size
  1069. verticalView.TextFormatter.Size = new (1, 20);
  1070. var frame = new FrameView { Width = Dim.Fill (), Height = Dim.Fill (), Text = "Window" };
  1071. frame.Add (horizontalView, verticalView);
  1072. top.Add (frame);
  1073. top.BeginInit ();
  1074. top.EndInit ();
  1075. Assert.Equal (new (0, 0, 20, 1), horizontalView.Frame);
  1076. Assert.Equal (new (0, 3, 1, 20), verticalView.Frame);
  1077. top.Draw ();
  1078. var expected = @"
  1079. ┌──────────────────────────────┐
  1080. │First line Second li │
  1081. │ │
  1082. │ │
  1083. │F │
  1084. │i │
  1085. │r │
  1086. │s │
  1087. │t │
  1088. │ │
  1089. │l │
  1090. │i │
  1091. │n │
  1092. │e │
  1093. │ │
  1094. │S │
  1095. │e │
  1096. │c │
  1097. │o │
  1098. │n │
  1099. │d │
  1100. │ │
  1101. │l │
  1102. │i │
  1103. │ │
  1104. │ │
  1105. │ │
  1106. │ │
  1107. │ │
  1108. │ │
  1109. │ │
  1110. └──────────────────────────────┘
  1111. ";
  1112. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  1113. verticalView.Text = $"最初の行{Environment.NewLine}二行目";
  1114. Assert.True (verticalView.TextFormatter.NeedsFormat);
  1115. // Autosize is off, so we have to explicitly set TextFormatter.Size
  1116. // We know these glpyhs are 2 cols wide, so we need to widen the view
  1117. verticalView.Width = 2;
  1118. verticalView.TextFormatter.Size = new (2, 20);
  1119. Assert.True (verticalView.TextFormatter.NeedsFormat);
  1120. top.Draw ();
  1121. Assert.Equal (new (0, 3, 2, 20), verticalView.Frame);
  1122. expected = @"
  1123. ┌──────────────────────────────┐
  1124. │First line Second li │
  1125. │ │
  1126. │ │
  1127. │最 │
  1128. │初 │
  1129. │の │
  1130. │行 │
  1131. │ │
  1132. │二 │
  1133. │行 │
  1134. │目 │
  1135. │ │
  1136. │ │
  1137. │ │
  1138. │ │
  1139. │ │
  1140. │ │
  1141. │ │
  1142. │ │
  1143. │ │
  1144. │ │
  1145. │ │
  1146. │ │
  1147. │ │
  1148. │ │
  1149. │ │
  1150. │ │
  1151. │ │
  1152. │ │
  1153. │ │
  1154. └──────────────────────────────┘
  1155. ";
  1156. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  1157. }
  1158. // Test behavior of AutoSize property.
  1159. // - Default is false
  1160. // - Setting to true invalidates Height/Width
  1161. // - Setting to false invalidates Height/Width
  1162. }