GUI: use Native File Dialog on Windows/macOS
latter is untested
This commit is contained in:
parent
d5d381328b
commit
d8513e0856
|
@ -520,8 +520,17 @@ src/gui/volMeter.cpp
|
||||||
src/gui/gui.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)
|
if (APPLE)
|
||||||
list(APPEND GUI_SOURCES src/gui/macstuff.m)
|
list(APPEND GUI_SOURCES src/gui/macstuff.m)
|
||||||
|
list(APPEND GUI_SOURCES extern/nfd-modified/src/nfd_cocoa.m)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT WIN32 AND NOT APPLE)
|
if (NOT WIN32 AND NOT APPLE)
|
||||||
|
@ -549,6 +558,11 @@ if (BUILD_GUI)
|
||||||
extern/IconFontCppHeaders
|
extern/IconFontCppHeaders
|
||||||
extern/igfd
|
extern/igfd
|
||||||
)
|
)
|
||||||
|
if (WIN32 OR APPLE)
|
||||||
|
list(APPEND DEPENDENCIES_INCLUDE_DIRS
|
||||||
|
extern/nfd-modified/src/include
|
||||||
|
)
|
||||||
|
endif()
|
||||||
list(APPEND DEPENDENCIES_DEFINES HAVE_GUI)
|
list(APPEND DEPENDENCIES_DEFINES HAVE_GUI)
|
||||||
message(STATUS "Building GUI")
|
message(STATUS "Building GUI")
|
||||||
else()
|
else()
|
||||||
|
|
|
@ -2,7 +2,62 @@
|
||||||
#include "ImGuiFileDialog.h"
|
#include "ImGuiFileDialog.h"
|
||||||
#include "../ta-log.h"
|
#include "../ta-log.h"
|
||||||
|
|
||||||
|
#ifdef USE_NFD
|
||||||
|
#include <nfd.h>
|
||||||
|
#else
|
||||||
#include "../../extern/pfd-fixed/portable-file-dialogs.h"
|
#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) {
|
bool FurnaceGUIFileDialog::openLoad(String header, std::vector<String> filter, const char* noSysFilter, String path, double dpiScale, FileDialogSelectCallback clickCallback) {
|
||||||
if (opened) return false;
|
if (opened) return false;
|
||||||
|
@ -10,7 +65,12 @@ bool FurnaceGUIFileDialog::openLoad(String header, std::vector<String> filter, c
|
||||||
curPath=path;
|
curPath=path;
|
||||||
logD("opening load file dialog with curPath %s",curPath.c_str());
|
logD("opening load file dialog with curPath %s",curPath.c_str());
|
||||||
if (sysDialog) {
|
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);
|
dialogO=new pfd::open_file(header,path,filter);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
ImGuiFileDialog::Instance()->DpiScale=dpiScale;
|
ImGuiFileDialog::Instance()->DpiScale=dpiScale;
|
||||||
ImGuiFileDialog::Instance()->OpenModal("FileDialog",header,noSysFilter,path,1,nullptr,0,clickCallback);
|
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;
|
curPath=path;
|
||||||
logD("opening save file dialog with curPath %s",curPath.c_str());
|
logD("opening save file dialog with curPath %s",curPath.c_str());
|
||||||
if (sysDialog) {
|
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);
|
dialogS=new pfd::save_file(header,path,filter);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
ImGuiFileDialog::Instance()->DpiScale=dpiScale;
|
ImGuiFileDialog::Instance()->DpiScale=dpiScale;
|
||||||
ImGuiFileDialog::Instance()->OpenModal("FileDialog",header,noSysFilter,path,1,nullptr,ImGuiFileDialogFlags_ConfirmOverwrite);
|
ImGuiFileDialog::Instance()->OpenModal("FileDialog",header,noSysFilter,path,1,nullptr,ImGuiFileDialogFlags_ConfirmOverwrite);
|
||||||
|
@ -46,15 +111,24 @@ void FurnaceGUIFileDialog::close() {
|
||||||
if (sysDialog) {
|
if (sysDialog) {
|
||||||
if (saving) {
|
if (saving) {
|
||||||
if (dialogS!=NULL) {
|
if (dialogS!=NULL) {
|
||||||
|
#ifdef USE_NFD
|
||||||
|
dialogS->join();
|
||||||
|
#endif
|
||||||
delete dialogS;
|
delete dialogS;
|
||||||
dialogS=NULL;
|
dialogS=NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (dialogO!=NULL) {
|
if (dialogO!=NULL) {
|
||||||
|
#ifdef USE_NFD
|
||||||
|
dialogO->join();
|
||||||
|
#endif
|
||||||
delete dialogO;
|
delete dialogO;
|
||||||
dialogO=NULL;
|
dialogO=NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef USE_NFD
|
||||||
|
dialogOK=false;
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
ImGuiFileDialog::Instance()->Close();
|
ImGuiFileDialog::Instance()->Close();
|
||||||
}
|
}
|
||||||
|
@ -63,6 +137,15 @@ void FurnaceGUIFileDialog::close() {
|
||||||
|
|
||||||
bool FurnaceGUIFileDialog::render(const ImVec2& min, const ImVec2& max) {
|
bool FurnaceGUIFileDialog::render(const ImVec2& min, const ImVec2& max) {
|
||||||
if (sysDialog) {
|
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 (saving) {
|
||||||
if (dialogS!=NULL) {
|
if (dialogS!=NULL) {
|
||||||
if (dialogS->ready(0)) {
|
if (dialogS->ready(0)) {
|
||||||
|
@ -90,6 +173,7 @@ bool FurnaceGUIFileDialog::render(const ImVec2& min, const ImVec2& max) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
return ImGuiFileDialog::Instance()->Display("FileDialog",ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove,min,max);
|
return ImGuiFileDialog::Instance()->Display("FileDialog",ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove,min,max);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,19 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
|
#define USE_NFD
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_NFD
|
||||||
|
#include <atomic>
|
||||||
|
#include <thread>
|
||||||
|
#else
|
||||||
namespace pfd {
|
namespace pfd {
|
||||||
class open_file;
|
class open_file;
|
||||||
class save_file;
|
class save_file;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef std::function<void(const char*)> FileDialogSelectCallback;
|
typedef std::function<void(const char*)> FileDialogSelectCallback;
|
||||||
|
|
||||||
|
@ -16,8 +25,15 @@ class FurnaceGUIFileDialog {
|
||||||
bool saving;
|
bool saving;
|
||||||
String curPath;
|
String curPath;
|
||||||
String fileName;
|
String fileName;
|
||||||
|
#ifdef USE_NFD
|
||||||
|
std::thread* dialogO;
|
||||||
|
std::thread* dialogS;
|
||||||
|
std::atomic<bool> dialogOK;
|
||||||
|
String nfdResult;
|
||||||
|
#else
|
||||||
pfd::open_file* dialogO;
|
pfd::open_file* dialogO;
|
||||||
pfd::save_file* dialogS;
|
pfd::save_file* dialogS;
|
||||||
|
#endif
|
||||||
public:
|
public:
|
||||||
bool openLoad(String header, std::vector<String> filter, const char* noSysFilter, String path, double dpiScale, FileDialogSelectCallback clickCallback=NULL);
|
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);
|
bool openSave(String header, std::vector<String> filter, const char* noSysFilter, String path, double dpiScale);
|
||||||
|
|
Loading…
Reference in New Issue