TreeTableSourceTests.cs 11 KB

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