| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655 |
- #nullable enable
- using System.IO.Abstractions;
- using System.Text;
- 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 CheckBox? _miArrowSymbolsCheckBox;
- private CheckBox? _miBasicIconsCheckBox;
- private CheckBox? _miColoredSymbolsCheckBox;
- private CheckBox? _miCursorCheckBox;
- private CheckBox? _miCustomColorsCheckBox;
- private CheckBox? _miFullPathsCheckBox;
- private CheckBox? _miHighlightModelTextOnlyCheckBox;
- private CheckBox? _miInvertSymbolsCheckBox;
- private CheckBox? _miLeaveLastRowCheckBox;
- private CheckBox? _miMultiSelectCheckBox;
- private CheckBox? _miNerdIconsCheckBox;
- private CheckBox? _miNoSymbolsCheckBox;
- private CheckBox? _miPlusMinusCheckBox;
- private CheckBox? _miShowLinesCheckBox;
- private CheckBox? _miUnicodeIconsCheckBox;
- /// <summary>A tree view where nodes are files and folders</summary>
- private TreeView<IFileSystemInfo>? _treeViewFiles;
- public override void Main ()
- {
- Application.Init ();
- Window win = new ()
- {
- Title = GetName (),
- Y = 1, // menu
- Height = Dim.Fill ()
- };
- // MenuBar
- MenuBar menu = new ();
- _treeViewFiles = new () { X = 0, Y = Pos.Bottom (menu), Width = Dim.Percent (50), Height = Dim.Fill () };
- _treeViewFiles.DrawLine += TreeViewFiles_DrawLine;
- _treeViewFiles.VerticalScrollBar.AutoShow = false;
- _detailsFrame = new (_iconProvider)
- {
- X = Pos.Right (_treeViewFiles),
- Y = Pos.Top (_treeViewFiles),
- Width = Dim.Fill (),
- Height = Dim.Fill ()
- };
- win.Add (_detailsFrame);
- _treeViewFiles.MouseClick += TreeViewFiles_MouseClick;
- _treeViewFiles.KeyDown += TreeViewFiles_KeyPress;
- _treeViewFiles.SelectionChanged += TreeViewFiles_SelectionChanged;
- SetupFileTree ();
- // Setup menu checkboxes
- _miFullPathsCheckBox = new ()
- {
- Title = "_Full Paths"
- };
- _miFullPathsCheckBox.CheckedStateChanged += (s, e) => SetFullName ();
- _miMultiSelectCheckBox = new ()
- {
- Title = "_Multi Select",
- CheckedState = CheckState.Checked
- };
- _miMultiSelectCheckBox.CheckedStateChanged += (s, e) => SetMultiSelect ();
- _miShowLinesCheckBox = new ()
- {
- Title = "_Show Lines",
- CheckedState = CheckState.Checked
- };
- _miShowLinesCheckBox.CheckedStateChanged += (s, e) => ShowLines ();
- _miPlusMinusCheckBox = new ()
- {
- Title = "_Plus Minus Symbols",
- CheckedState = CheckState.Checked
- };
- _miPlusMinusCheckBox.CheckedStateChanged += (s, e) => SetExpandableSymbols ((Rune)'+', (Rune)'-');
- _miArrowSymbolsCheckBox = new ()
- {
- Title = "_Arrow Symbols"
- };
- _miArrowSymbolsCheckBox.CheckedStateChanged += (s, e) => SetExpandableSymbols ((Rune)'>', (Rune)'v');
- _miNoSymbolsCheckBox = new ()
- {
- Title = "_No Symbols"
- };
- _miNoSymbolsCheckBox.CheckedStateChanged += (s, e) => SetExpandableSymbols (default (Rune), null);
- _miColoredSymbolsCheckBox = new ()
- {
- Title = "_Colored Symbols"
- };
- _miColoredSymbolsCheckBox.CheckedStateChanged += (s, e) => ShowColoredExpandableSymbols ();
- _miInvertSymbolsCheckBox = new ()
- {
- Title = "_Invert Symbols"
- };
- _miInvertSymbolsCheckBox.CheckedStateChanged += (s, e) => InvertExpandableSymbols ();
- _miBasicIconsCheckBox = new ()
- {
- Title = "_Basic Icons"
- };
- _miBasicIconsCheckBox.CheckedStateChanged += (s, e) => SetNoIcons ();
- _miUnicodeIconsCheckBox = new ()
- {
- Title = "_Unicode Icons"
- };
- _miUnicodeIconsCheckBox.CheckedStateChanged += (s, e) => SetUnicodeIcons ();
- _miNerdIconsCheckBox = new ()
- {
- Title = "_Nerd Icons"
- };
- _miNerdIconsCheckBox.CheckedStateChanged += (s, e) => SetNerdIcons ();
- _miLeaveLastRowCheckBox = new ()
- {
- Title = "_Leave Last Row",
- CheckedState = CheckState.Checked
- };
- _miLeaveLastRowCheckBox.CheckedStateChanged += (s, e) => SetLeaveLastRow ();
- _miHighlightModelTextOnlyCheckBox = new ()
- {
- Title = "_Highlight Model Text Only"
- };
- _miHighlightModelTextOnlyCheckBox.CheckedStateChanged += (s, e) => SetCheckHighlightModelTextOnly ();
- _miCustomColorsCheckBox = new ()
- {
- Title = "C_ustom Colors Hidden Files"
- };
- _miCustomColorsCheckBox.CheckedStateChanged += (s, e) => SetCustomColors ();
- _miCursorCheckBox = new ()
- {
- Title = "Curs_or (MultiSelect only)"
- };
- _miCursorCheckBox.CheckedStateChanged += (s, e) => SetCursor ();
- menu.Add (
- new MenuBarItem (
- "_File",
- [
- new MenuItem
- {
- Title = "_Quit",
- Key = Application.QuitKey,
- Action = Quit
- }
- ]
- )
- );
- menu.Add (
- new MenuBarItem (
- "_View",
- [
- new MenuItem
- {
- CommandView = _miFullPathsCheckBox
- },
- new MenuItem
- {
- CommandView = _miMultiSelectCheckBox
- }
- ]
- )
- );
- menu.Add (
- new MenuBarItem (
- "_Style",
- [
- new MenuItem
- {
- CommandView = _miShowLinesCheckBox
- },
- new MenuItem
- {
- CommandView = _miPlusMinusCheckBox
- },
- new MenuItem
- {
- CommandView = _miArrowSymbolsCheckBox
- },
- new MenuItem
- {
- CommandView = _miNoSymbolsCheckBox
- },
- new MenuItem
- {
- CommandView = _miColoredSymbolsCheckBox
- },
- new MenuItem
- {
- CommandView = _miInvertSymbolsCheckBox
- },
- new MenuItem
- {
- CommandView = _miBasicIconsCheckBox
- },
- new MenuItem
- {
- CommandView = _miUnicodeIconsCheckBox
- },
- new MenuItem
- {
- CommandView = _miNerdIconsCheckBox
- },
- new MenuItem
- {
- CommandView = _miLeaveLastRowCheckBox
- },
- new MenuItem
- {
- CommandView = _miHighlightModelTextOnlyCheckBox
- },
- new MenuItem
- {
- CommandView = _miCustomColorsCheckBox
- },
- new MenuItem
- {
- CommandView = _miCursorCheckBox
- }
- ]
- )
- );
- win.Add (menu, _treeViewFiles);
- _treeViewFiles.GoToFirst ();
- _treeViewFiles.Expand ();
- _treeViewFiles.SetFocus ();
- UpdateIconCheckedness ();
- Application.Run (win);
- win.Dispose ();
- Application.Shutdown ();
- }
- private string AspectGetter (IFileSystemInfo f) => (_iconProvider.GetIconWithOptionalSpace (f) + f.Name).Trim ();
- private void InvertExpandableSymbols ()
- {
- if (_treeViewFiles is null || _miInvertSymbolsCheckBox is null)
- {
- return;
- }
- _treeViewFiles.Style.InvertExpandSymbolColors = _miInvertSymbolsCheckBox.CheckedState == CheckState.Checked;
- _treeViewFiles.SetNeedsDraw ();
- }
- private void Quit () { Application.RequestStop (); }
- private void SetCheckHighlightModelTextOnly ()
- {
- if (_treeViewFiles is null || _miHighlightModelTextOnlyCheckBox is null)
- {
- return;
- }
- _treeViewFiles.Style.HighlightModelTextOnly = _miHighlightModelTextOnlyCheckBox.CheckedState == CheckState.Checked;
- _treeViewFiles.SetNeedsDraw ();
- }
- private void SetCursor ()
- {
- if (_treeViewFiles is null || _miCursorCheckBox is null)
- {
- return;
- }
- _treeViewFiles.CursorVisibility =
- _miCursorCheckBox.CheckedState == CheckState.Checked ? CursorVisibility.Default : CursorVisibility.Invisible;
- }
- private void SetCustomColors ()
- {
- if (_treeViewFiles is null || _miCustomColorsCheckBox is null)
- {
- return;
- }
- if (_miCustomColorsCheckBox.CheckedState == CheckState.Checked)
- {
- _treeViewFiles.ColorGetter = m =>
- {
- if (m is IDirectoryInfo && m.Attributes.HasFlag (FileAttributes.Hidden))
- {
- return new ()
- {
- Focus = new (
- Color.BrightRed,
- _treeViewFiles.GetAttributeForRole (VisualRole.Focus).Background
- ),
- Normal = new (
- Color.BrightYellow,
- _treeViewFiles.GetAttributeForRole (VisualRole.Normal).Background
- )
- };
- }
- if (m is IFileInfo && m.Attributes.HasFlag (FileAttributes.Hidden))
- {
- return new ()
- {
- Focus = new (
- Color.BrightRed,
- _treeViewFiles.GetAttributeForRole (VisualRole.Focus).Background
- ),
- Normal = new (
- Color.BrightYellow,
- _treeViewFiles.GetAttributeForRole (VisualRole.Normal).Background
- )
- };
- }
- return null;
- };
- }
- else
- {
- _treeViewFiles.ColorGetter = null;
- }
- _treeViewFiles.SetNeedsDraw ();
- }
- private void SetExpandableSymbols (Rune expand, Rune? collapse)
- {
- if (_treeViewFiles is null)
- {
- return;
- }
- if (_miPlusMinusCheckBox is { })
- {
- _miPlusMinusCheckBox.CheckedState = expand.Value == '+' ? CheckState.Checked : CheckState.UnChecked;
- }
- if (_miArrowSymbolsCheckBox is { })
- {
- _miArrowSymbolsCheckBox.CheckedState = expand.Value == '>' ? CheckState.Checked : CheckState.UnChecked;
- }
- if (_miNoSymbolsCheckBox is { })
- {
- _miNoSymbolsCheckBox.CheckedState = expand.Value == default (int) ? CheckState.Checked : CheckState.UnChecked;
- }
- _treeViewFiles.Style.ExpandableSymbol = expand;
- _treeViewFiles.Style.CollapseableSymbol = collapse;
- _treeViewFiles.SetNeedsDraw ();
- }
- private void SetFullName ()
- {
- if (_treeViewFiles is null || _miFullPathsCheckBox is null)
- {
- return;
- }
- if (_miFullPathsCheckBox.CheckedState == CheckState.Checked)
- {
- _treeViewFiles.AspectGetter = f => f.FullName;
- }
- else
- {
- _treeViewFiles.AspectGetter = f => f.Name;
- }
- _treeViewFiles.SetNeedsDraw ();
- }
- private void SetLeaveLastRow ()
- {
- if (_treeViewFiles is null || _miLeaveLastRowCheckBox is null)
- {
- return;
- }
- _treeViewFiles.Style.LeaveLastRow = _miLeaveLastRowCheckBox.CheckedState == CheckState.Checked;
- }
- private void SetMultiSelect ()
- {
- if (_treeViewFiles is null || _miMultiSelectCheckBox is null)
- {
- return;
- }
- _treeViewFiles.MultiSelect = _miMultiSelectCheckBox.CheckedState == CheckState.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 ()
- {
- if (_treeViewFiles is null)
- {
- return;
- }
- // setup how to build tree
- FileSystem fs = new ();
- 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 ShowColoredExpandableSymbols ()
- {
- if (_treeViewFiles is null || _miColoredSymbolsCheckBox is null)
- {
- return;
- }
- _treeViewFiles.Style.ColorExpandSymbol = _miColoredSymbolsCheckBox.CheckedState == CheckState.Checked;
- _treeViewFiles.SetNeedsDraw ();
- }
- private void ShowContextMenu (Point screenPoint, IFileSystemInfo forObject)
- {
- PopoverMenu contextMenu = new ([new ("Properties", $"Show {forObject.Name} properties", () => ShowPropertiesOf (forObject))]);
- // Registering with the PopoverManager will ensure that the context menu is closed when the view is no longer focused
- // and the context menu is disposed when it is closed.
- _detailsFrame?.App?.Popover?.Register (contextMenu);
- Application.Invoke (() => contextMenu?.MakeVisible (screenPoint));
- }
- private void ShowLines ()
- {
- if (_treeViewFiles is null || _miShowLinesCheckBox is null)
- {
- return;
- }
- _treeViewFiles.Style.ShowBranchLines = _miShowLinesCheckBox.CheckedState == CheckState.Checked;
- _treeViewFiles.SetNeedsDraw ();
- }
- private void ShowPropertiesOf (IFileSystemInfo fileSystemInfo)
- {
- if (_detailsFrame is { })
- {
- _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,
- cell.Attribute!.Value.Style
- );
- }
- }
- }
- }
- private void TreeViewFiles_KeyPress (object? sender, Key obj)
- {
- if (_treeViewFiles is null)
- {
- return;
- }
- if (obj.KeyCode == (KeyCode.R | KeyCode.CtrlMask))
- {
- IFileSystemInfo? selected = _treeViewFiles.SelectedObject;
- // nothing is selected
- if (selected is null)
- {
- return;
- }
- int? location = _treeViewFiles.GetObjectRow (selected);
- //selected object is offscreen or somehow not found
- if (location is null || location < 0 || location > _treeViewFiles.Frame.Height)
- {
- return;
- }
- ShowContextMenu (
- new (
- 5 + _treeViewFiles.Frame.X,
- location.Value + _treeViewFiles.Frame.Y + 2
- ),
- selected
- );
- }
- }
- private void TreeViewFiles_MouseClick (object? sender, MouseEventArgs obj)
- {
- if (_treeViewFiles is null)
- {
- return;
- }
- // if user right clicks
- if (obj.Flags.HasFlag (MouseFlags.Button3Clicked))
- {
- IFileSystemInfo? rightClicked = _treeViewFiles.GetObjectOnRow (obj.Position.Y);
- // nothing was clicked
- if (rightClicked is null)
- {
- return;
- }
- ShowContextMenu (
- new (
- 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 ()
- {
- if (_miBasicIconsCheckBox is { })
- {
- _miBasicIconsCheckBox.CheckedState = !_iconProvider.UseNerdIcons && !_iconProvider.UseUnicodeCharacters
- ? CheckState.Checked
- : CheckState.UnChecked;
- }
- if (_miUnicodeIconsCheckBox is { })
- {
- _miUnicodeIconsCheckBox.CheckedState = _iconProvider.UseUnicodeCharacters ? CheckState.Checked : CheckState.UnChecked;
- }
- if (_miNerdIconsCheckBox is { })
- {
- _miNerdIconsCheckBox.CheckedState = _iconProvider.UseNerdIcons ? CheckState.Checked : CheckState.UnChecked;
- }
- _treeViewFiles?.SetNeedsDraw ();
- }
- 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 ();
- 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 ();
- sb.AppendLine ($"Path:\n {dir.FullName}\n");
- sb.AppendLine ($"Modified:\n {dir.LastWriteTime}\n");
- sb.AppendLine ($"Created:\n {dir.CreationTime}\n");
- }
- Text = sb?.ToString () ?? string.Empty;
- }
- }
- }
- }
|