TreeTableSourceTests.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. using System.Text;
  2. using UnitTests;
  3. using Xunit.Abstractions;
  4. namespace Terminal.Gui.ViewsTests;
  5. public class TreeTableSourceTests : IDisposable
  6. {
  7. private readonly Rune _origChecked;
  8. private readonly Rune _origUnchecked;
  9. private readonly ITestOutputHelper _output;
  10. public TreeTableSourceTests (ITestOutputHelper output)
  11. {
  12. _output = output;
  13. _origChecked = Glyphs.CheckStateChecked;
  14. _origUnchecked = Glyphs.CheckStateUnChecked;
  15. Glyphs.CheckStateChecked = new Rune ('☑');
  16. Glyphs.CheckStateUnChecked = new Rune ('☐');
  17. }
  18. public void Dispose ()
  19. {
  20. Glyphs.CheckStateChecked = _origChecked;
  21. Glyphs.CheckStateUnChecked = _origUnchecked;
  22. }
  23. [Fact]
  24. [SetupFakeDriver]
  25. public void TestTreeTableSource_BasicExpanding_WithKeyboard ()
  26. {
  27. ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
  28. TableView tv = GetTreeTable (out _);
  29. tv.Style.GetOrCreateColumnStyle (1).MinAcceptableWidth = 1;
  30. tv.Draw ();
  31. var expected =
  32. @"
  33. │Name │Description │
  34. ├──────────────┼───────────────────────┤
  35. │├+Lost Highway│Exciting night road │
  36. │└+Route 66 │Great race course │";
  37. DriverAssert.AssertDriverContentsAre (expected, _output);
  38. Assert.Equal (2, tv.Table.Rows);
  39. // top left is selected cell
  40. Assert.Equal (0, tv.SelectedRow);
  41. Assert.Equal (0, tv.SelectedColumn);
  42. // when pressing right we should expand the top route
  43. tv.NewKeyDownEvent (Key.CursorRight);
  44. View.SetClipToScreen ();
  45. tv.Draw ();
  46. expected =
  47. @"
  48. │Name │Description │
  49. ├─────────────────┼────────────────────┤
  50. │├-Lost Highway │Exciting night road │
  51. ││ ├─Ford Trans-Am│Talking thunderbird │
  52. ││ └─DeLorean │Time travelling car │
  53. │└+Route 66 │Great race course │
  54. ";
  55. DriverAssert.AssertDriverContentsAre (expected, _output);
  56. // when pressing left we should collapse the top route again
  57. tv.NewKeyDownEvent (Key.CursorLeft);
  58. View.SetClipToScreen ();
  59. tv.Draw ();
  60. expected =
  61. @"
  62. │Name │Description │
  63. ├──────────────┼───────────────────────┤
  64. │├+Lost Highway│Exciting night road │
  65. │└+Route 66 │Great race course │
  66. ";
  67. DriverAssert.AssertDriverContentsAre (expected, _output);
  68. }
  69. [Fact]
  70. [SetupFakeDriver]
  71. public void TestTreeTableSource_BasicExpanding_WithMouse ()
  72. {
  73. ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
  74. TableView tv = GetTreeTable (out _);
  75. tv.Style.GetOrCreateColumnStyle (1).MinAcceptableWidth = 1;
  76. View.SetClipToScreen ();
  77. tv.Draw ();
  78. var expected =
  79. @"
  80. │Name │Description │
  81. ├──────────────┼───────────────────────┤
  82. │├+Lost Highway│Exciting night road │
  83. │└+Route 66 │Great race course │";
  84. DriverAssert.AssertDriverContentsAre (expected, _output);
  85. Assert.Equal (2, tv.Table.Rows);
  86. // top left is selected cell
  87. Assert.Equal (0, tv.SelectedRow);
  88. Assert.Equal (0, tv.SelectedColumn);
  89. Assert.True (tv.NewMouseEvent (new MouseEventArgs { Position = new (2, 2), Flags = MouseFlags.Button1Clicked }));
  90. View.SetClipToScreen ();
  91. tv.Draw ();
  92. expected =
  93. @"
  94. │Name │Description │
  95. ├─────────────────┼────────────────────┤
  96. │├-Lost Highway │Exciting night road │
  97. ││ ├─Ford Trans-Am│Talking thunderbird │
  98. ││ └─DeLorean │Time travelling car │
  99. │└+Route 66 │Great race course │
  100. ";
  101. DriverAssert.AssertDriverContentsAre (expected, _output);
  102. // Clicking to the right/left of the expand/collapse does nothing
  103. tv.NewMouseEvent (new MouseEventArgs { Position = new (3, 2), Flags = MouseFlags.Button1Clicked });
  104. tv.Draw ();
  105. DriverAssert.AssertDriverContentsAre (expected, _output);
  106. tv.NewMouseEvent (new MouseEventArgs { Position = new (1, 2), Flags = MouseFlags.Button1Clicked });
  107. tv.Draw ();
  108. DriverAssert.AssertDriverContentsAre (expected, _output);
  109. // Clicking on the + again should collapse
  110. tv.NewMouseEvent (new MouseEventArgs { Position = new (2, 2), Flags = MouseFlags.Button1Clicked });
  111. View.SetClipToScreen ();
  112. tv.Draw ();
  113. expected =
  114. @"
  115. │Name │Description │
  116. ├──────────────┼───────────────────────┤
  117. │├+Lost Highway│Exciting night road │
  118. │└+Route 66 │Great race course │";
  119. DriverAssert.AssertDriverContentsAre (expected, _output);
  120. }
  121. [Fact]
  122. [AutoInitShutdown (configLocation:ConfigLocations.Default)]
  123. public void TestTreeTableSource_CombinedWithCheckboxes ()
  124. {
  125. Toplevel top = new ();
  126. TableView tv = GetTreeTable (out TreeView<IDescribedThing> treeSource);
  127. CheckBoxTableSourceWrapperByIndex checkSource;
  128. tv.Table = checkSource = new CheckBoxTableSourceWrapperByIndex (tv, tv.Table);
  129. tv.Style.GetOrCreateColumnStyle (2).MinAcceptableWidth = 1;
  130. top.Add (tv);
  131. Application.Begin (top);
  132. tv.Draw ();
  133. var expected =
  134. @"
  135. │ │Name │Description │
  136. ├─┼──────────────┼─────────────────────┤
  137. │☐│├+Lost Highway│Exciting night road │
  138. │☐│└+Route 66 │Great race course │
  139. ";
  140. DriverAssert.AssertDriverContentsAre (expected, _output);
  141. Assert.Equal (2, tv.Table.Rows);
  142. // top left is selected cell
  143. Assert.Equal (0, tv.SelectedRow);
  144. Assert.Equal (0, tv.SelectedColumn);
  145. // when pressing right we move to tree column
  146. tv.NewKeyDownEvent (Key.CursorRight);
  147. // now we are in tree column
  148. Assert.Equal (0, tv.SelectedRow);
  149. Assert.Equal (1, tv.SelectedColumn);
  150. Application.RaiseKeyDownEvent (Key.CursorRight);
  151. View.SetClipToScreen ();
  152. tv.Draw ();
  153. expected =
  154. @"
  155. │ │Name │Description │
  156. ├─┼─────────────────┼──────────────────┤
  157. │☐│├-Lost Highway │Exciting night roa│
  158. │☐││ ├─Ford Trans-Am│Talking thunderbir│
  159. │☐││ └─DeLorean │Time travelling ca│
  160. │☐│└+Route 66 │Great race course │
  161. ";
  162. DriverAssert.AssertDriverContentsAre (expected, _output);
  163. tv.NewKeyDownEvent (Key.CursorDown);
  164. tv.NewKeyDownEvent (Key.Space);
  165. View.SetClipToScreen ();
  166. tv.Draw ();
  167. expected =
  168. @"
  169. │ │Name │Description │
  170. ├─┼─────────────────┼──────────────────┤
  171. │☐│├-Lost Highway │Exciting night roa│
  172. │☑││ ├─Ford Trans-Am│Talking thunderbir│
  173. │☐││ └─DeLorean │Time travelling ca│
  174. │☐│└+Route 66 │Great race course │
  175. ";
  176. DriverAssert.AssertDriverContentsAre (expected, _output);
  177. IDescribedThing [] selectedObjects = checkSource.CheckedRows.Select (treeSource.GetObjectOnRow).ToArray ();
  178. IDescribedThing selected = Assert.Single (selectedObjects);
  179. Assert.Equal ("Ford Trans-Am", selected.Name);
  180. Assert.Equal ("Talking thunderbird car", selected.Description);
  181. top.Dispose ();
  182. }
  183. private TableView GetTreeTable (out TreeView<IDescribedThing> tree)
  184. {
  185. var tableView = new TableView ();
  186. tableView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
  187. tableView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
  188. tableView.Viewport = new Rectangle (0, 0, 40, 6);
  189. tableView.Style.ShowHorizontalHeaderUnderline = true;
  190. tableView.Style.ShowHorizontalHeaderOverline = false;
  191. tableView.Style.AlwaysShowHeaders = true;
  192. tableView.Style.SmoothHorizontalScrolling = true;
  193. tree = new TreeView<IDescribedThing> ();
  194. tree.AspectGetter = d => d.Name;
  195. tree.TreeBuilder = new DelegateTreeBuilder<IDescribedThing> (
  196. d => d is Road r
  197. ? r.Traffic
  198. : Enumerable.Empty<IDescribedThing> ()
  199. );
  200. tree.AddObject (
  201. new Road
  202. {
  203. Name = "Lost Highway",
  204. Description = "Exciting night road",
  205. Traffic = new List<Car>
  206. {
  207. new () { Name = "Ford Trans-Am", Description = "Talking thunderbird car" },
  208. new () { Name = "DeLorean", Description = "Time travelling car" }
  209. }
  210. }
  211. );
  212. tree.AddObject (
  213. new Road
  214. {
  215. Name = "Route 66",
  216. Description = "Great race course",
  217. Traffic = new List<Car>
  218. {
  219. new () { Name = "Pink Compact", Description = "Penelope Pitstop's car" },
  220. new () { Name = "Mean Machine", Description = "Dick Dastardly's car" }
  221. }
  222. }
  223. );
  224. tableView.Table = new TreeTableSource<IDescribedThing> (
  225. tableView,
  226. "Name",
  227. tree,
  228. new Dictionary<string, Func<IDescribedThing, object>> { { "Description", d => d.Description } }
  229. );
  230. tableView.BeginInit ();
  231. tableView.EndInit ();
  232. tableView.LayoutSubViews ();
  233. var top = new Toplevel ();
  234. top.Add (tableView);
  235. top.SetFocus ();
  236. Assert.Equal (tableView, top.MostFocused);
  237. return tableView;
  238. }
  239. private class Car : IDescribedThing
  240. {
  241. public string Name { get; set; }
  242. public string Description { get; set; }
  243. }
  244. private interface IDescribedThing
  245. {
  246. string Description { get; }
  247. string Name { get; }
  248. }
  249. private class Road : IDescribedThing
  250. {
  251. public List<Car> Traffic { get; set; }
  252. public string Name { get; set; }
  253. public string Description { get; set; }
  254. }
  255. }