mirror of
https://github.com/grumpycoders/pcsx-redux.git
synced 2025-04-02 10:41:54 -04:00
1501 lines
69 KiB
C++
1501 lines
69 KiB
C++
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
|
#define _CRT_SECURE_NO_WARNINGS
|
|
#endif
|
|
#include "ImFileDialog.h"
|
|
|
|
#include <fstream>
|
|
#include <algorithm>
|
|
#include <sys/stat.h>
|
|
#define IMGUI_DEFINE_MATH_OPERATORS
|
|
#include <imgui/imgui.h>
|
|
#include <imgui/imgui_internal.h>
|
|
|
|
#define STB_IMAGE_IMPLEMENTATION
|
|
#define STB_IMAGE_STATIC
|
|
#define STBI_ASSERT(x) assert(x)
|
|
#include "stb/stb_image.h"
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#include <shellapi.h>
|
|
#include <lmcons.h>
|
|
#pragma comment(lib, "Shell32.lib")
|
|
#else
|
|
#include <unistd.h>
|
|
#include <pwd.h>
|
|
#endif
|
|
|
|
#define ICON_SIZE ImGui::GetFont()->FontSize + 3
|
|
#define GUI_ELEMENT_SIZE std::max(GImGui->FontSize + 10.f, 24.f)
|
|
#define DEFAULT_ICON_SIZE 32
|
|
#define PI 3.141592f
|
|
|
|
static std::string u8StringToString(const std::u8string& str) {
|
|
return reinterpret_cast<const char*>(str.c_str());
|
|
}
|
|
namespace ifd {
|
|
static const char* GetDefaultFolderIcon();
|
|
static const char* GetDefaultFileIcon();
|
|
|
|
/* UI CONTROLS */
|
|
bool FolderNode(const char* label, ImTextureID icon, bool& clicked)
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiWindow* window = g.CurrentWindow;
|
|
|
|
clicked = false;
|
|
|
|
ImU32 id = window->GetID(label);
|
|
int opened = window->StateStorage.GetInt(id, 0);
|
|
ImVec2 pos = window->DC.CursorPos;
|
|
const bool is_mouse_x_over_arrow = (g.IO.MousePos.x >= pos.x && g.IO.MousePos.x < pos.x + g.FontSize);
|
|
if (ImGui::InvisibleButton(label, ImVec2(-FLT_MIN, g.FontSize + g.Style.FramePadding.y * 2)))
|
|
{
|
|
if (is_mouse_x_over_arrow) {
|
|
int* p_opened = window->StateStorage.GetIntRef(id, 0);
|
|
opened = *p_opened = !*p_opened;
|
|
}
|
|
else {
|
|
clicked = true;
|
|
}
|
|
}
|
|
bool hovered = ImGui::IsItemHovered();
|
|
bool active = ImGui::IsItemActive();
|
|
bool doubleClick = ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left);
|
|
if (doubleClick && hovered) {
|
|
int* p_opened = window->StateStorage.GetIntRef(id, 0);
|
|
opened = *p_opened = !*p_opened;
|
|
clicked = false;
|
|
}
|
|
if (hovered || active)
|
|
window->DrawList->AddRectFilled(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, ImGui::ColorConvertFloat4ToU32(ImGui::GetStyle().Colors[active ? ImGuiCol_HeaderActive : ImGuiCol_HeaderHovered]));
|
|
|
|
// Icon, text
|
|
float icon_posX = pos.x + g.FontSize + g.Style.FramePadding.y;
|
|
float text_posX = icon_posX + g.Style.FramePadding.y + ICON_SIZE;
|
|
ImGui::RenderArrow(window->DrawList, ImVec2(pos.x, pos.y + g.Style.FramePadding.y), ImGui::ColorConvertFloat4ToU32(ImGui::GetStyle().Colors[((hovered && is_mouse_x_over_arrow) || opened) ? ImGuiCol_Text : ImGuiCol_TextDisabled]), opened ? ImGuiDir_Down : ImGuiDir_Right);
|
|
window->DrawList->AddImage(icon, ImVec2(icon_posX, pos.y), ImVec2(icon_posX + ICON_SIZE, pos.y + ICON_SIZE));
|
|
ImGui::RenderText(ImVec2(text_posX, pos.y + g.Style.FramePadding.y), label);
|
|
if (opened)
|
|
ImGui::TreePush(label);
|
|
return opened != 0;
|
|
}
|
|
bool FileNode(const char* label, ImTextureID icon) {
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiWindow* window = g.CurrentWindow;
|
|
|
|
//ImU32 id = window->GetID(label);
|
|
ImVec2 pos = window->DC.CursorPos;
|
|
bool ret = ImGui::InvisibleButton(label, ImVec2(-FLT_MIN, g.FontSize + g.Style.FramePadding.y * 2));
|
|
|
|
bool hovered = ImGui::IsItemHovered();
|
|
bool active = ImGui::IsItemActive();
|
|
if (hovered || active)
|
|
window->DrawList->AddRectFilled(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, ImGui::ColorConvertFloat4ToU32(ImGui::GetStyle().Colors[active ? ImGuiCol_HeaderActive : ImGuiCol_HeaderHovered]));
|
|
|
|
// Icon, text
|
|
window->DrawList->AddImage(icon, ImVec2(pos.x, pos.y), ImVec2(pos.x + ICON_SIZE, pos.y + ICON_SIZE));
|
|
ImGui::RenderText(ImVec2(pos.x + g.Style.FramePadding.y + ICON_SIZE, pos.y + g.Style.FramePadding.y), label);
|
|
|
|
return ret;
|
|
}
|
|
bool PathBox(const char* label, std::filesystem::path& path, char* pathBuffer, ImVec2 size_arg) {
|
|
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
|
if (window->SkipItems)
|
|
return false;
|
|
|
|
bool ret = false;
|
|
const ImGuiID id = window->GetID(label);
|
|
int* state = window->StateStorage.GetIntRef(id, 0);
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGuiContext& g = *GImGui;
|
|
const ImGuiStyle& style = g.Style;
|
|
ImVec2 pos = window->DC.CursorPos;
|
|
ImVec2 uiPos = ImGui::GetCursorPos();
|
|
ImVec2 size = ImGui::CalcItemSize(size_arg, 200, GUI_ELEMENT_SIZE);
|
|
const ImRect bb(pos, pos + size);
|
|
|
|
// buttons
|
|
if (!(*state & 0b001)) {
|
|
ImGui::PushClipRect(bb.Min, bb.Max, false);
|
|
|
|
// background
|
|
bool hovered = g.IO.MousePos.x >= bb.Min.x && g.IO.MousePos.x <= bb.Max.x &&
|
|
g.IO.MousePos.y >= bb.Min.y && g.IO.MousePos.y <= bb.Max.y;
|
|
bool clicked = hovered && ImGui::IsMouseReleased(ImGuiMouseButton_Left);
|
|
bool anyOtherHC = false; // are any other items hovered or clicked?
|
|
window->DrawList->AddRectFilled(pos, pos + size, ImGui::ColorConvertFloat4ToU32(ImGui::GetStyle().Colors[(*state & 0b10) ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg]));
|
|
|
|
// fetch the buttons (so that we can throw some away if needed)
|
|
std::vector<std::string> btnList;
|
|
float totalWidth = 0.0f;
|
|
for (auto comp : path) {
|
|
std::string section = u8StringToString(comp.u8string());
|
|
if (section.size() == 1 && (section[0] == '\\' || section[0] == '/'))
|
|
continue;
|
|
|
|
totalWidth += ImGui::CalcTextSize(section.c_str()).x + style.FramePadding.x * 2.0f + GUI_ELEMENT_SIZE;
|
|
btnList.push_back(section);
|
|
}
|
|
totalWidth -= GUI_ELEMENT_SIZE;
|
|
|
|
// UI buttons
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, ImGui::GetStyle().ItemSpacing.y));
|
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
|
|
bool isFirstElement = true;
|
|
for (size_t i = 0; i < btnList.size(); i++) {
|
|
if (totalWidth > size.x - 30 && i != btnList.size() - 1) { // trim some buttons if there's not enough space
|
|
float elSize = ImGui::CalcTextSize(btnList[i].c_str()).x + style.FramePadding.x * 2.0f + GUI_ELEMENT_SIZE;
|
|
totalWidth -= elSize;
|
|
continue;
|
|
}
|
|
|
|
ImGui::PushID(static_cast<int>(i));
|
|
if (!isFirstElement) {
|
|
ImGui::ArrowButtonEx("##dir_dropdown", ImGuiDir_Right, ImVec2(GUI_ELEMENT_SIZE, GUI_ELEMENT_SIZE));
|
|
anyOtherHC |= ImGui::IsItemHovered() | ImGui::IsItemClicked();
|
|
ImGui::SameLine();
|
|
}
|
|
if (ImGui::Button(btnList[i].c_str(), ImVec2(0, GUI_ELEMENT_SIZE))) {
|
|
#ifdef _WIN32
|
|
std::string newPath = "";
|
|
#else
|
|
std::string newPath = "/";
|
|
#endif
|
|
for (size_t j = 0; j <= i; j++) {
|
|
newPath += btnList[j];
|
|
#ifdef _WIN32
|
|
if (j != i)
|
|
newPath += "\\";
|
|
#else
|
|
if (j != i)
|
|
newPath += "/";
|
|
#endif
|
|
}
|
|
path = std::filesystem::u8path(newPath);
|
|
ret = true;
|
|
}
|
|
anyOtherHC |= ImGui::IsItemHovered() | ImGui::IsItemClicked();
|
|
ImGui::SameLine();
|
|
ImGui::PopID();
|
|
|
|
isFirstElement = false;
|
|
}
|
|
ImGui::PopStyleVar(2);
|
|
|
|
|
|
// click state
|
|
if (!anyOtherHC && clicked) {
|
|
strcpy(pathBuffer, u8StringToString(path.u8string()).c_str());
|
|
*state |= 0b001;
|
|
*state &= 0b011; // remove SetKeyboardFocus flag
|
|
}
|
|
else
|
|
*state &= 0b110;
|
|
|
|
// hover state
|
|
if (!anyOtherHC && hovered && !clicked)
|
|
*state |= 0b010;
|
|
else
|
|
*state &= 0b101;
|
|
|
|
ImGui::PopClipRect();
|
|
|
|
// allocate space
|
|
ImGui::SetCursorPos(uiPos);
|
|
ImGui::ItemSize(size);
|
|
}
|
|
// input box
|
|
else {
|
|
bool skipActiveCheck = false;
|
|
if (!(*state & 0b100)) {
|
|
skipActiveCheck = true;
|
|
ImGui::SetKeyboardFocusHere();
|
|
if (!ImGui::IsMouseClicked(ImGuiMouseButton_Left))
|
|
*state |= 0b100;
|
|
}
|
|
if (ImGui::InputTextEx("##pathbox_input", "", pathBuffer, 1024, size_arg, ImGuiInputTextFlags_EnterReturnsTrue)) {
|
|
std::string tempStr(pathBuffer);
|
|
if (std::filesystem::exists(tempStr))
|
|
path = std::filesystem::u8path(tempStr);
|
|
ret = true;
|
|
}
|
|
if (!skipActiveCheck && !ImGui::IsItemActive())
|
|
*state &= 0b010;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
bool FavoriteButton(const char* label, bool isFavorite)
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiWindow* window = g.CurrentWindow;
|
|
|
|
ImVec2 pos = window->DC.CursorPos;
|
|
bool ret = ImGui::InvisibleButton(label, ImVec2(GUI_ELEMENT_SIZE, GUI_ELEMENT_SIZE));
|
|
|
|
bool hovered = ImGui::IsItemHovered();
|
|
bool active = ImGui::IsItemActive();
|
|
|
|
float size = g.LastItemData.Rect.Max.x - g.LastItemData.Rect.Min.x;
|
|
|
|
int numPoints = 5;
|
|
float innerRadius = size / 4;
|
|
float outerRadius = size / 2;
|
|
float angle = PI / numPoints;
|
|
ImVec2 center = ImVec2(pos.x + size / 2, pos.y + size / 2);
|
|
|
|
// fill
|
|
if (isFavorite || hovered || active) {
|
|
ImU32 fillColor = 0xff00ffff;// ImGui::ColorConvertFloat4ToU32(ImGui::GetStyle().Colors[ImGuiCol_Text]);
|
|
if (hovered || active)
|
|
fillColor = ImGui::ColorConvertFloat4ToU32(ImGui::GetStyle().Colors[active ? ImGuiCol_HeaderActive : ImGuiCol_HeaderHovered]);
|
|
|
|
// since there is no PathFillConcave, fill first the inner part, then the triangles
|
|
// inner
|
|
window->DrawList->PathClear();
|
|
for (int i = 1; i < numPoints * 2; i += 2)
|
|
window->DrawList->PathLineTo(ImVec2(center.x + innerRadius * sin(i * angle), center.y - innerRadius * cos(i * angle)));
|
|
window->DrawList->PathFillConvex(fillColor);
|
|
|
|
// triangles
|
|
for (int i = 0; i < numPoints; i++) {
|
|
window->DrawList->PathClear();
|
|
|
|
int pIndex = i * 2;
|
|
window->DrawList->PathLineTo(ImVec2(center.x + outerRadius * sin(pIndex * angle), center.y - outerRadius * cos(pIndex * angle)));
|
|
window->DrawList->PathLineTo(ImVec2(center.x + innerRadius * sin((pIndex + 1) * angle), center.y - innerRadius * cos((pIndex + 1) * angle)));
|
|
window->DrawList->PathLineTo(ImVec2(center.x + innerRadius * sin((pIndex - 1) * angle), center.y - innerRadius * cos((pIndex - 1) * angle)));
|
|
|
|
window->DrawList->PathFillConvex(fillColor);
|
|
}
|
|
}
|
|
|
|
// outline
|
|
window->DrawList->PathClear();
|
|
for (int i = 0; i < numPoints * 2; i++) {
|
|
float radius = i & 1 ? innerRadius : outerRadius;
|
|
window->DrawList->PathLineTo(ImVec2(center.x + radius * sin(i * angle), center.y - radius * cos(i * angle)));
|
|
}
|
|
window->DrawList->PathStroke(ImGui::ColorConvertFloat4ToU32(ImGui::GetStyle().Colors[ImGuiCol_Text]), true, 2.0f);
|
|
|
|
return ret;
|
|
}
|
|
bool FileIcon(const char* label, bool isSelected, ImTextureID icon, ImVec2 size, bool hasPreview, int previewWidth, int previewHeight)
|
|
{
|
|
ImGuiStyle& style = ImGui::GetStyle();
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiWindow* window = g.CurrentWindow;
|
|
|
|
float windowSpace = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x;
|
|
ImVec2 pos = window->DC.CursorPos;
|
|
bool ret = false;
|
|
|
|
if (ImGui::InvisibleButton(label, size))
|
|
ret = true;
|
|
|
|
bool hovered = ImGui::IsItemHovered();
|
|
bool active = ImGui::IsItemActive();
|
|
bool doubleClick = ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left);
|
|
if (doubleClick && hovered)
|
|
ret = true;
|
|
|
|
|
|
float iconSize = size.y - g.FontSize * 2;
|
|
float iconPosX = pos.x + (size.x - iconSize) / 2.0f;
|
|
ImVec2 textSize = ImGui::CalcTextSize(label, 0, true, size.x);
|
|
|
|
|
|
if (hovered || active || isSelected)
|
|
window->DrawList->AddRectFilled(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, ImGui::ColorConvertFloat4ToU32(ImGui::GetStyle().Colors[active ? ImGuiCol_HeaderActive : (isSelected ? ImGuiCol_Header : ImGuiCol_HeaderHovered)]));
|
|
|
|
if (hasPreview) {
|
|
ImVec2 availSize = ImVec2(size.x, iconSize);
|
|
|
|
float scale = std::min<float>(availSize.x / previewWidth, availSize.y / previewHeight);
|
|
availSize.x = previewWidth * scale;
|
|
availSize.y = previewHeight * scale;
|
|
|
|
float previewPosX = pos.x + (size.x - availSize.x) / 2.0f;
|
|
float previewPosY = pos.y + (iconSize - availSize.y) / 2.0f;
|
|
|
|
window->DrawList->AddImage(icon, ImVec2(previewPosX, previewPosY), ImVec2(previewPosX + availSize.x, previewPosY + availSize.y));
|
|
}
|
|
else
|
|
window->DrawList->AddImage(icon, ImVec2(iconPosX, pos.y), ImVec2(iconPosX + iconSize, pos.y + iconSize));
|
|
|
|
window->DrawList->AddText(g.Font, g.FontSize, ImVec2(pos.x + (size.x - textSize.x) / 2.0f, pos.y + iconSize), ImGui::ColorConvertFloat4ToU32(ImGui::GetStyle().Colors[ImGuiCol_Text]), label, 0, size.x);
|
|
|
|
|
|
float lastButtomPos = ImGui::GetItemRectMax().x;
|
|
float thisButtonPos = lastButtomPos + style.ItemSpacing.x + size.x; // Expected position if next button was on same line
|
|
if (thisButtonPos < windowSpace)
|
|
ImGui::SameLine();
|
|
|
|
return ret;
|
|
}
|
|
|
|
FileDialog::FileData::FileData(const std::filesystem::path& path) {
|
|
std::error_code ec;
|
|
Path = path;
|
|
IsDirectory = std::filesystem::is_directory(path, ec);
|
|
Size = std::filesystem::file_size(path, ec);
|
|
|
|
struct stat attr;
|
|
stat(u8StringToString(path.u8string()).c_str(), &attr);
|
|
DateModified = attr.st_ctime;
|
|
|
|
HasIconPreview = false;
|
|
IconPreview = nullptr;
|
|
IconPreviewData = nullptr;
|
|
IconPreviewHeight = 0;
|
|
IconPreviewWidth = 0;
|
|
}
|
|
|
|
FileDialog::FileDialog() {
|
|
m_isOpen = false;
|
|
m_type = 0;
|
|
m_calledOpenPopup = false;
|
|
m_sortColumn = 0;
|
|
m_sortDirection = ImGuiSortDirection_Ascending;
|
|
m_filterSelection = 0;
|
|
m_inputTextbox[0] = 0;
|
|
m_pathBuffer[0] = 0;
|
|
m_searchBuffer[0] = 0;
|
|
m_newEntryBuffer[0] = 0;
|
|
m_selectedFileItem = -1;
|
|
m_zoom = 1.0f;
|
|
|
|
m_previewLoader = nullptr;
|
|
m_previewLoaderRunning = false;
|
|
|
|
m_setDirectory(std::filesystem::current_path(), false);
|
|
|
|
// favorites are available on every OS
|
|
FileTreeNode* quickAccess = new FileTreeNode("Quick Access");
|
|
quickAccess->Read = true;
|
|
m_treeCache.push_back(quickAccess);
|
|
|
|
#ifdef _WIN32
|
|
wchar_t username[UNLEN + 1] = { 0 };
|
|
DWORD username_len = UNLEN + 1;
|
|
GetUserNameW(username, &username_len);
|
|
|
|
std::wstring userPath = L"C:\\Users\\" + std::wstring(username) + L"\\";
|
|
|
|
// Quick Access / Bookmarks
|
|
quickAccess->Children.push_back(new FileTreeNode(userPath + L"Desktop"));
|
|
quickAccess->Children.push_back(new FileTreeNode(userPath + L"Documents"));
|
|
quickAccess->Children.push_back(new FileTreeNode(userPath + L"Downloads"));
|
|
quickAccess->Children.push_back(new FileTreeNode(userPath + L"Pictures"));
|
|
|
|
// OneDrive
|
|
FileTreeNode* oneDrive = new FileTreeNode(userPath + L"OneDrive");
|
|
m_treeCache.push_back(oneDrive);
|
|
|
|
// This PC
|
|
FileTreeNode* thisPC = new FileTreeNode("This PC");
|
|
thisPC->Read = true;
|
|
if (std::filesystem::exists(userPath + L"3D Objects"))
|
|
thisPC->Children.push_back(new FileTreeNode(userPath + L"3D Objects"));
|
|
thisPC->Children.push_back(new FileTreeNode(userPath + L"Desktop"));
|
|
thisPC->Children.push_back(new FileTreeNode(userPath + L"Documents"));
|
|
thisPC->Children.push_back(new FileTreeNode(userPath + L"Downloads"));
|
|
thisPC->Children.push_back(new FileTreeNode(userPath + L"Music"));
|
|
thisPC->Children.push_back(new FileTreeNode(userPath + L"Pictures"));
|
|
thisPC->Children.push_back(new FileTreeNode(userPath + L"Videos"));
|
|
DWORD d = GetLogicalDrives();
|
|
for (int i = 0; i < 26; i++)
|
|
if (d & (1 << i))
|
|
thisPC->Children.push_back(new FileTreeNode(std::string(1, 'A' + i) + ":"));
|
|
m_treeCache.push_back(thisPC);
|
|
#else
|
|
std::error_code ec;
|
|
|
|
// Quick Access
|
|
struct passwd* pw;
|
|
uid_t uid;
|
|
uid = geteuid();
|
|
pw = getpwuid(uid);
|
|
if (pw) {
|
|
std::string homePath = "/home/" + std::string(pw->pw_name);
|
|
|
|
if (std::filesystem::exists(homePath, ec))
|
|
quickAccess->Children.push_back(new FileTreeNode(homePath));
|
|
if (std::filesystem::exists(homePath + "/Desktop", ec))
|
|
quickAccess->Children.push_back(new FileTreeNode(homePath + "/Desktop"));
|
|
if (std::filesystem::exists(homePath + "/Documents", ec))
|
|
quickAccess->Children.push_back(new FileTreeNode(homePath + "/Documents"));
|
|
if (std::filesystem::exists(homePath + "/Downloads", ec))
|
|
quickAccess->Children.push_back(new FileTreeNode(homePath + "/Downloads"));
|
|
if (std::filesystem::exists(homePath + "/Pictures", ec))
|
|
quickAccess->Children.push_back(new FileTreeNode(homePath + "/Pictures"));
|
|
}
|
|
|
|
// This PC
|
|
FileTreeNode* thisPC = new FileTreeNode("This PC");
|
|
thisPC->Read = true;
|
|
for (const auto& entry : std::filesystem::directory_iterator("/", ec)) {
|
|
if (std::filesystem::is_directory(entry, ec))
|
|
thisPC->Children.push_back(new FileTreeNode(u8StringToString(entry.path().u8string())));
|
|
}
|
|
m_treeCache.push_back(thisPC);
|
|
#endif
|
|
}
|
|
FileDialog::~FileDialog() {
|
|
m_clearIconPreview();
|
|
m_clearIcons();
|
|
|
|
for (auto fn : m_treeCache)
|
|
m_clearTree(fn);
|
|
m_treeCache.clear();
|
|
}
|
|
bool FileDialog::Save(const std::string& key, const std::string& title, const std::string& filter, const std::string& startingDir)
|
|
{
|
|
if (!m_currentKey.empty())
|
|
return false;
|
|
|
|
m_currentKey = key;
|
|
m_currentTitle = title + "###" + key;
|
|
m_isOpen = true;
|
|
m_calledOpenPopup = false;
|
|
m_result.clear();
|
|
m_inputTextbox[0] = 0;
|
|
m_selections.clear();
|
|
m_selectedFileItem = -1;
|
|
m_isMultiselect = false;
|
|
m_type = IFD_DIALOG_SAVE;
|
|
|
|
m_parseFilter(filter);
|
|
if (!startingDir.empty())
|
|
m_setDirectory(std::filesystem::u8path(startingDir), false);
|
|
else
|
|
m_setDirectory(m_currentDirectory, false); // refresh contents
|
|
|
|
return true;
|
|
}
|
|
bool FileDialog::Open(const std::string& key, const std::string& title, const std::string& filter, bool isMultiselect, const std::string& startingDir)
|
|
{
|
|
if (!m_currentKey.empty())
|
|
return false;
|
|
|
|
m_currentKey = key;
|
|
m_currentTitle = title + "###" + key;
|
|
m_isOpen = true;
|
|
m_calledOpenPopup = false;
|
|
m_result.clear();
|
|
m_inputTextbox[0] = 0;
|
|
m_selections.clear();
|
|
m_selectedFileItem = -1;
|
|
m_isMultiselect = isMultiselect;
|
|
m_type = filter.empty() ? IFD_DIALOG_DIRECTORY : IFD_DIALOG_FILE;
|
|
|
|
m_parseFilter(filter);
|
|
if (!startingDir.empty())
|
|
m_setDirectory(std::filesystem::u8path(startingDir), false);
|
|
else
|
|
m_setDirectory(m_currentDirectory, false); // refresh contents
|
|
|
|
return true;
|
|
}
|
|
bool FileDialog::IsDone(const std::string& key)
|
|
{
|
|
bool isMe = m_currentKey == key;
|
|
|
|
if (isMe && m_isOpen) {
|
|
if (!m_calledOpenPopup) {
|
|
ImGui::SetNextWindowSize(ImVec2(600, 400), ImGuiCond_FirstUseEver);
|
|
ImGui::OpenPopup(m_currentTitle.c_str());
|
|
m_calledOpenPopup = true;
|
|
}
|
|
|
|
if (ImGui::BeginPopupModal(m_currentTitle.c_str(), &m_isOpen, ImGuiWindowFlags_NoScrollbar)) {
|
|
m_renderFileDialog();
|
|
ImGui::EndPopup();
|
|
}
|
|
else m_isOpen = false;
|
|
}
|
|
|
|
return isMe && !m_isOpen;
|
|
}
|
|
void FileDialog::Close()
|
|
{
|
|
m_currentKey.clear();
|
|
m_backHistory = std::stack<std::filesystem::path>();
|
|
m_forwardHistory = std::stack<std::filesystem::path>();
|
|
|
|
// clear the tree
|
|
for (auto fn : m_treeCache) {
|
|
for (auto item : fn->Children) {
|
|
for (auto ch : item->Children)
|
|
m_clearTree(ch);
|
|
item->Children.clear();
|
|
item->Read = false;
|
|
}
|
|
}
|
|
|
|
// free icon textures
|
|
m_clearIconPreview();
|
|
m_clearIcons();
|
|
}
|
|
|
|
void FileDialog::RemoveFavorite(const std::string& path)
|
|
{
|
|
auto itr = std::find(m_favorites.begin(), m_favorites.end(), u8StringToString(m_currentDirectory.u8string()));
|
|
|
|
if (itr != m_favorites.end())
|
|
m_favorites.erase(itr);
|
|
|
|
// remove from sidebar
|
|
for (auto& p : m_treeCache)
|
|
if (p->Path == "Quick Access") {
|
|
for (size_t i = 0; i < p->Children.size(); i++)
|
|
if (p->Children[i]->Path == path) {
|
|
p->Children.erase(p->Children.begin() + i);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
void FileDialog::AddFavorite(const std::string& path)
|
|
{
|
|
if (std::count(m_favorites.begin(), m_favorites.end(), path) > 0)
|
|
return;
|
|
|
|
if (!std::filesystem::exists(std::filesystem::u8path(path)))
|
|
return;
|
|
|
|
m_favorites.push_back(path);
|
|
|
|
// add to sidebar
|
|
for (auto& p : m_treeCache)
|
|
if (p->Path == "Quick Access") {
|
|
p->Children.push_back(new FileTreeNode(path));
|
|
break;
|
|
}
|
|
}
|
|
|
|
void FileDialog::m_select(const std::filesystem::path& path, bool isCtrlDown)
|
|
{
|
|
bool multiselect = isCtrlDown && m_isMultiselect;
|
|
|
|
if (!multiselect) {
|
|
m_selections.clear();
|
|
m_selections.push_back(path);
|
|
}
|
|
else {
|
|
auto it = std::find(m_selections.begin(), m_selections.end(), path);
|
|
if (it != m_selections.end())
|
|
m_selections.erase(it);
|
|
else
|
|
m_selections.push_back(path);
|
|
}
|
|
|
|
if (m_selections.size() == 1) {
|
|
std::string filename = u8StringToString(m_selections[0].filename().u8string());
|
|
if (filename.size() == 0)
|
|
filename = u8StringToString(m_selections[0].u8string()); // drive
|
|
|
|
strcpy(m_inputTextbox, filename.c_str());
|
|
}
|
|
else {
|
|
std::string textboxVal = "";
|
|
for (const auto& sel : m_selections) {
|
|
std::string filename = u8StringToString(sel.filename().u8string());
|
|
if (filename.size() == 0)
|
|
filename = u8StringToString(sel.u8string());
|
|
|
|
textboxVal += "\"" + filename + "\", ";
|
|
}
|
|
strcpy(m_inputTextbox, textboxVal.substr(0, textboxVal.size() - 2).c_str());
|
|
}
|
|
}
|
|
|
|
bool FileDialog::m_finalize(const std::string& filename)
|
|
{
|
|
bool hasResult = (!filename.empty() && m_type != IFD_DIALOG_DIRECTORY) || m_type == IFD_DIALOG_DIRECTORY;
|
|
|
|
if (hasResult) {
|
|
if (!m_isMultiselect || m_selections.size() <= 1) {
|
|
std::filesystem::path path = std::filesystem::u8path(filename);
|
|
if (path.is_absolute()) m_result.push_back(path);
|
|
else m_result.push_back(m_currentDirectory / path);
|
|
if (m_type == IFD_DIALOG_DIRECTORY || m_type == IFD_DIALOG_FILE) {
|
|
if (!std::filesystem::exists(m_result.back())) {
|
|
m_result.clear();
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for (const auto& sel : m_selections) {
|
|
if (sel.is_absolute()) m_result.push_back(sel);
|
|
else m_result.push_back(m_currentDirectory / sel);
|
|
if (m_type == IFD_DIALOG_DIRECTORY || m_type == IFD_DIALOG_FILE) {
|
|
if (!std::filesystem::exists(m_result.back())) {
|
|
m_result.clear();
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_type == IFD_DIALOG_SAVE) {
|
|
// add the extension
|
|
if (m_filterSelection < m_filterExtensions.size() && m_filterExtensions[m_filterSelection].size() > 0) {
|
|
if (!m_result.back().has_extension()) {
|
|
std::string extAdd = m_filterExtensions[m_filterSelection][0];
|
|
m_result.back().replace_extension(extAdd);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_isOpen = false;
|
|
|
|
return true;
|
|
}
|
|
void FileDialog::m_parseFilter(const std::string& filter)
|
|
{
|
|
m_filter = "";
|
|
m_filterExtensions.clear();
|
|
m_filterSelection = 0;
|
|
|
|
if (filter.empty())
|
|
return;
|
|
|
|
std::vector<std::string> exts;
|
|
|
|
size_t lastSplit = 0, lastExt = 0;
|
|
bool inExtList = false;
|
|
for (size_t i = 0; i < filter.size(); i++) {
|
|
if (filter[i] == ',') {
|
|
if (!inExtList)
|
|
lastSplit = i + 1;
|
|
else {
|
|
exts.push_back(filter.substr(lastExt, i - lastExt));
|
|
lastExt = i + 1;
|
|
}
|
|
}
|
|
else if (filter[i] == '{') {
|
|
std::string filterName = filter.substr(lastSplit, i - lastSplit);
|
|
if (filterName == ".*") {
|
|
m_filter += std::string(std::string("All Files (*.*)\0").c_str(), 16);
|
|
m_filterExtensions.push_back(std::vector<std::string>());
|
|
}
|
|
else
|
|
m_filter += std::string((filterName + "\0").c_str(), filterName.size() + 1);
|
|
inExtList = true;
|
|
lastExt = i + 1;
|
|
}
|
|
else if (filter[i] == '}') {
|
|
exts.push_back(filter.substr(lastExt, i - lastExt));
|
|
m_filterExtensions.push_back(exts);
|
|
exts.clear();
|
|
|
|
inExtList = false;
|
|
}
|
|
}
|
|
if (lastSplit != 0) {
|
|
std::string filterName = filter.substr(lastSplit);
|
|
if (filterName == ".*") {
|
|
m_filter += std::string(std::string("All Files (*.*)\0").c_str(), 16);
|
|
m_filterExtensions.push_back(std::vector<std::string>());
|
|
}
|
|
else
|
|
m_filter += std::string((filterName + "\0").c_str(), filterName.size() + 1);
|
|
}
|
|
}
|
|
|
|
void* FileDialog::m_getIcon(const std::filesystem::path& path)
|
|
{
|
|
#ifdef _WIN32
|
|
if (m_icons.count(u8StringToString(path.u8string())) > 0)
|
|
return m_icons[u8StringToString(path.u8string())];
|
|
|
|
std::string pathU8 = u8StringToString(path.u8string());
|
|
|
|
std::error_code ec;
|
|
m_icons[pathU8] = nullptr;
|
|
|
|
DWORD attrs = 0;
|
|
UINT flags = SHGFI_ICON | SHGFI_LARGEICON;
|
|
if (!std::filesystem::exists(path, ec)) {
|
|
flags |= SHGFI_USEFILEATTRIBUTES;
|
|
attrs = FILE_ATTRIBUTE_DIRECTORY;
|
|
}
|
|
|
|
SHFILEINFOW fileInfo = { 0 };
|
|
std::wstring pathW = path.wstring();
|
|
for (int i = 0; i < pathW.size(); i++)
|
|
if (pathW[i] == '/')
|
|
pathW[i] = '\\';
|
|
SHGetFileInfoW(pathW.c_str(), attrs, &fileInfo, sizeof(SHFILEINFOW), flags);
|
|
|
|
if (fileInfo.hIcon == nullptr)
|
|
return nullptr;
|
|
|
|
// check if icon is already loaded
|
|
auto itr = std::find(m_iconIndices.begin(), m_iconIndices.end(), fileInfo.iIcon);
|
|
if (itr != m_iconIndices.end()) {
|
|
const std::string& existingIconFilepath = m_iconFilepaths[itr - m_iconIndices.begin()];
|
|
m_icons[pathU8] = m_icons[existingIconFilepath];
|
|
return m_icons[pathU8];
|
|
}
|
|
|
|
m_iconIndices.push_back(fileInfo.iIcon);
|
|
m_iconFilepaths.push_back(pathU8);
|
|
|
|
ICONINFO iconInfo = { 0 };
|
|
GetIconInfo(fileInfo.hIcon, &iconInfo);
|
|
|
|
if (iconInfo.hbmColor == nullptr)
|
|
return nullptr;
|
|
|
|
DIBSECTION ds;
|
|
GetObject(iconInfo.hbmColor, sizeof(ds), &ds);
|
|
int byteSize = ds.dsBm.bmWidth * ds.dsBm.bmHeight * (ds.dsBm.bmBitsPixel / 8);
|
|
|
|
if (byteSize == 0)
|
|
return nullptr;
|
|
|
|
uint8_t* data = (uint8_t*)malloc(byteSize);
|
|
GetBitmapBits(iconInfo.hbmColor, byteSize, data);
|
|
|
|
m_icons[pathU8] = this->CreateTexture(data, ds.dsBm.bmWidth, ds.dsBm.bmHeight, 0);
|
|
|
|
free(data);
|
|
|
|
return m_icons[pathU8];
|
|
#else
|
|
if (m_icons.count(u8StringToString(path.u8string())) > 0)
|
|
return m_icons[u8StringToString(path.u8string())];
|
|
|
|
std::string pathU8 = u8StringToString(path.u8string());
|
|
|
|
m_icons[pathU8] = nullptr;
|
|
|
|
std::error_code ec;
|
|
int iconID = 1;
|
|
if (std::filesystem::is_directory(path, ec))
|
|
iconID = 0;
|
|
|
|
// check if icon is already loaded
|
|
auto itr = std::find(m_iconIndices.begin(), m_iconIndices.end(), iconID);
|
|
if (itr != m_iconIndices.end()) {
|
|
const std::string& existingIconFilepath = m_iconFilepaths[itr - m_iconIndices.begin()];
|
|
m_icons[pathU8] = m_icons[existingIconFilepath];
|
|
return m_icons[pathU8];
|
|
}
|
|
|
|
m_iconIndices.push_back(iconID);
|
|
m_iconFilepaths.push_back(pathU8);
|
|
|
|
ImVec4 wndBg = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg);
|
|
|
|
// light theme - load default icons
|
|
if ((wndBg.x + wndBg.y + wndBg.z) / 3.0f > 0.5f) {
|
|
uint8_t* data = (uint8_t*)ifd::GetDefaultFileIcon();
|
|
if (iconID == 0)
|
|
data = (uint8_t*)ifd::GetDefaultFolderIcon();
|
|
m_icons[pathU8] = this->CreateTexture(data, DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE, 0);
|
|
}
|
|
// dark theme - invert the colors
|
|
else {
|
|
uint8_t* data = (uint8_t*)ifd::GetDefaultFileIcon();
|
|
if (iconID == 0)
|
|
data = (uint8_t*)ifd::GetDefaultFolderIcon();
|
|
|
|
uint8_t* invData = (uint8_t*)malloc(DEFAULT_ICON_SIZE * DEFAULT_ICON_SIZE * 4);
|
|
for (int y = 0; y < 32; y++) {
|
|
for (int x = 0; x < 32; x++) {
|
|
int index = (y * DEFAULT_ICON_SIZE + x) * 4;
|
|
invData[index + 0] = 255 - data[index + 0];
|
|
invData[index + 1] = 255 - data[index + 1];
|
|
invData[index + 2] = 255 - data[index + 2];
|
|
invData[index + 3] = data[index + 3];
|
|
}
|
|
}
|
|
m_icons[pathU8] = this->CreateTexture(invData, DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE, 0);
|
|
|
|
free(invData);
|
|
}
|
|
|
|
return m_icons[pathU8];
|
|
#endif
|
|
}
|
|
void FileDialog::m_clearIcons()
|
|
{
|
|
std::vector<unsigned int> deletedIcons;
|
|
|
|
// delete textures
|
|
for (auto& icon : m_icons) {
|
|
unsigned int ptr = (unsigned int)((uintptr_t)icon.second);
|
|
if (std::count(deletedIcons.begin(), deletedIcons.end(), ptr)) // skip duplicates
|
|
continue;
|
|
|
|
deletedIcons.push_back(ptr);
|
|
DeleteTexture(icon.second);
|
|
}
|
|
m_iconFilepaths.clear();
|
|
m_iconIndices.clear();
|
|
m_icons.clear();
|
|
}
|
|
void FileDialog::m_refreshIconPreview()
|
|
{
|
|
if (m_zoom >= 5.0f) {
|
|
if (m_previewLoader == nullptr) {
|
|
m_previewLoaderRunning = true;
|
|
m_previewLoader = new std::thread(&FileDialog::m_loadPreview, this);
|
|
}
|
|
}
|
|
else
|
|
m_clearIconPreview();
|
|
}
|
|
void FileDialog::m_clearIconPreview()
|
|
{
|
|
m_stopPreviewLoader();
|
|
|
|
for (auto& data : m_content) {
|
|
if (!data.HasIconPreview)
|
|
continue;
|
|
|
|
data.HasIconPreview = false;
|
|
this->DeleteTexture(data.IconPreview);
|
|
|
|
if (data.IconPreviewData != nullptr) {
|
|
stbi_image_free(data.IconPreviewData);
|
|
data.IconPreviewData = nullptr;
|
|
}
|
|
}
|
|
}
|
|
void FileDialog::m_stopPreviewLoader()
|
|
{
|
|
if (m_previewLoader != nullptr) {
|
|
m_previewLoaderRunning = false;
|
|
|
|
if (m_previewLoader && m_previewLoader->joinable())
|
|
m_previewLoader->join();
|
|
|
|
delete m_previewLoader;
|
|
m_previewLoader = nullptr;
|
|
}
|
|
}
|
|
void FileDialog::m_loadPreview()
|
|
{
|
|
for (size_t i = 0; m_previewLoaderRunning && i < m_content.size(); i++) {
|
|
auto& data = m_content[i];
|
|
|
|
if (data.HasIconPreview)
|
|
continue;
|
|
|
|
if (data.Path.has_extension()) {
|
|
std::string ext = u8StringToString(data.Path.extension().u8string());
|
|
if (ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".bmp" || ext == ".tga") {
|
|
int width, height, nrChannels;
|
|
unsigned char* image = stbi_load(u8StringToString(data.Path.u8string()).c_str(), &width, &height, &nrChannels, STBI_rgb_alpha);
|
|
|
|
if (image == nullptr || width == 0 || height == 0)
|
|
continue;
|
|
|
|
data.HasIconPreview = true;
|
|
data.IconPreviewData = image;
|
|
data.IconPreviewWidth = width;
|
|
data.IconPreviewHeight = height;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_previewLoaderRunning = false;
|
|
}
|
|
void FileDialog::m_clearTree(FileTreeNode* node)
|
|
{
|
|
if (node == nullptr)
|
|
return;
|
|
|
|
for (auto n : node->Children)
|
|
m_clearTree(n);
|
|
|
|
delete node;
|
|
node = nullptr;
|
|
}
|
|
void FileDialog::m_setDirectory(const std::filesystem::path& p, bool addHistory)
|
|
{
|
|
bool isSameDir = m_currentDirectory == p;
|
|
|
|
if (addHistory && !isSameDir)
|
|
m_backHistory.push(m_currentDirectory);
|
|
|
|
m_currentDirectory = p;
|
|
#ifdef _WIN32
|
|
// drives don't work well without the backslash symbol
|
|
if (p.u8string().size() == 2 && p.u8string()[1] == ':')
|
|
m_currentDirectory = std::filesystem::u8path(p.u8string() + u8"\\");
|
|
#endif
|
|
|
|
m_clearIconPreview();
|
|
m_content.clear(); // p == "" after this line, due to reference
|
|
m_selectedFileItem = -1;
|
|
|
|
if (m_type == IFD_DIALOG_DIRECTORY || m_type == IFD_DIALOG_FILE)
|
|
m_inputTextbox[0] = 0;
|
|
m_selections.clear();
|
|
|
|
if (!isSameDir) {
|
|
m_searchBuffer[0] = 0;
|
|
m_clearIcons();
|
|
}
|
|
|
|
if (p.u8string() == u8"Quick Access") {
|
|
for (auto& node : m_treeCache) {
|
|
if (node->Path == p)
|
|
for (auto& c : node->Children)
|
|
m_content.push_back(FileData(c->Path));
|
|
}
|
|
}
|
|
else if (p.u8string() == u8"This PC") {
|
|
for (auto& node : m_treeCache) {
|
|
if (node->Path == p)
|
|
for (auto& c : node->Children)
|
|
m_content.push_back(FileData(c->Path));
|
|
}
|
|
}
|
|
else {
|
|
std::error_code ec;
|
|
if (std::filesystem::exists(m_currentDirectory, ec))
|
|
for (const auto& entry : std::filesystem::directory_iterator(m_currentDirectory, ec)) {
|
|
FileData info(entry.path());
|
|
|
|
// skip files when IFD_DIALOG_DIRECTORY
|
|
if (!info.IsDirectory && m_type == IFD_DIALOG_DIRECTORY)
|
|
continue;
|
|
|
|
// check if filename matches search query
|
|
if (m_searchBuffer[0]) {
|
|
std::string filename = u8StringToString(info.Path.u8string());
|
|
|
|
std::string filenameSearch = filename;
|
|
std::string query(m_searchBuffer);
|
|
std::transform(filenameSearch.begin(), filenameSearch.end(), filenameSearch.begin(), ::tolower);
|
|
std::transform(query.begin(), query.end(), query.begin(), ::tolower);
|
|
|
|
if (filenameSearch.find(query, 0) == std::string::npos)
|
|
continue;
|
|
}
|
|
|
|
// check if extension matches
|
|
if (!info.IsDirectory && m_type != IFD_DIALOG_DIRECTORY) {
|
|
if (m_filterSelection < m_filterExtensions.size()) {
|
|
const auto& exts = m_filterExtensions[m_filterSelection];
|
|
if (exts.size() > 0) {
|
|
std::string extension = u8StringToString(info.Path.extension().u8string());
|
|
|
|
// extension not found? skip
|
|
if (std::count(exts.begin(), exts.end(), extension) == 0)
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_content.push_back(info);
|
|
}
|
|
}
|
|
|
|
m_sortContent(m_sortColumn, m_sortDirection);
|
|
m_refreshIconPreview();
|
|
}
|
|
void FileDialog::m_sortContent(unsigned int column, unsigned int sortDirection)
|
|
{
|
|
// 0 -> name, 1 -> date, 2 -> size
|
|
m_sortColumn = column;
|
|
m_sortDirection = sortDirection;
|
|
|
|
// split into directories and files
|
|
std::partition(m_content.begin(), m_content.end(), [](const FileData& data) {
|
|
return data.IsDirectory;
|
|
});
|
|
|
|
if (m_content.size() > 0) {
|
|
// find where the file list starts
|
|
size_t fileIndex = 0;
|
|
for (; fileIndex < m_content.size(); fileIndex++)
|
|
if (!m_content[fileIndex].IsDirectory)
|
|
break;
|
|
|
|
// compare function
|
|
auto compareFn = [column, sortDirection](const FileData& left, const FileData& right) -> bool {
|
|
// name
|
|
if (column == 0) {
|
|
std::string lName = u8StringToString(left.Path.u8string());
|
|
std::string rName = u8StringToString(right.Path.u8string());
|
|
|
|
std::transform(lName.begin(), lName.end(), lName.begin(), ::tolower);
|
|
std::transform(rName.begin(), rName.end(), rName.begin(), ::tolower);
|
|
|
|
int comp = lName.compare(rName);
|
|
|
|
if (sortDirection == ImGuiSortDirection_Ascending)
|
|
return comp < 0;
|
|
return comp > 0;
|
|
}
|
|
// date
|
|
else if (column == 1) {
|
|
if (sortDirection == ImGuiSortDirection_Ascending)
|
|
return left.DateModified < right.DateModified;
|
|
else
|
|
return left.DateModified > right.DateModified;
|
|
}
|
|
// size
|
|
else if (column == 2) {
|
|
if (sortDirection == ImGuiSortDirection_Ascending)
|
|
return left.Size < right.Size;
|
|
else
|
|
return left.Size > right.Size;
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
// sort the directories
|
|
std::sort(m_content.begin(), m_content.begin() + fileIndex, compareFn);
|
|
|
|
// sort the files
|
|
std::sort(m_content.begin() + fileIndex, m_content.end(), compareFn);
|
|
}
|
|
}
|
|
|
|
void FileDialog::m_renderTree(FileTreeNode* node)
|
|
{
|
|
// directory
|
|
std::error_code ec;
|
|
ImGui::PushID(node);
|
|
bool isClicked = false;
|
|
std::string displayName = u8StringToString(node->Path.stem().u8string());
|
|
if (displayName.size() == 0)
|
|
displayName = u8StringToString(node->Path.u8string());
|
|
if (FolderNode(displayName.c_str(), (ImTextureID)m_getIcon(node->Path), isClicked)) {
|
|
if (!node->Read) {
|
|
// cache children if it's not already cached
|
|
if (std::filesystem::exists(node->Path, ec))
|
|
for (const auto& entry : std::filesystem::directory_iterator(node->Path, ec)) {
|
|
if (std::filesystem::is_directory(entry, ec))
|
|
node->Children.push_back(new FileTreeNode(u8StringToString(entry.path().u8string())));
|
|
}
|
|
node->Read = true;
|
|
}
|
|
|
|
// display children
|
|
for (auto c : node->Children)
|
|
m_renderTree(c);
|
|
|
|
ImGui::TreePop();
|
|
}
|
|
if (isClicked)
|
|
m_setDirectory(node->Path);
|
|
ImGui::PopID();
|
|
}
|
|
void FileDialog::m_renderContent()
|
|
{
|
|
if (ImGui::IsMouseClicked(ImGuiMouseButton_Right))
|
|
m_selectedFileItem = -1;
|
|
|
|
// table view
|
|
if (m_zoom == 1.0f) {
|
|
if (ImGui::BeginTable("##contentTable", 3, /*ImGuiTableFlags_Resizable |*/ ImGuiTableFlags_Sortable, ImVec2(0, -FLT_MIN))) {
|
|
// header
|
|
ImGui::TableSetupColumn("Name##filename", ImGuiTableColumnFlags_WidthStretch, 0.0f - 1.0f, 0);
|
|
ImGui::TableSetupColumn("Date modified##filedate", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize, 0.0f, 1);
|
|
ImGui::TableSetupColumn("Size##filesize", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize, 0.0f, 2);
|
|
ImGui::TableSetupScrollFreeze(0, 1);
|
|
ImGui::TableHeadersRow();
|
|
|
|
// sort
|
|
if (ImGuiTableSortSpecs* sortSpecs = ImGui::TableGetSortSpecs()) {
|
|
if (sortSpecs->SpecsDirty) {
|
|
sortSpecs->SpecsDirty = false;
|
|
m_sortContent(sortSpecs->Specs->ColumnUserID, sortSpecs->Specs->SortDirection);
|
|
}
|
|
}
|
|
|
|
// content
|
|
int fileId = 0;
|
|
for (auto& entry : m_content) {
|
|
std::string filename = u8StringToString(entry.Path.filename().u8string());
|
|
if (filename.size() == 0)
|
|
filename = u8StringToString(entry.Path.u8string()); // drive
|
|
|
|
bool isSelected = std::count(m_selections.begin(), m_selections.end(), entry.Path);
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
// file name
|
|
ImGui::TableSetColumnIndex(0);
|
|
ImGui::Image((ImTextureID)m_getIcon(entry.Path), ImVec2(ICON_SIZE, ICON_SIZE));
|
|
ImGui::SameLine();
|
|
if (ImGui::Selectable(filename.c_str(), isSelected, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowDoubleClick)) {
|
|
std::error_code ec;
|
|
bool isDir = std::filesystem::is_directory(entry.Path, ec);
|
|
|
|
if (ImGui::IsMouseDoubleClicked(0)) {
|
|
if (isDir) {
|
|
m_setDirectory(entry.Path);
|
|
break;
|
|
}
|
|
else
|
|
m_finalize(filename);
|
|
}
|
|
else {
|
|
if ((isDir && m_type == IFD_DIALOG_DIRECTORY) || !isDir)
|
|
m_select(entry.Path, ImGui::GetIO().KeyCtrl);
|
|
}
|
|
}
|
|
if (ImGui::IsItemClicked(ImGuiMouseButton_Right))
|
|
m_selectedFileItem = fileId;
|
|
fileId++;
|
|
|
|
// date
|
|
ImGui::TableSetColumnIndex(1);
|
|
auto tm = std::localtime(&entry.DateModified);
|
|
if (tm != nullptr)
|
|
ImGui::Text("%d/%d/%d %02d:%02d", tm->tm_mon + 1, tm->tm_mday, 1900 + tm->tm_year, tm->tm_hour, tm->tm_min);
|
|
else ImGui::Text("---");
|
|
|
|
// size
|
|
ImGui::TableSetColumnIndex(2);
|
|
ImGui::Text("%.3f KiB", entry.Size / 1024.0f);
|
|
}
|
|
|
|
ImGui::EndTable();
|
|
}
|
|
}
|
|
// "icon" view
|
|
else {
|
|
// content
|
|
int fileId = 0;
|
|
for (auto& entry : m_content) {
|
|
if (entry.HasIconPreview && entry.IconPreviewData != nullptr) {
|
|
entry.IconPreview = this->CreateTexture(entry.IconPreviewData, entry.IconPreviewWidth, entry.IconPreviewHeight, 1);
|
|
stbi_image_free(entry.IconPreviewData);
|
|
entry.IconPreviewData = nullptr;
|
|
}
|
|
|
|
std::string filename = u8StringToString(entry.Path.filename().u8string());
|
|
if (filename.size() == 0)
|
|
filename = u8StringToString(entry.Path.u8string()); // drive
|
|
|
|
bool isSelected = std::count(m_selections.begin(), m_selections.end(), entry.Path);
|
|
|
|
if (FileIcon(filename.c_str(), isSelected, entry.HasIconPreview ? entry.IconPreview : (ImTextureID)m_getIcon(entry.Path), ImVec2(32 + 16 * m_zoom, 32 + 16 * m_zoom), entry.HasIconPreview, entry.IconPreviewWidth, entry.IconPreviewHeight)) {
|
|
std::error_code ec;
|
|
bool isDir = std::filesystem::is_directory(entry.Path, ec);
|
|
|
|
if (ImGui::IsMouseDoubleClicked(0)) {
|
|
if (isDir) {
|
|
m_setDirectory(entry.Path);
|
|
break;
|
|
}
|
|
else
|
|
m_finalize(filename);
|
|
}
|
|
else {
|
|
if ((isDir && m_type == IFD_DIALOG_DIRECTORY) || !isDir)
|
|
m_select(entry.Path, ImGui::GetIO().KeyCtrl);
|
|
}
|
|
}
|
|
if (ImGui::IsItemClicked(ImGuiMouseButton_Right))
|
|
m_selectedFileItem = fileId;
|
|
fileId++;
|
|
}
|
|
}
|
|
}
|
|
void FileDialog::m_renderPopups()
|
|
{
|
|
bool openAreYouSureDlg = false, openNewFileDlg = false, openNewDirectoryDlg = false;
|
|
if (ImGui::BeginPopupContextItem("##dir_context")) {
|
|
if (ImGui::Selectable("New file"))
|
|
openNewFileDlg = true;
|
|
if (ImGui::Selectable("New directory"))
|
|
openNewDirectoryDlg = true;
|
|
if (m_selectedFileItem != -1 && ImGui::Selectable("Delete"))
|
|
openAreYouSureDlg = true;
|
|
ImGui::EndPopup();
|
|
}
|
|
if (openAreYouSureDlg)
|
|
ImGui::OpenPopup("Are you sure?##delete");
|
|
if (openNewFileDlg)
|
|
ImGui::OpenPopup("Enter file name##newfile");
|
|
if (openNewDirectoryDlg)
|
|
ImGui::OpenPopup("Enter directory name##newdir");
|
|
if (ImGui::BeginPopupModal("Are you sure?##delete")) {
|
|
if (m_selectedFileItem >= static_cast<int>(m_content.size()) || m_content.size() == 0)
|
|
ImGui::CloseCurrentPopup();
|
|
else {
|
|
const FileData& data = m_content[m_selectedFileItem];
|
|
ImGui::TextWrapped("Are you sure you want to delete %s?", u8StringToString(data.Path.filename().u8string()).c_str());
|
|
if (ImGui::Button("Yes")) {
|
|
std::error_code ec;
|
|
std::filesystem::remove_all(data.Path, ec);
|
|
m_setDirectory(m_currentDirectory, false); // refresh
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::SameLine();
|
|
if (ImGui::Button("No"))
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::EndPopup();
|
|
}
|
|
if (ImGui::BeginPopupModal("Enter file name##newfile")) {
|
|
ImGui::PushItemWidth(250.0f);
|
|
ImGui::InputText("##newfilename", m_newEntryBuffer, 1024); // TODO: remove hardcoded literals
|
|
ImGui::PopItemWidth();
|
|
|
|
if (ImGui::Button("OK")) {
|
|
std::ofstream out((m_currentDirectory / std::string(m_newEntryBuffer)).string());
|
|
out << "";
|
|
out.close();
|
|
|
|
m_setDirectory(m_currentDirectory, false); // refresh
|
|
m_newEntryBuffer[0] = 0;
|
|
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::SameLine();
|
|
if (ImGui::Button("Cancel")) {
|
|
m_newEntryBuffer[0] = 0;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::EndPopup();
|
|
}
|
|
if (ImGui::BeginPopupModal("Enter directory name##newdir")) {
|
|
ImGui::PushItemWidth(250.0f);
|
|
ImGui::InputText("##newfilename", m_newEntryBuffer, 1024); // TODO: remove hardcoded literals
|
|
ImGui::PopItemWidth();
|
|
|
|
if (ImGui::Button("OK")) {
|
|
std::error_code ec;
|
|
std::filesystem::create_directory(m_currentDirectory / std::string(m_newEntryBuffer), ec);
|
|
m_setDirectory(m_currentDirectory, false); // refresh
|
|
m_newEntryBuffer[0] = 0;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::SameLine();
|
|
if (ImGui::Button("Cancel")) {
|
|
ImGui::CloseCurrentPopup();
|
|
m_newEntryBuffer[0] = 0;
|
|
}
|
|
ImGui::EndPopup();
|
|
}
|
|
}
|
|
void FileDialog::m_renderFileDialog()
|
|
{
|
|
/***** TOP BAR *****/
|
|
bool noBackHistory = m_backHistory.empty(), noForwardHistory = m_forwardHistory.empty();
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Button, 0);
|
|
if (noBackHistory) ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
|
|
if (ImGui::ArrowButtonEx("##back", ImGuiDir_Left, ImVec2(GUI_ELEMENT_SIZE, GUI_ELEMENT_SIZE), m_backHistory.empty() * ImGuiItemFlags_Disabled)) {
|
|
std::filesystem::path newPath = m_backHistory.top();
|
|
m_backHistory.pop();
|
|
m_forwardHistory.push(m_currentDirectory);
|
|
|
|
m_setDirectory(newPath, false);
|
|
}
|
|
if (noBackHistory) ImGui::PopStyleVar();
|
|
ImGui::SameLine();
|
|
|
|
if (noForwardHistory) ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
|
|
if (ImGui::ArrowButtonEx("##forward", ImGuiDir_Right, ImVec2(GUI_ELEMENT_SIZE, GUI_ELEMENT_SIZE), m_forwardHistory.empty() * ImGuiItemFlags_Disabled)) {
|
|
std::filesystem::path newPath = m_forwardHistory.top();
|
|
m_forwardHistory.pop();
|
|
m_backHistory.push(m_currentDirectory);
|
|
|
|
m_setDirectory(newPath, false);
|
|
}
|
|
if (noForwardHistory) ImGui::PopStyleVar();
|
|
ImGui::SameLine();
|
|
|
|
if (ImGui::ArrowButtonEx("##up", ImGuiDir_Up, ImVec2(GUI_ELEMENT_SIZE, GUI_ELEMENT_SIZE))) {
|
|
if (m_currentDirectory.has_parent_path())
|
|
m_setDirectory(m_currentDirectory.parent_path());
|
|
}
|
|
|
|
std::filesystem::path curDirCopy = m_currentDirectory;
|
|
if (PathBox("##pathbox", curDirCopy, m_pathBuffer, ImVec2(-250, GUI_ELEMENT_SIZE)))
|
|
m_setDirectory(curDirCopy);
|
|
ImGui::SameLine();
|
|
|
|
if (FavoriteButton("##dirfav", std::count(m_favorites.begin(), m_favorites.end(), u8StringToString(m_currentDirectory.u8string())))) {
|
|
if (std::count(m_favorites.begin(), m_favorites.end(), u8StringToString(m_currentDirectory.u8string())))
|
|
RemoveFavorite(u8StringToString(m_currentDirectory.u8string()));
|
|
else
|
|
AddFavorite(u8StringToString(m_currentDirectory.u8string()));
|
|
}
|
|
ImGui::SameLine();
|
|
ImGui::PopStyleColor();
|
|
|
|
if (ImGui::InputTextEx("##searchTB", "Search", m_searchBuffer, 128, ImVec2(-FLT_MIN, GUI_ELEMENT_SIZE), 0)) // TODO: no hardcoded literals
|
|
m_setDirectory(m_currentDirectory, false); // refresh
|
|
|
|
|
|
|
|
/***** CONTENT *****/
|
|
float bottomBarHeight = (GImGui->FontSize + ImGui::GetStyle().FramePadding.y + ImGui::GetStyle().ItemSpacing.y * 2.0f) * 2;
|
|
if (ImGui::BeginTable("##table", 2, ImGuiTableFlags_Resizable, ImVec2(0, -bottomBarHeight))) {
|
|
ImGui::TableSetupColumn("##tree", ImGuiTableColumnFlags_WidthFixed, 125.0f);
|
|
ImGui::TableSetupColumn("##content", ImGuiTableColumnFlags_WidthStretch);
|
|
ImGui::TableNextRow();
|
|
|
|
// the tree on the left side
|
|
ImGui::TableSetColumnIndex(0);
|
|
ImGui::BeginChild("##treeContainer", ImVec2(0, -bottomBarHeight));
|
|
for (auto node : m_treeCache)
|
|
m_renderTree(node);
|
|
ImGui::EndChild();
|
|
|
|
// content on the right side
|
|
ImGui::TableSetColumnIndex(1);
|
|
ImGui::BeginChild("##contentContainer", ImVec2(0, -bottomBarHeight));
|
|
m_renderContent();
|
|
ImGui::EndChild();
|
|
if (ImGui::IsItemHovered() && ImGui::GetIO().KeyCtrl && ImGui::GetIO().MouseWheel != 0.0f) {
|
|
m_zoom = std::min<float>(25.0f, std::max<float>(1.0f, m_zoom + ImGui::GetIO().MouseWheel));
|
|
m_refreshIconPreview();
|
|
}
|
|
|
|
// New file, New directory and Delete popups
|
|
m_renderPopups();
|
|
|
|
ImGui::EndTable();
|
|
}
|
|
|
|
|
|
|
|
/***** BOTTOM BAR *****/
|
|
ImGui::Text("File name:");
|
|
ImGui::SameLine();
|
|
if (ImGui::InputTextEx("##file_input", "Filename", m_inputTextbox, 1024, ImVec2((m_type != IFD_DIALOG_DIRECTORY) ? -250.0f : -FLT_MIN, 0), ImGuiInputTextFlags_EnterReturnsTrue)) {
|
|
bool success = m_finalize(std::string(m_inputTextbox));
|
|
#ifdef _WIN32
|
|
if (!success)
|
|
MessageBeep(MB_ICONERROR);
|
|
#else
|
|
(void)success;
|
|
#endif
|
|
}
|
|
if (m_type != IFD_DIALOG_DIRECTORY) {
|
|
ImGui::SameLine();
|
|
ImGui::SetNextItemWidth(-FLT_MIN);
|
|
int sel = static_cast<int>(m_filterSelection);
|
|
if (ImGui::Combo("##ext_combo", &sel, m_filter.c_str())) {
|
|
m_filterSelection = static_cast<size_t>(sel);
|
|
m_setDirectory(m_currentDirectory, false); // refresh
|
|
}
|
|
}
|
|
|
|
// buttons
|
|
float ok_cancel_width = GUI_ELEMENT_SIZE * 7;
|
|
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - ok_cancel_width);
|
|
if (ImGui::Button(m_type == IFD_DIALOG_SAVE ? "Save" : "Open", ImVec2(ok_cancel_width / 2 - ImGui::GetStyle().ItemSpacing.x, 0.0f))) {
|
|
std::string filename(m_inputTextbox);
|
|
bool success = false;
|
|
if (!filename.empty() || m_type == IFD_DIALOG_DIRECTORY)
|
|
success = m_finalize(filename);
|
|
#ifdef _WIN32
|
|
if (!success)
|
|
MessageBeep(MB_ICONERROR);
|
|
#else
|
|
(void)success;
|
|
#endif
|
|
}
|
|
ImGui::SameLine();
|
|
if (ImGui::Button("Cancel", ImVec2(-FLT_MIN, 0.0f))) {
|
|
if (m_type == IFD_DIALOG_DIRECTORY)
|
|
m_isOpen = false;
|
|
else
|
|
m_finalize();
|
|
}
|
|
|
|
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) && ImGui::IsKeyPressed(ImGuiKey_Escape))
|
|
m_isOpen = false;
|
|
}
|
|
}
|
|
|
|
|
|
static const unsigned int file_icon[] = {
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x4c000000, 0xf5000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xdd000000, 0x2d000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0xd1000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6a000000, 0xa1000000, 0xff000000, 0xff000000, 0x2e000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x54000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x46000000, 0xf5000000, 0xe0000000, 0xff000000, 0x30000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6e000000, 0xf8000000, 0x01000000, 0xc3000000, 0xff000000, 0x30000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x00000000, 0x00000000, 0xd2000000, 0xff000000, 0x30000000, 0x00000000, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x13000000, 0x00000000, 0x00000000, 0xd2000000, 0xff000000, 0x30000000, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x73000000, 0xff000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xbe000000, 0xff000000, 0x30000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x65000000, 0xff000000, 0x34000000, 0x10000000, 0x10000000, 0x03000000, 0x0a000000, 0xdb000000, 0xff000000, 0x2f000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0f000000, 0xd9000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xed000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06000000, 0x5e000000, 0x6c000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x60000000, 0x9e000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x52000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6b000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6b000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x6a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6a000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0x54000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x54000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xff000000, 0xd2000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0x6b000000, 0xd2000000, 0xff000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x4c000000, 0xf5000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xf5000000, 0x4b000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
};
|
|
static const unsigned int folder_icon[] = {
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00000000, 0x00000000, 0x45000000, 0x8a000000, 0x99000000, 0x97000000, 0x97000000, 0x97000000, 0x97000000, 0x97000000, 0x98000000, 0x81000000, 0x35000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
|
0x00000000, 0x9e000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0x80000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
|
0x76000000, 0xff000000, 0xff000000, 0xf6000000, 0xe2000000, 0xe2000000, 0xe2000000, 0xe2000000, 0xe2000000, 0xe2000000, 0xe2000000, 0xff000000, 0xff000000, 0xff000000, 0x80000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
|
0xe7000000, 0xff000000, 0xbe000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1e000000, 0xd1000000, 0xff000000, 0xff000000, 0x75000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
|
0xfa000000, 0xff000000, 0x5a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06000000, 0xe0000000, 0xff000000, 0xff000000, 0x68000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
|
0xf4000000, 0xff000000, 0x67000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0xe4000000, 0xff000000, 0xff000000, 0xad000000, 0x94000000, 0x94000000, 0x94000000, 0x94000000, 0x94000000, 0x94000000, 0x94000000, 0x94000000, 0x94000000, 0x96000000, 0x8b000000, 0x4f000000, 0x00000000, 0x00000000,
|
|
0xf3000000, 0xff000000, 0x6a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x17000000, 0xe8000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xaf000000, 0x00000000,
|
|
0xf3000000, 0xff000000, 0x6a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0e000000, 0x88000000, 0xc3000000, 0xcd000000, 0xcc000000, 0xcc000000, 0xcc000000, 0xcc000000, 0xcc000000, 0xcc000000, 0xcc000000, 0xcb000000, 0xcc000000, 0xe2000000, 0xff000000, 0xff000000, 0x81000000,
|
|
0xf3000000, 0xff000000, 0x6a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xb6000000, 0xff000000, 0xec000000,
|
|
0xf3000000, 0xff000000, 0x6a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5b000000, 0xff000000, 0xf9000000,
|
|
0xf3000000, 0xff000000, 0x6a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x68000000, 0xff000000, 0xf4000000,
|
|
0xf3000000, 0xff000000, 0x6a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6a000000, 0xff000000, 0xf3000000,
|
|
0xf3000000, 0xff000000, 0x6a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6a000000, 0xff000000, 0xf3000000,
|
|
0xf3000000, 0xff000000, 0x6a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6a000000, 0xff000000, 0xf3000000,
|
|
0xf3000000, 0xff000000, 0x6a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6a000000, 0xff000000, 0xf3000000,
|
|
0xf3000000, 0xff000000, 0x6a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6a000000, 0xff000000, 0xf3000000,
|
|
0xf3000000, 0xff000000, 0x6a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6a000000, 0xff000000, 0xf3000000,
|
|
0xf3000000, 0xff000000, 0x6a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6a000000, 0xff000000, 0xf3000000,
|
|
0xf3000000, 0xff000000, 0x6a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6a000000, 0xff000000, 0xf3000000,
|
|
0xf3000000, 0xff000000, 0x6a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6a000000, 0xff000000, 0xf3000000,
|
|
0xf3000000, 0xff000000, 0x6a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6a000000, 0xff000000, 0xf3000000,
|
|
0xf3000000, 0xff000000, 0x6a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6a000000, 0xff000000, 0xf3000000,
|
|
0xf4000000, 0xff000000, 0x68000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x68000000, 0xff000000, 0xf4000000,
|
|
0xfa000000, 0xff000000, 0x5a000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5a000000, 0xff000000, 0xf9000000,
|
|
0xea000000, 0xff000000, 0xb5000000, 0x05000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x05000000, 0xb5000000, 0xff000000, 0xea000000,
|
|
0x7e000000, 0xff000000, 0xff000000, 0xeb000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xd6000000, 0xeb000000, 0xff000000, 0xff000000, 0x7f000000,
|
|
0x00000000, 0xac000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xac000000, 0x00000000,
|
|
0x00000000, 0x00000000, 0x53000000, 0x8f000000, 0x9a000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x99000000, 0x9a000000, 0x8f000000, 0x53000000, 0x00000000, 0x00000000,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
|
|
};
|
|
const char* ifd::GetDefaultFolderIcon()
|
|
{
|
|
return (const char*)&folder_icon[0];
|
|
}
|
|
const char* ifd::GetDefaultFileIcon()
|
|
{
|
|
return (const char*)&file_icon[0];
|
|
}
|