ViewTests.cs 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233
  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.Bounds.Width, view.Bounds.Height);
  18. for (var row = 0; row < view.Bounds.Height; row++)
  19. {
  20. Application.Driver.Move (1, row + 1);
  21. for (var col = 0; col < view.Bounds.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.Bounds);
  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.Bounds.Width, view.Bounds.Height);
  70. for (var row = 0; row < view.Bounds.Height; row++)
  71. {
  72. Application.Driver.Move (1, row + 1);
  73. for (var col = 0; col < view.Bounds.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.Bounds);
  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.Bounds);
  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.Bounds);
  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.Bounds);
  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.Bounds);
  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.Bounds);
  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.Bounds);
  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.Bounds);
  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.Bounds);
  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.Equal (LayoutStyle.Absolute, r.LayoutStyle);
  622. Assert.Equal ($"View(){r.Bounds}", r.ToString ());
  623. Assert.False (r.CanFocus);
  624. Assert.False (r.HasFocus);
  625. Assert.Equal (new Rectangle (0, 0, 0, 0), r.Bounds);
  626. Assert.Equal (new Rectangle (0, 0, 0, 0), r.Frame);
  627. Assert.Null (r.Focused);
  628. Assert.Null (r.ColorScheme);
  629. Assert.Equal (0, r.Width);
  630. Assert.Equal (0, r.Height);
  631. Assert.Equal (0, r.X);
  632. Assert.Equal (0, r.Y);
  633. Assert.False (r.IsCurrentTop);
  634. Assert.Empty (r.Id);
  635. Assert.Empty (r.Subviews);
  636. Assert.False (r.WantContinuousButtonPressed);
  637. Assert.False (r.WantMousePositionReports);
  638. Assert.Null (r.SuperView);
  639. Assert.Null (r.MostFocused);
  640. Assert.Equal (TextDirection.LeftRight_TopBottom, r.TextDirection);
  641. r.Dispose ();
  642. // Empty Rect
  643. r = new View { Frame = Rectangle.Empty };
  644. Assert.NotNull (r);
  645. Assert.Equal (LayoutStyle.Absolute, r.LayoutStyle);
  646. Assert.Equal ($"View(){r.Bounds}", r.ToString ());
  647. Assert.False (r.CanFocus);
  648. Assert.False (r.HasFocus);
  649. Assert.Equal (new Rectangle (0, 0, 0, 0), r.Bounds);
  650. Assert.Equal (new Rectangle (0, 0, 0, 0), r.Frame);
  651. Assert.Null (r.Focused);
  652. Assert.Null (r.ColorScheme);
  653. Assert.Equal (0, r.Width);
  654. Assert.Equal (0, r.Height);
  655. Assert.Equal (0, r.X);
  656. Assert.Equal (0, r.Y);
  657. Assert.False (r.IsCurrentTop);
  658. Assert.Empty (r.Id);
  659. Assert.Empty (r.Subviews);
  660. Assert.False (r.WantContinuousButtonPressed);
  661. Assert.False (r.WantMousePositionReports);
  662. Assert.Null (r.SuperView);
  663. Assert.Null (r.MostFocused);
  664. Assert.Equal (TextDirection.LeftRight_TopBottom, r.TextDirection);
  665. r.Dispose ();
  666. // Rect with values
  667. r = new View { Frame = new Rectangle (1, 2, 3, 4) };
  668. Assert.NotNull (r);
  669. Assert.Equal (LayoutStyle.Absolute, r.LayoutStyle);
  670. Assert.Equal ($"View(){r.Frame}", r.ToString ());
  671. Assert.False (r.CanFocus);
  672. Assert.False (r.HasFocus);
  673. Assert.Equal (new Rectangle (0, 0, 3, 4), r.Bounds);
  674. Assert.Equal (new Rectangle (1, 2, 3, 4), r.Frame);
  675. Assert.Null (r.Focused);
  676. Assert.Null (r.ColorScheme);
  677. Assert.Equal (3, r.Width);
  678. Assert.Equal (4, r.Height);
  679. Assert.Equal (1, r.X);
  680. Assert.Equal (2, r.Y);
  681. Assert.False (r.IsCurrentTop);
  682. Assert.Empty (r.Id);
  683. Assert.Empty (r.Subviews);
  684. Assert.False (r.WantContinuousButtonPressed);
  685. Assert.False (r.WantMousePositionReports);
  686. Assert.Null (r.SuperView);
  687. Assert.Null (r.MostFocused);
  688. Assert.Equal (TextDirection.LeftRight_TopBottom, r.TextDirection);
  689. r.Dispose ();
  690. // Initializes a view with a vertical direction
  691. r = new View
  692. {
  693. Text = "Vertical View", TextDirection = TextDirection.TopBottom_LeftRight, AutoSize = true
  694. }; // BUGBUG: AutoSize or Height need be set
  695. Assert.NotNull (r);
  696. Assert.Equal (LayoutStyle.Absolute, r.LayoutStyle);
  697. // BUGBUG: IsInitialized must be true to process calculation
  698. r.BeginInit ();
  699. r.EndInit ();
  700. Assert.False (r.CanFocus);
  701. Assert.False (r.HasFocus);
  702. Assert.Equal (new Rectangle (0, 0, 1, 13), r.Bounds);
  703. Assert.Equal (new Rectangle (0, 0, 1, 13), r.Frame);
  704. Assert.Null (r.Focused);
  705. Assert.Null (r.ColorScheme);
  706. Assert.False (r.IsCurrentTop);
  707. #if DEBUG
  708. Assert.Equal ("Vertical View", r.Id);
  709. #else
  710. Assert.Equal (string.Empty, r.Id);
  711. #endif
  712. Assert.Empty (r.Subviews);
  713. Assert.False (r.WantContinuousButtonPressed);
  714. Assert.False (r.WantMousePositionReports);
  715. Assert.Null (r.SuperView);
  716. Assert.Null (r.MostFocused);
  717. Assert.Equal (TextDirection.TopBottom_LeftRight, r.TextDirection);
  718. r.Dispose ();
  719. }
  720. [Fact]
  721. [TestRespondersDisposed]
  722. public void New_Methods_Return_False ()
  723. {
  724. var r = new View ();
  725. Assert.False (r.OnKeyDown (new Key { KeyCode = KeyCode.Null }));
  726. //Assert.False (r.OnKeyDown (new KeyEventArgs () { Key = Key.Unknown }));
  727. Assert.False (r.OnKeyUp (new Key { KeyCode = KeyCode.Null }));
  728. Assert.False (r.OnMouseEvent (new MouseEvent { Flags = MouseFlags.AllEvents }));
  729. Assert.False (r.OnMouseEnter (new MouseEvent { Flags = MouseFlags.AllEvents }));
  730. Assert.False (r.OnMouseLeave (new MouseEvent { Flags = MouseFlags.AllEvents }));
  731. var v1 = new View ();
  732. Assert.False (r.OnEnter (v1));
  733. v1.Dispose ();
  734. var v2 = new View ();
  735. Assert.False (r.OnLeave (v2));
  736. v2.Dispose ();
  737. r.Dispose ();
  738. // TODO: Add more
  739. }
  740. [Fact]
  741. [AutoInitShutdown]
  742. public void Test_Nested_Views_With_Height_Equal_To_One ()
  743. {
  744. var v = new View { Width = 11, Height = 3, ColorScheme = new ColorScheme () };
  745. var top = new View { Width = Dim.Fill (), Height = 1 };
  746. var bottom = new View { Width = Dim.Fill (), Height = 1, Y = 2 };
  747. top.Add (new Label { Text = "111" });
  748. v.Add (top);
  749. v.Add (new LineView (Orientation.Horizontal) { Y = 1 });
  750. bottom.Add (new Label { Text = "222" });
  751. v.Add (bottom);
  752. v.BeginInit ();
  753. v.EndInit ();
  754. v.LayoutSubviews ();
  755. v.Draw ();
  756. var looksLike =
  757. @"
  758. 111
  759. ───────────
  760. 222";
  761. TestHelpers.AssertDriverContentsAre (looksLike, _output);
  762. v.Dispose ();
  763. top.Dispose ();
  764. bottom.Dispose ();
  765. }
  766. [Fact]
  767. [TestRespondersDisposed]
  768. public void View_With_No_Difference_Between_An_Object_Initializer_Compute_And_A_Absolute ()
  769. {
  770. // Object Initializer Computed
  771. var view = new View { X = 1, Y = 2, Width = 3, Height = 4 };
  772. // Object Initializer Absolute
  773. var super = new View { Frame = new Rectangle (0, 0, 10, 10) };
  774. super.Add (view);
  775. super.BeginInit ();
  776. super.EndInit ();
  777. super.LayoutSubviews ();
  778. Assert.Equal (1, view.X);
  779. Assert.Equal (2, view.Y);
  780. Assert.Equal (3, view.Width);
  781. Assert.Equal (4, view.Height);
  782. Assert.False (view.Frame.IsEmpty);
  783. Assert.Equal (new Rectangle (1, 2, 3, 4), view.Frame);
  784. Assert.False (view.Bounds.IsEmpty);
  785. Assert.Equal (new Rectangle (0, 0, 3, 4), view.Bounds);
  786. view.LayoutSubviews ();
  787. Assert.Equal (1, view.X);
  788. Assert.Equal (2, view.Y);
  789. Assert.Equal (3, view.Width);
  790. Assert.Equal (4, view.Height);
  791. Assert.False (view.Frame.IsEmpty);
  792. Assert.False (view.Bounds.IsEmpty);
  793. super.Dispose ();
  794. #if DEBUG_IDISPOSABLE
  795. Assert.Empty (Responder.Instances);
  796. #endif
  797. // Default Constructor
  798. view = new View ();
  799. Assert.Equal (0, view.X);
  800. Assert.Equal (0, view.Y);
  801. Assert.Equal (0, view.Width);
  802. Assert.Equal (0, view.Height);
  803. Assert.True (view.Frame.IsEmpty);
  804. Assert.True (view.Bounds.IsEmpty);
  805. view.Dispose ();
  806. // Object Initializer
  807. view = new View { X = 1, Y = 2, Text = "" };
  808. Assert.Equal (1, view.X);
  809. Assert.Equal (2, view.Y);
  810. Assert.Equal (0, view.Width);
  811. Assert.Equal (0, view.Height);
  812. Assert.False (view.Frame.IsEmpty);
  813. Assert.True (view.Bounds.IsEmpty);
  814. view.Dispose ();
  815. // Default Constructor and post assignment equivalent to Object Initializer
  816. view = new View ();
  817. view.X = 1;
  818. view.Y = 2;
  819. view.Width = 3;
  820. view.Height = 4;
  821. super = new View { Frame = new Rectangle (0, 0, 10, 10) };
  822. super.Add (view);
  823. super.BeginInit ();
  824. super.EndInit ();
  825. super.LayoutSubviews ();
  826. Assert.Equal (1, view.X);
  827. Assert.Equal (2, view.Y);
  828. Assert.Equal (3, view.Width);
  829. Assert.Equal (4, view.Height);
  830. Assert.False (view.Frame.IsEmpty);
  831. Assert.Equal (new Rectangle (1, 2, 3, 4), view.Frame);
  832. Assert.False (view.Bounds.IsEmpty);
  833. Assert.Equal (new Rectangle (0, 0, 3, 4), view.Bounds);
  834. super.Dispose ();
  835. }
  836. [Fact]
  837. [AutoInitShutdown]
  838. public void Visible_Clear_The_View_Output ()
  839. {
  840. var view = new View { Text = "Testing visibility." }; // use View, not Label to avoid AutoSize == true
  841. // BUGBUG: AutoSize is false and size wasn't provided so it's 0,0
  842. Assert.Equal (0, view.Frame.Width);
  843. Assert.Equal (0, view.Height);
  844. var win = new Window ();
  845. win.Add (view);
  846. Toplevel top = Application.Top;
  847. top.Add (win);
  848. RunState rs = Application.Begin (top);
  849. view.AutoSize = true;
  850. Assert.Equal ("Testing visibility.".Length, view.Frame.Width);
  851. Assert.True (view.Visible);
  852. ((FakeDriver)Application.Driver).SetBufferSize (30, 5);
  853. TestHelpers.AssertDriverContentsWithFrameAre (
  854. @"
  855. ┌────────────────────────────┐
  856. │Testing visibility. │
  857. │ │
  858. │ │
  859. └────────────────────────────┘
  860. ",
  861. _output
  862. );
  863. view.Visible = false;
  864. var firstIteration = false;
  865. Application.RunIteration (ref rs, ref firstIteration);
  866. TestHelpers.AssertDriverContentsWithFrameAre (
  867. @"
  868. ┌────────────────────────────┐
  869. │ │
  870. │ │
  871. │ │
  872. └────────────────────────────┘
  873. ",
  874. _output
  875. );
  876. Application.End (rs);
  877. }
  878. [Fact]
  879. [AutoInitShutdown]
  880. public void Visible_Sets_Also_Sets_Subviews ()
  881. {
  882. var button = new Button { Text = "Click Me" };
  883. var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () };
  884. win.Add (button);
  885. Toplevel top = Application.Top;
  886. top.Add (win);
  887. var iterations = 0;
  888. Application.Iteration += (s, a) =>
  889. {
  890. iterations++;
  891. Assert.True (button.Visible);
  892. Assert.True (button.CanFocus);
  893. Assert.True (button.HasFocus);
  894. Assert.True (win.Visible);
  895. Assert.True (win.CanFocus);
  896. Assert.True (win.HasFocus);
  897. Assert.True (RunesCount () > 0);
  898. win.Visible = false;
  899. Assert.True (button.Visible);
  900. Assert.True (button.CanFocus);
  901. Assert.False (button.HasFocus);
  902. Assert.False (win.Visible);
  903. Assert.True (win.CanFocus);
  904. Assert.False (win.HasFocus);
  905. button.SetFocus ();
  906. Assert.False (button.HasFocus);
  907. Assert.False (win.HasFocus);
  908. win.SetFocus ();
  909. Assert.False (button.HasFocus);
  910. Assert.False (win.HasFocus);
  911. top.Draw ();
  912. Assert.True (RunesCount () == 0);
  913. win.Visible = true;
  914. win.FocusFirst ();
  915. Assert.True (button.HasFocus);
  916. Assert.True (win.HasFocus);
  917. top.Draw ();
  918. Assert.True (RunesCount () > 0);
  919. Application.RequestStop ();
  920. };
  921. Application.Run ();
  922. Assert.Equal (1, iterations);
  923. int RunesCount ()
  924. {
  925. Cell [,] contents = ((FakeDriver)Application.Driver).Contents;
  926. var runesCount = 0;
  927. for (var i = 0; i < Application.Driver.Rows; i++)
  928. {
  929. for (var j = 0; j < Application.Driver.Cols; j++)
  930. {
  931. if (contents [i, j].Rune != (Rune)' ')
  932. {
  933. runesCount++;
  934. }
  935. }
  936. }
  937. return runesCount;
  938. }
  939. }
  940. public class DerivedView : View
  941. {
  942. public DerivedView () { CanFocus = true; }
  943. public bool IsKeyDown { get; set; }
  944. public bool IsKeyPress { get; set; }
  945. public bool IsKeyUp { get; set; }
  946. public override string Text { get; set; }
  947. public override void OnDrawContent (Rectangle contentArea)
  948. {
  949. var idx = 0;
  950. // BUGBUG: v2 - this should use Bounds, not Frame
  951. for (var r = 0; r < Frame.Height; r++)
  952. {
  953. for (var c = 0; c < Frame.Width; c++)
  954. {
  955. if (idx < Text.Length)
  956. {
  957. char rune = Text [idx];
  958. if (rune != '\n')
  959. {
  960. AddRune (c, r, (Rune)Text [idx]);
  961. }
  962. idx++;
  963. if (rune == '\n')
  964. {
  965. break;
  966. }
  967. }
  968. }
  969. }
  970. ClearLayoutNeeded ();
  971. ClearNeedsDisplay ();
  972. }
  973. public override bool OnKeyDown (Key keyEvent)
  974. {
  975. IsKeyDown = true;
  976. return true;
  977. }
  978. public override bool OnKeyUp (Key keyEvent)
  979. {
  980. IsKeyUp = true;
  981. return true;
  982. }
  983. public override bool OnProcessKeyDown (Key keyEvent)
  984. {
  985. IsKeyPress = true;
  986. return true;
  987. }
  988. }
  989. // OnAccept/Accept tests
  990. [Fact]
  991. public void OnAccept_Fires_Accept ()
  992. {
  993. var view = new View ();
  994. var accepted = false;
  995. view.Accept += ViewOnAccept;
  996. view.InvokeCommand (Command.Accept);
  997. Assert.True (accepted);
  998. return;
  999. void ViewOnAccept (object sender, CancelEventArgs e) { accepted = true; }
  1000. }
  1001. [Fact]
  1002. public void Accept_Cancel_Event_OnAccept_Returns_True ()
  1003. {
  1004. var view = new View ();
  1005. var acceptInvoked = false;
  1006. view.Accept += ViewOnAccept;
  1007. var ret = view.InvokeCommand (Command.Accept);
  1008. Assert.True (ret);
  1009. Assert.True (acceptInvoked);
  1010. return;
  1011. void ViewOnAccept (object sender, CancelEventArgs e) {
  1012. acceptInvoked = true;
  1013. e.Cancel = true;
  1014. }
  1015. }
  1016. [Fact]
  1017. public void Accept_Command_Invokes_Accept_Event ()
  1018. {
  1019. var view = new View ();
  1020. var accepted = false;
  1021. view.Accept += ViewOnAccept;
  1022. view.InvokeCommand (Command.Accept);
  1023. Assert.True (accepted);
  1024. return;
  1025. void ViewOnAccept (object sender, CancelEventArgs e) { accepted = true; }
  1026. }
  1027. [Fact]
  1028. public void HotKey_Command_SetsFocus ()
  1029. {
  1030. var view = new View ();
  1031. view.CanFocus = true;
  1032. Assert.False (view.HasFocus);
  1033. view.InvokeCommand (Command.HotKey);
  1034. Assert.True (view.HasFocus);
  1035. }
  1036. }