ListColumns.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  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 ("Scrolling")]
  13. public class ListColumns : Scenario
  14. {
  15. private Scheme _alternatingScheme;
  16. private DataTable _currentTable;
  17. private TableView _listColView;
  18. private MenuItem _miAlternatingColors;
  19. private MenuItem _miAlwaysUseNormalColorForVerticalCellLines;
  20. private MenuItem _miBottomline;
  21. private MenuItem _miCellLines;
  22. private MenuItem _miCursor;
  23. private MenuItem _miExpandLastColumn;
  24. private MenuItem _miOrientVertical;
  25. private MenuItem _miScrollParallel;
  26. private MenuItem _miSmoothScrolling;
  27. private MenuItem _miTopline;
  28. /// <summary>
  29. /// Builds a simple list in which values are the index. This helps testing that scrolling etc is working
  30. /// correctly and not skipping out values when paging
  31. /// </summary>
  32. /// <param name="items"></param>
  33. /// <returns></returns>
  34. public static IList BuildSimpleList (int items)
  35. {
  36. List<object> list = new ();
  37. for (var i = 0; i < items; i++)
  38. {
  39. list.Add ("Item " + i);
  40. }
  41. return list;
  42. }
  43. public override void Main ()
  44. {
  45. // Init
  46. Application.Init ();
  47. // Setup - Create a top-level application window and configure it.
  48. Toplevel top = new ();
  49. Window appWindow = new ()
  50. {
  51. Title = GetQuitKeyAndName ()
  52. };
  53. _listColView = new ()
  54. {
  55. Width = Dim.Fill (),
  56. Height = Dim.Fill (),
  57. Style = new ()
  58. {
  59. ShowHeaders = false,
  60. ShowHorizontalHeaderOverline = false,
  61. ShowHorizontalHeaderUnderline = false,
  62. ShowHorizontalBottomline = false,
  63. ExpandLastColumn = false
  64. }
  65. };
  66. var listColStyle = new ListColumnStyle ();
  67. var menu = new MenuBar
  68. {
  69. Menus =
  70. [
  71. new (
  72. "_File",
  73. new MenuItem []
  74. {
  75. new (
  76. "Open_BigListExample",
  77. "",
  78. () => OpenSimpleList (true)
  79. ),
  80. new (
  81. "Open_SmListExample",
  82. "",
  83. () => OpenSimpleList (false)
  84. ),
  85. new (
  86. "_CloseExample",
  87. "",
  88. () => CloseExample ()
  89. ),
  90. new ("_Quit", "", () => Quit ())
  91. }
  92. ),
  93. new (
  94. "_View",
  95. new []
  96. {
  97. _miTopline =
  98. new ("_TopLine", "", () => ToggleTopline ())
  99. {
  100. Checked = _listColView.Style
  101. .ShowHorizontalHeaderOverline,
  102. CheckType = MenuItemCheckStyle.Checked
  103. },
  104. _miBottomline = new (
  105. "_BottomLine",
  106. "",
  107. () => ToggleBottomline ()
  108. )
  109. {
  110. Checked = _listColView.Style
  111. .ShowHorizontalBottomline,
  112. CheckType = MenuItemCheckStyle.Checked
  113. },
  114. _miCellLines = new (
  115. "_CellLines",
  116. "",
  117. () => ToggleCellLines ()
  118. )
  119. {
  120. Checked = _listColView.Style
  121. .ShowVerticalCellLines,
  122. CheckType = MenuItemCheckStyle.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. var statusBar = new StatusBar (
  204. new Shortcut []
  205. {
  206. new (Key.F2, "OpenBigListEx", () => OpenSimpleList (true)),
  207. new (Key.F3, "CloseExample", CloseExample),
  208. new (Key.F4, "OpenSmListEx", () => OpenSimpleList (false)),
  209. new (Application.QuitKey, "Quit", Quit)
  210. }
  211. );
  212. appWindow.Add (_listColView);
  213. var selectedCellLabel = new Label
  214. {
  215. X = 0,
  216. Y = Pos.Bottom (_listColView),
  217. Text = "0,0",
  218. Width = Dim.Fill (),
  219. TextAlignment = Alignment.End
  220. };
  221. appWindow.Add (selectedCellLabel);
  222. _listColView.SelectedCellChanged += (s, e) => { selectedCellLabel.Text = $"{_listColView.SelectedRow},{_listColView.SelectedColumn}"; };
  223. _listColView.KeyDown += TableViewKeyPress;
  224. //SetupScrollBar ();
  225. _alternatingScheme = new ()
  226. {
  227. Disabled = appWindow.GetAttributeForRole(VisualRole.Disabled),
  228. HotFocus = appWindow.GetAttributeForRole (VisualRole.HotFocus),
  229. Focus = appWindow.GetAttributeForRole(VisualRole.Focus),
  230. Normal = new (Color.White, Color.BrightBlue)
  231. };
  232. // if user clicks the mouse in TableView
  233. _listColView.MouseClick += (s, e) => { _listColView.ScreenToCell (e.Position, out int? clickedCol); };
  234. _listColView.KeyBindings.ReplaceCommands (Key.Space, Command.Accept);
  235. top.Add (menu, appWindow, statusBar);
  236. appWindow.Y = 1;
  237. appWindow.Height = Dim.Fill(Dim.Func (() => statusBar.Frame.Height));
  238. // Run - Start the application.
  239. Application.Run (top);
  240. top.Dispose ();
  241. // Shutdown - Calling Application.Shutdown is required.
  242. Application.Shutdown ();
  243. }
  244. private void CloseExample () { _listColView.Table = null; }
  245. private void OpenSimpleList (bool big) { SetTable (BuildSimpleList (big ? 1023 : 31)); }
  246. private void Quit () { Application.RequestStop (); }
  247. private void RunListWidthDialog (string prompt, Action<TableView, int> setter, Func<TableView, int> getter)
  248. {
  249. var accepted = false;
  250. var ok = new Button { Text = "Ok", IsDefault = true };
  251. ok.Accepting += (s, e) =>
  252. {
  253. accepted = true;
  254. Application.RequestStop ();
  255. };
  256. var cancel = new Button { Text = "Cancel" };
  257. cancel.Accepting += (s, e) => { Application.RequestStop (); };
  258. var d = new Dialog { Title = prompt, Buttons = [ok, cancel] };
  259. var tf = new TextField { Text = getter (_listColView).ToString (), X = 0, Y = 0, Width = Dim.Fill () };
  260. d.Add (tf);
  261. tf.SetFocus ();
  262. Application.Run (d);
  263. d.Dispose ();
  264. if (accepted)
  265. {
  266. try
  267. {
  268. setter (_listColView, int.Parse (tf.Text));
  269. }
  270. catch (Exception ex)
  271. {
  272. MessageBox.ErrorQuery (60, 20, "Failed to set", ex.Message, "Ok");
  273. }
  274. }
  275. }
  276. private void SetListMaxWidth ()
  277. {
  278. RunListWidthDialog ("MaxCellWidth", (s, v) => s.MaxCellWidth = v, s => s.MaxCellWidth);
  279. _listColView.SetNeedsDraw ();
  280. }
  281. private void SetListMinWidth ()
  282. {
  283. RunListWidthDialog ("MinCellWidth", (s, v) => s.MinCellWidth = v, s => s.MinCellWidth);
  284. _listColView.SetNeedsDraw ();
  285. }
  286. private void SetTable (IList list)
  287. {
  288. _listColView.Table = new ListTableSource (list, _listColView);
  289. if ((ListTableSource)_listColView.Table != null)
  290. {
  291. _currentTable = ((ListTableSource)_listColView.Table).DataTable;
  292. }
  293. }
  294. //private void SetupScrollBar ()
  295. //{
  296. // var scrollBar = new ScrollBarView (_listColView, true); // (listColView, true, true);
  297. // scrollBar.ChangedPosition += (s, e) =>
  298. // {
  299. // _listColView.RowOffset = scrollBar.Position;
  300. // if (_listColView.RowOffset != scrollBar.Position)
  301. // {
  302. // scrollBar.Position = _listColView.RowOffset;
  303. // }
  304. // _listColView.SetNeedsDraw ();
  305. // };
  306. // /*
  307. // scrollBar.OtherScrollBarView.ChangedPosition += (s,e) => {
  308. // listColView.ColumnOffset = scrollBar.OtherScrollBarView.Position;
  309. // if (listColView.ColumnOffset != scrollBar.OtherScrollBarView.Position) {
  310. // scrollBar.OtherScrollBarView.Position = listColView.ColumnOffset;
  311. // }
  312. // listColView.SetNeedsDraw ();
  313. // };
  314. // */
  315. // _listColView.DrawingContent += (s, e) =>
  316. // {
  317. // scrollBar.Size = _listColView.Table?.Rows ?? 0;
  318. // scrollBar.Position = _listColView.RowOffset;
  319. // //scrollBar.OtherScrollBarView.Size = listColView.Table?.Columns - 1 ?? 0;
  320. // //scrollBar.OtherScrollBarView.Position = listColView.ColumnOffset;
  321. // scrollBar.Refresh ();
  322. // };
  323. //}
  324. private void TableViewKeyPress (object sender, Key e)
  325. {
  326. if (e.KeyCode == Key.Delete)
  327. {
  328. // set all selected cells to null
  329. foreach (Point pt in _listColView.GetAllSelectedCells ())
  330. {
  331. _currentTable.Rows [pt.Y] [pt.X] = DBNull.Value;
  332. }
  333. _listColView.Update ();
  334. e.Handled = true;
  335. }
  336. }
  337. private void ToggleAlternatingColors ()
  338. {
  339. //toggle menu item
  340. _miAlternatingColors.Checked = !_miAlternatingColors.Checked;
  341. if (_miAlternatingColors.Checked == true)
  342. {
  343. _listColView.Style.RowColorGetter = a => { return a.RowIndex % 2 == 0 ? _alternatingScheme : null; };
  344. }
  345. else
  346. {
  347. _listColView.Style.RowColorGetter = null;
  348. }
  349. _listColView.SetNeedsDraw ();
  350. }
  351. private void ToggleAlwaysUseNormalColorForVerticalCellLines ()
  352. {
  353. _miAlwaysUseNormalColorForVerticalCellLines.Checked =
  354. !_miAlwaysUseNormalColorForVerticalCellLines.Checked;
  355. _listColView.Style.AlwaysUseNormalColorForVerticalCellLines =
  356. (bool)_miAlwaysUseNormalColorForVerticalCellLines.Checked;
  357. _listColView.Update ();
  358. }
  359. private void ToggleBottomline ()
  360. {
  361. _miBottomline.Checked = !_miBottomline.Checked;
  362. _listColView.Style.ShowHorizontalBottomline = (bool)_miBottomline.Checked;
  363. _listColView.Update ();
  364. }
  365. private void ToggleCellLines ()
  366. {
  367. _miCellLines.Checked = !_miCellLines.Checked;
  368. _listColView.Style.ShowVerticalCellLines = (bool)_miCellLines.Checked;
  369. _listColView.Update ();
  370. }
  371. private void ToggleExpandLastColumn ()
  372. {
  373. _miExpandLastColumn.Checked = !_miExpandLastColumn.Checked;
  374. _listColView.Style.ExpandLastColumn = (bool)_miExpandLastColumn.Checked;
  375. _listColView.Update ();
  376. }
  377. private void ToggleInvertSelectedCellFirstCharacter ()
  378. {
  379. //toggle menu item
  380. _miCursor.Checked = !_miCursor.Checked;
  381. _listColView.Style.InvertSelectedCellFirstCharacter = (bool)_miCursor.Checked;
  382. _listColView.SetNeedsDraw ();
  383. }
  384. private void ToggleScrollParallel ()
  385. {
  386. _miScrollParallel.Checked = !_miScrollParallel.Checked;
  387. if ((ListTableSource)_listColView.Table != null)
  388. {
  389. ((ListTableSource)_listColView.Table).Style.ScrollParallel = (bool)_miScrollParallel.Checked;
  390. _listColView.SetNeedsDraw ();
  391. }
  392. }
  393. private void ToggleSmoothScrolling ()
  394. {
  395. _miSmoothScrolling.Checked = !_miSmoothScrolling.Checked;
  396. _listColView.Style.SmoothHorizontalScrolling = (bool)_miSmoothScrolling.Checked;
  397. _listColView.Update ();
  398. }
  399. private void ToggleTopline ()
  400. {
  401. _miTopline.Checked = !_miTopline.Checked;
  402. _listColView.Style.ShowHorizontalHeaderOverline = (bool)_miTopline.Checked;
  403. _listColView.Update ();
  404. }
  405. private void ToggleVerticalOrientation ()
  406. {
  407. _miOrientVertical.Checked = !_miOrientVertical.Checked;
  408. if ((ListTableSource)_listColView.Table != null)
  409. {
  410. ((ListTableSource)_listColView.Table).Style.Orientation = (bool)_miOrientVertical.Checked
  411. ? Orientation.Vertical
  412. : Orientation.Horizontal;
  413. _listColView.SetNeedsDraw ();
  414. }
  415. }
  416. }