FileDialog extensions (#881)

* Fix ImGuiFileDialogFlags to be actually flags.

* Add customization points for quick access and window flags to FileDialog and FileDialogManager.

* Some general cleanup for FileDialog.
This commit is contained in:
Ottermandias 2022-06-15 20:45:48 +02:00 committed by GitHub
parent e2dc8802f7
commit c3f55249d2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 114 additions and 75 deletions

View file

@ -303,7 +303,7 @@ namespace Dalamud.Interface.ImGuiFileDialog
{ {
this.drives.Add(new SideBarItem this.drives.Add(new SideBarItem
{ {
Icon = (char)FontAwesomeIcon.Server, Icon = FontAwesomeIcon.Server,
Location = drive.Name, Location = drive.Name,
Text = drive.Name, Text = drive.Name,
}); });
@ -313,14 +313,14 @@ namespace Dalamud.Interface.ImGuiFileDialog
this.quickAccess.Add(new SideBarItem this.quickAccess.Add(new SideBarItem
{ {
Icon = (char)FontAwesomeIcon.Desktop, Icon = FontAwesomeIcon.Desktop,
Location = Environment.GetFolderPath(Environment.SpecialFolder.Desktop), Location = Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
Text = "Desktop", Text = "Desktop",
}); });
this.quickAccess.Add(new SideBarItem this.quickAccess.Add(new SideBarItem
{ {
Icon = (char)FontAwesomeIcon.File, Icon = FontAwesomeIcon.File,
Location = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), Location = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
Text = "Documents", Text = "Documents",
}); });
@ -329,7 +329,7 @@ namespace Dalamud.Interface.ImGuiFileDialog
{ {
this.quickAccess.Add(new SideBarItem this.quickAccess.Add(new SideBarItem
{ {
Icon = (char)FontAwesomeIcon.Download, Icon = FontAwesomeIcon.Download,
Location = Path.Combine(personal, "Downloads"), Location = Path.Combine(personal, "Downloads"),
Text = "Downloads", Text = "Downloads",
}); });
@ -337,28 +337,28 @@ namespace Dalamud.Interface.ImGuiFileDialog
this.quickAccess.Add(new SideBarItem this.quickAccess.Add(new SideBarItem
{ {
Icon = (char)FontAwesomeIcon.Star, Icon = FontAwesomeIcon.Star,
Location = Environment.GetFolderPath(Environment.SpecialFolder.Favorites), Location = Environment.GetFolderPath(Environment.SpecialFolder.Favorites),
Text = "Favorites", Text = "Favorites",
}); });
this.quickAccess.Add(new SideBarItem this.quickAccess.Add(new SideBarItem
{ {
Icon = (char)FontAwesomeIcon.Music, Icon = FontAwesomeIcon.Music,
Location = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic), Location = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic),
Text = "Music", Text = "Music",
}); });
this.quickAccess.Add(new SideBarItem this.quickAccess.Add(new SideBarItem
{ {
Icon = (char)FontAwesomeIcon.Image, Icon = FontAwesomeIcon.Image,
Location = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), Location = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures),
Text = "Pictures", Text = "Pictures",
}); });
this.quickAccess.Add(new SideBarItem this.quickAccess.Add(new SideBarItem
{ {
Icon = (char)FontAwesomeIcon.Video, Icon = FontAwesomeIcon.Video,
Location = Environment.GetFolderPath(Environment.SpecialFolder.MyVideos), Location = Environment.GetFolderPath(Environment.SpecialFolder.MyVideos),
Text = "Videos", Text = "Videos",
}); });

View file

@ -19,12 +19,7 @@ namespace Dalamud.Interface.ImGuiFileDialog
public string FileModifiedDate; public string FileModifiedDate;
} }
private struct SideBarItem private record struct SideBarItem(string Text, string Location, FontAwesomeIcon Icon);
{
public char Icon;
public string Text;
public string Location;
}
private struct FilterStruct private struct FilterStruct
{ {
@ -50,7 +45,7 @@ namespace Dalamud.Interface.ImGuiFileDialog
private struct IconColorItem private struct IconColorItem
{ {
public char Icon; public FontAwesomeIcon Icon;
public Vector4 Color; public Vector4 Color;
} }
} }

View file

