TileViewTests.cs 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066
  1. using System;
  2. using System.Linq;
  3. using Terminal.Gui;
  4. using Terminal.Gui.Graphs;
  5. using Xunit;
  6. using Xunit.Abstractions;
  7. namespace UnitTests {
  8. public class TileViewTests {
  9. readonly ITestOutputHelper output;
  10. public TileViewTests (ITestOutputHelper output)
  11. {
  12. this.output = output;
  13. }
  14. [Fact, AutoInitShutdown]
  15. public void TestTileView_Vertical ()
  16. {
  17. var tileView = Get11By3TileView (out var line);
  18. tileView.Redraw (tileView.Bounds);
  19. string looksLike =
  20. @"
  21. 11111│22222
  22. 11111│22222
  23. │ ";
  24. TestHelpers.AssertDriverContentsAre (looksLike, output);
  25. // Keyboard movement on splitter should have no effect if it is not focused
  26. line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()));
  27. tileView.SetNeedsDisplay ();
  28. tileView.Redraw (tileView.Bounds);
  29. TestHelpers.AssertDriverContentsAre (looksLike, output);
  30. }
  31. [Fact, AutoInitShutdown]
  32. public void TestTileView_Vertical_WithBorder ()
  33. {
  34. var tileView = Get11By3TileView (out var line, true);
  35. tileView.Redraw (tileView.Bounds);
  36. string looksLike =
  37. @"
  38. ┌────┬────┐
  39. │1111│2222│
  40. └────┴────┘";
  41. TestHelpers.AssertDriverContentsAre (looksLike, output);
  42. // Keyboard movement on splitter should have no effect if it is not focused
  43. line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()));
  44. tileView.SetNeedsDisplay ();
  45. tileView.Redraw (tileView.Bounds);
  46. TestHelpers.AssertDriverContentsAre (looksLike, output);
  47. }
  48. [Fact, AutoInitShutdown]
  49. public void TestTileView_Vertical_Focused ()
  50. {
  51. var tileView = Get11By3TileView (out var line);
  52. SetInputFocusLine (tileView);
  53. tileView.Redraw (tileView.Bounds);
  54. string looksLike =
  55. @"
  56. 11111│22222
  57. 11111◊22222
  58. │ ";
  59. TestHelpers.AssertDriverContentsAre (looksLike, output);
  60. // Now while focused move the splitter 1 unit right
  61. line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()));
  62. tileView.Redraw (tileView.Bounds);
  63. looksLike =
  64. @"
  65. 111111│2222
  66. 111111◊2222
  67. │ ";
  68. TestHelpers.AssertDriverContentsAre (looksLike, output);
  69. // and 2 to the left
  70. line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ()));
  71. line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ()));
  72. tileView.Redraw (tileView.Bounds);
  73. looksLike =
  74. @"
  75. 1111│222222
  76. 1111◊222222
  77. │ ";
  78. TestHelpers.AssertDriverContentsAre (looksLike, output);
  79. }
  80. [Fact, AutoInitShutdown]
  81. public void TestTileView_Vertical_Focused_WithBorder ()
  82. {
  83. var tileView = Get11By3TileView (out var line, true);
  84. SetInputFocusLine (tileView);
  85. tileView.Redraw (tileView.Bounds);
  86. string looksLike =
  87. @"
  88. ┌────┬────┐
  89. │1111◊2222│
  90. └────┴────┘";
  91. TestHelpers.AssertDriverContentsAre (looksLike, output);
  92. // Now while focused move the splitter 1 unit right
  93. line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()));
  94. tileView.Redraw (tileView.Bounds);
  95. looksLike =
  96. @"
  97. ┌─────┬───┐
  98. │11111◊222│
  99. └─────┴───┘";
  100. TestHelpers.AssertDriverContentsAre (looksLike, output);
  101. // and 2 to the left
  102. line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ()));
  103. line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ()));
  104. tileView.Redraw (tileView.Bounds);
  105. looksLike =
  106. @"
  107. ┌───┬─────┐
  108. │111◊22222│
  109. └───┴─────┘";
  110. TestHelpers.AssertDriverContentsAre (looksLike, output);
  111. }
  112. [Fact, AutoInitShutdown]
  113. public void TestTileView_Vertical_Focused_50PercentSplit ()
  114. {
  115. var tileView = Get11By3TileView (out var line);
  116. SetInputFocusLine (tileView);
  117. tileView.SetSplitterPos(0,Pos.Percent (50));
  118. Assert.IsType<Pos.PosFactor> (tileView.SplitterDistances.ElementAt(0));
  119. tileView.Redraw (tileView.Bounds);
  120. string looksLike =
  121. @"
  122. 11111│22222
  123. 11111◊22222
  124. │ ";
  125. TestHelpers.AssertDriverContentsAre (looksLike, output);
  126. // Now while focused move the splitter 1 unit right
  127. line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()));
  128. tileView.Redraw (tileView.Bounds);
  129. looksLike =
  130. @"
  131. 111111│2222
  132. 111111◊2222
  133. │ ";
  134. TestHelpers.AssertDriverContentsAre (looksLike, output);
  135. // Even when moving the splitter location it should stay a Percentage based one
  136. Assert.IsType<Pos.PosFactor> (tileView.SplitterDistances.ElementAt(0));
  137. // and 2 to the left
  138. line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ()));
  139. line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ()));
  140. tileView.Redraw (tileView.Bounds);
  141. looksLike =
  142. @"
  143. 1111│222222
  144. 1111◊222222
  145. │ ";
  146. TestHelpers.AssertDriverContentsAre (looksLike, output);
  147. // Even when moving the splitter location it should stay a Percentage based one
  148. Assert.IsType<Pos.PosFactor> (tileView.SplitterDistances.ElementAt (0));
  149. }
  150. [Fact, AutoInitShutdown]
  151. public void TestTileView_Horizontal ()
  152. {
  153. var tileView = Get11By3TileView (out var line);
  154. tileView.Orientation = Terminal.Gui.Graphs.Orientation.Horizontal;
  155. tileView.Redraw (tileView.Bounds);
  156. string looksLike =
  157. @"
  158. 11111111111
  159. ───────────
  160. 22222222222";
  161. TestHelpers.AssertDriverContentsAre (looksLike, output);
  162. // Keyboard movement on splitter should have no effect if it is not focused
  163. line.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ()));
  164. tileView.SetNeedsDisplay ();
  165. tileView.Redraw (tileView.Bounds);
  166. TestHelpers.AssertDriverContentsAre (looksLike, output);
  167. }
  168. [Fact, AutoInitShutdown]
  169. public void TestTileView_Vertical_View1MinSize_Absolute ()
  170. {
  171. var tileView = Get11By3TileView (out var line);
  172. SetInputFocusLine (tileView);
  173. tileView.Tiles.ElementAt(0).MinSize = 6;
  174. // distance is too small (below 6)
  175. tileView.SetSplitterPos(0, 2);
  176. // Should bound the value to the minimum distance
  177. Assert.Equal (6, tileView.SplitterDistances.ElementAt (0));
  178. tileView.Redraw (tileView.Bounds);
  179. // so should ignore the 2 distance and stick to 6
  180. string looksLike =
  181. @"
  182. 111111│2222
  183. 111111◊2222
  184. │ ";
  185. TestHelpers.AssertDriverContentsAre (looksLike, output);
  186. // Keyboard movement on splitter should have no effect because it
  187. // would take us below the minimum splitter size
  188. line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ()));
  189. tileView.SetNeedsDisplay ();
  190. tileView.Redraw (tileView.Bounds);
  191. TestHelpers.AssertDriverContentsAre (looksLike, output);
  192. // but we can continue to move the splitter right if we want
  193. line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()));
  194. tileView.SetNeedsDisplay ();
  195. tileView.Redraw (tileView.Bounds);
  196. looksLike =
  197. @"
  198. 1111111│222
  199. 1111111◊222
  200. │ ";
  201. TestHelpers.AssertDriverContentsAre (looksLike, output);
  202. }
  203. [Fact, AutoInitShutdown]
  204. public void TestTileView_Vertical_View1MinSize_Absolute_WithBorder ()
  205. {
  206. var tileView = Get11By3TileView (out var line,true);
  207. SetInputFocusLine (tileView);
  208. tileView.Tiles.ElementAt(0).MinSize = 5;
  209. // distance is too small (below 5)
  210. tileView.SetSplitterPos(0,2);
  211. // Should bound the value to the minimum distance
  212. Assert.Equal (6, tileView.SplitterDistances.ElementAt(0));
  213. tileView.Redraw (tileView.Bounds);
  214. // so should ignore the 2 distance and stick to 5
  215. string looksLike =
  216. @"
  217. ┌─────┬───┐
  218. │11111◊222│
  219. └─────┴───┘";
  220. TestHelpers.AssertDriverContentsAre (looksLike, output);
  221. // Keyboard movement on splitter should have no effect because it
  222. // would take us below the minimum splitter size
  223. line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ()));
  224. tileView.SetNeedsDisplay ();
  225. tileView.Redraw (tileView.Bounds);
  226. TestHelpers.AssertDriverContentsAre (looksLike, output);
  227. // but we can continue to move the splitter right if we want
  228. line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()));
  229. tileView.SetNeedsDisplay ();
  230. tileView.Redraw (tileView.Bounds);
  231. looksLike =
  232. @"
  233. ┌──────┬──┐
  234. │111111◊22│
  235. └──────┴──┘";
  236. TestHelpers.AssertDriverContentsAre (looksLike, output);
  237. }
  238. [Fact, AutoInitShutdown]
  239. public void TestTileView_Vertical_View2MinSize_Absolute ()
  240. {
  241. var tileView = Get11By3TileView (out var line);
  242. SetInputFocusLine (tileView);
  243. tileView.Tiles.ElementAt(1).MinSize = 6;
  244. // distance leaves too little space for view2 (less than 6 would remain)
  245. tileView.SetSplitterPos(0,8);
  246. // Should bound the value to the minimum distance
  247. Assert.Equal (4, tileView.SplitterDistances.ElementAt(0));
  248. tileView.Redraw (tileView.Bounds);
  249. // so should ignore the 2 distance and stick to 6
  250. string looksLike =
  251. @"
  252. 1111│222222
  253. 1111◊222222
  254. │ ";
  255. TestHelpers.AssertDriverContentsAre (looksLike, output);
  256. // Keyboard movement on splitter should have no effect because it
  257. // would take us below the minimum splitter size
  258. line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()));
  259. tileView.SetNeedsDisplay ();
  260. tileView.Redraw (tileView.Bounds);
  261. TestHelpers.AssertDriverContentsAre (looksLike, output);
  262. // but we can continue to move the splitter left if we want
  263. line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ()));
  264. tileView.SetNeedsDisplay ();
  265. tileView.Redraw (tileView.Bounds);
  266. looksLike =
  267. @"
  268. 111│2222222
  269. 111◊2222222
  270. │ ";
  271. TestHelpers.AssertDriverContentsAre (looksLike, output);
  272. }
  273. [Fact, AutoInitShutdown]
  274. public void TestTileView_Vertical_View2MinSize_Absolute_WithBorder ()
  275. {
  276. var tileView = Get11By3TileView (out var line, true);
  277. SetInputFocusLine (tileView);
  278. tileView.Tiles.ElementAt(1).MinSize = 5;
  279. // distance leaves too little space for view2 (less than 5 would remain)
  280. tileView.SetSplitterPos(0,8);
  281. // Should bound the value to the minimum distance
  282. Assert.Equal (4, tileView.SplitterDistances.ElementAt(0));
  283. tileView.Redraw (tileView.Bounds);
  284. // so should ignore the 2 distance and stick to 6
  285. string looksLike =
  286. @"
  287. ┌───┬─────┐
  288. │111◊22222│
  289. └───┴─────┘";
  290. TestHelpers.AssertDriverContentsAre (looksLike, output);
  291. // Keyboard movement on splitter should have no effect because it
  292. // would take us below the minimum splitter size
  293. line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()));
  294. tileView.SetNeedsDisplay ();
  295. tileView.Redraw (tileView.Bounds);
  296. TestHelpers.AssertDriverContentsAre (looksLike, output);
  297. // but we can continue to move the splitter left if we want
  298. line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ()));
  299. tileView.SetNeedsDisplay ();
  300. tileView.Redraw (tileView.Bounds);
  301. looksLike =
  302. @"
  303. ┌──┬──────┐
  304. │11◊222222│
  305. └──┴──────┘";
  306. TestHelpers.AssertDriverContentsAre (looksLike, output);
  307. }
  308. [Fact, AutoInitShutdown]
  309. public void TestTileView_InsertPanelAtStart ()
  310. {
  311. var tileView = Get11By3TileView (out var line, true);
  312. SetInputFocusLine (tileView);
  313. tileView.InsertTile (0);
  314. tileView.Redraw (tileView.Bounds);
  315. // so should ignore the 2 distance and stick to 6
  316. string looksLike =
  317. @"
  318. ┌──┬───┬──┐
  319. │ │111│22│
  320. └──┴───┴──┘";
  321. TestHelpers.AssertDriverContentsAre (looksLike, output);
  322. }
  323. [Fact, AutoInitShutdown]
  324. public void TestTileView_InsertPanelMiddle()
  325. {
  326. var tileView = Get11By3TileView (out var line, true);
  327. SetInputFocusLine (tileView);
  328. tileView.InsertTile (1);
  329. tileView.Redraw (tileView.Bounds);
  330. // so should ignore the 2 distance and stick to 6
  331. string looksLike =
  332. @"
  333. ┌──┬───┬──┐
  334. │11│ │22│
  335. └──┴───┴──┘";
  336. TestHelpers.AssertDriverContentsAre (looksLike, output);
  337. }
  338. [Fact, AutoInitShutdown]
  339. public void TestTileView_InsertPanelAtEnd ()
  340. {
  341. var tileView = Get11By3TileView (out var line, true);
  342. SetInputFocusLine (tileView);
  343. tileView.InsertTile (2);
  344. tileView.Redraw (tileView.Bounds);
  345. // so should ignore the 2 distance and stick to 6
  346. string looksLike =
  347. @"
  348. ┌──┬───┬──┐
  349. │11│222│ │
  350. └──┴───┴──┘";
  351. TestHelpers.AssertDriverContentsAre (looksLike, output);
  352. }
  353. [Fact, AutoInitShutdown]
  354. public void TestTileView_Horizontal_Focused ()
  355. {
  356. var tileView = Get11By3TileView (out var line);
  357. tileView.Orientation = Terminal.Gui.Graphs.Orientation.Horizontal;
  358. SetInputFocusLine (tileView);
  359. tileView.Redraw (tileView.Bounds);
  360. string looksLike =
  361. @"
  362. 11111111111
  363. ─────◊─────
  364. 22222222222";
  365. TestHelpers.AssertDriverContentsAre (looksLike, output);
  366. // Now move splitter line down
  367. line.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ()));
  368. tileView.Redraw (tileView.Bounds);
  369. looksLike =
  370. @"
  371. 11111111111
  372. 11111111111
  373. ─────◊─────";
  374. TestHelpers.AssertDriverContentsAre (looksLike, output);
  375. // And 2 up
  376. line.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ()));
  377. line.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ()));
  378. tileView.Redraw (tileView.Bounds);
  379. looksLike =
  380. @"
  381. ─────◊─────
  382. 22222222222
  383. 22222222222";
  384. TestHelpers.AssertDriverContentsAre (looksLike, output);
  385. }
  386. [Fact, AutoInitShutdown]
  387. public void TestTileView_Horizontal_View1MinSize_Absolute ()
  388. {
  389. var tileView = Get11By3TileView (out var line);
  390. tileView.Orientation = Terminal.Gui.Graphs.Orientation.Horizontal;
  391. SetInputFocusLine (tileView);
  392. tileView.Tiles.ElementAt(0).MinSize = 1;
  393. // 0 should not be allowed because it brings us below minimum size of View1
  394. tileView.SetSplitterPos(0,0);
  395. Assert.Equal ((Pos)1, tileView.SplitterDistances.ElementAt(0));
  396. tileView.Redraw (tileView.Bounds);
  397. string looksLike =
  398. @"
  399. 11111111111
  400. ─────◊─────
  401. 22222222222";
  402. TestHelpers.AssertDriverContentsAre (looksLike, output);
  403. // Now move splitter line down (allowed
  404. line.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ()));
  405. tileView.Redraw (tileView.Bounds);
  406. looksLike =
  407. @"
  408. 11111111111
  409. 11111111111
  410. ─────◊─────";
  411. TestHelpers.AssertDriverContentsAre (looksLike, output);
  412. // And up 2 (only 1 is allowed because of minimum size of 1 on view1)
  413. line.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ()));
  414. line.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ()));
  415. tileView.Redraw (tileView.Bounds);
  416. looksLike =
  417. @"
  418. 11111111111
  419. ─────◊─────
  420. 22222222222";
  421. TestHelpers.AssertDriverContentsAre (looksLike, output);
  422. }
  423. [Fact, AutoInitShutdown]
  424. public void TestTileView_CannotSetSplitterPosToFuncEtc ()
  425. {
  426. var tileView = Get11By3TileView ();
  427. var ex = Assert.Throws<ArgumentException> (() => tileView.SetSplitterPos(0,Pos.Right (tileView)));
  428. Assert.Equal ("Only Percent and Absolute values are supported. Passed value was PosCombine", ex.Message);
  429. ex = Assert.Throws<ArgumentException> (() => tileView.SetSplitterPos(0,Pos.Function (() => 1)));
  430. Assert.Equal ("Only Percent and Absolute values are supported. Passed value was PosFunc", ex.Message);
  431. // Also not allowed because this results in a PosCombine
  432. ex = Assert.Throws<ArgumentException> (() => tileView.SetSplitterPos(0, Pos.Percent (50) - 1));
  433. Assert.Equal ("Only Percent and Absolute values are supported. Passed value was PosCombine", ex.Message);
  434. }
  435. [Fact,AutoInitShutdown]
  436. public void TestNestedContainer2LeftAnd1Right_RendersNicely()
  437. {
  438. var tileView = GetNestedContainer2Left1Right (false);
  439. Assert.Equal (20,tileView.Frame.Width);
  440. Assert.Equal (10, tileView.Tiles.ElementAt(0).View.Frame.Width);
  441. Assert.Equal (9, tileView.Tiles.ElementAt (1).View.Frame.Width);
  442. Assert.IsType<TileView> (tileView.Tiles.ElementAt (0).View);
  443. var left = (TileView)tileView.Tiles.ElementAt (0).View;
  444. Assert.Same (left.SuperView, tileView);
  445. Assert.Equal(2, left.Tiles.ElementAt (0).View.Subviews.Count);
  446. Assert.IsType<Label> (left.Tiles.ElementAt (0).View.Subviews [0]);
  447. Assert.IsType<Label> (left.Tiles.ElementAt (0).View.Subviews [1]);
  448. var onesTop = (Label)left.Tiles.ElementAt (0).View.Subviews [0];
  449. var onesBottom = (Label)left.Tiles.ElementAt (0).View.Subviews [1];
  450. Assert.Same (left.Tiles.ElementAt (0).View, onesTop.SuperView);
  451. Assert.Same (left.Tiles.ElementAt (0).View, onesBottom.SuperView);
  452. Assert.Equal (10, onesTop.Frame.Width);
  453. Assert.Equal (10, onesBottom.Frame.Width);
  454. tileView.Redraw (tileView.Bounds);
  455. string looksLike =
  456. @"
  457. 1111111111│222222222
  458. 1111111111│222222222
  459. ──────────┤
  460. │";
  461. TestHelpers.AssertDriverContentsAre (looksLike, output);
  462. }
  463. [Fact,AutoInitShutdown]
  464. public void TestNestedContainer3RightAnd1Down_RendersNicely()
  465. {
  466. var tileView = GetNestedContainer3Right1Down (false);
  467. tileView.Redraw (tileView.Bounds);
  468. string looksLike =
  469. @"
  470. 111111│222222│333333
  471. 111111│222222│333333
  472. 111111│222222│333333
  473. 111111│222222│333333
  474. 111111│222222│333333
  475. 111111│222222├──────
  476. 111111│222222│444444
  477. 111111│222222│444444
  478. 111111│222222│444444
  479. 111111│222222│444444
  480. ";
  481. TestHelpers.AssertDriverContentsAre (looksLike, output);
  482. // It looks good but lets double check the measurements incase
  483. // anything is sticking out but drawn over
  484. // 3 panels + 2 splitters
  485. Assert.Equal(5,tileView.Subviews.Count);
  486. // Check X and Widths of Tiles
  487. Assert.Equal(0,tileView.Tiles.ElementAt(0).View.Frame.X);
  488. Assert.Equal(6,tileView.Tiles.ElementAt(0).View.Frame.Width);
  489. Assert.Equal(7,tileView.Tiles.ElementAt(1).View.Frame.X);
  490. Assert.Equal(6,tileView.Tiles.ElementAt(1).View.Frame.Width);
  491. Assert.Equal(14,tileView.Tiles.ElementAt(2).View.Frame.X);
  492. Assert.Equal(6,tileView.Tiles.ElementAt(2).View.Frame.Width);
  493. // Check Y and Heights of Tiles
  494. Assert.Equal(0,tileView.Tiles.ElementAt(0).View.Frame.Y);
  495. Assert.Equal(10,tileView.Tiles.ElementAt(0).View.Frame.Height);
  496. Assert.Equal(0,tileView.Tiles.ElementAt(1).View.Frame.Y);
  497. Assert.Equal(10,tileView.Tiles.ElementAt(1).View.Frame.Height);
  498. Assert.Equal(0,tileView.Tiles.ElementAt(2).View.Frame.Y);
  499. Assert.Equal(10,tileView.Tiles.ElementAt(2).View.Frame.Height);
  500. // Check Sub containers in last panel
  501. var subSplit = (TileView)tileView.Tiles.ElementAt(2).View;
  502. Assert.Equal(0,subSplit.Tiles.ElementAt(0).View.Frame.X);
  503. Assert.Equal(6,subSplit.Tiles.ElementAt(0).View.Frame.Width);
  504. Assert.Equal(0,subSplit.Tiles.ElementAt(0).View.Frame.Y);
  505. Assert.Equal(5,subSplit.Tiles.ElementAt(0).View.Frame.Height);
  506. Assert.IsType<TextView>(subSplit.Tiles.ElementAt(0).View.Subviews.Single());
  507. Assert.Equal(0,subSplit.Tiles.ElementAt(1).View.Frame.X);
  508. Assert.Equal(6,subSplit.Tiles.ElementAt(1).View.Frame.Width);
  509. Assert.Equal(6,subSplit.Tiles.ElementAt(1).View.Frame.Y);
  510. Assert.Equal(4,subSplit.Tiles.ElementAt(1).View.Frame.Height);
  511. Assert.IsType<TextView>(subSplit.Tiles.ElementAt(1).View.Subviews.Single());
  512. }
  513. [Fact,AutoInitShutdown]
  514. public void TestNestedContainer3RightAnd1Down_WithBorder_RendersNicely()
  515. {
  516. var tileView = GetNestedContainer3Right1Down (true);
  517. tileView.Redraw (tileView.Bounds);
  518. string looksLike =
  519. @"
  520. ┌─────┬──────┬─────┐
  521. │11111│222222│33333│
  522. │11111│222222│33333│
  523. │11111│222222│33333│
  524. │11111│222222│33333│
  525. │11111│222222├─────┤
  526. │11111│222222│44444│
  527. │11111│222222│44444│
  528. │11111│222222│44444│
  529. └─────┴──────┴─────┘";
  530. TestHelpers.AssertDriverContentsAre (looksLike, output);
  531. // It looks good but lets double check the measurements incase
  532. // anything is sticking out but drawn over
  533. // 3 panels + 2 splitters
  534. Assert.Equal(5,tileView.Subviews.Count);
  535. // Check X and Widths of Tiles
  536. Assert.Equal(1,tileView.Tiles.ElementAt(0).View.Frame.X);
  537. Assert.Equal(5,tileView.Tiles.ElementAt(0).View.Frame.Width);
  538. Assert.Equal(7,tileView.Tiles.ElementAt(1).View.Frame.X);
  539. Assert.Equal(6,tileView.Tiles.ElementAt(1).View.Frame.Width);
  540. Assert.Equal(14,tileView.Tiles.ElementAt(2).View.Frame.X);
  541. Assert.Equal(5,tileView.Tiles.ElementAt(2).View.Frame.Width);
  542. // Check Y and Heights of Tiles
  543. Assert.Equal(1,tileView.Tiles.ElementAt(0).View.Frame.Y);
  544. Assert.Equal(8,tileView.Tiles.ElementAt(0).View.Frame.Height);
  545. Assert.Equal(1,tileView.Tiles.ElementAt(1).View.Frame.Y);
  546. Assert.Equal(8,tileView.Tiles.ElementAt(1).View.Frame.Height);
  547. Assert.Equal(1,tileView.Tiles.ElementAt(2).View.Frame.Y);
  548. Assert.Equal(8,tileView.Tiles.ElementAt(2).View.Frame.Height);
  549. // Check Sub containers in last panel
  550. var subSplit = (TileView)tileView.Tiles.ElementAt(2).View;
  551. Assert.Equal(0,subSplit.Tiles.ElementAt(0).View.Frame.X);
  552. Assert.Equal(5,subSplit.Tiles.ElementAt(0).View.Frame.Width);
  553. Assert.Equal(0,subSplit.Tiles.ElementAt(0).View.Frame.Y);
  554. Assert.Equal(4,subSplit.Tiles.ElementAt(0).View.Frame.Height);
  555. Assert.IsType<TextView>(subSplit.Tiles.ElementAt(0).View.Subviews.Single());
  556. Assert.Equal(0,subSplit.Tiles.ElementAt(1).View.Frame.X);
  557. Assert.Equal(5,subSplit.Tiles.ElementAt(1).View.Frame.Width);
  558. Assert.Equal(5,subSplit.Tiles.ElementAt(1).View.Frame.Y);
  559. Assert.Equal(3,subSplit.Tiles.ElementAt(1).View.Frame.Height);
  560. Assert.IsType<TextView>(subSplit.Tiles.ElementAt(1).View.Subviews.Single());
  561. }
  562. [Fact,AutoInitShutdown]
  563. public void TestNestedContainer3RightAnd1Down_WithTitledBorder_RendersNicely()
  564. {
  565. var tileView = GetNestedContainer3Right1Down (true,true);
  566. tileView.Redraw (tileView.Bounds);
  567. string looksLike =
  568. @"
  569. ┌T1───┬T2────┬T3───┐
  570. │11111│222222│33333│
  571. │11111│222222│33333│
  572. │11111│222222│33333│
  573. │11111│222222│33333│
  574. │11111│222222├T4───┤
  575. │11111│222222│44444│
  576. │11111│222222│44444│
  577. │11111│222222│44444│
  578. └─────┴──────┴─────┘";
  579. TestHelpers.AssertDriverContentsAre (looksLike, output);
  580. }
  581. [Fact, AutoInitShutdown]
  582. public void TestNestedContainer3RightAnd1Down_WithBorder_RemovingTiles ()
  583. {
  584. var tileView = GetNestedContainer3Right1Down (true);
  585. tileView.Redraw (tileView.Bounds);
  586. string looksLike =
  587. @"
  588. ┌─────┬──────┬─────┐
  589. │11111│222222│33333│
  590. │11111│222222│33333│
  591. │11111│222222│33333│
  592. │11111│222222│33333│
  593. │11111│222222├─────┤
  594. │11111│222222│44444│
  595. │11111│222222│44444│
  596. │11111│222222│44444│
  597. └─────┴──────┴─────┘";
  598. TestHelpers.AssertDriverContentsAre (looksLike, output);
  599. var toRemove = tileView.Tiles.ElementAt(1);
  600. var removed = tileView.RemoveTile (1);
  601. Assert.Same(toRemove, removed);
  602. Assert.DoesNotContain(removed,tileView.Tiles);
  603. tileView.Redraw (tileView.Bounds);
  604. looksLike =
  605. @"
  606. ┌─────────┬────────┐
  607. │111111111│33333333│
  608. │111111111│33333333│
  609. │111111111│33333333│
  610. │111111111│33333333│
  611. │111111111├────────┤
  612. │111111111│44444444│
  613. │111111111│44444444│
  614. │111111111│44444444│
  615. └─────────┴────────┘";
  616. TestHelpers.AssertDriverContentsAre (looksLike, output);
  617. // cannot remove at this index because there is only one horizontal tile left
  618. Assert.Null (tileView.RemoveTile (2));
  619. tileView.RemoveTile (0);
  620. tileView.Redraw (tileView.Bounds);
  621. looksLike =
  622. @"
  623. ┌──────────────────┐
  624. │333333333333333333│
  625. │333333333333333333│
  626. │333333333333333333│
  627. │333333333333333333│
  628. ├──────────────────┤
  629. │444444444444444444│
  630. │444444444444444444│
  631. │444444444444444444│
  632. └──────────────────┘";
  633. TestHelpers.AssertDriverContentsAre (looksLike, output);
  634. Assert.NotNull(tileView.RemoveTile (0));
  635. tileView.Redraw (tileView.Bounds);
  636. looksLike =
  637. @"
  638. ┌──────────────────┐
  639. │ │
  640. │ │
  641. │ │
  642. │ │
  643. │ │
  644. │ │
  645. │ │
  646. │ │
  647. └──────────────────┘";
  648. TestHelpers.AssertDriverContentsAre (looksLike, output);
  649. // cannot remove
  650. Assert.Null (tileView.RemoveTile (0));
  651. }
  652. [Theory,AutoInitShutdown]
  653. [InlineData(true)]
  654. [InlineData(false)]
  655. public void TestTileView_IndexOf(bool recursive)
  656. {
  657. var tv = new TileView();
  658. var lbl1 = new Label();
  659. var lbl2 = new Label();
  660. var frame = new FrameView();
  661. var sub = new Label();
  662. frame.Add(sub);
  663. // IndexOf returns -1 when view not found
  664. Assert.Equal(-1,tv.IndexOf(lbl1, recursive));
  665. Assert.Equal(-1,tv.IndexOf(lbl2, recursive));
  666. // IndexOf supports looking for Tile.View
  667. Assert.Equal(0,tv.IndexOf(tv.Tiles.ElementAt(0).View, recursive));
  668. Assert.Equal(1,tv.IndexOf(tv.Tiles.ElementAt(1).View, recursive));
  669. // IndexOf supports looking for Tile.View.Subviews
  670. tv.Tiles.ElementAt(0).View.Add(lbl1);
  671. Assert.Equal(0,tv.IndexOf(lbl1, recursive));
  672. tv.Tiles.ElementAt(1).View.Add(lbl2);
  673. Assert.Equal(1,tv.IndexOf(lbl2, recursive));
  674. // IndexOf supports looking deep into subviews only when
  675. // the recursive true value is passed
  676. tv.Tiles.ElementAt(1).View.Add(frame);
  677. if(recursive)
  678. {
  679. Assert.Equal(1,tv.IndexOf(sub, recursive));
  680. }
  681. else
  682. {
  683. Assert.Equal(-1,tv.IndexOf(sub, recursive));
  684. }
  685. }
  686. [Fact,AutoInitShutdown]
  687. public void TestNestedRoots_BothRoots_BothCanHaveBorders()
  688. {
  689. var tv = new TileView{Width=10,Height=5,ColorScheme = new ColorScheme(),IntegratedBorder = BorderStyle.Single};
  690. var tv2 = new TileView{
  691. Width=Dim.Fill(),Height=Dim.Fill(),
  692. ColorScheme = new ColorScheme(),
  693. IntegratedBorder = BorderStyle.Single,
  694. Orientation = Orientation.Horizontal};
  695. Assert.True(tv.IsRootTileView());
  696. tv.Tiles.ElementAt(1).View.Add(tv2);
  697. Application.Top.Add (tv);
  698. tv.BeginInit();
  699. tv.EndInit ();
  700. tv.LayoutSubviews ();
  701. tv.LayoutSubviews ();
  702. tv.Tiles.ElementAt(1).View.LayoutSubviews ();
  703. tv2.LayoutSubviews ();
  704. // tv2 is still considered a root because
  705. // it was manually created by API user. That
  706. // means it will not have its lines joined to
  707. // parents and it is permitted to have a border
  708. Assert.True(tv2.IsRootTileView());
  709. tv.Redraw (tv.Bounds);
  710. var looksLike =
  711. @"
  712. ┌────┬───┐
  713. │ │┌─┐│
  714. │ │├─┤│
  715. │ │└─┘│
  716. └────┴───┘
  717. ";
  718. TestHelpers.AssertDriverContentsAre (looksLike, output);
  719. }
  720. [Fact, AutoInitShutdown]
  721. public void TestNestedNonRoots_OnlyOneRoot_OnlyRootCanHaveBorders ()
  722. {
  723. var tv = new TileView { Width = 10, Height = 5, ColorScheme = new ColorScheme (), IntegratedBorder = BorderStyle.Single };
  724. tv.TrySplitTile (1, 2, out var tv2);
  725. tv2.ColorScheme = new ColorScheme ();
  726. tv2.IntegratedBorder = BorderStyle.Single; // will not be respected
  727. tv2.Orientation = Orientation.Horizontal;
  728. Assert.True (tv.IsRootTileView ());
  729. Application.Top.Add (tv);
  730. tv.BeginInit ();
  731. tv.EndInit ();
  732. tv.LayoutSubviews ();
  733. tv.LayoutSubviews ();
  734. tv.Tiles.ElementAt (1).View.LayoutSubviews ();
  735. tv2.LayoutSubviews ();
  736. // tv2 is not considered a root because
  737. // it was created via TrySplitTile so it
  738. // will have its lines joined to
  739. // parent and cannot have its own border
  740. Assert.False (tv2.IsRootTileView ());
  741. tv.Redraw (tv.Bounds);
  742. var looksLike =
  743. @"
  744. ┌────┬───┐
  745. │ │ │
  746. │ ├───┤
  747. │ │ │
  748. └────┴───┘
  749. ";
  750. TestHelpers.AssertDriverContentsAre (looksLike, output);
  751. }
  752. /// <summary>
  753. /// Creates a vertical orientation root container with left pane split into
  754. /// two (with horizontal splitter line).
  755. /// </summary>
  756. /// <param name="withBorder"></param>
  757. /// <returns></returns>
  758. private TileView GetNestedContainer2Left1Right(bool withBorder)
  759. {
  760. var container = GetTileView (20, 10,withBorder);
  761. Assert.True (container.TrySplitTile (0,2, out var newContainer));
  762. newContainer.Orientation = Terminal.Gui.Graphs.Orientation.Horizontal;
  763. newContainer.ColorScheme = new ColorScheme ();
  764. container.ColorScheme = new ColorScheme ();
  765. container.LayoutSubviews ();
  766. return container;
  767. }
  768. /// <summary>
  769. /// Creates a vertical orientation root container with 3 tiles.
  770. /// The rightmost is split horizontally
  771. /// </summary>
  772. /// <param name="withBorder"></param>
  773. /// <returns></returns>
  774. private TileView GetNestedContainer3Right1Down(bool withBorder, bool withTitles = false)
  775. {
  776. var container =
  777. new TileView (3)
  778. {
  779. Width = 20,
  780. Height = 10,
  781. IntegratedBorder = withBorder ? BorderStyle.Single : BorderStyle.None
  782. };
  783. Assert.True (container.TrySplitTile (2,2, out var newContainer));
  784. newContainer.Orientation = Terminal.Gui.Graphs.Orientation.Horizontal;
  785. int i=0;
  786. foreach(var tile in container.Tiles.Take(2).Union(newContainer.Tiles))
  787. {
  788. i++;
  789. if(withTitles)
  790. {
  791. tile.Title = "T"+i;
  792. }
  793. tile.View.Add(new TextView{
  794. Width = Dim.Fill(),
  795. Height = Dim.Fill(),
  796. Text =
  797. string.Join('\n',
  798. Enumerable.Repeat(
  799. new string(i.ToString()[0],100)
  800. ,10).ToArray()),
  801. WordWrap = false
  802. });
  803. }
  804. newContainer.ColorScheme = new ColorScheme ();
  805. container.ColorScheme = new ColorScheme ();
  806. container.LayoutSubviews ();
  807. return container;
  808. }
  809. private LineView GetLine (TileView tileView)
  810. {
  811. return tileView.Subviews.OfType<LineView> ().Single ();
  812. }
  813. private void SetInputFocusLine (TileView tileView)
  814. {
  815. var line = GetLine (tileView);
  816. line.SetFocus ();
  817. Assert.True (line.HasFocus);
  818. }
  819. private TileView Get11By3TileView(out LineView line, bool withBorder = false)
  820. {
  821. var split = Get11By3TileView (withBorder);
  822. line = GetLine (split);
  823. return split;
  824. }
  825. private TileView Get11By3TileView (bool withBorder = false)
  826. {
  827. return GetTileView (11, 3, withBorder);
  828. }
  829. private TileView GetTileView (int width, int height, bool withBorder = false)
  830. {
  831. var container = new TileView () {
  832. Width = width,
  833. Height = height,
  834. };
  835. container.IntegratedBorder = withBorder ? BorderStyle.Single : BorderStyle.None;
  836. container.Tiles.ElementAt(0).View.Add (new Label (new string ('1', 100)) { Width = Dim.Fill(), Height = 1, AutoSize = false});
  837. container.Tiles.ElementAt (0).View.Add (new Label (new string ('1', 100)) { Width = Dim.Fill (), Height = 1, AutoSize = false,Y = 1});
  838. container.Tiles.ElementAt (1).View.Add (new Label (new string ('2', 100)) { Width = Dim.Fill (), Height = 1, AutoSize = false });
  839. container.Tiles.ElementAt (1).View.Add (new Label (new string ('2', 100)) { Width = Dim.Fill (), Height = 1, AutoSize = false,Y = 1});
  840. container.Tiles.ElementAt (0).MinSize = 0;
  841. container.Tiles.ElementAt (1).MinSize = 0;
  842. Application.Top.Add (container);
  843. container.ColorScheme = new ColorScheme ();
  844. container.LayoutSubviews ();
  845. container.BeginInit ();
  846. container.EndInit ();
  847. return container;
  848. }
  849. }
  850. }