ListColumns.cs 18 KB

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