diff --git a/Terminal.Gui/Windows/FileDialog2.cs b/Terminal.Gui/Windows/FileDialog2.cs index adea00878..3551933c0 100644 --- a/Terminal.Gui/Windows/FileDialog2.cs +++ b/Terminal.Gui/Windows/FileDialog2.cs @@ -22,6 +22,13 @@ namespace Terminal.Gui { private const string HeaderSize = "Size"; private const string HeaderModified = "Modified"; private const string HeaderType = "Type"; + + /// + /// True if the file/folder must exist already to be selected. + /// This prevents user from entering the name of something that + /// doesn't exist. Defaults to false. + /// + public bool MustExist { get; set; } private static char [] separators = new [] { @@ -90,7 +97,10 @@ namespace Terminal.Gui { this.btnCancel = new Button ("Cancel") { Y = Pos.AnchorEnd (1), X = Pos.AnchorEnd (okWidth + cancelWidth), - }; + }; + this.btnCancel.KeyPress += (k) => { + Application.RequestStop (); + }; this.lblUp = new Label (Driver.UpArrow.ToString ()) { X = 0, Y = 1 }; this.lblUp.Clicked += () => this.history.Up (); @@ -115,6 +125,8 @@ namespace Terminal.Gui { this.AcceptIf (k, Key.Enter); this.SuppressIfBadChar (k); + + ClearFeedback (); }; this.splitContainer = new TileView () { @@ -247,6 +259,11 @@ namespace Terminal.Gui { this.Add (lblFeedback); } + private void ClearFeedback () + { + lblFeedback.Text = string.Empty; + } + private void CycleToNextTableEntryBeginningWith (KeyEventEventArgs keyEvent) { if(tableView.Table.Rows.Count == 0) @@ -365,7 +382,7 @@ namespace Terminal.Gui { /// is or . /// /// If selecting only a single file/directory then you should use instead. - public IReadOnlyList MultiSelected { get; private set; } + public IReadOnlyList MultiSelected { get; private set; } /// @@ -495,18 +512,23 @@ namespace Terminal.Gui { return; } - this.MultiSelected = toMultiAccept.Select (s => s.FileSystemInfo).ToList ().AsReadOnly (); - this.tbPath.Text = this.MultiSelected.Count == 1 ? this.MultiSelected [0].FullName : string.Empty; + this.MultiSelected = toMultiAccept.Select (s => s.FileSystemInfo.FullName).ToList ().AsReadOnly (); + this.tbPath.Text = this.MultiSelected.Count == 1 ? this.MultiSelected [0] : string.Empty; this.Canceled = false; Application.RequestStop (); } private void Accept (FileInfo f) { - if (!this.IsCompatibleWithOpenMode (f)) { + if (!this.IsCompatibleWithOpenMode (f.FullName, out var reason)) { + lblFeedback.Text = reason; return; } this.tbPath.Text = f.FullName; + + if (AllowsMultipleSelection) { + this.MultiSelected = new List { f.FullName}.AsReadOnly(); + } this.Canceled = false; Application.RequestStop (); } @@ -690,7 +712,7 @@ namespace Terminal.Gui { { var multi = this.MultiRowToStats (); if (multi.Any ()) { - if (multi.All (this.IsCompatibleWithOpenMode)) { + if (multi.All (m=>this.IsCompatibleWithOpenMode(m.FileSystemInfo.FullName,out _))) { this.Accept (multi); } else { return; @@ -711,36 +733,6 @@ namespace Terminal.Gui { } } - private bool IsCompatibleWithOpenMode (FileSystemInfoStats arg) - { - // don't let the user select .. thats just going to be confusing - if (arg.IsParent) { - return false; - } - - switch (this.OpenMode) { - case OpenMode.Directory: return arg.IsDir (); - case OpenMode.File: return !arg.IsDir () && this.IsCompatibleWithOpenMode (arg.FileSystemInfo); - case OpenMode.Mixed: return true; - default: throw new ArgumentOutOfRangeException (nameof (this.OpenMode)); - } - } - - private bool IsCompatibleWithOpenMode (FileSystemInfo f) - { - switch (this.OpenMode) { - case OpenMode.Directory: return f is DirectoryInfo; - case OpenMode.File: - if (f is FileInfo file) { - return this.IsCompatibleWithAllowedExtensions (file); - } - - return false; - case OpenMode.Mixed: return true; - default: throw new ArgumentOutOfRangeException (nameof (this.OpenMode)); - } - } - private bool IsCompatibleWithAllowedExtensions (FileInfo file) { // no restrictions @@ -785,23 +777,39 @@ namespace Terminal.Gui { } if (!this.IsCompatibleWithAllowedExtensions (s)) { - reason = "File does not match allowed Type(s)"; + reason = "Wrong file type"; return false; } switch (this.OpenMode) { case OpenMode.Directory: + if(MustExist && !Directory.Exists(s)) { + reason = "Directory does not exist"; + return false; + } + if(File.Exists (s)) { reason = "You must pick a Directory"; return false; } return true; - case OpenMode.File: if(Directory.Exists (s)) { + case OpenMode.File: + + if (MustExist && !File.Exists (s)) { + reason = "File does not exist"; + return false; + } + if (Directory.Exists (s)) { reason = "You must pick a File"; return false; } return true; - case OpenMode.Mixed: return true; + case OpenMode.Mixed: + if (MustExist && !File.Exists (s) && !Directory.Exists (s)) { + reason = "File or Directory must exist"; + return false; + } + return true; default: throw new ArgumentOutOfRangeException (nameof (this.OpenMode)); } } diff --git a/UICatalog/Scenarios/FileDialog2Examples.cs b/UICatalog/Scenarios/FileDialog2Examples.cs index 1d5ab1c9d..fdc21f166 100644 --- a/UICatalog/Scenarios/FileDialog2Examples.cs +++ b/UICatalog/Scenarios/FileDialog2Examples.cs @@ -1,20 +1,21 @@ using System; -using System.Collections.Generic; -using System.ComponentModel; using System.Linq; -using System.Text; -using System.Threading.Tasks; using Terminal.Gui; namespace UICatalog.Scenarios { [ScenarioMetadata (Name: "FileDialog2", Description: "Demonstrates how to the FileDialog2 class")] [ScenarioCategory ("Dialogs")] public class FileDialog2Examples : Scenario { + private CheckBox cbMustExist; + public override void Setup () { var y = 1; var x = 1; + cbMustExist = new CheckBox ("Must Exist") { Checked = true }; + Win.Add (cbMustExist); + foreach(var multi in new bool [] {false, true }) { foreach (OpenDialog.OpenMode openMode in Enum.GetValues (typeof (OpenDialog.OpenMode))) { var btn = new Button ($"Select {(multi?"Many": "One")} {openMode}") { @@ -54,6 +55,7 @@ namespace UICatalog.Scenarios { var fd = new FileDialog2 { AllowsMultipleSelection = isMulti, OpenMode = mode, + MustExist = cbMustExist.Checked }; if (csv) { @@ -72,7 +74,7 @@ namespace UICatalog.Scenarios { MessageBox.Query ( "Chosen!", "You chose:" + Environment.NewLine + - string.Join (Environment.NewLine, fd.MultiSelected.Select (m => m.FullName)), + string.Join (Environment.NewLine, fd.MultiSelected.Select (m => m)), "Ok"); } else{