123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564 |
- using System.Collections.Generic;
- using System.IO;
- using System.IO.Abstractions;
- using System.Linq;
- using System.Text;
- using Terminal.Gui;
- namespace UICatalog.Scenarios;
- [ScenarioMetadata ("File System Explorer", "Hierarchical file system explorer demonstrating TreeView.")]
- [ScenarioCategory ("Controls")]
- [ScenarioCategory ("TreeView")]
- [ScenarioCategory ("Files and IO")]
- public class TreeViewFileSystem : Scenario
- {
- private readonly FileSystemIconProvider _iconProvider = new ();
- private DetailsFrame _detailsFrame;
- private MenuItem _miArrowSymbols;
- private MenuItem _miBasicIcons;
- private MenuItem _miColoredSymbols;
- private MenuItem _miCursor;
- private MenuItem _miCustomColors;
- private MenuItem _miFullPaths;
- private MenuItem _miHighlightModelTextOnly;
- private MenuItem _miInvertSymbols;
- private MenuItem _miLeaveLastRow;
- private MenuItem _miMultiSelect;
- private MenuItem _miNerdIcons;
- private MenuItem _miNoSymbols;
- private MenuItem _miPlusMinus;
- private MenuItem _miShowLines;
- private MenuItem _miUnicodeIcons;
- /// <summary>A tree view where nodes are files and folders</summary>
- private TreeView<IFileSystemInfo> _treeViewFiles;
- public override void Main ()
- {
- Application.Init ();
- var win = new Window
- {
- Title = GetName (),
- Y = 1, // menu
- Height = Dim.Fill ()
- };
- var top = new Toplevel ();
- var menu = new MenuBar
- {
- Menus =
- [
- new MenuBarItem (
- "_File",
- new MenuItem []
- {
- new (
- "_Quit",
- $"{Application.QuitKey}",
- () => Quit ()
- )
- }
- ),
- new MenuBarItem (
- "_View",
- new []
- {
- _miFullPaths =
- new MenuItem ("_Full Paths", "", () => SetFullName ())
- {
- Checked = false, CheckType = MenuItemCheckStyle.Checked
- },
- _miMultiSelect = new MenuItem (
- "_Multi Select",
- "",
- () => SetMultiSelect ()
- )
- {
- Checked = true,
- CheckType = MenuItemCheckStyle
- .Checked
- }
- }
- ),
- new MenuBarItem (
- "_Style",
- new []
- {
- _miShowLines =
- new MenuItem ("_Show Lines", "", () => ShowLines ())
- {
- Checked = true, CheckType = MenuItemCheckStyle.Checked
- },
- null /*separator*/,
- _miPlusMinus =
- new MenuItem (
- "_Plus Minus Symbols",
- "+ -",
- () => SetExpandableSymbols (
- (Rune)'+',
- (Rune)'-'
- )
- ) { Checked = true, CheckType = MenuItemCheckStyle.Radio },
- _miArrowSymbols =
- new MenuItem (
- "_Arrow Symbols",
- "> v",
- () => SetExpandableSymbols (
- (Rune)'>',
- (Rune)'v'
- )
- ) { Checked = false, CheckType = MenuItemCheckStyle.Radio },
- _miNoSymbols =
- new MenuItem (
- "_No Symbols",
- "",
- () => SetExpandableSymbols (
- default (Rune),
- null
- )
- ) { Checked = false, CheckType = MenuItemCheckStyle.Radio },
- null /*separator*/,
- _miColoredSymbols =
- new MenuItem (
- "_Colored Symbols",
- "",
- () => ShowColoredExpandableSymbols ()
- ) { Checked = false, CheckType = MenuItemCheckStyle.Checked },
- _miInvertSymbols =
- new MenuItem (
- "_Invert Symbols",
- "",
- () => InvertExpandableSymbols ()
- ) { Checked = false, CheckType = MenuItemCheckStyle.Checked },
- null /*separator*/,
- _miBasicIcons =
- new MenuItem ("_Basic Icons", null, SetNoIcons)
- {
- Checked = false, CheckType = MenuItemCheckStyle.Radio
- },
- _miUnicodeIcons =
- new MenuItem ("_Unicode Icons", null, SetUnicodeIcons)
- {
- Checked = false, CheckType = MenuItemCheckStyle.Radio
- },
- _miNerdIcons =
- new MenuItem ("_Nerd Icons", null, SetNerdIcons)
- {
- Checked = false, CheckType = MenuItemCheckStyle.Radio
- },
- null /*separator*/,
- _miLeaveLastRow =
- new MenuItem (
- "_Leave Last Row",
- "",
- () => SetLeaveLastRow ()
- ) { Checked = true, CheckType = MenuItemCheckStyle.Checked },
- _miHighlightModelTextOnly =
- new MenuItem (
- "_Highlight Model Text Only",
- "",
- () => SetCheckHighlightModelTextOnly ()
- ) { Checked = false, CheckType = MenuItemCheckStyle.Checked },
- null /*separator*/,
- _miCustomColors =
- new MenuItem (
- "C_ustom Colors Hidden Files",
- "Yellow/Red",
- () => SetCustomColors ()
- ) { Checked = false, CheckType = MenuItemCheckStyle.Checked },
- null /*separator*/,
- _miCursor = new MenuItem (
- "Curs_or (MultiSelect only)",
- "",
- () => SetCursor ()
- ) { Checked = false, CheckType = MenuItemCheckStyle.Checked }
- }
- )
- ]
- };
- top.Add (menu);
- _treeViewFiles = new TreeView<IFileSystemInfo> { X = 0, Y = 0, Width = Dim.Percent (50), Height = Dim.Fill () };
- _treeViewFiles.DrawLine += TreeViewFiles_DrawLine;
- _detailsFrame = new DetailsFrame (_iconProvider)
- {
- X = Pos.Right (_treeViewFiles), Y = 0, Width = Dim.Fill (), Height = Dim.Fill ()
- };
- win.Add (_detailsFrame);
- _treeViewFiles.MouseClick += TreeViewFiles_MouseClick;
- _treeViewFiles.KeyDown += TreeViewFiles_KeyPress;
- _treeViewFiles.SelectionChanged += TreeViewFiles_SelectionChanged;
- SetupFileTree ();
- win.Add (_treeViewFiles);
- top.Add (win);
- _treeViewFiles.GoToFirst ();
- _treeViewFiles.Expand ();
- SetupScrollBar ();
- _treeViewFiles.SetFocus ();
- UpdateIconCheckedness ();
- Application.Run (top);
- top.Dispose ();
- Application.Shutdown ();
- }
- private string AspectGetter (IFileSystemInfo f) { return (_iconProvider.GetIconWithOptionalSpace (f) + f.Name).Trim (); }
- private void InvertExpandableSymbols ()
- {
- _miInvertSymbols.Checked = !_miInvertSymbols.Checked;
- _treeViewFiles.Style.InvertExpandSymbolColors = (bool)_miInvertSymbols.Checked;
- _treeViewFiles.SetNeedsDisplay ();
- }
- private void Quit () { Application.RequestStop (); }
- private void SetCheckHighlightModelTextOnly ()
- {
- _treeViewFiles.Style.HighlightModelTextOnly = !_treeViewFiles.Style.HighlightModelTextOnly;
- _miHighlightModelTextOnly.Checked = _treeViewFiles.Style.HighlightModelTextOnly;
- _treeViewFiles.SetNeedsDisplay ();
- }
- private void SetCursor ()
- {
- _miCursor.Checked = !_miCursor.Checked;
- _treeViewFiles.CursorVisibility =
- _miCursor.Checked == true ? CursorVisibility.Default : CursorVisibility.Invisible;
- }
- private void SetCustomColors ()
- {
- _miCustomColors.Checked = !_miCustomColors.Checked;
- if (_miCustomColors.Checked == true)
- {
- _treeViewFiles.ColorGetter = m =>
- {
- if (m is IDirectoryInfo && m.Attributes.HasFlag (FileAttributes.Hidden))
- {
- return new ColorScheme
- {
- Focus = new Attribute (
- Color.BrightRed,
- _treeViewFiles.ColorScheme.Focus.Background
- ),
- Normal = new Attribute (
- Color.BrightYellow,
- _treeViewFiles.ColorScheme.Normal.Background
- )
- };
- ;
- }
- if (m is IFileInfo && m.Attributes.HasFlag (FileAttributes.Hidden))
- {
- return new ColorScheme
- {
- Focus = new Attribute (
- Color.BrightRed,
- _treeViewFiles.ColorScheme.Focus.Background
- ),
- Normal = new Attribute (
- Color.BrightYellow,
- _treeViewFiles.ColorScheme.Normal.Background
- )
- };
- ;
- }
- return null;
- };
- }
- else
- {
- _treeViewFiles.ColorGetter = null;
- }
- _treeViewFiles.SetNeedsDisplay ();
- }
- private void SetExpandableSymbols (Rune expand, Rune? collapse)
- {
- _miPlusMinus.Checked = expand.Value == '+';
- _miArrowSymbols.Checked = expand.Value == '>';
- _miNoSymbols.Checked = expand.Value == default (int);
- _treeViewFiles.Style.ExpandableSymbol = expand;
- _treeViewFiles.Style.CollapseableSymbol = collapse;
- _treeViewFiles.SetNeedsDisplay ();
- }
- private void SetFullName ()
- {
- _miFullPaths.Checked = !_miFullPaths.Checked;
- if (_miFullPaths.Checked == true)
- {
- _treeViewFiles.AspectGetter = f => f.FullName;
- }
- else
- {
- _treeViewFiles.AspectGetter = f => f.Name;
- }
- _treeViewFiles.SetNeedsDisplay ();
- }
- private void SetLeaveLastRow ()
- {
- _miLeaveLastRow.Checked = !_miLeaveLastRow.Checked;
- _treeViewFiles.Style.LeaveLastRow = (bool)_miLeaveLastRow.Checked;
- }
- private void SetMultiSelect ()
- {
- _miMultiSelect.Checked = !_miMultiSelect.Checked;
- _treeViewFiles.MultiSelect = (bool)_miMultiSelect.Checked;
- }
- private void SetNerdIcons ()
- {
- _iconProvider.UseNerdIcons = true;
- UpdateIconCheckedness ();
- }
- private void SetNoIcons ()
- {
- _iconProvider.UseUnicodeCharacters = false;
- _iconProvider.UseNerdIcons = false;
- UpdateIconCheckedness ();
- }
- private void SetUnicodeIcons ()
- {
- _iconProvider.UseUnicodeCharacters = true;
- UpdateIconCheckedness ();
- }
- private void SetupFileTree ()
- {
- // setup how to build tree
- var fs = new FileSystem ();
- IEnumerable<IDirectoryInfo> rootDirs =
- DriveInfo.GetDrives ().Select (d => fs.DirectoryInfo.New (d.RootDirectory.FullName));
- _treeViewFiles.TreeBuilder = new FileSystemTreeBuilder ();
- _treeViewFiles.AddObjects (rootDirs);
- // Determines how to represent objects as strings on the screen
- _treeViewFiles.AspectGetter = AspectGetter;
- _iconProvider.IsOpenGetter = _treeViewFiles.IsExpanded;
- }
- private void SetupScrollBar ()
- {
- // When using scroll bar leave the last row of the control free (for over-rendering with scroll bar)
- _treeViewFiles.Style.LeaveLastRow = true;
- var scrollBar = new ScrollBarView (_treeViewFiles, true);
- scrollBar.ChangedPosition += (s, e) =>
- {
- _treeViewFiles.ScrollOffsetVertical = scrollBar.Position;
- if (_treeViewFiles.ScrollOffsetVertical != scrollBar.Position)
- {
- scrollBar.Position = _treeViewFiles.ScrollOffsetVertical;
- }
- _treeViewFiles.SetNeedsDisplay ();
- };
- scrollBar.OtherScrollBarView.ChangedPosition += (s, e) =>
- {
- _treeViewFiles.ScrollOffsetHorizontal = scrollBar.OtherScrollBarView.Position;
- if (_treeViewFiles.ScrollOffsetHorizontal != scrollBar.OtherScrollBarView.Position)
- {
- scrollBar.OtherScrollBarView.Position = _treeViewFiles.ScrollOffsetHorizontal;
- }
- _treeViewFiles.SetNeedsDisplay ();
- };
- _treeViewFiles.DrawingContent += (s, e) =>
- {
- scrollBar.Size = _treeViewFiles.ContentHeight;
- scrollBar.Position = _treeViewFiles.ScrollOffsetVertical;
- scrollBar.OtherScrollBarView.Size = _treeViewFiles.GetContentWidth (true);
- scrollBar.OtherScrollBarView.Position = _treeViewFiles.ScrollOffsetHorizontal;
- scrollBar.Refresh ();
- };
- }
- private void ShowColoredExpandableSymbols ()
- {
- _miColoredSymbols.Checked = !_miColoredSymbols.Checked;
- _treeViewFiles.Style.ColorExpandSymbol = (bool)_miColoredSymbols.Checked;
- _treeViewFiles.SetNeedsDisplay ();
- }
- private void ShowContextMenu (Point screenPoint, IFileSystemInfo forObject)
- {
- var menu = new ContextMenu { Position = screenPoint };
- var menuItems = new MenuBarItem (
- new [] { new MenuItem ("Properties", null, () => ShowPropertiesOf (forObject)) }
- );
- Application.Invoke (() => menu.Show (menuItems));
- }
- private void ShowLines ()
- {
- _miShowLines.Checked = !_miShowLines.Checked;
- _treeViewFiles.Style.ShowBranchLines = (bool)_miShowLines.Checked!;
- _treeViewFiles.SetNeedsDisplay ();
- }
- private void ShowPropertiesOf (IFileSystemInfo fileSystemInfo) { _detailsFrame.FileInfo = fileSystemInfo; }
- private void TreeViewFiles_DrawLine (object sender, DrawTreeViewLineEventArgs<IFileSystemInfo> e)
- {
- // Render directory icons in yellow
- if (e.Model is IDirectoryInfo d)
- {
- if (_iconProvider.UseNerdIcons || _iconProvider.UseUnicodeCharacters)
- {
- if (e.IndexOfModelText > 0 && e.IndexOfModelText < e.Cells.Count)
- {
- Cell cell = e.Cells [e.IndexOfModelText];
- cell.Attribute = new Attribute (
- Color.BrightYellow,
- cell.Attribute!.Value.Background
- );
- }
- }
- }
- }
- private void TreeViewFiles_KeyPress (object sender, Key obj)
- {
- if (obj.KeyCode == (KeyCode.R | KeyCode.CtrlMask))
- {
- IFileSystemInfo selected = _treeViewFiles.SelectedObject;
- // nothing is selected
- if (selected == null)
- {
- return;
- }
- int? location = _treeViewFiles.GetObjectRow (selected);
- //selected object is offscreen or somehow not found
- if (location == null || location < 0 || location > _treeViewFiles.Frame.Height)
- {
- return;
- }
- ShowContextMenu (
- new Point (
- 5 + _treeViewFiles.Frame.X,
- location.Value + _treeViewFiles.Frame.Y + 2
- ),
- selected
- );
- }
- }
- private void TreeViewFiles_MouseClick (object sender, MouseEventArgs obj)
- {
- // if user right clicks
- if (obj.Flags.HasFlag (MouseFlags.Button3Clicked))
- {
- IFileSystemInfo rightClicked = _treeViewFiles.GetObjectOnRow (obj.Position.Y);
- // nothing was clicked
- if (rightClicked == null)
- {
- return;
- }
- ShowContextMenu (
- new Point (
- obj.Position.X + _treeViewFiles.Frame.X,
- obj.Position.Y + _treeViewFiles.Frame.Y + 2
- ),
- rightClicked
- );
- }
- }
- private void TreeViewFiles_SelectionChanged (object sender, SelectionChangedEventArgs<IFileSystemInfo> e) { ShowPropertiesOf (e.NewValue); }
- private void UpdateIconCheckedness ()
- {
- _miBasicIcons.Checked = !_iconProvider.UseNerdIcons && !_iconProvider.UseUnicodeCharacters;
- _miUnicodeIcons.Checked = _iconProvider.UseUnicodeCharacters;
- _miNerdIcons.Checked = _iconProvider.UseNerdIcons;
- _treeViewFiles.SetNeedsDisplay ();
- }
- private class DetailsFrame : FrameView
- {
- private readonly FileSystemIconProvider _iconProvider;
- private IFileSystemInfo _fileInfo;
- public DetailsFrame (FileSystemIconProvider iconProvider)
- {
- Title = "Details";
- Visible = true;
- CanFocus = true;
- _iconProvider = iconProvider;
- }
- public IFileSystemInfo FileInfo
- {
- get => _fileInfo;
- set
- {
- _fileInfo = value;
- StringBuilder sb = null;
- if (_fileInfo is IFileInfo f)
- {
- Title = $"{_iconProvider.GetIconWithOptionalSpace (f)}{f.Name}".Trim ();
- sb = new StringBuilder ();
- sb.AppendLine ($"Path:\n {f.FullName}\n");
- sb.AppendLine ($"Size:\n {f.Length:N0} bytes\n");
- sb.AppendLine ($"Modified:\n {f.LastWriteTime}\n");
- sb.AppendLine ($"Created:\n {f.CreationTime}");
- }
- if (_fileInfo is IDirectoryInfo dir)
- {
- Title = $"{_iconProvider.GetIconWithOptionalSpace (dir)}{dir.Name}".Trim ();
- sb = new StringBuilder ();
- sb.AppendLine ($"Path:\n {dir?.FullName}\n");
- sb.AppendLine ($"Modified:\n {dir.LastWriteTime}\n");
- sb.AppendLine ($"Created:\n {dir.CreationTime}\n");
- }
- Text = sb.ToString ();
- }
- }
- }
- }
|