ViewTests.cs 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236
  1. using System.ComponentModel;
  2. using System.Text;
  3. using Xunit.Abstractions;
  4. namespace Terminal.Gui.ViewTests;
  5. public class ViewTests
  6. {
  7. private readonly ITestOutputHelper _output;
  8. public ViewTests (ITestOutputHelper output) { _output = output; }
  9. [Fact]
  10. [AutoInitShutdown]
  11. public void Clear_Bounds_Can_Use_Driver_AddRune_Or_AddStr_Methods ()
  12. {
  13. var view = new FrameView { Width = Dim.Fill (), Height = Dim.Fill () };
  14. view.DrawContent += (s, e) =>
  15. {
  16. Rectangle savedClip = Application.Driver.Clip;
  17. Application.Driver.Clip = new Rectangle (1, 1, view.Viewport.Width, view.Viewport.Height);
  18. for (var row = 0; row < view.Viewport.Height; row++)
  19. {
  20. Application.Driver.Move (1, row + 1);
  21. for (var col = 0; col < view.Viewport.Width; col++)
  22. {
  23. Application.Driver.AddStr ($"{col}");
  24. }
  25. }
  26. Application.Driver.Clip = savedClip;
  27. e.Cancel = true;
  28. };
  29. Application.Top.Add (view);
  30. Application.Begin (Application.Top);
  31. ((FakeDriver)Application.Driver).SetBufferSize (20, 10);
  32. var expected = @"
  33. ┌──────────────────┐
  34. │012345678910111213│
  35. │012345678910111213│
  36. │012345678910111213│
  37. │012345678910111213│
  38. │012345678910111213│
  39. │012345678910111213│
  40. │012345678910111213│
  41. │012345678910111213│
  42. └──────────────────┘
  43. ";
  44. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  45. Assert.Equal (new Rectangle (0, 0, 20, 10), pos);
  46. view.Clear (view.Viewport);
  47. expected = @"
  48. ┌──────────────────┐
  49. │ │
  50. │ │
  51. │ │
  52. │ │
  53. │ │
  54. │ │
  55. │ │
  56. │ │
  57. └──────────────────┘
  58. ";
  59. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  60. }
  61. [Fact]
  62. [AutoInitShutdown]
  63. public void Clear_Can_Use_Driver_AddRune_Or_AddStr_Methods ()
  64. {
  65. var view = new FrameView { Width = Dim.Fill (), Height = Dim.Fill () };
  66. view.DrawContent += (s, e) =>
  67. {
  68. Rectangle savedClip = Application.Driver.Clip;
  69. Application.Driver.Clip = new Rectangle (1, 1, view.Viewport.Width, view.Viewport.Height);
  70. for (var row = 0; row < view.Viewport.Height; row++)
  71. {
  72. Application.Driver.Move (1, row + 1);
  73. for (var col = 0; col < view.Viewport.Width; col++)
  74. {
  75. Application.Driver.AddStr ($"{col}");
  76. }
  77. }
  78. Application.Driver.Clip = savedClip;
  79. e.Cancel = true;
  80. };
  81. Application.Top.Add (view);
  82. Application.Begin (Application.Top);
  83. ((FakeDriver)Application.Driver).SetBufferSize (20, 10);
  84. var expected = @"
  85. ┌──────────────────┐
  86. │012345678910111213│
  87. │012345678910111213│
  88. │012345678910111213│
  89. │012345678910111213│
  90. │012345678910111213│
  91. │012345678910111213│
  92. │012345678910111213│
  93. │012345678910111213│
  94. └──────────────────┘
  95. ";
  96. Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  97. Assert.Equal (new Rectangle (0, 0, 20, 10), pos);
  98. view.Clear (view.Viewport);
  99. expected = @"
  100. ┌──────────────────┐
  101. │ │
  102. │ │
  103. │ │
  104. │ │
  105. │ │
  106. │ │
  107. │ │
  108. │ │
  109. └──────────────────┘
  110. ";
  111. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
  112. }
  113. [Theory]
  114. [AutoInitShutdown]
  115. [InlineData (true)]
  116. [InlineData (false)]
  117. public void Clear_Does_Not_Spillover_Its_Parent (bool label)
  118. {
  119. var root = new View { Width = 20, Height = 10, ColorScheme = Colors.ColorSchemes ["Base"] };
  120. View v = label
  121. ? new Label { Text = new string ('c', 100) }
  122. : new TextView { Height = 1, Text = new string ('c', 100), Width = Dim.Fill () };
  123. root.Add (v);
  124. Application.Top.Add (root);
  125. RunState runState = Application.Begin (Application.Top);
  126. if (label)
  127. {
  128. Assert.True (v.AutoSize);
  129. Assert.False (v.CanFocus);
  130. Assert.Equal (new Rectangle (0, 0, 100, 1), v.Frame);
  131. }
  132. else
  133. {
  134. Assert.False (v.AutoSize);
  135. Assert.True (v.CanFocus);
  136. Assert.Equal (new Rectangle (0, 0, 20, 1), v.Frame);
  137. }
  138. TestHelpers.AssertDriverContentsWithFrameAre (
  139. @"
  140. cccccccccccccccccccc",
  141. _output
  142. );
  143. Attribute [] attributes =
  144. {
  145. Colors.ColorSchemes ["TopLevel"].Normal,
  146. Colors.ColorSchemes ["Base"].Normal,
  147. Colors.ColorSchemes ["Base"].Focus
  148. };
  149. if (label)
  150. {
  151. TestHelpers.AssertDriverAttributesAre (
  152. @"
  153. 111111111111111111110
  154. 111111111111111111110",
  155. Application.Driver,
  156. attributes
  157. );
  158. }
  159. else
  160. {
  161. TestHelpers.AssertDriverAttributesAre (
  162. @"
  163. 222222222222222222220
  164. 111111111111111111110",
  165. Application.Driver,
  166. attributes
  167. );
  168. }
  169. if (label)
  170. {
  171. root.CanFocus = true;
  172. v.CanFocus = true;
  173. Assert.False (v.HasFocus);
  174. v.SetFocus ();
  175. Assert.True (v.HasFocus);
  176. Application.Refresh ();
  177. TestHelpers.AssertDriverAttributesAre (
  178. @"
  179. 222222222222222222220
  180. 111111111111111111110",
  181. Application.Driver,
  182. attributes
  183. );
  184. }
  185. Application.End (runState);
  186. }
  187. [Fact]
  188. [AutoInitShutdown]
  189. public void Correct_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Down_Right_Using_Frame ()
  190. {
  191. var label = new Label { Text = "At 0,0" };
  192. var view = new DerivedView
  193. {
  194. X = 2,
  195. Y = 2,
  196. Width = 30,
  197. Height = 2,
  198. Text = "A text with some long width\n and also with two lines."
  199. };
  200. Toplevel top = Application.Top;
  201. top.Add (label, view);
  202. RunState runState = Application.Begin (top);
  203. TestHelpers.AssertDriverContentsWithFrameAre (
  204. @"
  205. At 0,0
  206. A text with some long width
  207. and also with two lines. ",
  208. _output
  209. );
  210. view.Frame = new Rectangle (3, 3, 10, 1);
  211. Assert.Equal (new Rectangle (3, 3, 10, 1), view.Frame);
  212. Assert.Equal (LayoutStyle.Absolute, view.LayoutStyle);
  213. Assert.Equal (new Rectangle (0, 0, 10, 1), view.Viewport);
  214. Assert.Equal (new Rectangle (0, 0, 10, 1), view._needsDisplayRect);
  215. top.Draw ();
  216. TestHelpers.AssertDriverContentsWithFrameAre (
  217. @"
  218. At 0,0
  219. A text wit",
  220. _output
  221. );
  222. Application.End (runState);
  223. }
  224. [Fact]
  225. [AutoInitShutdown]
  226. public void Correct_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Down_Right_Using_Pos_Dim ()
  227. {
  228. var label = new Label { Text = "At 0,0" };
  229. var view = new DerivedView
  230. {
  231. X = 2,
  232. Y = 2,
  233. Width = 30,
  234. Height = 2,
  235. Text = "A text with some long width\n and also with two lines."
  236. };
  237. Toplevel top = Application.Top;
  238. top.Add (label, view);
  239. RunState runState = Application.Begin (top);
  240. top.Draw ();
  241. TestHelpers.AssertDriverContentsWithFrameAre (
  242. @"
  243. At 0,0
  244. A text with some long width
  245. and also with two lines. ",
  246. _output
  247. );
  248. view.X = 3;
  249. view.Y = 3;
  250. view.Width = 10;
  251. view.Height = 1;
  252. Assert.Equal (new Rectangle (3, 3, 10, 1), view.Frame);
  253. Assert.Equal (new Rectangle (0, 0, 10, 1), view.Viewport);
  254. Assert.Equal (new Rectangle (0, 0, 30, 2), view._needsDisplayRect);
  255. top.Draw ();
  256. TestHelpers.AssertDriverContentsWithFrameAre (
  257. @"
  258. At 0,0
  259. A text wit",
  260. _output
  261. );
  262. Application.End (runState);
  263. }
  264. [Fact]
  265. [AutoInitShutdown]
  266. public void Correct_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Up_Left_Using_Frame ()
  267. {
  268. var label = new Label { Text = "At 0,0" };
  269. var view = new DerivedView
  270. {
  271. X = 2,
  272. Y = 2,
  273. Width = 30,
  274. Height = 2,
  275. Text = "A text with some long width\n and also with two lines."
  276. };
  277. Toplevel top = Application.Top;
  278. top.Add (label, view);
  279. RunState runState = Application.Begin (top);
  280. top.Draw ();
  281. TestHelpers.AssertDriverContentsWithFrameAre (
  282. @"
  283. At 0,0
  284. A text with some long width
  285. and also with two lines. ",
  286. _output
  287. );
  288. view.Frame = new Rectangle (1, 1, 10, 1);
  289. Assert.Equal (new Rectangle (1, 1, 10, 1), view.Frame);
  290. Assert.Equal (LayoutStyle.Absolute, view.LayoutStyle);
  291. Assert.Equal (new Rectangle (0, 0, 10, 1), view.Viewport);
  292. Assert.Equal (new Rectangle (0, 0, 10, 1), view._needsDisplayRect);
  293. top.Draw ();
  294. TestHelpers.AssertDriverContentsWithFrameAre (
  295. @"
  296. At 0,0
  297. A text wit",
  298. _output
  299. );
  300. Application.End (runState);
  301. }
  302. [Fact]
  303. [AutoInitShutdown]
  304. public void Correct_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Up_Left_Using_Pos_Dim ()
  305. {
  306. var label = new Label { Text = "At 0,0" };
  307. var view = new DerivedView
  308. {
  309. X = 2,
  310. Y = 2,
  311. Width = 30,
  312. Height = 2,
  313. Text = "A text with some long width\n and also with two lines."
  314. };
  315. Toplevel top = Application.Top;
  316. top.Add (label, view);
  317. RunState runState = Application.Begin (top);
  318. top.Draw ();
  319. TestHelpers.AssertDriverContentsWithFrameAre (
  320. @"
  321. At 0,0
  322. A text with some long width
  323. and also with two lines. ",
  324. _output
  325. );
  326. view.X = 1;
  327. view.Y = 1;
  328. view.Width = 10;
  329. view.Height = 1;
  330. Assert.Equal (new Rectangle (1, 1, 10, 1), view.Frame);
  331. Assert.Equal (new Rectangle (0, 0, 10, 1), view.Viewport);
  332. Assert.Equal (new Rectangle (0, 0, 30, 2), view._needsDisplayRect);
  333. top.Draw ();
  334. TestHelpers.AssertDriverContentsWithFrameAre (
  335. @"
  336. At 0,0
  337. A text wit",
  338. _output
  339. );
  340. Application.End (runState);
  341. }
  342. [Fact]
  343. [TestRespondersDisposed]
  344. public void Dispose_View ()
  345. {
  346. var view = new View ();
  347. Assert.NotNull (view.Margin);
  348. Assert.NotNull (view.Border);
  349. Assert.NotNull (view.Padding);
  350. #if DEBUG_IDISPOSABLE
  351. Assert.Equal (4, Responder.Instances.Count);
  352. #endif
  353. view.Dispose ();
  354. Assert.Null (view.Margin);
  355. Assert.Null (view.Border);
  356. Assert.Null (view.Padding);
  357. }
  358. [Fact]
  359. [AutoInitShutdown]
  360. public void DrawContentComplete_Event_Is_Always_Called ()
  361. {
  362. var viewCalled = false;
  363. var tvCalled = false;
  364. var view = new View { Width = 10, Height = 10, Text = "View" };
  365. view.DrawContentComplete += (s, e) => viewCalled = true;
  366. var tv = new TextView { Y = 11, Width = 10, Height = 10 };
  367. tv.DrawContentComplete += (s, e) => tvCalled = true;
  368. Application.Top.Add (view, tv);
  369. Application.Begin (Application.Top);
  370. Assert.True (viewCalled);
  371. Assert.True (tvCalled);
  372. }
  373. [Fact]
  374. [AutoInitShutdown]
  375. public void Frame_Set_After_Initialize_Update_NeededDisplay ()
  376. {
  377. var frame = new FrameView ();
  378. var label = new Label
  379. {
  380. ColorScheme = Colors.ColorSchemes ["Menu"], X = 0, Y = 0, Text = "This should be the first line."
  381. };
  382. var button = new Button
  383. {
  384. X = 0, // don't overcomplicate unit tests
  385. Y = 1,
  386. Text = "Press me!"
  387. };
  388. frame.Add (label, button);
  389. frame.X = Pos.Center ();
  390. frame.Y = Pos.Center ();
  391. frame.Width = 40;
  392. frame.Height = 8;
  393. Toplevel top = Application.Top;
  394. top.Add (frame);
  395. RunState runState = Application.Begin (top);
  396. top.LayoutComplete += (s, e) => { Assert.Equal (new Rectangle (0, 0, 80, 25), top._needsDisplayRect); };
  397. frame.LayoutComplete += (s, e) => { Assert.Equal (new Rectangle (0, 0, 40, 8), frame._needsDisplayRect); };
  398. label.LayoutComplete += (s, e) => { Assert.Equal (new Rectangle (0, 0, 38, 1), label._needsDisplayRect); };
  399. button.LayoutComplete += (s, e) => { Assert.Equal (new Rectangle (0, 0, 13, 1), button._needsDisplayRect); };
  400. Assert.True (label.AutoSize);
  401. Assert.Equal (new Rectangle (0, 0, 80, 25), top.Frame);
  402. Assert.Equal (new Rectangle (20, 8, 40, 8), frame.Frame);
  403. Assert.Equal (
  404. new Rectangle (20, 8, 60, 16),
  405. new Rectangle (
  406. frame.Frame.Left,
  407. frame.Frame.Top,
  408. frame.Frame.Right,
  409. frame.Frame.Bottom
  410. )
  411. );
  412. Assert.Equal (new Rectangle (0, 0, 30, 1), label.Frame);
  413. Assert.Equal (new Rectangle (0, 1, 13, 1), button.Frame); // this proves frame was set
  414. Application.End (runState);
  415. }
  416. [Fact]
  417. [AutoInitShutdown]
  418. public void GetHotNormalColor_ColorScheme ()
  419. {
  420. var view = new View { ColorScheme = Colors.ColorSchemes ["Base"] };
  421. Assert.Equal (view.ColorScheme.HotNormal, view.GetHotNormalColor ());
  422. view.Enabled = false;
  423. Assert.Equal (view.ColorScheme.Disabled, view.GetHotNormalColor ());
  424. view.Dispose ();
  425. }
  426. [Fact]
  427. [AutoInitShutdown]
  428. public void GetNormalColor_ColorScheme ()
  429. {
  430. var view = new View { ColorScheme = Colors.ColorSchemes ["Base"] };
  431. Assert.Equal (view.ColorScheme.Normal, view.GetNormalColor ());
  432. view.Enabled = false;
  433. Assert.Equal (view.ColorScheme.Disabled, view.GetNormalColor ());
  434. view.Dispose ();
  435. }
  436. [Fact]
  437. [AutoInitShutdown]
  438. public void Incorrect_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Down_Right_Using_Frame ()
  439. {
  440. var label = new Label { Text = "At 0,0" };
  441. var view = new DerivedView
  442. {
  443. X = 2,
  444. Y = 2,
  445. Width = 30,
  446. Height = 2,
  447. Text = "A text with some long width\n and also with two lines."
  448. };
  449. Toplevel top = Application.Top;
  450. top.Add (label, view);
  451. RunState runState = Application.Begin (top);
  452. view.Draw ();
  453. TestHelpers.AssertDriverContentsWithFrameAre (
  454. @"
  455. At 0,0
  456. A text with some long width
  457. and also with two lines. ",
  458. _output
  459. );
  460. view.Frame = new Rectangle (3, 3, 10, 1);
  461. Assert.Equal (new Rectangle (0, 0, 10, 1), view.Viewport);
  462. Assert.Equal (new Rectangle (0, 0, 10, 1), view._needsDisplayRect);
  463. view.Draw ();
  464. TestHelpers.AssertDriverContentsWithFrameAre (
  465. @"
  466. At 0,0
  467. A text with some long width
  468. A text witith two lines. ",
  469. _output
  470. );
  471. Application.End (runState);
  472. }
  473. [Fact]
  474. [AutoInitShutdown]
  475. public void Incorrect_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Down_Right_Using_Pos_Dim ()
  476. {
  477. var label = new Label { Text = "At 0,0" };
  478. var view = new DerivedView
  479. {
  480. X = 2,
  481. Y = 2,
  482. Width = 30,
  483. Height = 2,
  484. Text = "A text with some long width\n and also with two lines."
  485. };
  486. Toplevel top = Application.Top;
  487. top.Add (label, view);
  488. RunState runState = Application.Begin (top);
  489. view.Draw ();
  490. TestHelpers.AssertDriverContentsWithFrameAre (
  491. @"
  492. At 0,0
  493. A text with some long width
  494. and also with two lines. ",
  495. _output
  496. );
  497. view.X = 3;
  498. view.Y = 3;
  499. view.Width = 10;
  500. view.Height = 1;
  501. Assert.Equal (new Rectangle (3, 3, 10, 1), view.Frame);
  502. Assert.Equal (new Rectangle (0, 0, 10, 1), view.Viewport);
  503. Assert.Equal (new Rectangle (0, 0, 30, 2), view._needsDisplayRect);
  504. view.Draw ();
  505. TestHelpers.AssertDriverContentsWithFrameAre (
  506. @"
  507. At 0,0
  508. A text with some long width
  509. A text witith two lines. ",
  510. _output
  511. );
  512. Application.End (runState);
  513. }
  514. [Fact]
  515. [AutoInitShutdown]
  516. public void Incorrect_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Up_Left_Using_Frame ()
  517. {
  518. var label = new Label { Text = "At 0,0" };
  519. var view = new DerivedView
  520. {
  521. X = 2,
  522. Y = 2,
  523. Width = 30,
  524. Height = 2,
  525. Text = "A text with some long width\n and also with two lines."
  526. };
  527. Toplevel top = Application.Top;
  528. top.Add (label, view);
  529. RunState runState = Application.Begin (top);
  530. view.Draw ();
  531. TestHelpers.AssertDriverContentsWithFrameAre (
  532. @"
  533. At 0,0
  534. A text with some long width
  535. and also with two lines. ",
  536. _output
  537. );
  538. view.Frame = new Rectangle (1, 1, 10, 1);
  539. Assert.Equal (new Rectangle (1, 1, 10, 1), view.Frame);
  540. Assert.Equal (LayoutStyle.Absolute, view.LayoutStyle);
  541. Assert.Equal (new Rectangle (0, 0, 10, 1), view.Viewport);
  542. Assert.Equal (new Rectangle (0, 0, 10, 1), view._needsDisplayRect);
  543. view.Draw ();
  544. TestHelpers.AssertDriverContentsWithFrameAre (
  545. @"
  546. At 0,0
  547. A text wit
  548. A text with some long width
  549. and also with two lines. ",
  550. _output
  551. );
  552. Application.End (runState);
  553. }
  554. [Fact]
  555. [AutoInitShutdown]
  556. public void Incorrect_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Up_Left_Using_Pos_Dim ()
  557. {
  558. var label = new Label { Text = "At 0,0" };
  559. var view = new DerivedView
  560. {
  561. X = 2,
  562. Y = 2,
  563. Width = 30,
  564. Height = 2,
  565. Text = "A text with some long width\n and also with two lines."
  566. };
  567. Toplevel top = Application.Top;
  568. top.Add (label, view);
  569. RunState runState = Application.Begin (top);
  570. view.Draw ();
  571. TestHelpers.AssertDriverContentsWithFrameAre (
  572. @"
  573. At 0,0
  574. A text with some long width
  575. and also with two lines. ",
  576. _output
  577. );
  578. view.X = 1;
  579. view.Y = 1;
  580. view.Width = 10;
  581. view.Height = 1;
  582. Assert.Equal (new Rectangle (1, 1, 10, 1), view.Frame);
  583. Assert.Equal (new Rectangle (0, 0, 10, 1), view.Viewport);
  584. Assert.Equal (new Rectangle (0, 0, 30, 2), view._needsDisplayRect);
  585. view.Draw ();
  586. TestHelpers.AssertDriverContentsWithFrameAre (
  587. @"
  588. At 0,0
  589. A text wit
  590. A text with some long width
  591. and also with two lines. ",
  592. _output
  593. );
  594. Application.End (runState);
  595. }
  596. [Fact]
  597. public void Internal_Tests ()
  598. {
  599. var rect = new Rectangle (1, 1, 10, 1);
  600. var view = new View { Frame = rect };
  601. }
  602. [Fact]
  603. [SetupFakeDriver]
  604. public void SetText_RendersCorrectly ()
  605. {
  606. View view;
  607. var text = "test";
  608. view = new Label { Text = text };
  609. view.BeginInit ();
  610. view.EndInit ();
  611. view.Draw ();
  612. TestHelpers.AssertDriverContentsWithFrameAre ( text, _output);
  613. }
  614. [Fact]
  615. [TestRespondersDisposed]
  616. public void New_Initializes ()
  617. {
  618. // Parameterless
  619. var r = new View ();
  620. Assert.NotNull (r);
  621. Assert.True (r.Enabled);
  622. Assert.True (r.Visible);
  623. Assert.Equal (LayoutStyle.Absolute, r.LayoutStyle);
  624. Assert.Equal ($"View(){r.Viewport}", r.ToString ());
  625. Assert.False (r.CanFocus);
  626. Assert.False (r.HasFocus);
  627. Assert.Equal (new Rectangle (0, 0, 0, 0), r.Viewport);
  628. Assert.Equal (new Rectangle (0, 0, 0, 0), r.Frame);
  629. Assert.Null (r.Focused);
  630. Assert.Null (r.ColorScheme);
  631. Assert.Equal (0, r.Width);
  632. Assert.Equal (0, r.Height);
  633. Assert.Equal (0, r.X);
  634. Assert.Equal (0, r.Y);
  635. Assert.False (r.IsCurrentTop);
  636. Assert.Empty (r.Id);
  637. Assert.Empty (r.Subviews);
  638. Assert.False (r.WantContinuousButtonPressed);
  639. Assert.False (r.WantMousePositionReports);
  640. Assert.Null (r.SuperView);
  641. Assert.Null (r.MostFocused);
  642. Assert.Equal (TextDirection.LeftRight_TopBottom, r.TextDirection);
  643. r.Dispose ();
  644. // Empty Rect
  645. r = new View { Frame = Rectangle.Empty };
  646. Assert.NotNull (r);
  647. Assert.Equal (LayoutStyle.Absolute, r.LayoutStyle);
  648. Assert.Equal ($"View(){r.Viewport}", r.ToString ());
  649. Assert.False (r.CanFocus);
  650. Assert.False (r.HasFocus);
  651. Assert.Equal (new Rectangle (0, 0, 0, 0), r.Viewport);
  652. Assert.Equal (new Rectangle (0, 0, 0, 0), r.Frame);
  653. Assert.Null (r.Focused);
  654. Assert.Null (r.ColorScheme);
  655. Assert.Equal (0, r.Width);
  656. Assert.Equal (0, r.Height);
  657. Assert.Equal (0, r.X);
  658. Assert.Equal (0, r.Y);
  659. Assert.False (r.IsCurrentTop);
  660. Assert.Empty (r.Id);
  661. Assert.Empty (r.Subviews);
  662. Assert.False (r.WantContinuousButtonPressed);
  663. Assert.False (r.WantMousePositionReports);
  664. Assert.Null (r.SuperView);
  665. Assert.Null (r.MostFocused);
  666. Assert.Equal (TextDirection.LeftRight_TopBottom, r.TextDirection);
  667. r.Dispose ();
  668. // Rect with values
  669. r = new View { Frame = new Rectangle (1, 2, 3, 4) };
  670. Assert.NotNull (r);
  671. Assert.Equal (LayoutStyle.Absolute, r.LayoutStyle);
  672. Assert.Equal ($"View(){r.Frame}", r.ToString ());
  673. Assert.False (r.CanFocus);
  674. Assert.False (r.HasFocus);
  675. Assert.Equal (new Rectangle (0, 0, 3, 4), r.Viewport);
  676. Assert.Equal (new Rectangle (1, 2, 3, 4), r.Frame);
  677. Assert.Null (r.Focused);
  678. Assert.Null (r.ColorScheme);
  679. Assert.Equal (3, r.Width);
  680. Assert.Equal (4, r.Height);
  681. Assert.Equal (1, r.X);
  682. Assert.Equal (2, r.Y);
  683. Assert.False (r.IsCurrentTop);
  684. Assert.Empty (r.Id);
  685. Assert.Empty (r.Subviews);
  686. Assert.False (r.WantContinuousButtonPressed);
  687. Assert.False (r.WantMousePositionReports);
  688. Assert.Null (r.SuperView);
  689. Assert.Null (r.MostFocused);
  690. Assert.Equal (TextDirection.LeftRight_TopBottom, r.TextDirection);
  691. r.Dispose ();
  692. // Initializes a view with a vertical direction
  693. r = new View
  694. {
  695. Text = "Vertical View", TextDirection = TextDirection.TopBottom_LeftRight, AutoSize = true
  696. }; // BUGBUG: AutoSize or Height need be set
  697. Assert.NotNull (r);
  698. Assert.Equal (LayoutStyle.Absolute, r.LayoutStyle);
  699. // BUGBUG: IsInitialized must be true to process calculation
  700. r.BeginInit ();
  701. r.EndInit ();
  702. Assert.False (r.CanFocus);
  703. Assert.False (r.HasFocus);
  704. Assert.Equal (new Rectangle (0, 0, 1, 13), r.Viewport);
  705. Assert.Equal (new Rectangle (0, 0, 1, 13), r.Frame);
  706. Assert.Null (r.Focused);
  707. Assert.Null (r.ColorScheme);
  708. Assert.False (r.IsCurrentTop);
  709. #if DEBUG
  710. Assert.Equal ("Vertical View", r.Id);
  711. #else
  712. Assert.Equal (string.Empty, r.Id);
  713. #endif
  714. Assert.Empty (r.Subviews);
  715. Assert.False (r.WantContinuousButtonPressed);
  716. Assert.False (r.WantMousePositionReports);
  717. Assert.Null (r.SuperView);
  718. Assert.Null (r.MostFocused);
  719. Assert.Equal (TextDirection.TopBottom_LeftRight, r.TextDirection);
  720. r.Dispose ();
  721. }
  722. [Fact]
  723. [TestRespondersDisposed]
  724. public void New_Methods_Return_False ()
  725. {
  726. var r = new View ();
  727. Assert.False (r.OnKeyDown (new Key { KeyCode = KeyCode.Null }));
  728. //Assert.False (r.OnKeyDown (new KeyEventArgs () { Key = Key.Unknown }));
  729. Assert.False (r.OnKeyUp (new Key { KeyCode = KeyCode.Null }));
  730. Assert.False (r.OnMouseEvent (new MouseEvent { Flags = MouseFlags.AllEvents }));
  731. Assert.False (r.OnMouseEnter (new MouseEvent { Flags = MouseFlags.AllEvents }));
  732. Assert.False (r.OnMouseLeave (new MouseEvent { Flags = MouseFlags.AllEvents }));
  733. var v1 = new View ();
  734. Assert.False (r.OnEnter (v1));
  735. v1.Dispose ();
  736. var v2 = new View ();
  737. Assert.False (r.OnLeave (v2));
  738. v2.Dispose ();
  739. r.Dispose ();
  740. // TODO: Add more
  741. }
  742. [Fact]
  743. [AutoInitShutdown]
  744. public void Test_Nested_Views_With_Height_Equal_To_One ()
  745. {
  746. var v = new View { Width = 11, Height = 3, ColorScheme = new ColorScheme () };
  747. var top = new View { Width = Dim.Fill (), Height = 1 };
  748. var bottom = new View { Width = Dim.Fill (), Height = 1, Y = 2 };
  749. top.Add (new Label { Text = "111" });
  750. v.Add (top);
  751. v.Add (new LineView (Orientation.Horizontal) { Y = 1 });
  752. bottom.Add (new Label { Text = "222" });
  753. v.Add (bottom);
  754. v.BeginInit ();
  755. v.EndInit ();
  756. v.LayoutSubviews ();
  757. v.Draw ();
  758. var looksLike =
  759. @"
  760. 111
  761. ───────────
  762. 222";
  763. TestHelpers.AssertDriverContentsAre (looksLike, _output);
  764. v.Dispose ();
  765. top.Dispose ();
  766. bottom.Dispose ();
  767. }
  768. [Fact]
  769. [TestRespondersDisposed]
  770. public void View_With_No_Difference_Between_An_Object_Initializer_Compute_And_A_Absolute ()
  771. {
  772. // Object Initializer Computed
  773. var view = new View { X = 1, Y = 2, Width = 3, Height = 4 };
  774. // Object Initializer Absolute
  775. var super = new View { Frame = new Rectangle (0, 0, 10, 10) };
  776. super.Add (view);
  777. super.BeginInit ();
  778. super.EndInit ();
  779. super.LayoutSubviews ();
  780. Assert.Equal (1, view.X);
  781. Assert.Equal (2, view.Y);
  782. Assert.Equal (3, view.Width);
  783. Assert.Equal (4, view.Height);
  784. Assert.False (view.Frame.IsEmpty);
  785. Assert.Equal (new Rectangle (1, 2, 3, 4), view.Frame);
  786. Assert.False (view.Viewport.IsEmpty);
  787. Assert.Equal (new Rectangle (0, 0, 3, 4), view.Viewport);
  788. view.LayoutSubviews ();
  789. Assert.Equal (1, view.X);
  790. Assert.Equal (2, view.Y);
  791. Assert.Equal (3, view.Width);
  792. Assert.Equal (4, view.Height);
  793. Assert.False (view.Frame.IsEmpty);
  794. Assert.False (view.Viewport.IsEmpty);
  795. super.Dispose ();
  796. #if DEBUG_IDISPOSABLE
  797. Assert.Empty (Responder.Instances);
  798. #endif
  799. // Default Constructor
  800. view = new View ();
  801. Assert.Equal (0, view.X);
  802. Assert.Equal (0, view.Y);
  803. Assert.Equal (0, view.Width);
  804. Assert.Equal (0, view.Height);
  805. Assert.True (view.Frame.IsEmpty);
  806. Assert.True (view.Viewport.IsEmpty);
  807. view.Dispose ();
  808. // Object Initializer
  809. view = new View { X = 1, Y = 2, Text = "" };
  810. Assert.Equal (1, view.X);
  811. Assert.Equal (2, view.Y);
  812. Assert.Equal (0, view.Width);
  813. Assert.Equal (0, view.Height);
  814. Assert.False (view.Frame.IsEmpty);
  815. Assert.True (view.Viewport.IsEmpty);
  816. view.Dispose ();
  817. // Default Constructor and post assignment equivalent to Object Initializer
  818. view = new View ();
  819. view.X = 1;
  820. view.Y = 2;
  821. view.Width = 3;
  822. view.Height = 4;
  823. super = new View { Frame = new Rectangle (0, 0, 10, 10) };
  824. super.Add (view);
  825. super.BeginInit ();
  826. super.EndInit ();
  827. super.LayoutSubviews ();
  828. Assert.Equal (1, view.X);
  829. Assert.Equal (2, view.Y);
  830. Assert.Equal (3, view.Width);
  831. Assert.Equal (4, view.Height);
  832. Assert.False (view.Frame.IsEmpty);
  833. Assert.Equal (new Rectangle (1, 2, 3, 4), view.Frame);
  834. Assert.False (view.Viewport.IsEmpty);
  835. Assert.Equal (new Rectangle (0, 0, 3, 4), view.Viewport);
  836. super.Dispose ();
  837. }
  838. [Fact]
  839. [AutoInitShutdown]
  840. public void Visible_Clear_The_View_Output ()
  841. {
  842. var view = new View { Text = "Testing visibility." }; // use View, not Label to avoid AutoSize == true
  843. // BUGBUG: AutoSize is false and size wasn't provided so it's 0,0
  844. Assert.Equal (0, view.Frame.Width);
  845. Assert.Equal (0, view.Height);
  846. var win = new Window ();
  847. win.Add (view);
  848. Toplevel top = Application.Top;
  849. top.Add (win);
  850. RunState rs = Application.Begin (top);
  851. view.AutoSize = true;
  852. Assert.Equal ("Testing visibility.".Length, view.Frame.Width);
  853. Assert.True (view.Visible);
  854. ((FakeDriver)Application.Driver).SetBufferSize (30, 5);
  855. TestHelpers.AssertDriverContentsWithFrameAre (
  856. @"
  857. ┌────────────────────────────┐
  858. │Testing visibility. │
  859. │ │
  860. │ │
  861. └────────────────────────────┘
  862. ",
  863. _output
  864. );
  865. view.Visible = false;
  866. var firstIteration = false;
  867. Application.RunIteration (ref rs, ref firstIteration);
  868. TestHelpers.AssertDriverContentsWithFrameAre (
  869. @"
  870. ┌────────────────────────────┐
  871. │ │
  872. │ │
  873. │ │
  874. └────────────────────────────┘
  875. ",
  876. _output
  877. );
  878. Application.End (rs);
  879. }
  880. [Fact]
  881. [AutoInitShutdown]
  882. public void Visible_Sets_Also_Sets_Subviews ()
  883. {
  884. var button = new Button { Text = "Click Me" };
  885. var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () };
  886. win.Add (button);
  887. Toplevel top = Application.Top;
  888. top.Add (win);
  889. var iterations = 0;
  890. Application.Iteration += (s, a) =>
  891. {
  892. iterations++;
  893. Assert.True (button.Visible);
  894. Assert.True (button.CanFocus);
  895. Assert.True (button.HasFocus);
  896. Assert.True (win.Visible);
  897. Assert.True (win.CanFocus);
  898. Assert.True (win.HasFocus);
  899. Assert.True (RunesCount () > 0);
  900. win.Visible = false;
  901. Assert.True (button.Visible);
  902. Assert.True (button.CanFocus);
  903. Assert.False (button.HasFocus);
  904. Assert.False (win.Visible);
  905. Assert.True (win.CanFocus);
  906. Assert.False (win.HasFocus);
  907. button.SetFocus ();
  908. Assert.False (button.HasFocus);
  909. Assert.False (win.HasFocus);
  910. win.SetFocus ();
  911. Assert.False (button.HasFocus);
  912. Assert.False (win.HasFocus);
  913. top.Draw ();
  914. Assert.True (RunesCount () == 0);
  915. win.Visible = true;
  916. win.FocusFirst ();
  917. Assert.True (button.HasFocus);
  918. Assert.True (win.HasFocus);
  919. top.Draw ();
  920. Assert.True (RunesCount () > 0);
  921. Application.RequestStop ();
  922. };
  923. Application.Run ();
  924. Assert.Equal (1, iterations);
  925. int RunesCount ()
  926. {
  927. Cell [,] contents = ((FakeDriver)Application.Driver).Contents;
  928. var runesCount = 0;
  929. for (var i = 0; i < Application.Driver.Rows; i++)
  930. {
  931. for (var j = 0; j < Application.Driver.Cols; j++)
  932. {
  933. if (contents [i, j].Rune != (Rune)' ')
  934. {
  935. runesCount++;
  936. }
  937. }
  938. }
  939. return runesCount;
  940. }
  941. }
  942. public class DerivedView : View
  943. {
  944. public DerivedView () { CanFocus = true; }
  945. public bool IsKeyDown { get; set; }
  946. public bool IsKeyPress { get; set; }
  947. public bool IsKeyUp { get; set; }
  948. public override string Text { get; set; }
  949. public override void OnDrawContent (Rectangle viewport)
  950. {
  951. var idx = 0;
  952. // BUGBUG: v2 - this should use Viewport, not Frame
  953. for (var r = 0; r < Frame.Height; r++)
  954. {
  955. for (var c = 0; c < Frame.Width; c++)
  956. {
  957. if (idx < Text.Length)
  958. {
  959. char rune = Text [idx];
  960. if (rune != '\n')
  961. {
  962. AddRune (c, r, (Rune)Text [idx]);
  963. }
  964. idx++;
  965. if (rune == '\n')
  966. {
  967. break;
  968. }
  969. }
  970. }
  971. }
  972. ClearLayoutNeeded ();
  973. ClearNeedsDisplay ();
  974. }
  975. public override bool OnKeyDown (Key keyEvent)
  976. {
  977. IsKeyDown = true;
  978. return true;
  979. }
  980. public override bool OnKeyUp (Key keyEvent)
  981. {
  982. IsKeyUp = true;
  983. return true;
  984. }
  985. public override bool OnProcessKeyDown (Key keyEvent)
  986. {
  987. IsKeyPress = true;
  988. return true;
  989. }
  990. }
  991. // OnAccept/Accept tests
  992. [Fact]
  993. public void OnAccept_Fires_Accept ()
  994. {
  995. var view = new View ();
  996. var accepted = false;
  997. view.Accept += ViewOnAccept;
  998. view.InvokeCommand (Command.Accept);
  999. Assert.True (accepted);
  1000. return;
  1001. void ViewOnAccept (object sender, CancelEventArgs e) { accepted = true; }
  1002. }
  1003. [Fact]
  1004. public void Accept_Cancel_Event_OnAccept_Returns_True ()
  1005. {
  1006. var view = new View ();
  1007. var acceptInvoked = false;
  1008. view.Accept += ViewOnAccept;
  1009. var ret = view.InvokeCommand (Command.Accept);
  1010. Assert.True (ret);
  1011. Assert.True (acceptInvoked);
  1012. return;
  1013. void ViewOnAccept (object sender, CancelEventArgs e) {
  1014. acceptInvoked = true;
  1015. e.Cancel = true;
  1016. }
  1017. }
  1018. [Fact]
  1019. public void Accept_Command_Invokes_Accept_Event ()
  1020. {
  1021. var view = new View ();
  1022. var accepted = false;
  1023. view.Accept += ViewOnAccept;
  1024. view.InvokeCommand (Command.Accept);
  1025. Assert.True (accepted);
  1026. return;
  1027. void ViewOnAccept (object sender, CancelEventArgs e) { accepted = true; }
  1028. }
  1029. [Fact]
  1030. public void HotKey_Command_SetsFocus ()
  1031. {
  1032. var view = new View ();
  1033. view.CanFocus = true;
  1034. Assert.False (view.HasFocus);
  1035. view.InvokeCommand (Command.HotKey);
  1036. Assert.True (view.HasFocus);
  1037. }
  1038. }