TreeViewFileSystem.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using Terminal.Gui;
  6. namespace UICatalog.Scenarios {
  7. [ScenarioMetadata (Name: "TreeViewFileSystem", Description: "Hierarchical file system explorer based on TreeView")]
  8. [ScenarioCategory ("Controls")]
  9. [ScenarioCategory ("Dialogs")]
  10. [ScenarioCategory ("Text")]
  11. [ScenarioCategory ("Dialogs")]
  12. [ScenarioCategory ("TopLevel")]
  13. class TreeViewFileSystem : Scenario {
  14. /// <summary>
  15. /// A tree view where nodes are files and folders
  16. /// </summary>
  17. TreeView<FileSystemInfo> treeViewFiles;
  18. /// <summary>
  19. /// A tree view where nodes are <see cref="ITreeNode"/>
  20. /// </summary>
  21. TreeView treeViewNodes;
  22. MenuItem miShowLines;
  23. private MenuItem miPlusMinus;
  24. private MenuItem miArrowSymbols;
  25. private MenuItem miNoSymbols;
  26. private MenuItem miColoredSymbols;
  27. private Terminal.Gui.Attribute green;
  28. private Terminal.Gui.Attribute red;
  29. public override void Setup ()
  30. {
  31. Win.Title = this.GetName();
  32. Win.Y = 1; // menu
  33. Win.Height = Dim.Fill (1); // status bar
  34. Top.LayoutSubviews ();
  35. var menu = new MenuBar (new MenuBarItem [] {
  36. new MenuBarItem ("_File", new MenuItem [] {
  37. new MenuItem ("_Quit", "", () => Quit()),
  38. }),
  39. new MenuBarItem ("_View", new MenuItem [] {
  40. miShowLines = new MenuItem ("_ShowLines", "", () => ShowLines()){
  41. Checked = true, CheckType = MenuItemCheckStyle.Checked
  42. },
  43. miPlusMinus = new MenuItem ("_PlusMinusSymbols", "", () => SetExpandableSymbols('+','-')){Checked = true, CheckType = MenuItemCheckStyle.Radio},
  44. miArrowSymbols = new MenuItem ("_ArrowSymbols", "", () => SetExpandableSymbols('>','v')){Checked = false, CheckType = MenuItemCheckStyle.Radio},
  45. miNoSymbols = new MenuItem ("_NoSymbols", "", () => SetExpandableSymbols(null,null)){Checked = false, CheckType = MenuItemCheckStyle.Radio},
  46. miColoredSymbols = new MenuItem ("_ColoredSymbols", "", () => ShowColoredExpandableSymbols()){Checked = false, CheckType = MenuItemCheckStyle.Checked},
  47. }),
  48. });
  49. Top.Add (menu);
  50. var statusBar = new StatusBar (new StatusItem [] {
  51. new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => Quit()),
  52. });
  53. Top.Add (statusBar);
  54. var lblFiles = new Label("File Tree:"){
  55. X=0,
  56. Y=1
  57. };
  58. Win.Add(lblFiles);
  59. treeViewFiles = new TreeView<FileSystemInfo> () {
  60. X = 0,
  61. Y = Pos.Bottom(lblFiles),
  62. Width = 40,
  63. Height = 9,
  64. };
  65. SetupFileTree();
  66. Win.Add(treeViewFiles);
  67. var lblNodeTree = new Label("Node Tree:"){
  68. X=0,
  69. Y=Pos.Bottom(treeViewFiles)+1
  70. };
  71. Win.Add(lblNodeTree);
  72. treeViewNodes = new TreeView() {
  73. X = 0,
  74. Y = Pos.Bottom(lblNodeTree),
  75. Width = Dim.Fill (),
  76. Height = Dim.Fill (),
  77. };
  78. SetupNodeTree();
  79. Win.Add(treeViewNodes);
  80. green = Application.Driver.MakeAttribute (Color.Green, Color.Blue);
  81. red = Application.Driver.MakeAttribute (Color.Red, Color.Blue);
  82. }
  83. private void SetupNodeTree ()
  84. {
  85. // Add 2 root nodes with simple set of subfolders
  86. treeViewNodes.AddObject(CreateSimpleRoot());
  87. treeViewNodes.AddObject(CreateSimpleRoot());
  88. }
  89. private void SetupFileTree ()
  90. {
  91. // setup delegates
  92. treeViewFiles.TreeBuilder = new DelegateTreeBuilder<FileSystemInfo>(
  93. // Determines how to compute children of any given branch
  94. GetChildren,
  95. // As a shortcut to enumerating half the file system, tell tree that all directories are expandable (even if they turn out to be empty later on)
  96. (o)=>o is DirectoryInfo
  97. );
  98. // Determines how to represent objects as strings on the screen
  99. treeViewFiles.AspectGetter = FileSystemAspectGetter;
  100. treeViewFiles.AddObjects(DriveInfo.GetDrives().Select(d=>d.RootDirectory));
  101. }
  102. private void ShowLines ()
  103. {
  104. miShowLines.Checked = !miShowLines.Checked;
  105. treeViewNodes.Style.ShowBranchLines = miShowLines.Checked;
  106. treeViewNodes.SetNeedsDisplay();
  107. treeViewFiles.Style.ShowBranchLines = miShowLines.Checked;
  108. treeViewFiles.SetNeedsDisplay();
  109. }
  110. private void SetExpandableSymbols(Rune? expand, Rune? collapse)
  111. {
  112. miPlusMinus.Checked = expand == '+';
  113. miArrowSymbols.Checked = expand == '>';
  114. miNoSymbols.Checked = expand == null;
  115. treeViewNodes.Style.ExpandableSymbol = expand;
  116. treeViewNodes.Style.CollapseableSymbol = collapse;
  117. treeViewNodes.SetNeedsDisplay();
  118. treeViewFiles.Style.ExpandableSymbol = expand;
  119. treeViewFiles.Style.CollapseableSymbol = collapse;
  120. treeViewFiles.SetNeedsDisplay();
  121. }
  122. private void ShowColoredExpandableSymbols()
  123. {
  124. miColoredSymbols.Checked = !miColoredSymbols.Checked;
  125. ShowColoredExpandableSymbols(treeViewFiles);
  126. ShowColoredExpandableSymbols(treeViewNodes);
  127. }
  128. private void ShowColoredExpandableSymbols (ITreeView treeView)
  129. {
  130. // Toggle Green expand symbols
  131. if(miColoredSymbols.Checked)
  132. treeView.Style.ExpandableSymbolColor = green;
  133. else
  134. treeView.Style.ExpandableSymbolColor = null; //clear it
  135. // Toggle Red collapse symbols
  136. if(miColoredSymbols.Checked)
  137. treeView.Style.CollapseableSymbolColor = red;
  138. else
  139. treeView.Style.CollapseableSymbolColor = null; //clear it
  140. treeView.SetNeedsDisplay();
  141. }
  142. private ITreeNode CreateSimpleRoot ()
  143. {
  144. return new TreeNode("Root"){
  145. Children = new List<ITreeNode>()
  146. {
  147. new TreeNode("Folder_1"){
  148. Children = new List<ITreeNode>()
  149. {
  150. new TreeNode("Folder_1.1"){
  151. Children = new List<ITreeNode>()
  152. {
  153. new TreeNode("File_1.1.1"),
  154. new TreeNode("File_1.1.2")
  155. }},
  156. new TreeNode("Folder_1.2"){
  157. Children = new List<ITreeNode>()
  158. {
  159. new TreeNode("File_1.2.1"),
  160. new TreeNode("File_1.2.2")
  161. }},
  162. new TreeNode("File_1.1")
  163. }},
  164. new TreeNode("Folder_2"){
  165. Children = new List<ITreeNode>()
  166. {
  167. new TreeNode("Folder_2.1"){
  168. Children = new List<ITreeNode>()
  169. {
  170. new TreeNode("File_2.1.1"),
  171. new TreeNode("File_2.1.2")
  172. }},
  173. new TreeNode("Folder_2.2"){
  174. Children = new List<ITreeNode>()
  175. {
  176. new TreeNode("File_2.2.1"),
  177. new TreeNode("File_2.2.2")
  178. }},
  179. new TreeNode("File_2.1")
  180. }},
  181. new TreeNode("Folder_3"){
  182. Children = new List<ITreeNode>()
  183. {
  184. new TreeNode("Folder_3.1"){
  185. Children = new List<ITreeNode>()
  186. {
  187. new TreeNode("File_3.1.1"),
  188. new TreeNode("File_3.1.2")
  189. }},
  190. new TreeNode("Folder_3.2"){
  191. Children = new List<ITreeNode>()
  192. {
  193. new TreeNode("File_3.2.1"),
  194. new TreeNode("File_3.2.2")
  195. }},
  196. new TreeNode("File_3.1")
  197. }}
  198. }
  199. };
  200. }
  201. private IEnumerable<FileSystemInfo> GetChildren(FileSystemInfo model)
  202. {
  203. // If it is a directory it's children are all contained files and dirs
  204. if(model is DirectoryInfo d) {
  205. try {
  206. return d.GetFileSystemInfos()
  207. //show directories first
  208. .OrderBy(a=>a is DirectoryInfo ? 0:1)
  209. .ThenBy(b=>b.Name);
  210. }
  211. catch(SystemException) {
  212. // Access violation or other error getting the file list for directory
  213. return Enumerable.Empty<FileSystemInfo>();
  214. }
  215. }
  216. return Enumerable.Empty<FileSystemInfo>();;
  217. }
  218. private string FileSystemAspectGetter(FileSystemInfo model)
  219. {
  220. if(model is DirectoryInfo d)
  221. return d.Name;
  222. if(model is FileInfo f)
  223. return f.Name;
  224. return model.ToString();
  225. }
  226. private void Quit ()
  227. {
  228. Application.RequestStop ();
  229. }
  230. }
  231. }