@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Numerics; using System.Numerics;
using ImGuiNET; using ImGuiNET;
@ -43,11 +44,11 @@ namespace Dalamud.Interface.ImGuiFileDialog
if (this.isModal && !this.okResultToConfirm) if (this.isModal && !this.okResultToConfirm)
{ {
ImGui.OpenPopup(name); ImGui.OpenPopup(name);
windowVisible = ImGui.BeginPopupModal(name, ref this.visible, ImGuiWindowFlags.NoScrollbar); windowVisible = ImGui.BeginPopupModal(name, ref this.visible, this.WindowFlags);
} }
else else
{ {
windowVisible = ImGui.Begin(name, ref this.visible, ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoNav); windowVisible = ImGui.Begin(name, ref this.visible, this.WindowFlags);
} }
bool wasClosed = false; bool wasClosed = false;
@ -99,7 +100,7 @@ namespace Dalamud.Interface.ImGuiFileDialog
return wasClosed || this.ConfirmOrOpenOverWriteFileDialogIfNeeded(res); return wasClosed || this.ConfirmOrOpenOverWriteFileDialogIfNeeded(res);
} }
private static void AddToIconMap(string[] extensions, char icon, Vector4 color) private static void AddToIconMap(string[] extensions, FontAwesomeIcon icon, Vector4 color)
{ {
foreach (var ext in extensions) foreach (var ext in extensions)
{ {
@ -116,19 +117,19 @@ namespace Dalamud.Interface.ImGuiFileDialog
if (iconMap == null) if (iconMap == null)
{ {
iconMap = new(); iconMap = new();
AddToIconMap(new[] { "mp4", "gif", "mov", "avi" }, (char)FontAwesomeIcon.FileVideo, miscTextColor); AddToIconMap(new[] { "mp4", "gif", "mov", "avi" }, FontAwesomeIcon.FileVideo, miscTextColor);
AddToIconMap(new[] { "pdf" }, (char)FontAwesomeIcon.FilePdf, miscTextColor); AddToIconMap(new[] { "pdf" }, FontAwesomeIcon.FilePdf, miscTextColor);
AddToIconMap(new[] { "png", "jpg", "jpeg", "tiff" }, (char)FontAwesomeIcon.FileImage, imageTextColor); AddToIconMap(new[] { "png", "jpg", "jpeg", "tiff" }, FontAwesomeIcon.FileImage, imageTextColor);
AddToIconMap(new[] { "cs", "json", "cpp", "h", "py", "xml", "yaml", "js", "html", "css", "ts", "java" }, (char)FontAwesomeIcon.FileCode, codeTextColor); AddToIconMap(new[] { "cs", "json", "cpp", "h", "py", "xml", "yaml", "js", "html", "css", "ts", "java" }, FontAwesomeIcon.FileCode, codeTextColor);
AddToIconMap(new[] { "txt", "md" }, (char)FontAwesomeIcon.FileAlt, standardTextColor); AddToIconMap(new[] { "txt", "md" }, FontAwesomeIcon.FileAlt, standardTextColor);
AddToIconMap(new[] { "zip", "7z", "gz", "tar" }, (char)FontAwesomeIcon.FileArchive, miscTextColor); AddToIconMap(new[] { "zip", "7z", "gz", "tar" }, FontAwesomeIcon.FileArchive, miscTextColor);
AddToIconMap(new[] { "mp3", "m4a", "ogg", "wav" }, (char)FontAwesomeIcon.FileAudio, miscTextColor); AddToIconMap(new[] { "mp3", "m4a", "ogg", "wav" }, FontAwesomeIcon.FileAudio, miscTextColor);
AddToIconMap(new[] { "csv" }, (char)FontAwesomeIcon.FileCsv, miscTextColor); AddToIconMap(new[] { "csv" }, FontAwesomeIcon.FileCsv, miscTextColor);
} }
return iconMap.TryGetValue(ext.ToLower(), out var icon) ? icon : new IconColorItem return iconMap.TryGetValue(ext.ToLower(), out var icon) ? icon : new IconColorItem
{ {
Icon = (char)FontAwesomeIcon.File, Icon = FontAwesomeIcon.File,
Color = standardTextColor, Color = standardTextColor,
}; };
} }
@ -222,7 +223,7 @@ namespace Dalamud.Interface.ImGuiFileDialog
if (!this.createDirectoryMode) if (!this.createDirectoryMode)
{ {
ImGui.SameLine(); ImGui.SameLine();
ImGui.Text("Search :"); ImGui.TextUnformatted("Search :");
ImGui.SameLine(); ImGui.SameLine();
ImGui.PushItemWidth(ImGui.GetContentRegionAvail().X); ImGui.PushItemWidth(ImGui.GetContentRegionAvail().X);
var edited = ImGui.InputText("##InputImGuiFileDialogSearchField", ref this.searchBuffer, 255); var edited = ImGui.InputText("##InputImGuiFileDialogSearchField", ref this.searchBuffer, 255);
@ -239,7 +240,7 @@ namespace Dalamud.Interface.ImGuiFileDialog
if (this.flags.HasFlag(ImGuiFileDialogFlags.DisableCreateDirectoryButton)) return; if (this.flags.HasFlag(ImGuiFileDialogFlags.DisableCreateDirectoryButton)) return;
ImGui.PushFont(UiBuilder.IconFont); ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button($"{(char)FontAwesomeIcon.FolderPlus}")) if (ImGui.Button(FontAwesomeIcon.FolderPlus.ToIconString()))
{ {
if (!this.createDirectoryMode) if (!this.createDirectoryMode)
{ {
@ -258,7 +259,7 @@ namespace Dalamud.Interface.ImGuiFileDialog
if (this.createDirectoryMode) if (this.createDirectoryMode)
{ {
ImGui.SameLine(); ImGui.SameLine();
ImGui.Text("New Directory Name"); ImGui.TextUnformatted("New Directory Name");
ImGui.SameLine(); ImGui.SameLine();
ImGui.PushItemWidth(ImGui.GetContentRegionAvail().X - 100f); ImGui.PushItemWidth(ImGui.GetContentRegionAvail().X - 100f);
@ -317,41 +318,29 @@ namespace Dalamud.Interface.ImGuiFileDialog
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + 5); ImGui.SetCursorPosY(ImGui.GetCursorPosY() + 5);
foreach (var drive in this.drives) var idx = 0;
foreach (var (name, location, icon) in this.drives.Concat(this.quickAccess))
{ {
ImGui.PushFont(UiBuilder.IconFont); if (string.IsNullOrEmpty(location) || !Directory.Exists(location))
if (ImGui.Selectable($"{drive.Icon}##{drive.Text}", drive.Text == this.selectedSideBar))
{
this.SetPath(drive.Location);
this.selectedSideBar = drive.Text;
}
ImGui.PopFont();
ImGui.SameLine(25);
ImGui.Text(drive.Text);
}
foreach (var quick in this.quickAccess)
{
if (string.IsNullOrEmpty(quick.Location))
{ {
continue; continue;
} }
ImGui.PushFont(UiBuilder.IconFont); ImGui.PushID(idx++);
if (ImGui.Selectable($"{quick.Icon}##{quick.Text}", quick.Text == this.selectedSideBar)) ImGui.SetCursorPosX(25);
if (ImGui.Selectable(name, name == this.selectedSideBar))
{ {
this.SetPath(quick.Location); this.SetPath(location);
this.selectedSideBar = quick.Text; this.selectedSideBar = name;
} }
ImGui.PushFont(UiBuilder.IconFont);
ImGui.SameLine();
ImGui.SetCursorPosX(0);
ImGui.TextUnformatted(icon.ToIconString());
ImGui.PopFont(); ImGui.PopFont();
ImGui.PopID();
ImGui.SameLine(25);
ImGui.Text(quick.Text);
} }
ImGui.EndChild(); ImGui.EndChild();
@ -429,7 +418,7 @@ namespace Dalamud.Interface.ImGuiFileDialog
var item = !dir ? GetIcon(file.Ext) : new IconColorItem var item = !dir ? GetIcon(file.Ext) : new IconColorItem
{ {
Color = dirTextColor, Color = dirTextColor,
Icon = (char)FontAwesomeIcon.Folder, Icon = FontAwesomeIcon.Folder,
}; };
ImGui.PushStyleColor(ImGuiCol.Text, item.Color); ImGui.PushStyleColor(ImGuiCol.Text, item.Color);
@ -444,18 +433,18 @@ namespace Dalamud.Interface.ImGuiFileDialog
if (ImGui.TableNextColumn()) if (ImGui.TableNextColumn())
{ {
ImGui.Text(file.Ext); ImGui.TextUnformatted(file.Ext);
} }
if (ImGui.TableNextColumn()) if (ImGui.TableNextColumn())
{ {
if (file.Type == FileStructType.File) if (file.Type == FileStructType.File)
{ {
ImGui.Text(file.FormattedFileSize + " "); ImGui.TextUnformatted(file.FormattedFileSize + " ");
} }
else else
{ {
ImGui.Text(" "); ImGui.TextUnformatted(" ");
} }
} }
@ -463,7 +452,7 @@ namespace Dalamud.Interface.ImGuiFileDialog
{ {
var sz = ImGui.CalcTextSize(file.FileModifiedDate); var sz = ImGui.CalcTextSize(file.FileModifiedDate);
ImGui.PushItemWidth(sz.X + 5); ImGui.PushItemWidth(sz.X + 5);
ImGui.Text(file.FileModifiedDate + " "); ImGui.TextUnformatted(file.FileModifiedDate + " ");
ImGui.PopItemWidth(); ImGui.PopItemWidth();
} }
@ -503,13 +492,13 @@ namespace Dalamud.Interface.ImGuiFileDialog
ImGui.EndChild(); ImGui.EndChild();
} }
private bool SelectableItem(FileStruct file, bool selected, char icon) private bool SelectableItem(FileStruct file, bool selected, FontAwesomeIcon icon)
{ {
var flags = ImGuiSelectableFlags.AllowDoubleClick | ImGuiSelectableFlags.SpanAllColumns; const ImGuiSelectableFlags flags = ImGuiSelectableFlags.AllowDoubleClick | ImGuiSelectableFlags.SpanAllColumns;
ImGui.PushFont(UiBuilder.IconFont); ImGui.PushFont(UiBuilder.IconFont);
ImGui.Text($"{icon}"); ImGui.TextUnformatted(icon.ToIconString());
ImGui.PopFont(); ImGui.PopFont();
ImGui.SameLine(25f); ImGui.SameLine(25f);
@ -712,11 +701,11 @@ namespace Dalamud.Interface.ImGuiFileDialog
if (this.IsDirectoryMode()) if (this.IsDirectoryMode())
{ {
ImGui.Text("Directory Path :"); ImGui.TextUnformatted("Directory Path :");
} }
else else
{ {
ImGui.Text("File Name :"); ImGui.TextUnformatted("File Name :");
} }
ImGui.SameLine(); ImGui.SameLine();
@ -839,7 +828,7 @@ namespace Dalamud.Interface.ImGuiFileDialog
ImGui.OpenPopup(name); ImGui.OpenPopup(name);
if (ImGui.BeginPopupModal(name, ref open, ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove)) if (ImGui.BeginPopupModal(name, ref open, ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove))
{ {
ImGui.Text("Would you like to Overwrite it ?"); ImGui.TextUnformatted("Would you like to Overwrite it ?");
if (ImGui.Button("Confirm")) if (ImGui.Button("Confirm"))
{ {
this.okResultToConfirm = false; this.okResultToConfirm = false;

View file

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using ImGuiNET;
namespace Dalamud.Interface.ImGuiFileDialog namespace Dalamud.Interface.ImGuiFileDialog
{ {
@ -10,6 +11,11 @@ namespace Dalamud.Interface.ImGuiFileDialog
/// </summary> /// </summary>
public partial class FileDialog public partial class FileDialog
{ {
/// <summary>
/// The flags used to draw the file picker window.
/// </summary>
public ImGuiWindowFlags WindowFlags;
private readonly string title; private readonly string title;
private readonly int selectionCountMax; private readonly int selectionCountMax;
private readonly ImGuiFileDialogFlags flags; private readonly ImGuiFileDialogFlags flags;
@ -74,6 +80,9 @@ namespace Dalamud.Interface.ImGuiFileDialog
this.flags = flags; this.flags = flags;
this.selectionCountMax = selectionCountMax; this.selectionCountMax = selectionCountMax;
this.isModal = isModal; this.isModal = isModal;
this.WindowFlags = ImGuiWindowFlags.NoNav;
if (!isModal)
this.WindowFlags |= ImGuiWindowFlags.NoScrollbar;
this.currentPath = path; this.currentPath = path;
this.defaultExtension = defaultExtension; this.defaultExtension = defaultExtension;
@ -161,6 +170,42 @@ namespace Dalamud.Interface.ImGuiFileDialog
return this.currentPath; return this.currentPath;
} }
/// <summary>
/// Set or remove a quick access folder for the navigation panel.
/// </summary>
/// <param name="name">The displayed name of the folder. If this name already exists, it will be overwritten.</param>
/// <param name="path">The new linked path. If this is empty, no link will be added and existing links will be removed.</param>
/// <param name="icon">The FontAwesomeIcon-ID of the icon displayed before the name.</param>
/// <param name="position">An optional position at which to insert the new link. If the link is updated, having this less than zero will keep its position.
/// Otherwise, invalid indices will insert it at the end.</param>
public void SetQuickAccess(string name, string path, FontAwesomeIcon icon, int position = -1)
{
var idx = this.quickAccess.FindIndex(q => q.Text.Equals(name, StringComparison.InvariantCultureIgnoreCase));
if (idx >= 0)
{
if (position >= 0 || path.Length == 0)
{
this.quickAccess.RemoveAt(idx);
}
else
{
this.quickAccess[idx] = new SideBarItem(name, path, icon);
return;
}
}
if (path.Length == 0) return;
if (position < 0 || position >= this.quickAccess.Count)
{
this.quickAccess.Add(new SideBarItem(name, path, icon));
}
else
{
this.quickAccess.Insert(position, new SideBarItem(name, path, icon));
}
}
private string GetFilePathName() private string GetFilePathName()
{ {
var path = this.GetCurrentPath(); var path = this.GetCurrentPath();

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using ImGuiNET;
namespace Dalamud.Interface.ImGuiFileDialog namespace Dalamud.Interface.ImGuiFileDialog
{ {
@ -8,6 +9,12 @@ namespace Dalamud.Interface.ImGuiFileDialog
/// </summary> /// </summary>
public class FileDialogManager public class FileDialogManager
{ {
/// <summary> Additional quick access items for the side bar.</summary>
public readonly List<(string Name, string Path, FontAwesomeIcon Icon, int Position)> CustomSideBarItems = new();
/// <summary> Additional flags with which to draw the window. </summary>
public ImGuiWindowFlags AddedWindowFlags = ImGuiWindowFlags.None;
private FileDialog? dialog; private FileDialog? dialog;
private Action<bool, string>? callback; private Action<bool, string>? callback;
private Action<bool, List<string>>? multiCallback; private Action<bool, List<string>>? multiCallback;
@ -181,6 +188,9 @@ namespace Dalamud.Interface.ImGuiFileDialog
} }
this.dialog = new FileDialog(id, title, filters, path, defaultFileName, defaultExtension, selectionCountMax, isModal, flags); this.dialog = new FileDialog(id, title, filters, path, defaultFileName, defaultExtension, selectionCountMax, isModal, flags);
this.dialog.WindowFlags |= this.AddedWindowFlags;
foreach (var (name, location, icon, position) in this.CustomSideBarItems)
this.dialog.SetQuickAccess(name, location, icon, position);
this.dialog.Show(); this.dialog.Show();
} }
} }

View file

@ -16,41 +16,41 @@ namespace Dalamud.Interface.ImGuiFileDialog
/// <summary> /// <summary>
/// Confirm the selection when choosing a file which already exists. /// Confirm the selection when choosing a file which already exists.
/// </summary> /// </summary>
ConfirmOverwrite = 1, ConfirmOverwrite = 0x01,
/// <summary> /// <summary>
/// Only allow selection of files or folders which currently exist. /// Only allow selection of files or folders which currently exist.
/// </summary> /// </summary>
SelectOnly = 2, SelectOnly = 0x02,
/// <summary> /// <summary>
/// Hide files or folders which start with a period. /// Hide files or folders which start with a period.
/// </summary> /// </summary>
DontShowHiddenFiles = 3, DontShowHiddenFiles = 0x04,
/// <summary> /// <summary>
/// Disable the creation of new folders within the dialog. /// Disable the creation of new folders within the dialog.
/// </summary> /// </summary>
DisableCreateDirectoryButton = 4, DisableCreateDirectoryButton = 0x08,
/// <summary> /// <summary>
/// Hide the type column. /// Hide the type column.
/// </summary> /// </summary>
HideColumnType = 5, HideColumnType = 0x10,
/// <summary> /// <summary>
/// Hide the file size column. /// Hide the file size column.
/// </summary> /// </summary>
HideColumnSize = 6, HideColumnSize = 0x20,
/// <summary> /// <summary>
/// Hide the last modified date column. /// Hide the last modified date column.
/// </summary> /// </summary>
HideColumnDate = 7, HideColumnDate = 0x40,
/// <summary> /// <summary>
/// Hide the quick access sidebar. /// Hide the quick access sidebar.
/// </summary> /// </summary>
HideSideBar = 8, HideSideBar = 0x80,
} }
} }