ListColumns.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Data;
  5. using Terminal.Gui;
  6. using static Terminal.Gui.TableView;
  7. namespace UICatalog.Scenarios {
  8. [ScenarioMetadata (Name: "ListColumns", Description: "Implements a columned list via a data table.")]
  9. [ScenarioCategory ("TableView")]
  10. [ScenarioCategory ("Controls")]
  11. [ScenarioCategory ("Dialogs")]
  12. [ScenarioCategory ("Text and Formatting")]
  13. [ScenarioCategory ("Top Level Windows")]
  14. public class ListColumns : Scenario {
  15. TableView listColView;
  16. DataTable currentTable;
  17. private MenuItem _miCellLines;
  18. private MenuItem _miExpandLastColumn;
  19. private MenuItem _miAlwaysUseNormalColorForVerticalCellLines;
  20. private MenuItem _miSmoothScrolling;
  21. private MenuItem _miAlternatingColors;
  22. private MenuItem _miCursor;
  23. private MenuItem _miTopline;
  24. private MenuItem _miBottomline;
  25. private MenuItem _miOrientVertical;
  26. private MenuItem _miScrollParallel;
  27. ColorScheme alternatingColorScheme;
  28. public override void Setup ()
  29. {
  30. Win.Title = this.GetName ();
  31. Win.Y = 1; // menu
  32. Win.Height = Dim.Fill (1); // status bar
  33. Application.Top.LayoutSubviews ();
  34. this.listColView = new TableView () {
  35. X = 0,
  36. Y = 0,
  37. Width = Dim.Fill (),
  38. Height = Dim.Fill (1),
  39. Style = new TableStyle {
  40. ShowHeaders = false,
  41. ShowHorizontalHeaderOverline = false,
  42. ShowHorizontalHeaderUnderline = false,
  43. ShowHorizontalBottomline = false,
  44. ExpandLastColumn = false,
  45. }
  46. };
  47. var listColStyle = new ListColumnStyle ();
  48. var menu = new MenuBar (new MenuBarItem [] {
  49. new MenuBarItem ("_File", new MenuItem [] {
  50. new MenuItem ("Open_BigListExample", "", () => OpenSimpleList (true)),
  51. new MenuItem ("Open_SmListExample", "", () => OpenSimpleList (false)),
  52. new MenuItem ("_CloseExample", "", () => CloseExample ()),
  53. new MenuItem ("_Quit", "", () => Quit()),
  54. }),
  55. new MenuBarItem ("_View", new MenuItem [] {
  56. _miTopline = new MenuItem ("_TopLine", "", () => ToggleTopline ()) { Checked = listColView.Style.ShowHorizontalHeaderOverline, CheckType = MenuItemCheckStyle.Checked },
  57. _miBottomline = new MenuItem ("_BottomLine", "", () => ToggleBottomline ()) { Checked = listColView.Style.ShowHorizontalBottomline, CheckType = MenuItemCheckStyle.Checked },
  58. _miCellLines = new MenuItem ("_CellLines", "", () => ToggleCellLines ()) { Checked = listColView.Style.ShowVerticalCellLines, CheckType = MenuItemCheckStyle.Checked },
  59. _miExpandLastColumn = new MenuItem ("_ExpandLastColumn", "", () => ToggleExpandLastColumn ()) { Checked = listColView.Style.ExpandLastColumn, CheckType = MenuItemCheckStyle.Checked },
  60. _miAlwaysUseNormalColorForVerticalCellLines = new MenuItem ("_AlwaysUseNormalColorForVerticalCellLines", "", () => ToggleAlwaysUseNormalColorForVerticalCellLines ()) { Checked = listColView.Style.AlwaysUseNormalColorForVerticalCellLines, CheckType = MenuItemCheckStyle.Checked },
  61. _miSmoothScrolling = new MenuItem ("_SmoothHorizontalScrolling", "", () => ToggleSmoothScrolling ()) { Checked = listColView.Style.SmoothHorizontalScrolling, CheckType = MenuItemCheckStyle.Checked },
  62. _miAlternatingColors = new MenuItem ("Alternating Colors", "", () => ToggleAlternatingColors ()) { CheckType = MenuItemCheckStyle.Checked},
  63. _miCursor = new MenuItem ("Invert Selected Cell First Character", "", () => ToggleInvertSelectedCellFirstCharacter ()) { Checked = listColView.Style.InvertSelectedCellFirstCharacter,CheckType = MenuItemCheckStyle.Checked},
  64. }),
  65. new MenuBarItem ("_List", new MenuItem [] {
  66. //new MenuItem ("_Hide Headers", "", HideHeaders),
  67. _miOrientVertical = new MenuItem ("_OrientVertical", "", () => ToggleVerticalOrientation ()) { Checked = listColStyle.Orientation == Orientation.Vertical, CheckType = MenuItemCheckStyle.Checked },
  68. _miScrollParallel = new MenuItem ("_ScrollParallel", "", () => ToggleScrollParallel ()) { Checked = listColStyle.ScrollParallel, CheckType = MenuItemCheckStyle.Checked },
  69. new MenuItem ("Set _Max Cell Width", "", SetListMaxWidth),
  70. new MenuItem ("Set Mi_n Cell Width", "", SetListMinWidth),
  71. }),
  72. });
  73. Application.Top.Add (menu);
  74. var statusBar = new StatusBar (new StatusItem [] {
  75. new StatusItem(Key.F2, "~F2~ OpenBigListEx", () => OpenSimpleList (true)),
  76. new StatusItem(Key.F3, "~F3~ CloseExample", () => CloseExample ()),
  77. new StatusItem(Key.F4, "~F4~ OpenSmListEx", () => OpenSimpleList (false)),
  78. new StatusItem(Application.QuitKey, $"{Application.QuitKey} to Quit", () => Quit()),
  79. });
  80. Application.Top.Add (statusBar);
  81. Win.Add (listColView);
  82. var selectedCellLabel = new Label () {
  83. X = 0,
  84. Y = Pos.Bottom (listColView),
  85. Text = "0,0",
  86. Width = Dim.Fill (),
  87. TextAlignment = TextAlignment.Right
  88. };
  89. Win.Add (selectedCellLabel);
  90. listColView.SelectedCellChanged += (s, e) => { selectedCellLabel.Text = $"{listColView.SelectedRow},{listColView.SelectedColumn}"; };
  91. listColView.KeyPress += TableViewKeyPress;
  92. SetupScrollBar ();
  93. alternatingColorScheme = new ColorScheme () {
  94. Disabled = Win.ColorScheme.Disabled,
  95. HotFocus = Win.ColorScheme.HotFocus,
  96. Focus = Win.ColorScheme.Focus,
  97. Normal = new Attribute (Color.White, Color.BrightBlue)
  98. };
  99. // if user clicks the mouse in TableView
  100. listColView.MouseClick += (s, e) => {
  101. listColView.ScreenToCell (e.MouseEvent.X, e.MouseEvent.Y, out int? clickedCol);
  102. };
  103. listColView.AddKeyBinding (Key.Space, Command.ToggleChecked);
  104. }
  105. private void SetupScrollBar ()
  106. {
  107. var scrollBar = new ScrollBarView (listColView, true); // (listColView, true, true);
  108. scrollBar.ChangedPosition += (s, e) => {
  109. listColView.RowOffset = scrollBar.Position;
  110. if (listColView.RowOffset != scrollBar.Position) {
  111. scrollBar.Position = listColView.RowOffset;
  112. }
  113. listColView.SetNeedsDisplay ();
  114. };
  115. /*
  116. scrollBar.OtherScrollBarView.ChangedPosition += (s,e) => {
  117. listColView.ColumnOffset = scrollBar.OtherScrollBarView.Position;
  118. if (listColView.ColumnOffset != scrollBar.OtherScrollBarView.Position) {
  119. scrollBar.OtherScrollBarView.Position = listColView.ColumnOffset;
  120. }
  121. listColView.SetNeedsDisplay ();
  122. };
  123. */
  124. listColView.DrawContent += (s, e) => {
  125. scrollBar.Size = listColView.Table?.Rows ?? 0;
  126. scrollBar.Position = listColView.RowOffset;
  127. //scrollBar.OtherScrollBarView.Size = listColView.Table?.Columns - 1 ?? 0;
  128. //scrollBar.OtherScrollBarView.Position = listColView.ColumnOffset;
  129. scrollBar.Refresh ();
  130. };
  131. }
  132. private void TableViewKeyPress (object sender, KeyEventEventArgs e)
  133. {
  134. if (e.KeyEvent.Key == Key.DeleteChar) {
  135. // set all selected cells to null
  136. foreach (var pt in listColView.GetAllSelectedCells ()) {
  137. currentTable.Rows [pt.Y] [pt.X] = DBNull.Value;
  138. }
  139. listColView.Update ();
  140. e.Handled = true;
  141. }
  142. }
  143. private void ToggleTopline ()
  144. {
  145. _miTopline.Checked = !_miTopline.Checked;
  146. listColView.Style.ShowHorizontalHeaderOverline = (bool)_miTopline.Checked;
  147. listColView.Update ();
  148. }
  149. private void ToggleBottomline ()
  150. {
  151. _miBottomline.Checked = !_miBottomline.Checked;
  152. listColView.Style.ShowHorizontalBottomline = (bool)_miBottomline.Checked;
  153. listColView.Update ();
  154. }
  155. private void ToggleExpandLastColumn ()
  156. {
  157. _miExpandLastColumn.Checked = !_miExpandLastColumn.Checked;
  158. listColView.Style.ExpandLastColumn = (bool)_miExpandLastColumn.Checked;
  159. listColView.Update ();
  160. }
  161. private void ToggleAlwaysUseNormalColorForVerticalCellLines ()
  162. {
  163. _miAlwaysUseNormalColorForVerticalCellLines.Checked = !_miAlwaysUseNormalColorForVerticalCellLines.Checked;
  164. listColView.Style.AlwaysUseNormalColorForVerticalCellLines = (bool)_miAlwaysUseNormalColorForVerticalCellLines.Checked;
  165. listColView.Update ();
  166. }
  167. private void ToggleSmoothScrolling ()
  168. {
  169. _miSmoothScrolling.Checked = !_miSmoothScrolling.Checked;
  170. listColView.Style.SmoothHorizontalScrolling = (bool)_miSmoothScrolling.Checked;
  171. listColView.Update ();
  172. }
  173. private void ToggleCellLines ()
  174. {
  175. _miCellLines.Checked = !_miCellLines.Checked;
  176. listColView.Style.ShowVerticalCellLines = (bool)_miCellLines.Checked;
  177. listColView.Update ();
  178. }
  179. private void ToggleAlternatingColors ()
  180. {
  181. //toggle menu item
  182. _miAlternatingColors.Checked = !_miAlternatingColors.Checked;
  183. if (_miAlternatingColors.Checked == true) {
  184. listColView.Style.RowColorGetter = (a) => { return a.RowIndex % 2 == 0 ? alternatingColorScheme : null; };
  185. } else {
  186. listColView.Style.RowColorGetter = null;
  187. }
  188. listColView.SetNeedsDisplay ();
  189. }
  190. private void ToggleInvertSelectedCellFirstCharacter ()
  191. {
  192. //toggle menu item
  193. _miCursor.Checked = !_miCursor.Checked;
  194. listColView.Style.InvertSelectedCellFirstCharacter = (bool)_miCursor.Checked;
  195. listColView.SetNeedsDisplay ();
  196. }
  197. private void ToggleVerticalOrientation ()
  198. {
  199. _miOrientVertical.Checked = !_miOrientVertical.Checked;
  200. if ((ListTableSource)listColView.Table != null) {
  201. ((ListTableSource)listColView.Table).Style.Orientation = (bool)_miOrientVertical.Checked ? Orientation.Vertical : Orientation.Horizontal;
  202. listColView.SetNeedsDisplay ();
  203. }
  204. }
  205. private void ToggleScrollParallel ()
  206. {
  207. _miScrollParallel.Checked = !_miScrollParallel.Checked;
  208. if ((ListTableSource)listColView.Table != null) {
  209. ((ListTableSource)listColView.Table).Style.ScrollParallel = (bool)_miScrollParallel.Checked;
  210. listColView.SetNeedsDisplay ();
  211. }
  212. }
  213. private void SetListMinWidth ()
  214. {
  215. RunListWidthDialog ("MinCellWidth", (s, v) => s.MinCellWidth = v, (s) => s.MinCellWidth);
  216. listColView.SetNeedsDisplay ();
  217. }
  218. private void SetListMaxWidth ()
  219. {
  220. RunListWidthDialog ("MaxCellWidth", (s, v) => s.MaxCellWidth = v, (s) => s.MaxCellWidth);
  221. listColView.SetNeedsDisplay ();
  222. }
  223. private void RunListWidthDialog (string prompt, Action<TableView, int> setter, Func<TableView, int> getter)
  224. {
  225. var accepted = false;
  226. var ok = new Button ("Ok", is_default: true);
  227. ok.Clicked += (s, e) => { accepted = true; Application.RequestStop (); };
  228. var cancel = new Button ("Cancel");
  229. cancel.Clicked += (s, e) => { Application.RequestStop (); };
  230. var d = new Dialog (ok, cancel) { Title = prompt };
  231. var tf = new TextField () {
  232. Text = getter (listColView).ToString (),
  233. X = 0,
  234. Y = 1,
  235. Width = Dim.Fill ()
  236. };
  237. d.Add (tf);
  238. tf.SetFocus ();
  239. Application.Run (d);
  240. if (accepted) {
  241. try {
  242. setter (listColView, int.Parse (tf.Text));
  243. } catch (Exception ex) {
  244. MessageBox.ErrorQuery (60, 20, "Failed to set", ex.Message, "Ok");
  245. }
  246. }
  247. }
  248. private void CloseExample ()
  249. {
  250. listColView.Table = null;
  251. }
  252. private void Quit ()
  253. {
  254. Application.RequestStop ();
  255. }
  256. private void OpenSimpleList (bool big)
  257. {
  258. SetTable (BuildSimpleList (big ? 1023 : 31));
  259. }
  260. private void SetTable (IList list)
  261. {
  262. listColView.Table = new ListTableSource (list, listColView);
  263. if ((ListTableSource)listColView.Table != null) {
  264. currentTable = ((ListTableSource)listColView.Table).DataTable;
  265. }
  266. }
  267. /// <summary>
  268. /// Builds a simple list in which values are the index. This helps testing that scrolling etc is working correctly and not skipping out values when paging
  269. /// </summary>
  270. /// <param name="items"></param>
  271. /// <returns></returns>
  272. public static IList BuildSimpleList (int items)
  273. {
  274. var list = new List<object> ();
  275. for (int i = 0; i < items; i++) {
  276. list.Add ("Item " + i);
  277. }
  278. return list;
  279. }
  280. }
  281. }