ListColumns.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Data;
  5. using Terminal.Gui;
  6. namespace UICatalog.Scenarios;
  7. [ScenarioMetadata ("ListColumns", "Implements a columned list via a data table.")]
  8. [ScenarioCategory ("TableView")]
  9. [ScenarioCategory ("Controls")]
  10. [ScenarioCategory ("Dialogs")]
  11. [ScenarioCategory ("Text and Formatting")]
  12. [ScenarioCategory ("Top Level Windows")]
  13. [ScenarioCategory ("Scrolling")]
  14. public class ListColumns : Scenario
  15. {
  16. private ColorScheme _alternatingColorScheme;
  17. private DataTable _currentTable;
  18. private TableView _listColView;
  19. private MenuItem _miAlternatingColors;
  20. private MenuItem _miAlwaysUseNormalColorForVerticalCellLines;
  21. private MenuItem _miBottomline;
  22. private MenuItem _miCellLines;
  23. private MenuItem _miCursor;
  24. private MenuItem _miExpandLastColumn;
  25. private MenuItem _miOrientVertical;
  26. private MenuItem _miScrollParallel;
  27. private MenuItem _miSmoothScrolling;
  28. private MenuItem _miTopline;
  29. /// <summary>
  30. /// Builds a simple list in which values are the index. This helps testing that scrolling etc is working
  31. /// correctly and not skipping out values when paging
  32. /// </summary>
  33. /// <param name="items"></param>
  34. /// <returns></returns>
  35. public static IList BuildSimpleList (int items)
  36. {
  37. List<object> list = new ();
  38. for (var i = 0; i < items; i++)
  39. {
  40. list.Add ("Item " + i);
  41. }
  42. return list;
  43. }
  44. public override void Setup ()
  45. {
  46. Win.Title = GetName ();
  47. Win.Y = 1; // menu
  48. Win.Height = Dim.Fill (1); // status bar
  49. _listColView = new()
  50. {
  51. X = 0,
  52. Y = 0,
  53. Width = Dim.Fill (),
  54. Height = Dim.Fill (1),
  55. Style = new()
  56. {
  57. ShowHeaders = false,
  58. ShowHorizontalHeaderOverline = false,
  59. ShowHorizontalHeaderUnderline = false,
  60. ShowHorizontalBottomline = false,
  61. ExpandLastColumn = false
  62. }
  63. };
  64. var listColStyle = new ListColumnStyle ();
  65. var menu = new MenuBar
  66. {
  67. Menus =
  68. [
  69. new (
  70. "_File",
  71. new MenuItem []
  72. {
  73. new (
  74. "Open_BigListExample",
  75. "",
  76. () => OpenSimpleList (true)
  77. ),
  78. new (
  79. "Open_SmListExample",
  80. "",
  81. () => OpenSimpleList (false)
  82. ),
  83. new (
  84. "_CloseExample",
  85. "",
  86. () => CloseExample ()
  87. ),
  88. new ("_Quit", "", () => Quit ())
  89. }
  90. ),
  91. new (
  92. "_View",
  93. new []
  94. {
  95. _miTopline =
  96. new ("_TopLine", "", () => ToggleTopline ())
  97. {
  98. Checked = _listColView.Style
  99. .ShowHorizontalHeaderOverline,
  100. CheckType = MenuItemCheckStyle.Checked
  101. },
  102. _miBottomline = new (
  103. "_BottomLine",
  104. "",
  105. () => ToggleBottomline ()
  106. )
  107. {
  108. Checked = _listColView.Style
  109. .ShowHorizontalBottomline,
  110. CheckType = MenuItemCheckStyle
  111. .Checked
  112. },
  113. _miCellLines = new (
  114. "_CellLines",
  115. "",
  116. () => ToggleCellLines ()
  117. )
  118. {
  119. Checked = _listColView.Style
  120. .ShowVerticalCellLines,
  121. CheckType = MenuItemCheckStyle
  122. .Checked
  123. },
  124. _miExpandLastColumn = new (
  125. "_ExpandLastColumn",
  126. "",
  127. () => ToggleExpandLastColumn ()
  128. )
  129. {
  130. Checked = _listColView.Style.ExpandLastColumn,
  131. CheckType = MenuItemCheckStyle.Checked
  132. },
  133. _miAlwaysUseNormalColorForVerticalCellLines =
  134. new (
  135. "_AlwaysUseNormalColorForVerticalCellLines",
  136. "",
  137. () =>
  138. ToggleAlwaysUseNormalColorForVerticalCellLines ()
  139. )
  140. {
  141. Checked = _listColView.Style
  142. .AlwaysUseNormalColorForVerticalCellLines,
  143. CheckType = MenuItemCheckStyle.Checked
  144. },
  145. _miSmoothScrolling = new (
  146. "_SmoothHorizontalScrolling",
  147. "",
  148. () => ToggleSmoothScrolling ()
  149. )
  150. {
  151. Checked = _listColView.Style
  152. .SmoothHorizontalScrolling,
  153. CheckType = MenuItemCheckStyle.Checked
  154. },
  155. _miAlternatingColors = new (
  156. "Alternating Colors",
  157. "",
  158. () => ToggleAlternatingColors ()
  159. ) { CheckType = MenuItemCheckStyle.Checked },
  160. _miCursor = new (
  161. "Invert Selected Cell First Character",
  162. "",
  163. () =>
  164. ToggleInvertSelectedCellFirstCharacter ()
  165. )
  166. {
  167. Checked = _listColView.Style
  168. .InvertSelectedCellFirstCharacter,
  169. CheckType = MenuItemCheckStyle.Checked
  170. }
  171. }
  172. ),
  173. new (
  174. "_List",
  175. new []
  176. {
  177. //new MenuItem ("_Hide Headers", "", HideHeaders),
  178. _miOrientVertical = new (
  179. "_OrientVertical",
  180. "",
  181. () => ToggleVerticalOrientation ()
  182. )
  183. {
  184. Checked = listColStyle.Orientation
  185. == Orientation.Vertical,
  186. CheckType = MenuItemCheckStyle.Checked
  187. },
  188. _miScrollParallel = new (
  189. "_ScrollParallel",
  190. "",
  191. () => ToggleScrollParallel ()
  192. )
  193. {
  194. Checked = listColStyle.ScrollParallel,
  195. CheckType = MenuItemCheckStyle.Checked
  196. },
  197. new ("Set _Max Cell Width", "", SetListMaxWidth),
  198. new ("Set Mi_n Cell Width", "", SetListMinWidth)
  199. }
  200. )
  201. ]
  202. };
  203. Top.Add (menu);
  204. var statusBar = new StatusBar (
  205. new StatusItem []
  206. {
  207. new (
  208. KeyCode.F2,
  209. "~F2~ OpenBigListEx",
  210. () => OpenSimpleList (true)
  211. ),
  212. new (
  213. KeyCode.F3,
  214. "~F3~ CloseExample",
  215. () => CloseExample ()
  216. ),
  217. new (
  218. KeyCode.F4,
  219. "~F4~ OpenSmListEx",
  220. () => OpenSimpleList (false)
  221. ),
  222. new (
  223. Application.QuitKey,
  224. $"{Application.QuitKey} to Quit",
  225. () => Quit ()
  226. )
  227. }
  228. );
  229. Top.Add (statusBar);
  230. Win.Add (_listColView);
  231. var selectedCellLabel = new Label
  232. {
  233. X = 0,
  234. Y = Pos.Bottom (_listColView),
  235. Text = "0,0",
  236. Width = Dim.Fill (),
  237. TextJustification = Alignment.Right
  238. };
  239. Win.Add (selectedCellLabel);
  240. _listColView.SelectedCellChanged += (s, e) => { selectedCellLabel.Text = $"{_listColView.SelectedRow},{_listColView.SelectedColumn}"; };
  241. _listColView.KeyDown += TableViewKeyPress;
  242. SetupScrollBar ();
  243. _alternatingColorScheme = new()
  244. {
  245. Disabled = Win.ColorScheme.Disabled,
  246. HotFocus = Win.ColorScheme.HotFocus,
  247. Focus = Win.ColorScheme.Focus,
  248. Normal = new (Color.White, Color.BrightBlue)
  249. };
  250. // if user clicks the mouse in TableView
  251. _listColView.MouseClick += (s, e) => { _listColView.ScreenToCell (e.MouseEvent.X, e.MouseEvent.Y, out int? clickedCol); };
  252. _listColView.KeyBindings.Add (Key.Space, Command.Accept);
  253. }
  254. private void CloseExample () { _listColView.Table = null; }
  255. private void OpenSimpleList (bool big) { SetTable (BuildSimpleList (big ? 1023 : 31)); }
  256. private void Quit () { Application.RequestStop (); }
  257. private void RunListWidthDialog (string prompt, Action<TableView, int> setter, Func<TableView, int> getter)
  258. {
  259. var accepted = false;
  260. var ok = new Button { Text = "Ok", IsDefault = true };
  261. ok.Accept += (s, e) =>
  262. {
  263. accepted = true;
  264. Application.RequestStop ();
  265. };
  266. var cancel = new Button { Text = "Cancel" };
  267. cancel.Accept += (s, e) => { Application.RequestStop (); };
  268. var d = new Dialog { Title = prompt, Buttons = [ok, cancel] };
  269. var tf = new TextField { Text = getter (_listColView).ToString (), X = 0, Y = 1, Width = Dim.Fill () };
  270. d.Add (tf);
  271. tf.SetFocus ();
  272. Application.Run (d);
  273. d.Dispose ();
  274. if (accepted)
  275. {
  276. try
  277. {
  278. setter (_listColView, int.Parse (tf.Text));
  279. }
  280. catch (Exception ex)
  281. {
  282. MessageBox.ErrorQuery (60, 20, "Failed to set", ex.Message, "Ok");
  283. }
  284. }
  285. }
  286. private void SetListMaxWidth ()
  287. {
  288. RunListWidthDialog ("MaxCellWidth", (s, v) => s.MaxCellWidth = v, s => s.MaxCellWidth);
  289. _listColView.SetNeedsDisplay ();
  290. }
  291. private void SetListMinWidth ()
  292. {
  293. RunListWidthDialog ("MinCellWidth", (s, v) => s.MinCellWidth = v, s => s.MinCellWidth);
  294. _listColView.SetNeedsDisplay ();
  295. }
  296. private void SetTable (IList list)
  297. {
  298. _listColView.Table = new ListTableSource (list, _listColView);
  299. if ((ListTableSource)_listColView.Table != null)
  300. {
  301. _currentTable = ((ListTableSource)_listColView.Table).DataTable;
  302. }
  303. }
  304. private void SetupScrollBar ()
  305. {
  306. var scrollBar = new ScrollBarView (_listColView, true); // (listColView, true, true);
  307. scrollBar.ChangedPosition += (s, e) =>
  308. {
  309. _listColView.RowOffset = scrollBar.Position;
  310. if (_listColView.RowOffset != scrollBar.Position)
  311. {
  312. scrollBar.Position = _listColView.RowOffset;
  313. }
  314. _listColView.SetNeedsDisplay ();
  315. };
  316. /*
  317. scrollBar.OtherScrollBarView.ChangedPosition += (s,e) => {
  318. listColView.ColumnOffset = scrollBar.OtherScrollBarView.Position;
  319. if (listColView.ColumnOffset != scrollBar.OtherScrollBarView.Position) {
  320. scrollBar.OtherScrollBarView.Position = listColView.ColumnOffset;
  321. }
  322. listColView.SetNeedsDisplay ();
  323. };
  324. */
  325. _listColView.DrawContent += (s, e) =>
  326. {
  327. scrollBar.Size = _listColView.Table?.Rows ?? 0;
  328. scrollBar.Position = _listColView.RowOffset;
  329. //scrollBar.OtherScrollBarView.Size = listColView.Table?.Columns - 1 ?? 0;
  330. //scrollBar.OtherScrollBarView.Position = listColView.ColumnOffset;
  331. scrollBar.Refresh ();
  332. };
  333. }
  334. private void TableViewKeyPress (object sender, Key e)
  335. {
  336. if (e.KeyCode == KeyCode.Delete)
  337. {
  338. // set all selected cells to null
  339. foreach (Point pt in _listColView.GetAllSelectedCells ())
  340. {
  341. _currentTable.Rows [pt.Y] [pt.X] = DBNull.Value;
  342. }
  343. _listColView.Update ();
  344. e.Handled = true;
  345. }
  346. }
  347. private void ToggleAlternatingColors ()
  348. {
  349. //toggle menu item
  350. _miAlternatingColors.Checked = !_miAlternatingColors.Checked;
  351. if (_miAlternatingColors.Checked == true)
  352. {
  353. _listColView.Style.RowColorGetter = a => { return a.RowIndex % 2 == 0 ? _alternatingColorScheme : null; };
  354. }
  355. else
  356. {
  357. _listColView.Style.RowColorGetter = null;
  358. }
  359. _listColView.SetNeedsDisplay ();
  360. }
  361. private void ToggleAlwaysUseNormalColorForVerticalCellLines ()
  362. {
  363. _miAlwaysUseNormalColorForVerticalCellLines.Checked =
  364. !_miAlwaysUseNormalColorForVerticalCellLines.Checked;
  365. _listColView.Style.AlwaysUseNormalColorForVerticalCellLines =
  366. (bool)_miAlwaysUseNormalColorForVerticalCellLines.Checked;
  367. _listColView.Update ();
  368. }
  369. private void ToggleBottomline ()
  370. {
  371. _miBottomline.Checked = !_miBottomline.Checked;
  372. _listColView.Style.ShowHorizontalBottomline = (bool)_miBottomline.Checked;
  373. _listColView.Update ();
  374. }
  375. private void ToggleCellLines ()
  376. {
  377. _miCellLines.Checked = !_miCellLines.Checked;
  378. _listColView.Style.ShowVerticalCellLines = (bool)_miCellLines.Checked;
  379. _listColView.Update ();
  380. }
  381. private void ToggleExpandLastColumn ()
  382. {
  383. _miExpandLastColumn.Checked = !_miExpandLastColumn.Checked;
  384. _listColView.Style.ExpandLastColumn = (bool)_miExpandLastColumn.Checked;
  385. _listColView.Update ();
  386. }
  387. private void ToggleInvertSelectedCellFirstCharacter ()
  388. {
  389. //toggle menu item
  390. _miCursor.Checked = !_miCursor.Checked;
  391. _listColView.Style.InvertSelectedCellFirstCharacter = (bool)_miCursor.Checked;
  392. _listColView.SetNeedsDisplay ();
  393. }
  394. private void ToggleScrollParallel ()
  395. {
  396. _miScrollParallel.Checked = !_miScrollParallel.Checked;
  397. if ((ListTableSource)_listColView.Table != null)
  398. {
  399. ((ListTableSource)_listColView.Table).Style.ScrollParallel = (bool)_miScrollParallel.Checked;
  400. _listColView.SetNeedsDisplay ();
  401. }
  402. }
  403. private void ToggleSmoothScrolling ()
  404. {
  405. _miSmoothScrolling.Checked = !_miSmoothScrolling.Checked;
  406. _listColView.Style.SmoothHorizontalScrolling = (bool)_miSmoothScrolling.Checked;
  407. _listColView.Update ();
  408. }
  409. private void ToggleTopline ()
  410. {
  411. _miTopline.Checked = !_miTopline.Checked;
  412. _listColView.Style.ShowHorizontalHeaderOverline = (bool)_miTopline.Checked;
  413. _listColView.Update ();
  414. }
  415. private void ToggleVerticalOrientation ()
  416. {
  417. _miOrientVertical.Checked = !_miOrientVertical.Checked;
  418. if ((ListTableSource)_listColView.Table != null)
  419. {
  420. ((ListTableSource)_listColView.Table).Style.Orientation = (bool)_miOrientVertical.Checked
  421. ? Orientation.Vertical
  422. : Orientation.Horizontal;
  423. _listColView.SetNeedsDisplay ();
  424. }
  425. }
  426. }