using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ImGuiNET;
namespace Dalamud.Interface.ImGuiFileDialog;
///
/// A file or folder picker.
///
public partial class FileDialog
{
///
/// The flags used to draw the file picker window.
///
#pragma warning disable SA1401
public ImGuiWindowFlags WindowFlags;
#pragma warning restore SA1401
private readonly string title;
private readonly int selectionCountMax;
private readonly ImGuiFileDialogFlags flags;
private readonly string id;
private readonly string defaultExtension;
private readonly string defaultFileName;
private bool visible;
private string currentPath;
private string fileNameBuffer = string.Empty;
private List pathDecomposition = new();
private bool pathClicked = true;
private bool pathInputActivated = false;
private string pathInputBuffer = string.Empty;
private bool isModal = false;
private bool okResultToConfirm = false;
private bool isOk;
private bool wantsToQuit;
private bool createDirectoryMode = false;
private string createDirectoryBuffer = string.Empty;
private string searchBuffer = string.Empty;
private string lastSelectedFileName = string.Empty;
private List selectedFileNames = new();
private float footerHeight = 0;
private string selectedSideBar = string.Empty;
private List drives = new();
private List quickAccess = new();
///
/// Initializes a new instance of the class.
///
/// A unique id for the dialog.
/// The text which is shown at the top of the dialog.
/// Which file extension filters to apply. This should be left blank to select directories.
/// The directory which the dialog should start inside of.
/// The default file or directory name.
/// The default extension when creating new files.
/// The maximum amount of files or directories which can be selected. Set to 0 for an infinite number.
/// Whether the dialog should be a modal popup.
/// Settings flags for the dialog, see .
public FileDialog(
string id,
string title,
string filters,
string path,
string defaultFileName,
string defaultExtension,
int selectionCountMax,
bool isModal,
ImGuiFileDialogFlags flags)
{
this.id = id;
this.title = title;
this.flags = flags;
this.selectionCountMax = selectionCountMax;
this.isModal = isModal;
this.WindowFlags = ImGuiWindowFlags.NoNav;
if (!isModal)
this.WindowFlags |= ImGuiWindowFlags.NoScrollbar;
this.currentPath = path;
this.defaultExtension = defaultExtension;
this.defaultFileName = defaultFileName;
this.ParseFilters(filters);
this.SetSelectedFilterWithExt(this.defaultExtension);
this.SetDefaultFileName();
this.SetPath(this.currentPath);
this.SetupSideBar();
}
///
/// Shows the dialog.
///
public void Show()
{
this.visible = true;
}
///
/// Hides the dialog.
///
public void Hide()
{
this.visible = false;
}
///
/// Gets whether a file or folder was successfully selected.
///
/// The success state. Will be false if the selection was canceled or was otherwise unsuccessful.
public bool GetIsOk()
{
return this.isOk;
}
///
/// Gets the result of the selection.
///
/// 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 new List { this.GetFilePathName() };
}
if (this.IsDirectoryMode() && this.selectedFileNames.Count == 0)
{
return new List { this.GetFilePathName() }; // current directory
}
var fullPaths = this.selectedFileNames.Where(x => !string.IsNullOrEmpty(x)).Select(x => Path.Combine(this.currentPath, x));
return fullPaths.ToList();
}
///
/// Gets the current path of the dialog.
///
/// The path of the directory which the dialog is current viewing.
public string GetCurrentPath()
{
if (this.IsDirectoryMode())
{
// combine path file with directory input
var selectedDirectory = this.fileNameBuffer;
if (!string.IsNullOrEmpty(selectedDirectory) && selectedDirectory != ".")
{
return string.IsNullOrEmpty(this.currentPath) ? selectedDirectory : Path.Combine(this.currentPath, selectedDirectory);
}
}
return this.currentPath;
}
///
/// Set or remove a quick access folder for the navigation panel.
///
/// The displayed name of the folder. If this name already exists, it will be overwritten.
/// The new linked path. If this is empty, no link will be added and existing links will be removed.
/// The FontAwesomeIcon-ID of the icon displayed before the name.
/// 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.
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()
{
var path = this.GetCurrentPath();
var fileName = this.GetCurrentFileName();
if (!string.IsNullOrEmpty(fileName))
{
return Path.Combine(path, fileName);
}
return path;
}
private string GetCurrentFileName()
{
if (this.IsDirectoryMode())
{
return string.Empty;
}
var result = this.fileNameBuffer;
// a collection like {.cpp, .h}, so can't decide on an extension
if (this.selectedFilter.CollectionFilters is { Count: > 0 })
{
return result;
}
// a single one, like .cpp
if (!this.selectedFilter.Filter.Contains('*') && result != this.selectedFilter.Filter)
{
var lastPoint = result.LastIndexOf('.');
if (lastPoint != -1)
{
result = result[..lastPoint];
}
result += this.selectedFilter.Filter;
}
return result;
}
private void SetDefaultFileName()
{
this.fileNameBuffer = this.defaultFileName;
}
private void SetPath(string path)
{
this.selectedSideBar = string.Empty;
this.currentPath = path;
this.files.Clear();
this.pathDecomposition.Clear();
this.selectedFileNames.Clear();
if (this.IsDirectoryMode())
{
this.SetDefaultFileName();
}
this.ScanDir(this.currentPath);
}
private void SetCurrentDir(string path)
{
var dir = new DirectoryInfo(path);
this.currentPath = dir.FullName;
if (this.currentPath[^1] == Path.DirectorySeparatorChar)
{ // handle selecting a drive, like C: -> C:\
this.currentPath = this.currentPath[..^1];
}
this.pathInputBuffer = this.currentPath;
this.pathDecomposition = new List(this.currentPath.Split(Path.DirectorySeparatorChar));
}
private bool IsDirectoryMode()
{
return this.filters.Count == 0;
}
private void ResetEvents()
{
this.pathClicked = false;
}
}