GUI: add multi-selection capability to file dialog
This commit is contained in:
parent
d085f76c7f
commit
666b0d581a
|
@ -260,6 +260,20 @@ void FurnaceGUI::drawDebug() {
|
||||||
ImGui::Unindent();
|
ImGui::Unindent();
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
|
if (ImGui::TreeNode("File Selection Test")) {
|
||||||
|
if (ImGui::Button("Test Open")) {
|
||||||
|
openFileDialog(GUI_FILE_TEST_OPEN);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Test Open Multi")) {
|
||||||
|
openFileDialog(GUI_FILE_TEST_OPEN_MULTI);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Test Save")) {
|
||||||
|
openFileDialog(GUI_FILE_TEST_SAVE);
|
||||||
|
}
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
if (ImGui::TreeNode("Playground")) {
|
if (ImGui::TreeNode("Playground")) {
|
||||||
if (pgSys<0 || pgSys>=e->song.systemLen) pgSys=0;
|
if (pgSys<0 || pgSys>=e->song.systemLen) pgSys=0;
|
||||||
if (ImGui::BeginCombo("System",fmt::sprintf("%d. %s",pgSys+1,e->getSystemName(e->song.system[pgSys])).c_str())) {
|
if (ImGui::BeginCombo("System",fmt::sprintf("%d. %s",pgSys+1,e->getSystemName(e->song.system[pgSys])).c_str())) {
|
||||||
|
|
|
@ -10,13 +10,14 @@
|
||||||
|
|
||||||
#ifdef USE_NFD
|
#ifdef USE_NFD
|
||||||
struct NFDState {
|
struct NFDState {
|
||||||
bool isSave;
|
bool isSave, allowMultiple;
|
||||||
String header;
|
String header;
|
||||||
std::vector<String> filter;
|
std::vector<String> filter;
|
||||||
String path;
|
String path;
|
||||||
FileDialogSelectCallback clickCallback;
|
FileDialogSelectCallback clickCallback;
|
||||||
NFDState(bool save, String h, std::vector<String> filt, String pa, FileDialogSelectCallback cc):
|
NFDState(bool save, String h, std::vector<String> filt, String pa, FileDialogSelectCallback cc, bool multi):
|
||||||
isSave(save),
|
isSave(save),
|
||||||
|
allowMultiple(multi),
|
||||||
header(h),
|
header(h),
|
||||||
filter(filt),
|
filter(filt),
|
||||||
path(pa),
|
path(pa),
|
||||||
|
@ -61,7 +62,7 @@ void _nfdThread(const NFDState state, std::atomic<bool>* ok, String* result, boo
|
||||||
}
|
}
|
||||||
#endif
|
#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, bool allowMultiple) {
|
||||||
if (opened) return false;
|
if (opened) return false;
|
||||||
saving=false;
|
saving=false;
|
||||||
curPath=path;
|
curPath=path;
|
||||||
|
@ -70,18 +71,18 @@ bool FurnaceGUIFileDialog::openLoad(String header, std::vector<String> filter, c
|
||||||
#ifdef USE_NFD
|
#ifdef USE_NFD
|
||||||
dialogOK=false;
|
dialogOK=false;
|
||||||
#ifdef NFD_NON_THREADED
|
#ifdef NFD_NON_THREADED
|
||||||
_nfdThread(NFDState(false,header,filter,path,clickCallback),&dialogOK,&nfdResult,&hasError);
|
_nfdThread(NFDState(false,header,filter,path,clickCallback,allowMultiple),&dialogOK,&nfdResult,&hasError);
|
||||||
#else
|
#else
|
||||||
dialogO=new std::thread(_nfdThread,NFDState(false,header,filter,path,clickCallback),&dialogOK,&nfdResult,&hasError);
|
dialogO=new std::thread(_nfdThread,NFDState(false,header,filter,path,clickCallback,allowMultiple),&dialogOK,&nfdResult,&hasError);
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
dialogO=new pfd::open_file(header,path,filter);
|
dialogO=new pfd::open_file(header,path,filter,allowMultiple?(pfd::opt::multiselect):(pfd::opt::none));
|
||||||
hasError=!pfd::settings::available();
|
hasError=!pfd::settings::available();
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
hasError=false;
|
hasError=false;
|
||||||
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,allowMultiple?999:1,nullptr,0,clickCallback);
|
||||||
}
|
}
|
||||||
opened=true;
|
opened=true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -96,9 +97,9 @@ bool FurnaceGUIFileDialog::openSave(String header, std::vector<String> filter, c
|
||||||
#ifdef USE_NFD
|
#ifdef USE_NFD
|
||||||
dialogOK=false;
|
dialogOK=false;
|
||||||
#ifdef NFD_NON_THREADED
|
#ifdef NFD_NON_THREADED
|
||||||
_nfdThread(NFDState(true,header,filter,path,NULL),&dialogOK,&nfdResult,&hasError);
|
_nfdThread(NFDState(true,header,filter,path,NULL,false),&dialogOK,&nfdResult,&hasError);
|
||||||
#else
|
#else
|
||||||
dialogS=new std::thread(_nfdThread,NFDState(true,header,filter,path,NULL),&dialogOK,&nfdResult,&hasError);
|
dialogS=new std::thread(_nfdThread,NFDState(true,header,filter,path,NULL,false),&dialogOK,&nfdResult,&hasError);
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
dialogS=new pfd::save_file(header,path,filter);
|
dialogS=new pfd::save_file(header,path,filter);
|
||||||
|
@ -115,7 +116,7 @@ bool FurnaceGUIFileDialog::openSave(String header, std::vector<String> filter, c
|
||||||
|
|
||||||
bool FurnaceGUIFileDialog::accepted() {
|
bool FurnaceGUIFileDialog::accepted() {
|
||||||
if (sysDialog) {
|
if (sysDialog) {
|
||||||
return (fileName!="");
|
return (!fileName.empty());
|
||||||
} else {
|
} else {
|
||||||
return ImGuiFileDialog::Instance()->IsOk();
|
return ImGuiFileDialog::Instance()->IsOk();
|
||||||
}
|
}
|
||||||
|
@ -153,10 +154,15 @@ bool FurnaceGUIFileDialog::render(const ImVec2& min, const ImVec2& max) {
|
||||||
if (sysDialog) {
|
if (sysDialog) {
|
||||||
#ifdef USE_NFD
|
#ifdef USE_NFD
|
||||||
if (dialogOK) {
|
if (dialogOK) {
|
||||||
fileName=nfdResult;
|
fileName.clear();
|
||||||
size_t dsPos=fileName.rfind(DIR_SEPARATOR);
|
fileName.push_back(nfdResult);
|
||||||
if (dsPos!=String::npos) curPath=fileName.substr(0,dsPos);
|
if (!fileName.empty()) {
|
||||||
logD("returning %s",fileName.c_str());
|
size_t dsPos=fileName[0].rfind(DIR_SEPARATOR);
|
||||||
|
if (dsPos!=String::npos) curPath=fileName[0].substr(0,dsPos);
|
||||||
|
}
|
||||||
|
for (String& i: fileName) {
|
||||||
|
logD("- returning %s",i);
|
||||||
|
}
|
||||||
dialogOK=false;
|
dialogOK=false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -165,10 +171,11 @@ bool FurnaceGUIFileDialog::render(const ImVec2& min, const ImVec2& max) {
|
||||||
if (saving) {
|
if (saving) {
|
||||||
if (dialogS!=NULL) {
|
if (dialogS!=NULL) {
|
||||||
if (dialogS->ready(0)) {
|
if (dialogS->ready(0)) {
|
||||||
fileName=dialogS->result();
|
fileName.clear();
|
||||||
size_t dsPos=fileName.rfind(DIR_SEPARATOR);
|
fileName.push_back(dialogS->result());
|
||||||
if (dsPos!=String::npos) curPath=fileName.substr(0,dsPos);
|
size_t dsPos=fileName[0].rfind(DIR_SEPARATOR);
|
||||||
logD("returning %s",fileName.c_str());
|
if (dsPos!=String::npos) curPath=fileName[0].substr(0,dsPos);
|
||||||
|
logD("returning %s",fileName[0]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,13 +183,19 @@ bool FurnaceGUIFileDialog::render(const ImVec2& min, const ImVec2& max) {
|
||||||
if (dialogO!=NULL) {
|
if (dialogO!=NULL) {
|
||||||
if (dialogO->ready(0)) {
|
if (dialogO->ready(0)) {
|
||||||
if (dialogO->result().empty()) {
|
if (dialogO->result().empty()) {
|
||||||
fileName="";
|
fileName.clear();
|
||||||
logD("returning nothing");
|
logD("returning nothing");
|
||||||
} else {
|
} else {
|
||||||
fileName=dialogO->result()[0];
|
fileName=dialogO->result();
|
||||||
size_t dsPos=fileName.rfind(DIR_SEPARATOR);
|
if (fileName.empty()) {
|
||||||
if (dsPos!=String::npos) curPath=fileName.substr(0,dsPos);
|
// don't touch
|
||||||
logD("returning %s",fileName.c_str());
|
} else {
|
||||||
|
size_t dsPos=fileName[0].rfind(DIR_SEPARATOR);
|
||||||
|
if (dsPos!=String::npos) curPath=fileName[0].substr(0,dsPos);
|
||||||
|
for (String& i: fileName) {
|
||||||
|
logD("- returning %s",i);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -217,10 +230,12 @@ String FurnaceGUIFileDialog::getPath() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String FurnaceGUIFileDialog::getFileName() {
|
std::vector<String>& FurnaceGUIFileDialog::getFileName() {
|
||||||
if (sysDialog) {
|
if (sysDialog) {
|
||||||
return fileName;
|
return fileName;
|
||||||
} else {
|
} else {
|
||||||
return ImGuiFileDialog::Instance()->GetFilePathName();
|
fileName.clear();
|
||||||
|
fileName.push_back(ImGuiFileDialog::Instance()->GetFilePathName());
|
||||||
|
return fileName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ class FurnaceGUIFileDialog {
|
||||||
bool saving;
|
bool saving;
|
||||||
bool hasError;
|
bool hasError;
|
||||||
String curPath;
|
String curPath;
|
||||||
String fileName;
|
std::vector<String> fileName;
|
||||||
#ifdef USE_NFD
|
#ifdef USE_NFD
|
||||||
std::thread* dialogO;
|
std::thread* dialogO;
|
||||||
std::thread* dialogS;
|
std::thread* dialogS;
|
||||||
|
@ -41,7 +41,7 @@ class FurnaceGUIFileDialog {
|
||||||
pfd::save_file* dialogS;
|
pfd::save_file* dialogS;
|
||||||
#endif
|
#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 allowMultiple=false);
|
||||||
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);
|
||||||
bool accepted();
|
bool accepted();
|
||||||
void close();
|
void close();
|
||||||
|
@ -49,7 +49,7 @@ class FurnaceGUIFileDialog {
|
||||||
bool isOpen();
|
bool isOpen();
|
||||||
bool isError();
|
bool isError();
|
||||||
String getPath();
|
String getPath();
|
||||||
String getFileName();
|
std::vector<String>& getFileName();
|
||||||
explicit FurnaceGUIFileDialog(bool system):
|
explicit FurnaceGUIFileDialog(bool system):
|
||||||
sysDialog(system),
|
sysDialog(system),
|
||||||
opened(false),
|
opened(false),
|
||||||
|
|
|
@ -1495,6 +1495,43 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
|
||||||
dpiScale
|
dpiScale
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case GUI_FILE_TEST_OPEN:
|
||||||
|
if (!dirExists(workingDirTest)) workingDirTest=getHomeDir();
|
||||||
|
hasOpened=fileDialog->openLoad(
|
||||||
|
"Open Test",
|
||||||
|
{"compatible files", "*.fur *.dmf *.mod",
|
||||||
|
"another option", "*.wav *.ttf",
|
||||||
|
"all files", ".*"},
|
||||||
|
"compatible files{.fur,.dmf,.mod},another option{.wav,.ttf},.*",
|
||||||
|
workingDirTest,
|
||||||
|
dpiScale
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case GUI_FILE_TEST_OPEN_MULTI:
|
||||||
|
if (!dirExists(workingDirTest)) workingDirTest=getHomeDir();
|
||||||
|
hasOpened=fileDialog->openLoad(
|
||||||
|
"Open Test (Multi)",
|
||||||
|
{"compatible files", "*.fur *.dmf *.mod",
|
||||||
|
"another option", "*.wav *.ttf",
|
||||||
|
"all files", ".*"},
|
||||||
|
"compatible files{.fur,.dmf,.mod},another option{.wav,.ttf},.*",
|
||||||
|
workingDirTest,
|
||||||
|
dpiScale,
|
||||||
|
NULL,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case GUI_FILE_TEST_SAVE:
|
||||||
|
if (!dirExists(workingDirTest)) workingDirTest=getHomeDir();
|
||||||
|
hasOpened=fileDialog->openSave(
|
||||||
|
"Save Test",
|
||||||
|
{"Furnace song", "*.fur",
|
||||||
|
"DefleMask module", "*.dmf"},
|
||||||
|
"Furnace song{.fur},DefleMask module{.dmf}",
|
||||||
|
workingDirTest,
|
||||||
|
dpiScale
|
||||||
|
);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (hasOpened) curFileDialog=type;
|
if (hasOpened) curFileDialog=type;
|
||||||
//ImGui::GetIO().ConfigFlags|=ImGuiConfigFlags_NavEnableKeyboard;
|
//ImGui::GetIO().ConfigFlags|=ImGuiConfigFlags_NavEnableKeyboard;
|
||||||
|
@ -3220,6 +3257,11 @@ bool FurnaceGUI::loop() {
|
||||||
case GUI_FILE_MU5_ROM_OPEN:
|
case GUI_FILE_MU5_ROM_OPEN:
|
||||||
workingDirROM=fileDialog->getPath()+DIR_SEPARATOR_STR;
|
workingDirROM=fileDialog->getPath()+DIR_SEPARATOR_STR;
|
||||||
break;
|
break;
|
||||||
|
case GUI_FILE_TEST_OPEN:
|
||||||
|
case GUI_FILE_TEST_OPEN_MULTI:
|
||||||
|
case GUI_FILE_TEST_SAVE:
|
||||||
|
workingDirTest=fileDialog->getPath()+DIR_SEPARATOR_STR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (fileDialog->isError()) {
|
if (fileDialog->isError()) {
|
||||||
#if defined(_WIN32) || defined(__APPLE__)
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
|
@ -3229,7 +3271,11 @@ bool FurnaceGUI::loop() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (fileDialog->accepted()) {
|
if (fileDialog->accepted()) {
|
||||||
fileName=fileDialog->getFileName();
|
if (fileDialog->getFileName().empty()) {
|
||||||
|
fileName="";
|
||||||
|
} else {
|
||||||
|
fileName=fileDialog->getFileName()[0];
|
||||||
|
}
|
||||||
if (fileName!="") {
|
if (fileName!="") {
|
||||||
if (curFileDialog==GUI_FILE_SAVE) {
|
if (curFileDialog==GUI_FILE_SAVE) {
|
||||||
// we can't tell whether the user chose .dmf or .fur in the system file picker
|
// we can't tell whether the user chose .dmf or .fur in the system file picker
|
||||||
|
@ -3468,6 +3514,20 @@ bool FurnaceGUI::loop() {
|
||||||
case GUI_FILE_MU5_ROM_OPEN:
|
case GUI_FILE_MU5_ROM_OPEN:
|
||||||
settings.mu5Path=copyOfName;
|
settings.mu5Path=copyOfName;
|
||||||
break;
|
break;
|
||||||
|
case GUI_FILE_TEST_OPEN:
|
||||||
|
showWarning(fmt::sprintf("You opened: %s",copyOfName),GUI_WARN_GENERIC);
|
||||||
|
break;
|
||||||
|
case GUI_FILE_TEST_OPEN_MULTI: {
|
||||||
|
String msg="You opened:";
|
||||||
|
for (String i: fileDialog->getFileName()) {
|
||||||
|
msg+=fmt::sprintf("\n- %s",i);
|
||||||
|
}
|
||||||
|
showWarning(msg,GUI_WARN_GENERIC);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GUI_FILE_TEST_SAVE:
|
||||||
|
showWarning(fmt::sprintf("You saved: %s",copyOfName),GUI_WARN_GENERIC);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
curFileDialog=GUI_FILE_OPEN;
|
curFileDialog=GUI_FILE_OPEN;
|
||||||
}
|
}
|
||||||
|
@ -4018,6 +4078,7 @@ bool FurnaceGUI::init() {
|
||||||
workingDirColors=e->getConfString("lastDirColors",workingDir);
|
workingDirColors=e->getConfString("lastDirColors",workingDir);
|
||||||
workingDirKeybinds=e->getConfString("lastDirKeybinds",workingDir);
|
workingDirKeybinds=e->getConfString("lastDirKeybinds",workingDir);
|
||||||
workingDirLayout=e->getConfString("lastDirLayout",workingDir);
|
workingDirLayout=e->getConfString("lastDirLayout",workingDir);
|
||||||
|
workingDirTest=e->getConfString("lastDirTest",workingDir);
|
||||||
|
|
||||||
editControlsOpen=e->getConfBool("editControlsOpen",true);
|
editControlsOpen=e->getConfBool("editControlsOpen",true);
|
||||||
ordersOpen=e->getConfBool("ordersOpen",true);
|
ordersOpen=e->getConfBool("ordersOpen",true);
|
||||||
|
@ -4255,6 +4316,7 @@ bool FurnaceGUI::finish() {
|
||||||
e->setConf("lastDirColors",workingDirColors);
|
e->setConf("lastDirColors",workingDirColors);
|
||||||
e->setConf("lastDirKeybinds",workingDirKeybinds);
|
e->setConf("lastDirKeybinds",workingDirKeybinds);
|
||||||
e->setConf("lastDirLayout",workingDirLayout);
|
e->setConf("lastDirLayout",workingDirLayout);
|
||||||
|
e->setConf("lastDirTest",workingDirTest);
|
||||||
|
|
||||||
// commit last open windows
|
// commit last open windows
|
||||||
e->setConf("editControlsOpen",editControlsOpen);
|
e->setConf("editControlsOpen",editControlsOpen);
|
||||||
|
|
|
@ -277,7 +277,11 @@ enum FurnaceGUIFileDialogs {
|
||||||
GUI_FILE_EXPORT_LAYOUT,
|
GUI_FILE_EXPORT_LAYOUT,
|
||||||
GUI_FILE_YRW801_ROM_OPEN,
|
GUI_FILE_YRW801_ROM_OPEN,
|
||||||
GUI_FILE_TG100_ROM_OPEN,
|
GUI_FILE_TG100_ROM_OPEN,
|
||||||
GUI_FILE_MU5_ROM_OPEN
|
GUI_FILE_MU5_ROM_OPEN,
|
||||||
|
|
||||||
|
GUI_FILE_TEST_OPEN,
|
||||||
|
GUI_FILE_TEST_OPEN_MULTI,
|
||||||
|
GUI_FILE_TEST_SAVE
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FurnaceGUIWarnings {
|
enum FurnaceGUIWarnings {
|
||||||
|
@ -943,7 +947,7 @@ class FurnaceGUI {
|
||||||
bool updateSampleTex;
|
bool updateSampleTex;
|
||||||
|
|
||||||
String workingDir, fileName, clipboard, warnString, errorString, lastError, curFileName, nextFile;
|
String workingDir, fileName, clipboard, warnString, errorString, lastError, curFileName, nextFile;
|
||||||
String workingDirSong, workingDirIns, workingDirWave, workingDirSample, workingDirAudioExport, workingDirVGMExport, workingDirFont, workingDirColors, workingDirKeybinds, workingDirLayout, workingDirROM;
|
String workingDirSong, workingDirIns, workingDirWave, workingDirSample, workingDirAudioExport, workingDirVGMExport, workingDirFont, workingDirColors, workingDirKeybinds, workingDirLayout, workingDirROM, workingDirTest;
|
||||||
String mmlString[32];
|
String mmlString[32];
|
||||||
String mmlStringW;
|
String mmlStringW;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue