diff --git a/include/settings.hpp b/include/settings.hpp index df1c6ec1..28dc2abc 100644 --- a/include/settings.hpp +++ b/include/settings.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,7 @@ extern int frameSwapInterval; extern float autosavePeriod; extern bool skipLoadOnLaunch; extern std::string patchPath; +extern std::list recentPatchPaths; extern std::vector cableColors; // pluginSlug -> moduleSlugs extern std::map> moduleWhitelist; diff --git a/src/app/MenuBar.cpp b/src/app/MenuBar.cpp index f14da2e5..c4d323b4 100644 --- a/src/app/MenuBar.cpp +++ b/src/app/MenuBar.cpp @@ -90,6 +90,28 @@ struct OpenItem : ui::MenuItem { } }; +struct OpenPathItem : ui::MenuItem { + std::string path; + void onAction(const event::Action& e) override { + APP->patch->loadPathDialog(path); + } +}; + +struct OpenRecentItem : ui::MenuItem { + ui::Menu* createChildMenu() override { + ui::Menu* menu = new ui::Menu; + + for (const std::string& path : settings::recentPatchPaths) { + OpenPathItem* item = new OpenPathItem; + item->text = string::filename(path); + item->path = path; + menu->addChild(item); + } + + return menu; + } +}; + struct SaveItem : ui::MenuItem { void onAction(const event::Action& e) override { APP->patch->saveDialog(); @@ -136,6 +158,11 @@ struct FileButton : MenuButton { openItem->rightText = RACK_MOD_CTRL_NAME "+O"; menu->addChild(openItem); + OpenRecentItem* openRecentItem = new OpenRecentItem; + openRecentItem->text = "Open recent"; + openRecentItem->rightText = RIGHT_ARROW; + menu->addChild(openRecentItem); + SaveItem* saveItem = new SaveItem; saveItem->text = "Save"; saveItem->rightText = RACK_MOD_CTRL_NAME "+S"; diff --git a/src/patch.cpp b/src/patch.cpp index eb8be637..43fa5a62 100644 --- a/src/patch.cpp +++ b/src/patch.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -47,7 +48,7 @@ void PatchManager::init(std::string path) { } // Load autosave - if (load(asset::autosavePath)) { + if (load("")) { return; } @@ -164,8 +165,10 @@ void PatchManager::saveTemplateDialog() { } bool PatchManager::load(std::string path) { - INFO("Loading patch %s", path.c_str()); - FILE* file = std::fopen(path.c_str(), "r"); + std::string actualPath = (path != "") ? path : asset::autosavePath; + + INFO("Loading patch %s", actualPath.c_str()); + FILE* file = std::fopen(actualPath.c_str(), "r"); if (!file) { // Exit silently return false; @@ -192,6 +195,18 @@ bool PatchManager::load(std::string path) { } APP->engine->clear(); fromJson(rootJ); + + // Update recent patches + if (path != "") { + auto& recent = settings::recentPatchPaths; + // Remove path from recent patches (if exists) + recent.erase(std::remove(recent.begin(), recent.end(), path), recent.end()); + // Add path to top of recent patches + recent.push_front(path); + // Limit recent patches size + recent.resize(std::min((int) recent.size(), 10)); + } + return true; } diff --git a/src/settings.cpp b/src/settings.cpp index dbe92849..4d3edf12 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -39,6 +39,7 @@ bool lockModules = false; float autosavePeriod = 15.0; bool skipLoadOnLaunch = false; std::string patchPath; +std::list recentPatchPaths; std::vector cableColors = { nvgRGB(0xc9, 0xb7, 0x0e), // yellow nvgRGB(0x0c, 0x8e, 0x15), // green @@ -92,6 +93,12 @@ json_t* toJson() { json_object_set_new(rootJ, "patchPath", json_string(patchPath.c_str())); + json_t* recentPatchPathsJ = json_array(); + for (const std::string& path : recentPatchPaths) { + json_array_append_new(recentPatchPathsJ, json_string(path.c_str())); + } + json_object_set_new(rootJ, "recentPatchPaths", recentPatchPathsJ); + json_t* cableColorsJ = json_array(); for (NVGcolor cableColor : cableColors) { std::string colorStr = color::toHexString(cableColor); @@ -195,6 +202,17 @@ void fromJson(json_t* rootJ) { if (patchPathJ) patchPath = json_string_value(patchPathJ); + recentPatchPaths.clear(); + json_t* recentPatchPathsJ = json_object_get(rootJ, "recentPatchPaths"); + if (recentPatchPathsJ) { + size_t i; + json_t* pathJ; + json_array_foreach(recentPatchPathsJ, i, pathJ) { + std::string path = json_string_value(pathJ); + recentPatchPaths.push_back(path); + } + } + cableColors.clear(); json_t* cableColorsJ = json_object_get(rootJ, "cableColors"); if (cableColorsJ) {