5#include "hellfire/utilities/FileDialog.h"
16 std::string
FileDialog::win32_open_file(
const std::vector<FileFilter> &filters) {
20 CHAR szFile[260] = {};
21 ZeroMemory(&ofn,
sizeof(ofn));
22 ofn.lStructSize =
sizeof(ofn);
23 ofn.hwndOwner = GetActiveWindow();
24 ofn.lpstrFile = szFile;
25 ofn.nMaxFile =
sizeof(szFile);
28 std::string filterStr;
29 if (filters.empty()) {
31 filterStr =
"All Files\0*.*\0";
33 for (
const auto &filter: filters) {
34 filterStr += filter.name +
'\0' + filter.extensions +
'\0';
39 std::vector filterBuf(filterStr.begin(), filterStr.end());
40 filterBuf.push_back(
'\0');
42 ofn.lpstrFilter = filterBuf.data();
44 ofn.lpstrFileTitle = NULL;
45 ofn.nMaxFileTitle = 0;
46 ofn.lpstrInitialDir = NULL;
47 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
49 if (GetOpenFileNameA(&ofn) == TRUE) {
50 filepath = ofn.lpstrFile;
56 std::string
FileDialog::win32_save_file(
const std::string &default_filename,
57 const std::vector<FileFilter> &filters, std::string &save_name_to) {
61 CHAR szFile[260] = {0};
64 if (!default_filename.empty()) {
65 strncpy(szFile, default_filename.c_str(),
sizeof(szFile) - 1);
68 ZeroMemory(&ofn,
sizeof(ofn));
69 ofn.lStructSize =
sizeof(ofn);
70 ofn.hwndOwner = GetActiveWindow();
71 ofn.lpstrFile = szFile;
72 ofn.nMaxFile =
sizeof(szFile);
75 std::string filterStr;
76 std::string defaultExt;
78 if (filters.empty()) {
80 filterStr =
"All Files\0*.*\0";
82 for (
const auto &filter: filters) {
83 filterStr += filter.name +
'\0' + filter.extensions +
'\0';
86 if (defaultExt.empty() && !filter.extensions.empty()) {
88 size_t pos = filter.extensions.find(
"*.");
89 if (pos != std::string::npos) {
90 size_t endPos = filter.extensions.find(
';', pos);
91 if (endPos == std::string::npos) {
92 endPos = filter.extensions.size();
95 defaultExt = filter.extensions.substr(pos + 2, endPos - pos - 2);
102 std::vector<
char> filterBuf(filterStr.begin(), filterStr.end());
103 filterBuf.push_back(
'\0');
105 ofn.lpstrFilter = filterBuf.data();
106 ofn.nFilterIndex = 1;
107 ofn.lpstrFileTitle = NULL;
108 ofn.nMaxFileTitle = 0;
109 ofn.lpstrInitialDir = NULL;
110 ofn.Flags = OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR;
113 if (!defaultExt.empty()) {
115 std::vector<
char> extBuf(defaultExt.begin(), defaultExt.end());
116 extBuf.push_back(
'\0');
117 ofn.lpstrDefExt = extBuf.data();
120 if (GetSaveFileNameA(&ofn) == TRUE) {
121 filepath = ofn.lpstrFile;
124 size_t lastSlash = filepath.find_last_of(
"\\/");
125 if (lastSlash != std::string::npos) {
126 save_name_to = filepath.substr(lastSlash + 1);
128 save_name_to = filepath;
135 std::string
FileDialog::imgui_open_file(
const std::vector<FileFilter> &filters) {
136 static std::string filepath;
140 std::string filterDesc =
"Supported formats: ";
141 if (filters.empty()) {
142 filterDesc +=
"All files";
144 for (size_t i = 0; i < filters.size(); ++i) {
145 filterDesc += filters[i].name;
146 if (i < filters.size() - 1) {
152 ImGui::OpenPopup(
"Open File");
154 if (ImGui::BeginPopupModal(
"Open File", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
155 static char buf[512] =
"assets/";
156 ImGui::Text(
"%s", filterDesc.c_str());
157 ImGui::InputText(
"Path to file", buf, 512);
159 if (ImGui::Button(
"OK", ImVec2(120, 0))) {
161 ImGui::CloseCurrentPopup();
164 if (ImGui::Button(
"Cancel", ImVec2(120, 0))) {
165 ImGui::CloseCurrentPopup();
174 std::string folder_path;
177 HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
182 IFileDialog* pfd =
nullptr;
183 hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd));
188 hr = pfd->GetOptions(&dwOptions);
191 hr = pfd->SetOptions(dwOptions | FOS_PICKFOLDERS);
195 if (SUCCEEDED(hr) && !title.empty()) {
196 std::wstring wideTitle(title.begin(), title.end());
197 pfd->SetTitle(wideTitle.c_str());
202 hr = pfd->Show(GetActiveWindow());
207 IShellItem* psi =
nullptr;
208 hr = pfd->GetResult(&psi);
210 PWSTR pszPath =
nullptr;
211 hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath);
212 if (SUCCEEDED(hr) && pszPath) {
214 const int size = WideCharToMultiByte(CP_UTF8, 0, pszPath, -1,
nullptr, 0,
nullptr,
nullptr);
216 folder_path.resize(size - 1);
217 WideCharToMultiByte(CP_UTF8, 0, pszPath, -1, &folder_path[0], size,
nullptr,
nullptr);
219 CoTaskMemFree(pszPath);
232 std::string
FileDialog::imgui_save_file(
const std::string &default_filename,
233 const std::vector<FileFilter> &filters) {
234 static std::string filepath;
238 std::string filterDesc =
"Save as: ";
239 if (filters.empty()) {
240 filterDesc +=
"All files";
242 for (size_t i = 0; i < filters.size(); ++i) {
243 filterDesc += filters[i].name;
244 if (i < filters.size() - 1) {
250 ImGui::OpenPopup(
"Save File");
252 if (ImGui::BeginPopupModal(
"Save File", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
253 static char buf[512] =
"";
256 if (buf[0] ==
'\0' && !default_filename.empty()) {
257 strncpy(buf, default_filename.c_str(),
sizeof(buf) - 1);
260 ImGui::Text(
"%s", filterDesc.c_str());
261 ImGui::InputText(
"Filename", buf, 512);
263 if (ImGui::Button(
"Save", ImVec2(120, 0))) {
267 if (!filters.empty() && filepath.find(
'.') == std::string::npos) {
268 const auto &firstFilter = filters[0];
269 size_t pos = firstFilter.extensions.find(
"*.");
270 if (pos != std::string::npos) {
271 size_t endPos = firstFilter.extensions.find(
';', pos);
272 if (endPos == std::string::npos) {
273 endPos = firstFilter.extensions.size();
275 std::string ext = firstFilter.extensions.substr(pos + 1, endPos - pos - 1);
280 ImGui::CloseCurrentPopup();
285 if (ImGui::Button(
"Cancel", ImVec2(120, 0))) {
286 ImGui::CloseCurrentPopup();
296 std::string
FileDialog::open_file(
const std::vector<FileFilter> &filters) {
298 return win32_open_file(filters);
306 return win32_select_folder(title);
308 return imgui_select_folder(title);
312 std::string
FileDialog::save_file(std::string &save_name_to,
const std::string &default_filename,
313 const std::vector<FileFilter> &filters) {
315 return win32_save_file(default_filename, filters, save_name_to);
static std::string imgui_open_file(const std::vector< FileFilter > &filters)
static std::string select_folder(const std::string &title)
static std::string imgui_save_file(const std::string &default_filename, const std::vector< FileFilter > &filters)
static std::string win32_select_folder(const std::string &title)