From 8c6b599a07b0a32d36a6e19ee2bd9b80e21dcc87 Mon Sep 17 00:00:00 2001 From: Ottermandias <70807659+Ottermandias@users.noreply.github.com> Date: Sat, 23 Apr 2022 16:43:16 +0200 Subject: [PATCH] File Selector (#807) --- .../Interface/ImGuiFileDialog/FileDialog.cs | 21 ++- .../ImGuiFileDialog/FileDialogManager.cs | 121 ++++++++++++++---- 2 files changed, 110 insertions(+), 32 deletions(-) diff --git a/Dalamud/Interface/ImGuiFileDialog/FileDialog.cs b/Dalamud/Interface/ImGuiFileDialog/FileDialog.cs index 98b70a3ab..924dc68c3 100644 --- a/Dalamud/Interface/ImGuiFileDialog/FileDialog.cs +++ b/Dalamud/Interface/ImGuiFileDialog/FileDialog.cs @@ -115,22 +115,31 @@ namespace Dalamud.Interface.ImGuiFileDialog /// /// Gets the result of the selection. /// - /// The separator to put between multiple selected entries. - /// The result of the selection (file or folder path). If multiple entries were selected, they are separated with the given separator, which is a comma by default. - public string GetResult(char separator = ',') + /// The result of the selection (file or folder path). If multiple entries were selected, they are separated with commas. + [Obsolete("Use GetResults() instead.", true)] + public string GetResult() + { + return string.Join(',', this.GetResults()); + } + + /// + /// Gets the result of the selection. + /// + /// The list of selected paths. + public List GetResults() { if (!this.flags.HasFlag(ImGuiFileDialogFlags.SelectOnly)) { - return this.GetFilePathName(); + return new List { this.GetFilePathName() }; } if (this.IsDirectoryMode() && this.selectedFileNames.Count == 0) { - return this.GetFilePathName(); // current directory + return new List { this.GetFilePathName() }; // current directory } var fullPaths = this.selectedFileNames.Where(x => !string.IsNullOrEmpty(x)).Select(x => Path.Combine(this.currentPath, x)); - return string.Join(separator, fullPaths.ToArray()); + return fullPaths.ToList(); } /// diff --git a/Dalamud/Interface/ImGuiFileDialog/FileDialogManager.cs b/Dalamud/Interface/ImGuiFileDialog/FileDialogManager.cs index 2c1bab735..e5c5854db 100644 --- a/Dalamud/Interface/ImGuiFileDialog/FileDialogManager.cs +++ b/Dalamud/Interface/ImGuiFileDialog/FileDialogManager.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace Dalamud.Interface.ImGuiFileDialog { @@ -7,21 +8,33 @@ namespace Dalamud.Interface.ImGuiFileDialog /// public class FileDialogManager { - private FileDialog dialog; + private FileDialog? dialog; + private Action? callback; + private Action>? multiCallback; private string savedPath = "."; - private Action callback; - private char selectionSeparator; /// /// Create a dialog which selects an already existing folder. /// /// The header title of the dialog. /// The action to execute when the dialog is finished. - /// The directory which the dialog should start inside of. - /// Whether the dialog should be a modal popup. - public void OpenFolderDialog(string title, Action callback, string? startPath = null, bool isModal = false) + public void OpenFolderDialog(string title, Action callback) { - this.SetDialog("OpenFolderDialog", title, string.Empty, startPath ?? this.savedPath, ".", string.Empty, 1, isModal, ImGuiFileDialogFlags.SelectOnly, callback); + this.SetCallback(callback); + this.SetDialog("OpenFolderDialog", title, string.Empty, this.savedPath, ".", string.Empty, 1, false, ImGuiFileDialogFlags.SelectOnly); + } + + /// + /// Create a dialog which selects an already existing folder. + /// + /// The header title of the dialog. + /// The action to execute when the dialog is finished. + /// The directory which the dialog should start inside of. The last path this manager was in is used if this is null. + /// Whether the dialog should be a modal popup. + public void OpenFolderDialog(string title, Action callback, string? startPath, bool isModal = false) + { + this.SetCallback(callback); + this.SetDialog("OpenFolderDialog", title, string.Empty, startPath ?? this.savedPath, ".", string.Empty, 1, isModal, ImGuiFileDialogFlags.SelectOnly); } /// @@ -30,34 +43,57 @@ namespace Dalamud.Interface.ImGuiFileDialog /// The header title of the dialog. /// The default name to use when creating a new folder. /// The action to execute when the dialog is finished. - /// The directory which the dialog should start inside of. - /// Whether the dialog should be a modal popup. - public void SaveFolderDialog(string title, string defaultFolderName, Action callback, string? startPath = null, bool isModal = false) + public void SaveFolderDialog(string title, string defaultFolderName, Action callback) { - this.SetDialog("SaveFolderDialog", title, string.Empty, startPath ?? this.savedPath, defaultFolderName, string.Empty, 1, isModal, ImGuiFileDialogFlags.None, callback); + this.SetCallback(callback); + this.SetDialog("SaveFolderDialog", title, string.Empty, this.savedPath, defaultFolderName, string.Empty, 1, false, ImGuiFileDialogFlags.None); } /// - /// Create a dialog which selects an already existing file. + /// Create a dialog which selects an already existing folder or new folder. + /// + /// The header title of the dialog. + /// The default name to use when creating a new folder. + /// The action to execute when the dialog is finished. + /// The directory which the dialog should start inside of. The last path this manager was in is used if this is null. + /// Whether the dialog should be a modal popup. + public void SaveFolderDialog(string title, string defaultFolderName, Action callback, string? startPath, bool isModal = false) + { + this.SetCallback(callback); + this.SetDialog("SaveFolderDialog", title, string.Empty, startPath ?? this.savedPath, defaultFolderName, string.Empty, 1, isModal, ImGuiFileDialogFlags.None); + } + + /// + /// Create a dialog which selects a single, already existing file. /// /// The header title of the dialog. /// Which files to show in the dialog. /// The action to execute when the dialog is finished. - /// The directory which the dialog should start inside of. + public void OpenFileDialog(string title, string filters, Action callback) + { + this.SetCallback(callback); + this.SetDialog("OpenFileDialog", title, filters, this.savedPath, ".", string.Empty, 1, false, ImGuiFileDialogFlags.SelectOnly); + } + + /// + /// Create a dialog which selects already existing files. + /// + /// The header title of the dialog. + /// Which files to show in the dialog. + /// The action to execute when the dialog is finished. + /// The directory which the dialog should start inside of. The last path this manager was in is used if this is null. /// The maximum amount of files or directories which can be selected. Set to 0 for an infinite number. - /// The separator to put between multiple selected entries. /// Whether the dialog should be a modal popup. public void OpenFileDialog( string title, string filters, - Action callback, + Action> callback, string? startPath = null, int selectionCountMax = 1, - char selectionSeparator = '\0', bool isModal = false) { - this.selectionSeparator = selectionSeparator; - this.SetDialog("OpenFileDialog", title, filters, startPath ?? this.savedPath, ".", string.Empty, selectionCountMax, isModal, ImGuiFileDialogFlags.SelectOnly, callback); + this.SetCallback(callback); + this.SetDialog("OpenFileDialog", title, filters, startPath ?? this.savedPath, ".", string.Empty, selectionCountMax, isModal, ImGuiFileDialogFlags.SelectOnly); } /// @@ -68,7 +104,26 @@ namespace Dalamud.Interface.ImGuiFileDialog /// The default name to use when creating a new file. /// The extension to use when creating a new file. /// The action to execute when the dialog is finished. - /// The directory which the dialog should start inside of. + public void SaveFileDialog( + string title, + string filters, + string defaultFileName, + string defaultExtension, + Action callback) + { + this.SetCallback(callback); + this.SetDialog("SaveFileDialog", title, filters, this.savedPath, defaultFileName, defaultExtension, 1, false, ImGuiFileDialogFlags.None); + } + + /// + /// Create a dialog which selects an already existing folder or new file. + /// + /// The header title of the dialog. + /// Which files to show in the dialog. + /// The default name to use when creating a new file. + /// The extension to use when creating a new file. + /// The action to execute when the dialog is finished. + /// The directory which the dialog should start inside of. The last path this manager was in is used if this is null. /// Whether the dialog should be a modal popup. public void SaveFileDialog( string title, @@ -76,10 +131,11 @@ namespace Dalamud.Interface.ImGuiFileDialog string defaultFileName, string defaultExtension, Action callback, - string? startPath = null, + string? startPath, bool isModal = false) { - this.SetDialog("SaveFileDialog", title, filters, startPath ?? this.savedPath, defaultFileName, defaultExtension, 1, isModal, ImGuiFileDialogFlags.None, callback); + this.SetCallback(callback); + this.SetDialog("SaveFileDialog", title, filters, startPath ?? this.savedPath, defaultFileName, defaultExtension, 1, isModal, ImGuiFileDialogFlags.None); } /// @@ -90,7 +146,10 @@ namespace Dalamud.Interface.ImGuiFileDialog if (this.dialog == null) return; if (this.dialog.Draw()) { - this.callback(this.dialog.GetIsOk(), this.dialog.GetResult(this.selectionSeparator)); + var isOk = this.dialog.GetIsOk(); + var results = this.dialog.GetResults(); + this.callback?.Invoke(isOk, results.Count > 0 ? results[0] : string.Empty); + this.multiCallback?.Invoke(isOk, results); this.savedPath = this.dialog.GetCurrentPath(); this.Reset(); } @@ -104,7 +163,19 @@ namespace Dalamud.Interface.ImGuiFileDialog this.dialog?.Hide(); this.dialog = null; this.callback = null; - this.selectionSeparator = '\0'; + this.multiCallback = null; + } + + private void SetCallback(Action action) + { + this.callback = action; + this.multiCallback = null; + } + + private void SetCallback(Action> action) + { + this.multiCallback = action; + this.callback = null; } private void SetDialog( @@ -116,11 +187,9 @@ namespace Dalamud.Interface.ImGuiFileDialog string defaultExtension, int selectionCountMax, bool isModal, - ImGuiFileDialogFlags flags, - Action callback) + ImGuiFileDialogFlags flags) { this.Reset(); - this.callback = callback; this.dialog = new FileDialog(id, title, filters, path, defaultFileName, defaultExtension, selectionCountMax, isModal, flags); this.dialog.Show(); }