From cedc4fba81abc82e5b89bfc56fc929919cb551e2 Mon Sep 17 00:00:00 2001 From: tznind Date: Sun, 19 Mar 2023 10:07:00 +0000 Subject: [PATCH] Add FilesSelected event Allows user to do things like confirm dialogs on selecting existing file(s) --- Terminal.Gui/Windows/FileDialog.cs | 28 ++++++++++++++--- .../Windows/FilesSelectedEventArgs.cs | 31 +++++++++++++++++++ UICatalog/Scenarios/FileDialogExamples.cs | 15 +++++++++ UnitTests/FileDialogTests.cs | 19 ++++++++++++ 4 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 Terminal.Gui/Windows/FilesSelectedEventArgs.cs diff --git a/Terminal.Gui/Windows/FileDialog.cs b/Terminal.Gui/Windows/FileDialog.cs index 5a7dddd64..7e30de0e6 100644 --- a/Terminal.Gui/Windows/FileDialog.cs +++ b/Terminal.Gui/Windows/FileDialog.cs @@ -234,6 +234,12 @@ namespace Terminal.Gui { private MenuBarItem allowedTypeMenu; private MenuItem [] allowedTypeMenuItems; + /// + /// Event fired when user attempts to confirm a selection (or multi selection). + /// Allows you to cancel the selection or undertake alternative behavior e.g. + /// open a dialog "File already exists, Overwrite? yes/no". + /// + public event EventHandler FilesSelected; /// /// Initializes a new instance of the class. @@ -850,9 +856,11 @@ namespace Terminal.Gui { 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 (); + + FinishAccept (); } + + private void Accept (FileInfo f) { if (!this.IsCompatibleWithOpenMode (f.FullName, out var reason)) { @@ -866,8 +874,8 @@ namespace Terminal.Gui { if (AllowsMultipleSelection) { this.MultiSelected = new List { f.FullName }.AsReadOnly (); } - this.Canceled = false; - Application.RequestStop (); + + FinishAccept (); } private void Accept () @@ -880,6 +888,18 @@ namespace Terminal.Gui { return; } + FinishAccept (); + } + + private void FinishAccept () + { + var e = new FilesSelectedEventArgs (this); + + this.FilesSelected?.Invoke (this, e); + + if(e.Cancel) { + return; + } this.Canceled = false; Application.RequestStop (); diff --git a/Terminal.Gui/Windows/FilesSelectedEventArgs.cs b/Terminal.Gui/Windows/FilesSelectedEventArgs.cs new file mode 100644 index 000000000..d8c97d7c8 --- /dev/null +++ b/Terminal.Gui/Windows/FilesSelectedEventArgs.cs @@ -0,0 +1,31 @@ +using System; + +namespace Terminal.Gui { + /// + /// Event args for the event + /// + public class FilesSelectedEventArgs : EventArgs + { + /// + /// Set to true if you want to prevent the selection + /// going ahead (this will leave the + /// still showing). + /// + public bool Cancel { get; set; } + + /// + /// The dialog where the choice is being made. Use + /// and/or to evaluate the users choice. + /// + public FileDialog Dialog { get; } + + /// + /// Creates a new instance of the + /// + /// + public FilesSelectedEventArgs (FileDialog dialog) + { + Dialog = dialog; + } + } +} \ No newline at end of file diff --git a/UICatalog/Scenarios/FileDialogExamples.cs b/UICatalog/Scenarios/FileDialogExamples.cs index 68775c2a0..6bafc247d 100644 --- a/UICatalog/Scenarios/FileDialogExamples.cs +++ b/UICatalog/Scenarios/FileDialogExamples.cs @@ -118,6 +118,11 @@ namespace UICatalog.Scenarios { fd.Style.OkButtonText = rgCaption.RadioLabels [rgCaption.SelectedItem].ToString (); + // If Save style dialog then give them an overwrite prompt + if(rgCaption.SelectedItem == 2) { + fd.FilesSelected += ConfirmOverwrite; + } + if (cbIcons.Checked ?? false) { fd.IconGetter = GetIcon; } @@ -170,6 +175,16 @@ namespace UICatalog.Scenarios { }; } + private void ConfirmOverwrite (object sender, FilesSelectedEventArgs e) + { + if (!string.IsNullOrWhiteSpace (e.Dialog.Path)) { + if(File.Exists(e.Dialog.Path)) { + int result = MessageBox.Query ("Overwrite?", "File already exists", "Yes", "No"); + e.Cancel = result == 1; + } + } + } + private class CaseSensitiveSearchMatcher : FileDialog.ISearchMatcher { private string terms; diff --git a/UnitTests/FileDialogTests.cs b/UnitTests/FileDialogTests.cs index cb872fcfd..da3e53573 100644 --- a/UnitTests/FileDialogTests.cs +++ b/UnitTests/FileDialogTests.cs @@ -118,6 +118,25 @@ namespace Terminal.Gui.Core { Assert.False(dlg.Canceled); } + [Theory, AutoInitShutdown] + [InlineData(true)] + [InlineData (false)] + public void CancelSelection (bool cancel) + { + var dlg = GetInitializedFileDialog (); + var openIn = Path.Combine (Environment.CurrentDirectory, "zz"); + Directory.CreateDirectory (openIn); + dlg.Path = openIn + Path.DirectorySeparatorChar; + + dlg.FilesSelected += (s, e) => e.Cancel = cancel; + + //pressing enter will complete the current selection + // unless the event cancels the confirm + Send ('\n', ConsoleKey.Enter, false); + + Assert.Equal(cancel,dlg.Canceled); + } + private void Send (char ch, ConsoleKey ck, bool shift = false, bool alt = false, bool control=false) { Application.Driver.SendKeys (ch, ck, shift, alt, control);