diff --git a/src/engine/config.cpp b/src/engine/config.cpp index 862cd4c03..38cb2b042 100644 --- a/src/engine/config.cpp +++ b/src/engine/config.cpp @@ -239,6 +239,10 @@ void DivEngine::setConf(String key, double value) { conf[key]=fmt::sprintf("%f",value); } +void DivEngine::setConf(String key, const char* value) { + conf[key]=String(value); +} + void DivEngine::setConf(String key, String value) { conf[key]=value; } diff --git a/src/engine/engine.h b/src/engine/engine.h index 4b78828e8..7c700e005 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -544,6 +544,7 @@ class DivEngine { void setConf(String key, int value); void setConf(String key, float value); void setConf(String key, double value); + void setConf(String key, const char* value); void setConf(String key, String value); // calculate base frequency/period diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 0b1d008b3..0d0635ec5 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -536,6 +536,7 @@ void FurnaceGUI::setFileName(String name) { } #endif updateWindowTitle(); + pushRecentFile(curFileName); } void FurnaceGUI::updateWindowTitle() { @@ -1724,6 +1725,7 @@ int FurnaceGUI::save(String path, int dmfVersion) { if (!e->getWarnings().empty()) { showWarning(e->getWarnings(),GUI_WARN_GENERIC); } + pushRecentFile(path); return 0; } @@ -1801,9 +1803,26 @@ int FurnaceGUI::load(String path) { if (!e->getWarnings().empty()) { showWarning(e->getWarnings(),GUI_WARN_GENERIC); } + pushRecentFile(path); return 0; } +void FurnaceGUI::pushRecentFile(String path) { + if (path.empty()) return; + if (path==backupPath) return; + for (int i=0; i<(int)recentFile.size(); i++) { + if (recentFile[i]==path) { + recentFile.erase(recentFile.begin()+i); + i--; + } + } + recentFile.push_front(path); + + while (!recentFile.empty() && (int)recentFile.size()>settings.maxRecentFile) { + recentFile.pop_back(); + } +} + void FurnaceGUI::exportAudio(String path, DivAudioExportModes mode) { e->saveAudio(path.c_str(),exportLoops+1,mode,exportFadeOut); displayExporting=true; @@ -3045,6 +3064,27 @@ bool FurnaceGUI::loop() { openFileDialog(GUI_FILE_OPEN); } } + if (ImGui::BeginMenu("open recent")) { + for (int i=0; i<(int)recentFile.size(); i++) { + String item=recentFile[i]; + if (ImGui::MenuItem(item.c_str())) { + if (modified) { + nextFile=item; + showWarning("Unsaved changes! Save changes before opening file?",GUI_WARN_OPEN_DROP); + } else { + recentFile.erase(recentFile.begin()+i); + i--; + if (load(item)>0) { + showError(fmt::sprintf("Error while loading file! (%s)",lastError)); + } + } + } + } + if (recentFile.empty()) { + ImGui::Text("nothing here yet"); + } + ImGui::EndMenu(); + } ImGui::Separator(); if (ImGui::MenuItem("save",BIND_FOR(GUI_ACTION_SAVE))) { if (curFileName=="" || curFileName==backupPath || e->song.version>=0xff00) { @@ -4628,6 +4668,13 @@ bool FurnaceGUI::init() { syncSettings(); + for (int i=0; igetConfString(fmt::sprintf("recentFile%d",i),""); + if (!r.empty()) { + recentFile.push_back(r); + } + } + if (settings.dpiScale>=0.5f) { dpiScale=settings.dpiScale; } @@ -4900,6 +4947,16 @@ bool FurnaceGUI::finish() { e->setConf("chanOscUseGrad",chanOscUseGrad); e->setConf("chanOscGrad",chanOscGrad.toString()); + // commit recent files + for (int i=0; i<30; i++) { + String key=fmt::sprintf("recentFile%d",i); + if (i>=settings.maxRecentFile || i>=(int)recentFile.size()) { + e->setConf(key,""); + } else { + e->setConf(key,recentFile[i]); + } + } + for (int i=0; i sysSearchResults; std::vector newSongSearchResults; + std::deque recentFile; bool quit, warnQuit, willCommit, edit, modified, displayError, displayExporting, vgmExportLoop, vgmExportPatternHints; bool portrait, mobileMenuOpen; @@ -1171,6 +1172,7 @@ class FurnaceGUI { int channelStyle; int channelVolStyle; int channelFeedbackStyle; + int maxRecentFile; unsigned int maxUndoSteps; String mainFontPath; String patFontPath; @@ -1291,6 +1293,7 @@ class FurnaceGUI { channelStyle(0), channelVolStyle(0), channelFeedbackStyle(1), + maxRecentFile(10), maxUndoSteps(100), mainFontPath(""), patFontPath(""), @@ -1728,6 +1731,7 @@ class FurnaceGUI { void openFileDialog(FurnaceGUIFileDialogs type); int save(String path, int dmfVersion); int load(String path); + void pushRecentFile(String path); void exportAudio(String path, DivAudioExportModes mode); bool parseSysEx(unsigned char* data, size_t len); diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index 53ce0cdeb..54da8e893 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -1130,6 +1130,13 @@ void FurnaceGUI::drawSettings() { ImGui::Separator(); + if (ImGui::InputInt("Number of recent files",&settings.maxRecentFile)) { + if (settings.maxRecentFile<0) settings.maxRecentFile=0; + if (settings.maxRecentFile>30) settings.maxRecentFile=30; + } + + ImGui::Separator(); + ImGui::Text("Pattern view labels:"); ImGui::InputTextWithHint("Note off (3-char)","OFF",&settings.noteOffLabel); ImGui::InputTextWithHint("Note release (3-char)","===",&settings.noteRelLabel); @@ -2273,6 +2280,7 @@ void FurnaceGUI::syncSettings() { settings.channelStyle=e->getConfInt("channelStyle",0); settings.channelVolStyle=e->getConfInt("channelVolStyle",0); settings.channelFeedbackStyle=e->getConfInt("channelFeedbackStyle",1); + settings.maxRecentFile=e->getConfInt("maxRecentFile",10); clampSetting(settings.mainFontSize,2,96); clampSetting(settings.patFontSize,2,96); @@ -2371,6 +2379,7 @@ void FurnaceGUI::syncSettings() { clampSetting(settings.channelStyle,0,5); clampSetting(settings.channelVolStyle,0,3); clampSetting(settings.channelFeedbackStyle,0,3); + clampSetting(settings.maxRecentFile,0,30); settings.initialSys=e->decodeSysDesc(e->getConfString("initialSys","")); if (settings.initialSys.size()<4) { @@ -2403,7 +2412,7 @@ void FurnaceGUI::syncSettings() { } void FurnaceGUI::commitSettings() { - bool sampleROMsChanged = settings.yrw801Path!=e->getConfString("yrw801Path","") || + bool sampleROMsChanged=settings.yrw801Path!=e->getConfString("yrw801Path","") || settings.tg100Path!=e->getConfString("tg100Path","") || settings.mu5Path!=e->getConfString("mu5Path",""); @@ -2525,6 +2534,7 @@ void FurnaceGUI::commitSettings() { e->setConf("channelStyle",settings.channelStyle); e->setConf("channelVolStyle",settings.channelVolStyle); e->setConf("channelFeedbackStyle",settings.channelFeedbackStyle); + e->setConf("maxRecentFile",settings.maxRecentFile); // colors for (int i=0; isaveConf(); + while (!recentFile.empty() && (int)recentFile.size()>settings.maxRecentFile) { + recentFile.pop_back(); + } + if (sampleROMsChanged) { if (e->loadSampleROMs()) { showError(e->getLastError());