TabViewTests.cs 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554
  1. using System.Globalization;
  2. using Xunit.Abstractions;
  3. namespace Terminal.Gui.ViewsTests;
  4. public class TabViewTests (ITestOutputHelper output)
  5. {
  6. [Fact]
  7. public void AddTab_SameTabMoreThanOnce ()
  8. {
  9. TabView tv = GetTabView (out Tab tab1, out Tab tab2);
  10. Assert.Equal (2, tv.Tabs.Count);
  11. // Tab is already part of the control so shouldn't result in duplication
  12. tv.AddTab (tab1, false);
  13. tv.AddTab (tab1, false);
  14. tv.AddTab (tab1, false);
  15. tv.AddTab (tab1, false);
  16. Assert.Equal (2, tv.Tabs.Count);
  17. // Shutdown must be called to safely clean up Application if Init has been called
  18. Application.Shutdown ();
  19. }
  20. [Fact]
  21. public void AddTwoTabs_SecondIsSelected ()
  22. {
  23. InitFakeDriver ();
  24. var tv = new TabView ();
  25. Tab tab1;
  26. Tab tab2;
  27. tv.AddTab (tab1 = new () { DisplayText = "Tab1", View = new TextField { Text = "hi" } }, false);
  28. tv.AddTab (tab2 = new () { DisplayText = "Tab1", View = new Label { Text = "hi2" } }, true);
  29. Assert.Equal (2, tv.Tabs.Count);
  30. Assert.Equal (tab2, tv.SelectedTab);
  31. Application.Shutdown ();
  32. }
  33. [Fact]
  34. public void EnsureSelectedTabVisible_MustScroll ()
  35. {
  36. TabView tv = GetTabView (out Tab tab1, out Tab tab2);
  37. // Make tab width small to force only one tab visible at once
  38. tv.Width = 4;
  39. tv.SelectedTab = tab1;
  40. Assert.Equal (0, tv.TabScrollOffset);
  41. tv.EnsureSelectedTabIsVisible ();
  42. Assert.Equal (0, tv.TabScrollOffset);
  43. // Asking to show tab2 should automatically move scroll offset accordingly
  44. tv.SelectedTab = tab2;
  45. Assert.Equal (1, tv.TabScrollOffset);
  46. // Shutdown must be called to safely clean up Application if Init has been called
  47. Application.Shutdown ();
  48. }
  49. [Fact]
  50. public void EnsureSelectedTabVisible_NullSelect ()
  51. {
  52. TabView tv = GetTabView ();
  53. tv.SelectedTab = null;
  54. Assert.Null (tv.SelectedTab);
  55. Assert.Equal (0, tv.TabScrollOffset);
  56. tv.EnsureSelectedTabIsVisible ();
  57. Assert.Null (tv.SelectedTab);
  58. Assert.Equal (0, tv.TabScrollOffset);
  59. Application.Shutdown ();
  60. }
  61. [Fact]
  62. public void EnsureValidScrollOffsets_TabScrollOffset ()
  63. {
  64. TabView tv = GetTabView (out Tab tab1, out Tab tab2);
  65. // Make tab width small to force only one tab visible at once
  66. tv.Width = 4;
  67. tv.SelectedTab = tab1;
  68. Assert.Equal (0, tv.TabScrollOffset);
  69. tv.TabScrollOffset = 10;
  70. tv.SelectedTab = tab2;
  71. Assert.Equal (1, tv.TabScrollOffset);
  72. tv.TabScrollOffset = -1;
  73. tv.SelectedTab = tab1;
  74. Assert.Equal (0, tv.TabScrollOffset);
  75. // Shutdown must be called to safely clean up Application if Init has been called
  76. Application.Shutdown ();
  77. }
  78. [Fact]
  79. [AutoInitShutdown]
  80. public void MouseClick_ChangesTab ()
  81. {
  82. TabView tv = GetTabView (out Tab tab1, out Tab tab2, false);
  83. tv.Width = 20;
  84. tv.Height = 5;
  85. tv.Draw ();
  86. View tabRow = tv.Subviews [0];
  87. Assert.Equal ("TabRowView", tabRow.GetType ().Name);
  88. TestHelpers.AssertDriverContentsAre (
  89. @"
  90. ╭────┬────╮
  91. │Tab1│Tab2│
  92. │ ╰────┴────────╮
  93. │hi │
  94. └──────────────────┘
  95. ",
  96. output
  97. );
  98. Tab clicked = null;
  99. tv.TabClicked += (s, e) => { clicked = e.Tab; };
  100. var top = new Toplevel ();
  101. top.Add (tv);
  102. Application.Begin (top);
  103. MouseEventArgs args;
  104. // Waving mouse around does not trigger click
  105. for (var i = 0; i < 100; i++)
  106. {
  107. args = new () { ScreenPosition = new (i, 1), Flags = MouseFlags.ReportMousePosition };
  108. Application.RaiseMouseEvent (args);
  109. Application.LayoutAndDraw ();
  110. Assert.Null (clicked);
  111. Assert.Equal (tab1, tv.SelectedTab);
  112. }
  113. args = new () { ScreenPosition = new (3, 1), Flags = MouseFlags.Button1Clicked };
  114. Application.RaiseMouseEvent (args);
  115. Application.LayoutAndDraw ();
  116. Assert.Equal (tab1, clicked);
  117. Assert.Equal (tab1, tv.SelectedTab);
  118. // Click to tab2
  119. args = new () { ScreenPosition = new (6, 1), Flags = MouseFlags.Button1Clicked };
  120. Application.RaiseMouseEvent (args);
  121. Application.LayoutAndDraw ();
  122. Assert.Equal (tab2, clicked);
  123. Assert.Equal (tab2, tv.SelectedTab);
  124. // cancel navigation
  125. tv.TabClicked += (s, e) =>
  126. {
  127. clicked = e.Tab;
  128. e.MouseEvent.Handled = true;
  129. };
  130. args = new () { ScreenPosition = new (3, 1), Flags = MouseFlags.Button1Clicked };
  131. Application.RaiseMouseEvent (args);
  132. Application.LayoutAndDraw ();
  133. // Tab 1 was clicked but event handler blocked navigation
  134. Assert.Equal (tab1, clicked);
  135. Assert.Equal (tab2, tv.SelectedTab);
  136. args = new () { ScreenPosition = new (12, 1), Flags = MouseFlags.Button1Clicked };
  137. Application.RaiseMouseEvent (args);
  138. Application.LayoutAndDraw ();
  139. // Clicking beyond last tab should raise event with null Tab
  140. Assert.Null (clicked);
  141. Assert.Equal (tab2, tv.SelectedTab);
  142. top.Dispose ();
  143. }
  144. [Fact]
  145. [AutoInitShutdown]
  146. public void MouseClick_Right_Left_Arrows_ChangesTab ()
  147. {
  148. TabView tv = GetTabView (out Tab tab1, out Tab tab2, false);
  149. tv.Width = 7;
  150. tv.Height = 5;
  151. tv.Draw ();
  152. View tabRow = tv.Subviews [0];
  153. Assert.Equal ("TabRowView", tabRow.GetType ().Name);
  154. TestHelpers.AssertDriverContentsAre (
  155. @"
  156. ╭────╮
  157. │Tab1│
  158. │ ╰►
  159. │hi │
  160. └─────┘
  161. ",
  162. output
  163. );
  164. Tab clicked = null;
  165. tv.TabClicked += (s, e) => { clicked = e.Tab; };
  166. Tab oldChanged = null;
  167. Tab newChanged = null;
  168. tv.SelectedTabChanged += (s, e) =>
  169. {
  170. oldChanged = e.OldTab;
  171. newChanged = e.NewTab;
  172. };
  173. var top = new Toplevel ();
  174. top.Add (tv);
  175. Application.Begin (top);
  176. // Click the right arrow
  177. var args = new MouseEventArgs { ScreenPosition = new (6, 2), Flags = MouseFlags.Button1Clicked };
  178. Application.RaiseMouseEvent (args);
  179. Application.LayoutAndDraw ();
  180. Assert.Null (clicked);
  181. Assert.Equal (tab1, oldChanged);
  182. Assert.Equal (tab2, newChanged);
  183. Assert.Equal (tab2, tv.SelectedTab);
  184. TestHelpers.AssertDriverContentsAre (
  185. @"
  186. ╭────╮
  187. │Tab2│
  188. ◄ ╰╮
  189. │hi2 │
  190. └─────┘
  191. ",
  192. output
  193. );
  194. // Click the left arrow
  195. args = new () { ScreenPosition = new (0, 2), Flags = MouseFlags.Button1Clicked };
  196. Application.RaiseMouseEvent (args);
  197. Application.LayoutAndDraw ();
  198. Assert.Null (clicked);
  199. Assert.Equal (tab2, oldChanged);
  200. Assert.Equal (tab1, newChanged);
  201. Assert.Equal (tab1, tv.SelectedTab);
  202. TestHelpers.AssertDriverContentsAre (
  203. @"
  204. ╭────╮
  205. │Tab1│
  206. │ ╰►
  207. │hi │
  208. └─────┘
  209. ",
  210. output
  211. );
  212. top.Dispose ();
  213. }
  214. [Fact]
  215. [AutoInitShutdown]
  216. public void MouseClick_Right_Left_Arrows_ChangesTab_With_Border ()
  217. {
  218. TabView tv = GetTabView (out Tab tab1, out Tab tab2, false);
  219. tv.Width = 9;
  220. tv.Height = 7;
  221. Assert.Equal (LineStyle.None, tv.BorderStyle);
  222. tv.BorderStyle = LineStyle.Single;
  223. tv.Layout ();
  224. tv.Draw ();
  225. View tabRow = tv.Subviews [0];
  226. Assert.Equal ("TabRowView", tabRow.GetType ().Name);
  227. TestHelpers.AssertDriverContentsAre (
  228. @"
  229. ┌───────┐
  230. │╭────╮ │
  231. ││Tab1│ │
  232. ││ ╰►│
  233. ││hi ││
  234. │└─────┘│
  235. └───────┘
  236. ",
  237. output
  238. );
  239. Tab clicked = null;
  240. tv.TabClicked += (s, e) => { clicked = e.Tab; };
  241. Tab oldChanged = null;
  242. Tab newChanged = null;
  243. tv.SelectedTabChanged += (s, e) =>
  244. {
  245. oldChanged = e.OldTab;
  246. newChanged = e.NewTab;
  247. };
  248. var top = new Toplevel ();
  249. top.Add (tv);
  250. Application.Begin (top);
  251. // Click the right arrow
  252. var args = new MouseEventArgs { ScreenPosition = new (7, 3), Flags = MouseFlags.Button1Clicked };
  253. Application.RaiseMouseEvent (args);
  254. Application.LayoutAndDraw ();
  255. Assert.Null (clicked);
  256. Assert.Equal (tab1, oldChanged);
  257. Assert.Equal (tab2, newChanged);
  258. Assert.Equal (tab2, tv.SelectedTab);
  259. TestHelpers.AssertDriverContentsAre (
  260. @"
  261. ┌───────┐
  262. │╭────╮ │
  263. ││Tab2│ │
  264. │◄ ╰╮│
  265. ││hi2 ││
  266. │└─────┘│
  267. └───────┘
  268. ",
  269. output
  270. );
  271. // Click the left arrow
  272. args = new () { ScreenPosition = new (1, 3), Flags = MouseFlags.Button1Clicked };
  273. Application.RaiseMouseEvent (args);
  274. Application.LayoutAndDraw ();
  275. Assert.Null (clicked);
  276. Assert.Equal (tab2, oldChanged);
  277. Assert.Equal (tab1, newChanged);
  278. Assert.Equal (tab1, tv.SelectedTab);
  279. TestHelpers.AssertDriverContentsAre (
  280. @"
  281. ┌───────┐
  282. │╭────╮ │
  283. ││Tab1│ │
  284. ││ ╰►│
  285. ││hi ││
  286. │└─────┘│
  287. └───────┘
  288. ",
  289. output
  290. );
  291. top.Dispose ();
  292. }
  293. [Fact]
  294. [SetupFakeDriver]
  295. public void ProcessKey_Down_Up_Right_Left_Home_End_PageDown_PageUp_F6 ()
  296. {
  297. TabView tv = GetTabView (out Tab tab1, out Tab tab2);
  298. tv.Width = 7;
  299. tv.Height = 5;
  300. var btn = new Button
  301. {
  302. Id = "btn",
  303. Y = Pos.Bottom (tv) + 1,
  304. Height = 1,
  305. Width = 7,
  306. Text = "Ok"
  307. };
  308. Toplevel top = new ();
  309. top.Add (tv, btn);
  310. Application.Begin (top);
  311. // Is the selected tab view hosting focused
  312. Assert.Equal (tab1, tv.SelectedTab);
  313. Assert.Equal (tv, top.Focused);
  314. Assert.Equal (tv.MostFocused, top.Focused.MostFocused);
  315. Assert.Equal (tv.SelectedTab.View, top.Focused.MostFocused);
  316. // Press the cursor up key to focus the selected tab
  317. Assert.True (Application.RaiseKeyDownEvent (Key.CursorUp));
  318. Application.LayoutAndDraw ();
  319. // Is the selected tab focused
  320. Assert.Equal (tab1, tv.SelectedTab);
  321. Assert.Equal (tv, top.Focused);
  322. Assert.Equal (tv.MostFocused, top.Focused.MostFocused);
  323. Tab oldChanged = null;
  324. Tab newChanged = null;
  325. tv.SelectedTabChanged += (s, e) =>
  326. {
  327. oldChanged = e.OldTab;
  328. newChanged = e.NewTab;
  329. };
  330. // Press the cursor right key to select the next tab
  331. Assert.True (Application.RaiseKeyDownEvent (Key.CursorRight));
  332. Application.LayoutAndDraw ();
  333. Assert.Equal (tab1, oldChanged);
  334. Assert.Equal (tab2, newChanged);
  335. Assert.Equal (tab2, tv.SelectedTab);
  336. Assert.Equal (tv, top.Focused);
  337. Assert.Equal (tv.MostFocused, top.Focused.MostFocused);
  338. // Press the cursor down key. Since the selected tab has no focusable views, the focus should move to the next view in the toplevel
  339. Assert.True (Application.RaiseKeyDownEvent (Key.CursorDown));
  340. Assert.Equal (tab2, tv.SelectedTab);
  341. Assert.Equal (btn, top.MostFocused);
  342. // Add a focusable subview to Selected Tab View which is a Label with CanFocus as false
  343. var btnSubView = new View ()
  344. {
  345. Id = "btnSubView",
  346. Title = "_Subview",
  347. CanFocus = true
  348. };
  349. tv.SelectedTab.View.Add (btnSubView);
  350. Assert.False (tv.SelectedTab.View.CanFocus);
  351. // Press cursor up. Should focus the subview in the selected tab.
  352. Assert.True (Application.RaiseKeyDownEvent (Key.CursorUp));
  353. Assert.Equal (tab2, tv.SelectedTab);
  354. Assert.NotEqual (btnSubView, top.MostFocused);
  355. Assert.Equal (tab2, top.MostFocused);
  356. tv.SelectedTab.View.CanFocus = true;
  357. Assert.True (Application.RaiseKeyDownEvent (Key.CursorDown));
  358. Assert.Equal (tab2, tv.SelectedTab);
  359. Assert.Equal (btnSubView, top.MostFocused);
  360. Assert.True (Application.RaiseKeyDownEvent (Key.CursorUp));
  361. // TabRowView now has TabGroup which only F6 is allowed
  362. Assert.NotEqual (tab2, top.MostFocused);
  363. Assert.Equal (btn, top.MostFocused);
  364. Assert.True (Application.RaiseKeyDownEvent (Key.CursorUp));
  365. Assert.Equal (btnSubView, top.MostFocused);
  366. Assert.True (Application.RaiseKeyDownEvent (Key.F6));
  367. Assert.Equal (tab2, top.MostFocused);
  368. // Press the cursor down key twice.
  369. Assert.True (Application.RaiseKeyDownEvent (Key.CursorDown));
  370. Assert.True (Application.RaiseKeyDownEvent (Key.CursorDown));
  371. Assert.Equal (btn, top.MostFocused);
  372. // Press the cursor down key again will focus next view in the toplevel, which is the TabView
  373. Assert.True (Application.RaiseKeyDownEvent (Key.CursorDown));
  374. Assert.Equal (tab2, tv.SelectedTab);
  375. Assert.Equal (tv, top.Focused);
  376. // Due to the RestoreFocus method prioritize the _previouslyFocused, so btnSubView will be focused again
  377. Assert.Equal (btnSubView, tv.MostFocused);
  378. // Press the cursor up key to focus the selected tab which it's the only way to do that
  379. Assert.True (Application.RaiseKeyDownEvent (Key.CursorUp));
  380. Assert.Equal (tab2, tv.SelectedTab);
  381. Assert.Equal (btn, top.Focused);
  382. Assert.True (Application.RaiseKeyDownEvent (Key.CursorUp));
  383. Assert.Equal (tv, top.Focused);
  384. Assert.Equal (btnSubView, top.MostFocused);
  385. Assert.True (Application.RaiseKeyDownEvent (Key.F6));
  386. Assert.Equal (tv, top.Focused);
  387. Assert.Equal (tab2, top.Focused.MostFocused);
  388. Assert.Equal (tv.MostFocused, top.Focused.MostFocused);
  389. // Press the cursor left key to select the previous tab
  390. Assert.True (Application.RaiseKeyDownEvent (Key.CursorLeft));
  391. Application.LayoutAndDraw ();
  392. Assert.Equal (tab2, oldChanged);
  393. Assert.Equal (tab1, newChanged);
  394. Assert.Equal (tab1, tv.SelectedTab);
  395. Assert.Equal (tv, top.Focused);
  396. Assert.Equal (tv.MostFocused, top.Focused.MostFocused);
  397. Assert.Equal (tab1, top.Focused.MostFocused);
  398. // Press the end key to select the last tab
  399. Assert.True (Application.RaiseKeyDownEvent (Key.End));
  400. Application.LayoutAndDraw ();
  401. Assert.Equal (tab1, oldChanged);
  402. Assert.Equal (tab2, newChanged);
  403. Assert.Equal (tab2, tv.SelectedTab);
  404. Assert.Equal (tv, top.Focused);
  405. Assert.Equal (tv.MostFocused, top.Focused.MostFocused);
  406. // Press the home key to select the first tab
  407. Assert.True (Application.RaiseKeyDownEvent (Key.Home));
  408. Application.LayoutAndDraw ();
  409. Assert.Equal (tab2, oldChanged);
  410. Assert.Equal (tab1, newChanged);
  411. Assert.Equal (tab1, tv.SelectedTab);
  412. Assert.Equal (tv, top.Focused);
  413. Assert.Equal (tv.MostFocused, top.Focused.MostFocused);
  414. // Press the page down key to select the next set of tabs
  415. Assert.True (Application.RaiseKeyDownEvent (Key.PageDown));
  416. Application.LayoutAndDraw ();
  417. Assert.Equal (tab1, oldChanged);
  418. Assert.Equal (tab2, newChanged);
  419. Assert.Equal (tab2, tv.SelectedTab);
  420. Assert.Equal (tv, top.Focused);
  421. Assert.Equal (tv.MostFocused, top.Focused.MostFocused);
  422. // Press the page up key to select the previous set of tabs
  423. Assert.True (Application.RaiseKeyDownEvent (Key.PageUp));
  424. Application.LayoutAndDraw ();
  425. Assert.Equal (tab2, oldChanged);
  426. Assert.Equal (tab1, newChanged);
  427. Assert.Equal (tab1, tv.SelectedTab);
  428. Assert.Equal (tv, top.Focused);
  429. Assert.Equal (tv.MostFocused, top.Focused.MostFocused);
  430. top.Dispose ();
  431. }
  432. [Fact]
  433. public void RemoveAllTabs_ClearsSelection ()
  434. {
  435. TabView tv = GetTabView (out Tab tab1, out Tab tab2);
  436. tv.SelectedTab = tab1;
  437. tv.RemoveTab (tab1);
  438. tv.RemoveTab (tab2);
  439. Assert.Null (tv.SelectedTab);
  440. // Shutdown must be called to safely clean up Application if Init has been called
  441. Application.Shutdown ();
  442. }
  443. [Fact]
  444. public void RemoveTab_ChangesSelection ()
  445. {
  446. TabView tv = GetTabView (out Tab tab1, out Tab tab2);
  447. tv.SelectedTab = tab1;
  448. tv.RemoveTab (tab1);
  449. Assert.Equal (tab2, tv.SelectedTab);
  450. // Shutdown must be called to safely clean up Application if Init has been called
  451. Application.Shutdown ();
  452. }
  453. [Fact]
  454. public void RemoveTab_MultipleCalls_NotAnError ()
  455. {
  456. TabView tv = GetTabView (out Tab tab1, out Tab tab2);
  457. tv.SelectedTab = tab1;
  458. // Repeated calls to remove a tab that is not part of
  459. // the collection should be ignored
  460. tv.RemoveTab (tab1);
  461. tv.RemoveTab (tab1);
  462. tv.RemoveTab (tab1);
  463. tv.RemoveTab (tab1);
  464. Assert.Equal (tab2, tv.SelectedTab);
  465. // Shutdown must be called to safely clean up Application if Init has been called
  466. Application.Shutdown ();
  467. }
  468. [Fact]
  469. public void SelectedTabChanged_Called ()
  470. {
  471. TabView tv = GetTabView (out Tab tab1, out Tab tab2);
  472. tv.SelectedTab = tab1;
  473. Tab oldTab = null;
  474. Tab newTab = null;
  475. var called = 0;
  476. tv.SelectedTabChanged += (s, e) =>
  477. {
  478. oldTab = e.OldTab;
  479. newTab = e.NewTab;
  480. called++;
  481. };
  482. tv.SelectedTab = tab2;
  483. Assert.Equal (1, called);
  484. Assert.Equal (tab1, oldTab);
  485. Assert.Equal (tab2, newTab);
  486. // Shutdown must be called to safely clean up Application if Init has been called
  487. Application.Shutdown ();
  488. }
  489. [Fact]
  490. [SetupFakeDriver]
  491. public void ShowTopLine_False_TabsOnBottom_False_TestTabView_Width3 ()
  492. {
  493. TabView tv = GetTabView (out _, out _, false);
  494. tv.Width = 3;
  495. tv.Height = 5;
  496. tv.Style = new () { ShowTopLine = false };
  497. tv.ApplyStyleChanges ();
  498. tv.Layout ();
  499. tv.Draw ();
  500. TestHelpers.AssertDriverContentsWithFrameAre (
  501. @"
  502. ││
  503. │╰►
  504. │h│
  505. │ │
  506. └─┘",
  507. output
  508. );
  509. }
  510. [Fact]
  511. [SetupFakeDriver]
  512. public void ShowTopLine_False_TabsOnBottom_False_TestTabView_Width4 ()
  513. {
  514. TabView tv = GetTabView (out _, out _, false);
  515. tv.Width = 4;
  516. tv.Height = 5;
  517. tv.Style = new () { ShowTopLine = false };
  518. tv.ApplyStyleChanges ();
  519. tv.Layout ();
  520. tv.Draw ();
  521. TestHelpers.AssertDriverContentsWithFrameAre (
  522. @"
  523. │T│
  524. │ ╰►
  525. │hi│
  526. │ │
  527. └──┘",
  528. output
  529. );
  530. }
  531. [Fact]
  532. [SetupFakeDriver]
  533. public void ShowTopLine_False_TabsOnBottom_False_TestThinTabView_WithLongNames ()
  534. {
  535. TabView tv = GetTabView (out Tab tab1, out Tab tab2, false);
  536. tv.Width = 10;
  537. tv.Height = 5;
  538. tv.Style = new () { ShowTopLine = false };
  539. tv.ApplyStyleChanges ();
  540. // Test two tab names that fit
  541. tab1.DisplayText = "12";
  542. tab2.DisplayText = "13";
  543. // Ensures that the tab bar subview gets the bounds of the parent TabView
  544. tv.Layout ();
  545. tv.Draw ();
  546. TestHelpers.AssertDriverContentsWithFrameAre (
  547. @"
  548. │12│13│
  549. │ ╰──┴──╮
  550. │hi │
  551. │ │
  552. └────────┘",
  553. output
  554. );
  555. tv.SelectedTab = tab2;
  556. Assert.Equal (tab2, tv.Subviews.First (v => v.Id.Contains ("tabRowView")).MostFocused);
  557. tv.Layout ();
  558. View.SetClipToScreen ();
  559. tv.Draw ();
  560. TestHelpers.AssertDriverContentsWithFrameAre (
  561. @"
  562. │12│13│
  563. ├──╯ ╰──╮
  564. │hi2 │
  565. │ │
  566. └────────┘",
  567. output
  568. );
  569. tv.SelectedTab = tab1;
  570. // Test first tab name too long
  571. tab1.DisplayText = "12345678910";
  572. tab2.DisplayText = "13";
  573. tv.Layout ();
  574. View.SetClipToScreen ();
  575. tv.Draw ();
  576. TestHelpers.AssertDriverContentsWithFrameAre (
  577. @"
  578. │1234567│
  579. │ ╰►
  580. │hi │
  581. │ │
  582. └────────┘",
  583. output
  584. );
  585. //switch to tab2
  586. tv.SelectedTab = tab2;
  587. tv.Layout ();
  588. View.SetClipToScreen ();
  589. tv.Draw ();
  590. TestHelpers.AssertDriverContentsWithFrameAre (
  591. @"
  592. │13│
  593. ◄ ╰─────╮
  594. │hi2 │
  595. │ │
  596. └────────┘",
  597. output
  598. );
  599. // now make both tabs too long
  600. tab1.DisplayText = "12345678910";
  601. tab2.DisplayText = "abcdefghijklmnopq";
  602. tv.Layout ();
  603. View.SetClipToScreen ();
  604. tv.Draw ();
  605. TestHelpers.AssertDriverContentsWithFrameAre (
  606. @"
  607. │abcdefg│
  608. ◄ ╰╮
  609. │hi2 │
  610. │ │
  611. └────────┘",
  612. output
  613. );
  614. }
  615. [Fact]
  616. [SetupFakeDriver]
  617. public void ShowTopLine_False_TabsOnBottom_True_TestTabView_Width3 ()
  618. {
  619. TabView tv = GetTabView (out _, out _, false);
  620. tv.Width = 3;
  621. tv.Height = 5;
  622. tv.Style = new () { ShowTopLine = false, TabsOnBottom = true };
  623. tv.ApplyStyleChanges ();
  624. tv.Layout ();
  625. tv.Draw ();
  626. TestHelpers.AssertDriverContentsWithFrameAre (
  627. @"
  628. ┌─┐
  629. │h│
  630. │ │
  631. │╭►
  632. ││ ",
  633. output
  634. );
  635. }
  636. [Fact]
  637. [SetupFakeDriver]
  638. public void ShowTopLine_False_TabsOnBottom_True_TestTabView_Width4 ()
  639. {
  640. TabView tv = GetTabView (out _, out _, false);
  641. tv.Width = 4;
  642. tv.Height = 5;
  643. tv.Style = new () { ShowTopLine = false, TabsOnBottom = true };
  644. tv.ApplyStyleChanges ();
  645. tv.Layout ();
  646. tv.Draw ();
  647. TestHelpers.AssertDriverContentsWithFrameAre (
  648. @"
  649. ┌──┐
  650. │hi│
  651. │ │
  652. │ ╭►
  653. │T│ ",
  654. output
  655. );
  656. }
  657. [Fact]
  658. [SetupFakeDriver]
  659. public void ShowTopLine_False_TabsOnBottom_True_TestThinTabView_WithLongNames ()
  660. {
  661. TabView tv = GetTabView (out Tab tab1, out Tab tab2, false);
  662. tv.Width = 10;
  663. tv.Height = 5;
  664. tv.Style = new () { ShowTopLine = false, TabsOnBottom = true };
  665. tv.ApplyStyleChanges ();
  666. tv.Layout ();
  667. // Test two tab names that fit
  668. tab1.DisplayText = "12";
  669. tab2.DisplayText = "13";
  670. tv.Layout ();
  671. tv.Draw ();
  672. TestHelpers.AssertDriverContentsWithFrameAre (
  673. @"
  674. ┌────────┐
  675. │hi │
  676. │ │
  677. │ ╭──┬──╯
  678. │12│13│ ",
  679. output
  680. );
  681. tv.SelectedTab = tab2;
  682. Assert.Equal (tab2, tv.Subviews.First (v => v.Id.Contains ("tabRowView")).MostFocused);
  683. tv.Layout ();
  684. View.SetClipToScreen ();
  685. tv.Draw ();
  686. TestHelpers.AssertDriverContentsWithFrameAre (
  687. @"
  688. ┌────────┐
  689. │hi2 │
  690. │ │
  691. ├──╮ ╭──╯
  692. │12│13│ ",
  693. output
  694. );
  695. tv.SelectedTab = tab1;
  696. // Test first tab name too long
  697. tab1.DisplayText = "12345678910";
  698. tab2.DisplayText = "13";
  699. tv.Layout ();
  700. View.SetClipToScreen ();
  701. tv.Draw ();
  702. TestHelpers.AssertDriverContentsWithFrameAre (
  703. @"
  704. ┌────────┐
  705. │hi │
  706. │ │
  707. │ ╭►
  708. │1234567│ ",
  709. output
  710. );
  711. //switch to tab2
  712. tv.SelectedTab = tab2;
  713. tv.Layout ();
  714. View.SetClipToScreen ();
  715. tv.Draw ();
  716. TestHelpers.AssertDriverContentsWithFrameAre (
  717. @"
  718. ┌────────┐
  719. │hi2 │
  720. │ │
  721. ◄ ╭─────╯
  722. │13│ ",
  723. output
  724. );
  725. // now make both tabs too long
  726. tab1.DisplayText = "12345678910";
  727. tab2.DisplayText = "abcdefghijklmnopq";
  728. tv.Layout ();
  729. View.SetClipToScreen ();
  730. tv.Draw ();
  731. TestHelpers.AssertDriverContentsWithFrameAre (
  732. @"
  733. ┌────────┐
  734. │hi2 │
  735. │ │
  736. ◄ ╭╯
  737. │abcdefg│ ",
  738. output
  739. );
  740. }
  741. [Fact]
  742. [SetupFakeDriver]
  743. public void ShowTopLine_True_TabsOnBottom_False_TestTabView_Width3 ()
  744. {
  745. TabView tv = GetTabView (out _, out _, false);
  746. tv.Width = 3;
  747. tv.Height = 5;
  748. tv.Layout ();
  749. tv.Draw ();
  750. TestHelpers.AssertDriverContentsWithFrameAre (
  751. @"
  752. ╭╮
  753. ││
  754. │╰►
  755. │h│
  756. └─┘",
  757. output
  758. );
  759. }
  760. [Fact]
  761. [SetupFakeDriver]
  762. public void ShowTopLine_True_TabsOnBottom_False_TestTabView_Width4 ()
  763. {
  764. TabView tv = GetTabView (out _, out _, false);
  765. tv.Width = 4;
  766. tv.Height = 5;
  767. tv.Layout ();
  768. View.SetClipToScreen ();
  769. tv.Draw ();
  770. TestHelpers.AssertDriverContentsWithFrameAre (
  771. @"
  772. ╭─╮
  773. │T│
  774. │ ╰►
  775. │hi│
  776. └──┘",
  777. output
  778. );
  779. }
  780. [Fact]
  781. [SetupFakeDriver]
  782. public void ShowTopLine_True_TabsOnBottom_False_TestThinTabView_WithLongNames ()
  783. {
  784. TabView tv = GetTabView (out Tab tab1, out Tab tab2, false);
  785. tv.Width = 10;
  786. tv.Height = 5;
  787. // Test two tab names that fit
  788. tab1.DisplayText = "12";
  789. tab2.DisplayText = "13";
  790. tv.Layout ();
  791. tv.Draw ();
  792. TestHelpers.AssertDriverContentsWithFrameAre (
  793. @"
  794. ╭──┬──╮
  795. │12│13│
  796. │ ╰──┴──╮
  797. │hi │
  798. └────────┘",
  799. output
  800. );
  801. tv.SelectedTab = tab2;
  802. tv.Layout ();
  803. View.SetClipToScreen ();
  804. tv.Draw ();
  805. TestHelpers.AssertDriverContentsWithFrameAre (
  806. @"
  807. ╭──┬──╮
  808. │12│13│
  809. ├──╯ ╰──╮
  810. │hi2 │
  811. └────────┘",
  812. output
  813. );
  814. tv.SelectedTab = tab1;
  815. // Test first tab name too long
  816. tab1.DisplayText = "12345678910";
  817. tab2.DisplayText = "13";
  818. tv.Layout ();
  819. View.SetClipToScreen ();
  820. tv.Draw ();
  821. TestHelpers.AssertDriverContentsWithFrameAre (
  822. @"
  823. ╭───────╮
  824. │1234567│
  825. │ ╰►
  826. │hi │
  827. └────────┘",
  828. output
  829. );
  830. //switch to tab2
  831. tv.SelectedTab = tab2;
  832. tv.Layout ();
  833. View.SetClipToScreen ();
  834. tv.Draw ();
  835. TestHelpers.AssertDriverContentsWithFrameAre (
  836. @"
  837. ╭──╮
  838. │13│
  839. ◄ ╰─────╮
  840. │hi2 │
  841. └────────┘",
  842. output
  843. );
  844. // now make both tabs too long
  845. tab1.DisplayText = "12345678910";
  846. tab2.DisplayText = "abcdefghijklmnopq";
  847. tv.Layout ();
  848. View.SetClipToScreen ();
  849. tv.Draw ();
  850. TestHelpers.AssertDriverContentsWithFrameAre (
  851. @"
  852. ╭───────╮
  853. │abcdefg│
  854. ◄ ╰╮
  855. │hi2 │
  856. └────────┘",
  857. output
  858. );
  859. }
  860. [Fact]
  861. [SetupFakeDriver]
  862. public void ShowTopLine_True_TabsOnBottom_False_With_Unicode ()
  863. {
  864. TabView tv = GetTabView (out Tab tab1, out Tab tab2, false);
  865. tv.Width = 20;
  866. tv.Height = 5;
  867. tab1.DisplayText = "Tab0";
  868. tab2.DisplayText = "Les Mise" + char.ConvertFromUtf32 (int.Parse ("0301", NumberStyles.HexNumber)) + "rables";
  869. tv.Layout ();
  870. tv.Draw ();
  871. TestHelpers.AssertDriverContentsWithFrameAre (
  872. @"
  873. ╭────╮
  874. │Tab0│
  875. │ ╰─────────────►
  876. │hi │
  877. └──────────────────┘",
  878. output
  879. );
  880. tv.SelectedTab = tab2;
  881. tv.Layout ();
  882. View.SetClipToScreen ();
  883. tv.Draw ();
  884. TestHelpers.AssertDriverContentsWithFrameAre (
  885. @"
  886. ╭──────────────╮
  887. │Les Misérables│
  888. ◄ ╰───╮
  889. │hi2 │
  890. └──────────────────┘",
  891. output
  892. );
  893. }
  894. [Fact]
  895. [SetupFakeDriver]
  896. public void ShowTopLine_True_TabsOnBottom_True_TestTabView_Width3 ()
  897. {
  898. TabView tv = GetTabView (out _, out _, false);
  899. tv.Width = 3;
  900. tv.Height = 5;
  901. tv.Style = new () { TabsOnBottom = true };
  902. tv.ApplyStyleChanges ();
  903. tv.Layout ();
  904. tv.Draw ();
  905. TestHelpers.AssertDriverContentsWithFrameAre (
  906. @"
  907. ┌─┐
  908. │h│
  909. │╭►
  910. ││
  911. ╰╯ ",
  912. output
  913. );
  914. }
  915. [Fact]
  916. [SetupFakeDriver]
  917. public void ShowTopLine_True_TabsOnBottom_True_TestTabView_Width4 ()
  918. {
  919. TabView tv = GetTabView (out _, out _, false);
  920. tv.Width = 4;
  921. tv.Height = 5;
  922. tv.Style = new () { TabsOnBottom = true };
  923. tv.ApplyStyleChanges ();
  924. tv.Layout ();
  925. tv.Draw ();
  926. TestHelpers.AssertDriverContentsWithFrameAre (
  927. @"
  928. ┌──┐
  929. │hi│
  930. │ ╭►
  931. │T│
  932. ╰─╯ ",
  933. output
  934. );
  935. }
  936. [Fact]
  937. [SetupFakeDriver]
  938. public void ShowTopLine_True_TabsOnBottom_True_TestThinTabView_WithLongNames ()
  939. {
  940. TabView tv = GetTabView (out Tab tab1, out Tab tab2, false);
  941. tv.Width = 10;
  942. tv.Height = 5;
  943. tv.Style = new () { TabsOnBottom = true };
  944. tv.ApplyStyleChanges ();
  945. tv.Layout ();
  946. // Test two tab names that fit
  947. tab1.DisplayText = "12";
  948. tab2.DisplayText = "13";
  949. tv.Layout ();
  950. tv.Draw ();
  951. TestHelpers.AssertDriverContentsWithFrameAre (
  952. @"
  953. ┌────────┐
  954. │hi │
  955. │ ╭──┬──╯
  956. │12│13│
  957. ╰──┴──╯ ",
  958. output
  959. );
  960. // Test first tab name too long
  961. tab1.DisplayText = "12345678910";
  962. tab2.DisplayText = "13";
  963. tv.Layout ();
  964. View.SetClipToScreen ();
  965. tv.Draw ();
  966. TestHelpers.AssertDriverContentsWithFrameAre (
  967. @"
  968. ┌────────┐
  969. │hi │
  970. │ ╭►
  971. │1234567│
  972. ╰───────╯ ",
  973. output
  974. );
  975. //switch to tab2
  976. tv.SelectedTab = tab2;
  977. tv.Layout ();
  978. View.SetClipToScreen ();
  979. tv.Draw ();
  980. TestHelpers.AssertDriverContentsWithFrameAre (
  981. @"
  982. ┌────────┐
  983. │hi2 │
  984. ◄ ╭─────╯
  985. │13│
  986. ╰──╯ ",
  987. output
  988. );
  989. // now make both tabs too long
  990. tab1.DisplayText = "12345678910";
  991. tab2.DisplayText = "abcdefghijklmnopq";
  992. tv.Layout ();
  993. View.SetClipToScreen ();
  994. tv.Draw ();
  995. TestHelpers.AssertDriverContentsWithFrameAre (
  996. @"
  997. ┌────────┐
  998. │hi2 │
  999. ◄ ╭╯
  1000. │abcdefg│
  1001. ╰───────╯ ",
  1002. output
  1003. );
  1004. }
  1005. [Fact]
  1006. [SetupFakeDriver]
  1007. public void ShowTopLine_True_TabsOnBottom_True_With_Unicode ()
  1008. {
  1009. TabView tv = GetTabView (out Tab tab1, out Tab tab2, false);
  1010. tv.Width = 20;
  1011. tv.Height = 5;
  1012. tv.Style = new () { TabsOnBottom = true };
  1013. tv.ApplyStyleChanges ();
  1014. tab1.DisplayText = "Tab0";
  1015. tab2.DisplayText = "Les Mise" + char.ConvertFromUtf32 (int.Parse ("0301", NumberStyles.HexNumber)) + "rables";
  1016. tv.Layout ();
  1017. tv.Draw ();
  1018. TestHelpers.AssertDriverContentsWithFrameAre (
  1019. @"
  1020. ┌──────────────────┐
  1021. │hi │
  1022. │ ╭─────────────►
  1023. │Tab0│
  1024. ╰────╯ ",
  1025. output
  1026. );
  1027. tv.SelectedTab = tab2;
  1028. tv.Layout ();
  1029. View.SetClipToScreen ();
  1030. tv.Draw ();
  1031. TestHelpers.AssertDriverContentsWithFrameAre (
  1032. @"
  1033. ┌──────────────────┐
  1034. │hi2 │
  1035. ◄ ╭───╯
  1036. │Les Misérables│
  1037. ╰──────────────╯ ",
  1038. output
  1039. );
  1040. }
  1041. [Fact]
  1042. public void SwitchTabBy_NormalUsage ()
  1043. {
  1044. TabView tv = GetTabView (out Tab tab1, out Tab tab2);
  1045. Tab tab3;
  1046. Tab tab4;
  1047. Tab tab5;
  1048. tv.AddTab (tab3 = new (), false);
  1049. tv.AddTab (tab4 = new (), false);
  1050. tv.AddTab (tab5 = new (), false);
  1051. tv.SelectedTab = tab1;
  1052. var called = 0;
  1053. tv.SelectedTabChanged += (s, e) => { called++; };
  1054. tv.SwitchTabBy (1);
  1055. Assert.Equal (1, called);
  1056. Assert.Equal (tab2, tv.SelectedTab);
  1057. //reset called counter
  1058. called = 0;
  1059. // go right 2
  1060. tv.SwitchTabBy (2);
  1061. // even though we go right 2 indexes the event should only be called once
  1062. Assert.Equal (1, called);
  1063. Assert.Equal (tab4, tv.SelectedTab);
  1064. // Shutdown must be called to safely clean up Application if Init has been called
  1065. Application.Shutdown ();
  1066. }
  1067. [Fact]
  1068. public void SwitchTabBy_OutOfTabsRange ()
  1069. {
  1070. TabView tv = GetTabView (out Tab tab1, out Tab tab2);
  1071. tv.SelectedTab = tab1;
  1072. tv.SwitchTabBy (500);
  1073. Assert.Equal (tab2, tv.SelectedTab);
  1074. tv.SwitchTabBy (-500);
  1075. Assert.Equal (tab1, tv.SelectedTab);
  1076. // Shutdown must be called to safely clean up Application if Init has been called
  1077. Application.Shutdown ();
  1078. }
  1079. [Fact]
  1080. public void RemoveTab_ThatHasFocus ()
  1081. {
  1082. TabView tv = GetTabView (out Tab _, out Tab tab2);
  1083. tv.SelectedTab = tab2;
  1084. tab2.HasFocus = true;
  1085. Assert.Equal (2, tv.Tabs.Count);
  1086. foreach (Tab t in tv.Tabs.ToArray ())
  1087. {
  1088. tv.RemoveTab (t);
  1089. }
  1090. Assert.Empty (tv.Tabs);
  1091. // Shutdown must be called to safely clean up Application if Init has been called
  1092. Application.Shutdown ();
  1093. }
  1094. [Fact]
  1095. [SetupFakeDriver]
  1096. public void Add_Three_TabsOnTop_ChangesTab ()
  1097. {
  1098. TabView tv = GetTabView (out Tab tab1, out Tab tab2, false);
  1099. Tab tab3;
  1100. tv.AddTab (
  1101. tab3 = new () { Id = "tab3", DisplayText = "Tab3", View = new TextView { Id = "tab3.TextView", Width = 3, Height = 1, Text = "hi3" } },
  1102. false);
  1103. tv.Width = 20;
  1104. tv.Height = 5;
  1105. tv.Layout ();
  1106. tv.Draw ();
  1107. Assert.Equal (tab1, tv.SelectedTab);
  1108. TestHelpers.AssertDriverContentsAre (
  1109. @"
  1110. ╭────┬────┬────╮
  1111. │Tab1│Tab2│Tab3│
  1112. │ ╰────┴────┴───╮
  1113. │hi │
  1114. └──────────────────┘
  1115. ",
  1116. output
  1117. );
  1118. tv.SelectedTab = tab2;
  1119. tv.Layout ();
  1120. View.SetClipToScreen ();
  1121. tv.Draw ();
  1122. TestHelpers.AssertDriverContentsWithFrameAre (
  1123. @"
  1124. ╭────┬────┬────╮
  1125. │Tab1│Tab2│Tab3│
  1126. ├────╯ ╰────┴───╮
  1127. │hi2 │
  1128. └──────────────────┘
  1129. ",
  1130. output
  1131. );
  1132. tv.SelectedTab = tab3;
  1133. tv.Layout ();
  1134. View.SetClipToScreen ();
  1135. tv.Draw ();
  1136. TestHelpers.AssertDriverContentsWithFrameAre (
  1137. @"
  1138. ╭────┬────┬────╮
  1139. │Tab1│Tab2│Tab3│
  1140. ├────┴────╯ ╰───╮
  1141. │hi3 │
  1142. └──────────────────┘
  1143. ",
  1144. output
  1145. );
  1146. }
  1147. [Fact]
  1148. [SetupFakeDriver]
  1149. public void Add_Three_TabsOnBottom_ChangesTab ()
  1150. {
  1151. TabView tv = GetTabView (out Tab tab1, out Tab tab2, false);
  1152. Tab tab3;
  1153. tv.AddTab (
  1154. tab3 = new () { Id = "tab3", DisplayText = "Tab3", View = new TextView { Id = "tab3.TextView", Width = 3, Height = 1, Text = "hi3" } },
  1155. false);
  1156. tv.Width = 20;
  1157. tv.Height = 5;
  1158. tv.Style = new () { TabsOnBottom = true };
  1159. tv.ApplyStyleChanges ();
  1160. tv.Layout ();
  1161. tv.Draw ();
  1162. Assert.Equal (tab1, tv.SelectedTab);
  1163. TestHelpers.AssertDriverContentsAre (
  1164. @"
  1165. ┌──────────────────┐
  1166. │hi │
  1167. │ ╭────┬────┬───╯
  1168. │Tab1│Tab2│Tab3│
  1169. ╰────┴────┴────╯
  1170. ",
  1171. output
  1172. );
  1173. tv.SelectedTab = tab2;
  1174. tv.Layout ();
  1175. View.SetClipToScreen ();
  1176. tv.Draw ();
  1177. TestHelpers.AssertDriverContentsWithFrameAre (
  1178. @"
  1179. ┌──────────────────┐
  1180. │hi2 │
  1181. ├────╮ ╭────┬───╯
  1182. │Tab1│Tab2│Tab3│
  1183. ╰────┴────┴────╯
  1184. ",
  1185. output
  1186. );
  1187. tv.SelectedTab = tab3;
  1188. tv.Layout ();
  1189. View.SetClipToScreen ();
  1190. tv.Draw ();
  1191. TestHelpers.AssertDriverContentsWithFrameAre (
  1192. @"
  1193. ┌──────────────────┐
  1194. │hi3 │
  1195. ├────┬────╮ ╭───╯
  1196. │Tab1│Tab2│Tab3│
  1197. ╰────┴────┴────╯
  1198. ",
  1199. output
  1200. );
  1201. }
  1202. [Fact]
  1203. [SetupFakeDriver]
  1204. public void Tab_Get_Focus_By_Press_F6 ()
  1205. {
  1206. TabView tv = GetTabView (out Tab tab1, out Tab tab2);
  1207. tv.Width = 20;
  1208. tv.Height = 5;
  1209. Toplevel top = new ();
  1210. top.Add (tv);
  1211. Application.Begin (top);
  1212. Assert.False (tab1.HasFocus);
  1213. Assert.True (Application.RaiseKeyDownEvent (Key.F6));
  1214. Assert.True (tab1.HasFocus);
  1215. top.Dispose ();
  1216. }
  1217. [Fact]
  1218. [SetupFakeDriver]
  1219. public void Mouse_Wheel_Changes_Tab ()
  1220. {
  1221. TabView tv = GetTabView (out Tab tab1, out Tab tab2);
  1222. tv.Width = 20;
  1223. tv.Height = 5;
  1224. Toplevel top = new ();
  1225. top.Add (tv);
  1226. Application.Begin (top);
  1227. Assert.False (tab1.HasFocus);
  1228. Application.RaiseMouseEvent (new () { Position = new (1, 1), Flags = MouseFlags.WheeledDown });
  1229. Assert.True (tab2.HasFocus);
  1230. Application.RaiseMouseEvent (new () { Position = new (1, 1), Flags = MouseFlags.WheeledUp });
  1231. Assert.True (tab1.HasFocus);
  1232. Application.RaiseMouseEvent (new () { Position = new (1, 1), Flags = MouseFlags.WheeledRight });
  1233. Assert.True (tab2.HasFocus);
  1234. Application.RaiseMouseEvent (new () { Position = new (1, 1), Flags = MouseFlags.WheeledLeft });
  1235. Assert.True (tab1.HasFocus);
  1236. top.Dispose ();
  1237. }
  1238. private TabView GetTabView () { return GetTabView (out _, out _); }
  1239. private TabView GetTabView (out Tab tab1, out Tab tab2, bool initFakeDriver = true)
  1240. {
  1241. if (initFakeDriver)
  1242. {
  1243. InitFakeDriver ();
  1244. }
  1245. var tv = new TabView () { Id = "tv " };
  1246. tv.BeginInit ();
  1247. tv.EndInit ();
  1248. tv.ColorScheme = new ();
  1249. tv.AddTab (
  1250. tab1 = new () { Id = "tab1", DisplayText = "Tab1", View = new TextField { Id = "tab1.TextField", Width = 2, Text = "hi" } },
  1251. false
  1252. );
  1253. tv.AddTab (tab2 = new () { Id = "tab2", DisplayText = "Tab2", View = new Label { Id = "tab1.Label", Text = "hi2" } }, false);
  1254. return tv;
  1255. }
  1256. private void InitFakeDriver ()
  1257. {
  1258. ConfigurationManager.Locations = ConfigLocations.Default;
  1259. ConfigurationManager.Reset ();
  1260. var driver = new FakeDriver ();
  1261. Application.Init (driver);
  1262. driver.Init ();
  1263. }
  1264. }