diff --git a/Example/demo.cs b/Example/demo.cs index 550367e07..aecbd4212 100644 --- a/Example/demo.cs +++ b/Example/demo.cs @@ -211,7 +211,7 @@ static class Demo { Application.Init (); var top = Application.Top; var tframe = top.Frame; - //Open (); + Open (); #if true var win = new Window ("Hello") { X = 0, diff --git a/Terminal.Gui/Dialogs/FileDialog.cs b/Terminal.Gui/Dialogs/FileDialog.cs index e31878396..8f0e8df01 100644 --- a/Terminal.Gui/Dialogs/FileDialog.cs +++ b/Terminal.Gui/Dialogs/FileDialog.cs @@ -23,11 +23,14 @@ namespace Terminal.Gui { internal class DirListView : View { int top, selected; DirectoryInfo dirInfo; - List<(string,bool)> infos; + List<(string,bool,bool)> infos; + internal bool canChooseFiles = true; + internal bool canChooseDirectories = false; + internal bool allowsMultipleSelection = false; public DirListView () { - infos = new List<(string,bool)> (); + infos = new List<(string,bool,bool)> (); CanFocus = true; } @@ -43,14 +46,14 @@ namespace Terminal.Gui { return false; } - void Reload () + internal void Reload () { dirInfo = new DirectoryInfo (directory.ToString ()); infos = (from x in dirInfo.GetFileSystemInfos () where IsAllowed (x) orderby (!x.Attributes.HasFlag (FileAttributes.Directory)) + x.Name - select (x.Name, x.Attributes.HasFlag (FileAttributes.Directory))).ToList (); - infos.Insert (0, ("..", true)); + select (x.Name, x.Attributes.HasFlag (FileAttributes.Directory), false)).ToList (); + infos.Insert (0, ("..", true, false)); top = 0; selected = 0; SetNeedsDisplay (); @@ -78,7 +81,7 @@ namespace Terminal.Gui { var width = f.Width; var ustr = ustring.Make (str); - Move (2, line); + Move (allowsMultipleSelection ? 3 : 2, line); int byteLen = ustr.Length; int used = 0; for (int i = 0; i < byteLen;) { @@ -121,6 +124,10 @@ namespace Terminal.Gui { var fi = infos [item]; Driver.AddRune (isSelected ? '>' : ' '); + + if (allowsMultipleSelection) + Driver.AddRune (fi.Item3 ? '*' : ' '); + if (fi.Item2) Driver.AddRune ('/'); else @@ -134,8 +141,10 @@ namespace Terminal.Gui { void SelectionChanged () { - if (SelectedChanged != null) - SelectedChanged (infos [selected]); + if (SelectedChanged != null) { + var sel = infos [selected]; + SelectedChanged ((sel.Item1, sel.Item2)); + } } public override bool ProcessKey (KeyEvent keyEvent) @@ -201,6 +210,19 @@ namespace Terminal.Gui { SetNeedsDisplay (); } return true; + + case Key.Space: + case Key.ControlT: + if (allowsMultipleSelection) { + if ((canChooseFiles && infos [selected].Item2 == false) || + (canChooseDirectories && infos [selected].Item2 && + infos [selected].Item1 != "..")){ + infos [selected] = (infos [selected].Item1, infos [selected].Item2, !infos [selected].Item3); + SelectionChanged (); + SetNeedsDisplay (); + } + } + return true; } return base.ProcessKey (keyEvent); } @@ -214,13 +236,42 @@ namespace Terminal.Gui { } } + public string MakePath (string relativePath) + { + return Path.GetFullPath (Path.Combine (Directory.ToString (), relativePath)); + } + + public IReadOnlyList FilePaths { + get { + if (allowsMultipleSelection) { + var res = new List (); + foreach (var item in infos) + if (item.Item3) + res.Add (MakePath (item.Item1)); + return res; + } else { + if (infos [selected].Item2) { + if (canChooseDirectories) + return new List () { MakePath (infos [selected].Item1) }; + return Array.Empty (); + } else { + if (canChooseFiles) + return new List () { MakePath (infos [selected].Item1) }; + return Array.Empty (); + } + } + } + } } + /// + /// Base class for the OpenDialog and the SaveDialog + /// public class FileDialog : Dialog { Button prompt, cancel; Label nameFieldLabel, message, dirLabel; TextField dirEntry, nameEntry; - DirListView dirListView; + internal DirListView dirListView; public FileDialog (ustring title, ustring prompt, ustring nameFieldLabel, ustring message) : base (title, Driver.Cols - 20, Driver.Rows - 5, null) { @@ -358,6 +409,19 @@ namespace Terminal.Gui { } } + /// + /// The Open Dialog provides an interactive dialog box for users to select files or directories. + /// + /// + /// + /// The open dialog can be used to select files for opening, it can be configured to allow + /// multiple items to be selected (based on the AllowsMultipleSelection) variable and + /// you can control whether this should allow files or directories to be selected. + /// + /// + /// To select more than one file, users can use the spacebar, or control-t. + /// + /// public class OpenDialog : FileDialog { public OpenDialog (ustring title, ustring message) : base (title, prompt: "Open", nameFieldLabel: "Open", message: message) { @@ -366,25 +430,45 @@ namespace Terminal.Gui { /// /// Gets or sets a value indicating whether this can choose files. /// - /// true if can choose files; otherwise, false. - public bool CanChooseFiles { get; set; } + /// true if can choose files; otherwise, false. Defaults to true + public bool CanChooseFiles { + get => dirListView.canChooseFiles; + set { + dirListView.canChooseDirectories = value; + dirListView.Reload (); + } + } /// /// Gets or sets a value indicating whether this can choose directories. /// - /// true if can choose directories; otherwise, false. - public bool CanChooseDirectories { get; set; } + /// true if can choose directories; otherwise, false defaults to false. + public bool CanChooseDirectories { + get => dirListView.canChooseDirectories; + set { + dirListView.canChooseDirectories = value; + dirListView.Reload (); + } + } /// /// Gets or sets a value indicating whether this allows multiple selection. /// - /// true if allows multiple selection; otherwise, false. - public bool AllowsMultipleSelection { get; set; } + /// true if allows multiple selection; otherwise, false, defaults to false. + public bool AllowsMultipleSelection { + get => dirListView.allowsMultipleSelection; + set { + dirListView.allowsMultipleSelection = value; + dirListView.Reload (); + } + } /// - /// Gets the file paths selected + /// Returns the selected files, or an empty list if nothing has been selected /// /// The file paths. - public IReadOnlyList FilePaths { get; } + public IReadOnlyList FilePaths { + get => dirListView.FilePaths; + } } }