GUI: use Native File Dialog on Windows/macOS

latter is untested
This commit is contained in:
tildearrow 2022-06-17 01:28:22 -05:00
parent d5d381328b
commit d8513e0856
3 changed files with 114 additions and 0 deletions

View File

@ -520,8 +520,17 @@ src/gui/volMeter.cpp
src/gui/gui.cpp
)
if (WIN32 OR APPLE)
list(APPEND GUI_SOURCES extern/nfd-modified/src/nfd_common.c)
endif()
if (WIN32)
list(APPEND GUI_SOURCES extern/nfd-modified/src/nfd_win.cpp)
endif()
if (APPLE)
list(APPEND GUI_SOURCES src/gui/macstuff.m)
list(APPEND GUI_SOURCES extern/nfd-modified/src/nfd_cocoa.m)
endif()
if (NOT WIN32 AND NOT APPLE)
@ -549,6 +558,11 @@ if (BUILD_GUI)
extern/IconFontCppHeaders
extern/igfd
)
if (WIN32 OR APPLE)
list(APPEND DEPENDENCIES_INCLUDE_DIRS
extern/nfd-modified/src/include
)
endif()
list(APPEND DEPENDENCIES_DEFINES HAVE_GUI)
message(STATUS "Building GUI")
else()

View File

@ -2,7 +2,62 @@
#include "ImGuiFileDialog.h"
#include "../ta-log.h"
#ifdef USE_NFD
#include <nfd.h>
#else
#include "../../extern/pfd-fixed/portable-file-dialogs.h"
#endif
#ifdef USE_NFD
struct NFDState {
bool isSave;
String header;
std::vector<String> filter;
String path;
FileDialogSelectCallback clickCallback;
NFDState(bool save, String h, std::vector<String> filt, String pa, FileDialogSelectCallback cc):
isSave(save),
header(h),
filter(filt),
path(pa),
clickCallback(cc) {
}
};
// TODO: filter
void _nfdThread(const NFDState state, std::atomic<bool>* ok, String* result) {
nfdchar_t* out=NULL;
nfdresult_t ret=NFD_CANCEL;
if (state.isSave) {
ret=NFD_SaveDialog(NULL,state.path.c_str(),&out);
} else {
ret=NFD_OpenDialog(NULL,state.path.c_str(),&out);
}
switch (ret) {
case NFD_OKAY:
if (out!=NULL) {
(*result)=out;
} else {
(*result)="";
}
break;
case NFD_CANCEL:
(*result)="";
break;
case NFD_ERROR:
(*result)="";
logE("NFD error! %s\n",NFD_GetError());
break;
default:
logE("NFD unknown return code %d!\n",ret);
(*result)="";
break;
}
(*ok)=true;
}
#endif
bool FurnaceGUIFileDialog::openLoad(String header, std::vector<String> filter, const char* noSysFilter, String path, double dpiScale, FileDialogSelectCallback clickCallback) {
if (opened) return false;
@ -10,7 +65,12 @@ bool FurnaceGUIFileDialog::openLoad(String header, std::vector<String> filter, c
curPath=path;
logD("opening load file dialog with curPath %s",curPath.c_str());
if (sysDialog) {
#ifdef USE_NFD
dialogOK=false;
dialogO=new std::thread(_nfdThread,NFDState(false,header,filter,path,clickCallback),&dialogOK,&nfdResult);
#else
dialogO=new pfd::open_file(header,path,filter);
#endif
} else {
ImGuiFileDialog::Instance()->DpiScale=dpiScale;
ImGuiFileDialog::Instance()->OpenModal("FileDialog",header,noSysFilter,path,1,nullptr,0,clickCallback);
@ -25,7 +85,12 @@ bool FurnaceGUIFileDialog::openSave(String header, std::vector<String> filter, c
curPath=path;
logD("opening save file dialog with curPath %s",curPath.c_str());
if (sysDialog) {
#ifdef USE_NFD
dialogOK=false;
dialogS=new std::thread(_nfdThread,NFDState(true,header,filter,path,NULL),&dialogOK,&nfdResult);
#else
dialogS=new pfd::save_file(header,path,filter);
#endif
} else {
ImGuiFileDialog::Instance()->DpiScale=dpiScale;
ImGuiFileDialog::Instance()->OpenModal("FileDialog",header,noSysFilter,path,1,nullptr,ImGuiFileDialogFlags_ConfirmOverwrite);
@ -46,15 +111,24 @@ void FurnaceGUIFileDialog::close() {
if (sysDialog) {
if (saving) {
if (dialogS!=NULL) {
#ifdef USE_NFD
dialogS->join();
#endif
delete dialogS;
dialogS=NULL;
}
} else {
if (dialogO!=NULL) {
#ifdef USE_NFD
dialogO->join();
#endif
delete dialogO;
dialogO=NULL;
}
}
#ifdef USE_NFD
dialogOK=false;
#endif
} else {
ImGuiFileDialog::Instance()->Close();
}
@ -63,6 +137,15 @@ void FurnaceGUIFileDialog::close() {
bool FurnaceGUIFileDialog::render(const ImVec2& min, const ImVec2& max) {
if (sysDialog) {
#ifdef USE_NFD
if (dialogOK) {
fileName=nfdResult;
logD("returning %s",fileName.c_str());
dialogOK=false;
return true;
}
return false;
#else
if (saving) {
if (dialogS!=NULL) {
if (dialogS->ready(0)) {
@ -90,6 +173,7 @@ bool FurnaceGUIFileDialog::render(const ImVec2& min, const ImVec2& max) {
}
}
return false;
#endif
} else {
return ImGuiFileDialog::Instance()->Display("FileDialog",ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove,min,max);
}

View File

@ -3,10 +3,19 @@
#include <functional>
#include <vector>
#if defined(_WIN32) || defined(__APPLE__)
#define USE_NFD
#endif
#ifdef USE_NFD
#include <atomic>
#include <thread>
#else
namespace pfd {
class open_file;
class save_file;
}
#endif
typedef std::function<void(const char*)> FileDialogSelectCallback;
@ -16,8 +25,15 @@ class FurnaceGUIFileDialog {
bool saving;
String curPath;
String fileName;
#ifdef USE_NFD
std::thread* dialogO;
std::thread* dialogS;
std::atomic<bool> dialogOK;
String nfdResult;
#else
pfd::open_file* dialogO;
pfd::save_file* dialogS;
#endif
public:
bool openLoad(String header, std::vector<String> filter, const char* noSysFilter, String path, double dpiScale, FileDialogSelectCallback clickCallback=NULL);
bool openSave(String header, std::vector<String> filter, const char* noSysFilter, String path, double dpiScale);