diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bb4b1f7..22264b78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ In this document, Ctrl means Cmd on Mac. +### 2.5.2 (in development) +- Add configurable cable color labels. + ### 2.5.1 (2024-04-16) - Remember the last selected cable color from the port's "New cable" menu item. When "Auto-rotate cables" is enabled, the next color in the rotation is used. - Fix crash when modules such as VCV MIDI-Map bind parameters. diff --git a/dep/osdialog b/dep/osdialog index 56259696..64482bde 160000 --- a/dep/osdialog +++ b/dep/osdialog @@ -1 +1 @@ -Subproject commit 562596968dbd07c67ad8d9d57ec5ff54bc827a9b +Subproject commit 64482bde25a8e19cc38342ed21aa0e38c2751f6c diff --git a/include/settings.hpp b/include/settings.hpp index db8456c4..9783e933 100644 --- a/include/settings.hpp +++ b/include/settings.hpp @@ -77,6 +77,7 @@ extern float autosaveInterval; extern bool skipLoadOnLaunch; extern std::list recentPatchPaths; extern std::vector cableColors; +extern std::vector cableLabels; extern bool cableAutoRotate; extern bool autoCheckUpdates; extern bool verifyHttpsCerts; @@ -118,7 +119,7 @@ struct PluginWhitelist { extern std::map moduleWhitelist; bool isModuleWhitelisted(const std::string& pluginSlug, const std::string& moduleSlug); -void cableColorsReset(); +void resetCables(); PRIVATE void init(); PRIVATE void destroy(); diff --git a/src/app/MenuBar.cpp b/src/app/MenuBar.cpp index a9a2edf4..5f3b79f0 100644 --- a/src/app/MenuBar.cpp +++ b/src/app/MenuBar.cpp @@ -468,49 +468,88 @@ struct ViewButton : MenuButton { // Add color items for (size_t i = 0; i < settings::cableColors.size(); i++) { NVGcolor color = settings::cableColors[i]; - ui::ColorDotMenuItem* item = createSubmenuItem(string::uppercase(color::toHexString(color)), "", [=](ui::Menu* menu) { + std::string label = get(settings::cableLabels, i); + std::string labelFallback = (label != "") ? label : string::f("Color #%lld", (long long) (i + 1)); + + ui::ColorDotMenuItem* item = createSubmenuItem(labelFallback, "", [=](ui::Menu* menu) { // Helper for launching color dialog - auto selectColor = [](NVGcolor color) { + auto selectColor = [](NVGcolor& color) -> bool { osdialog_color c = { uint8_t(color.r * 255.f), uint8_t(color.g * 255.f), uint8_t(color.b * 255.f), uint8_t(color.a * 255.f), }; - osdialog_color_picker(&c, false); - return nvgRGBA(c.r, c.g, c.b, c.a); + if (!osdialog_color_picker(&c, false)) + return false; + color = nvgRGBA(c.r, c.g, c.b, c.a); + return true; }; + menu->addChild(createMenuItem("Set label", "", [=]() { + if (i >= settings::cableColors.size()) + return; + char* s = osdialog_prompt(OSDIALOG_INFO, "", label.c_str()); + if (!s) + return; + settings::cableLabels.resize(settings::cableColors.size()); + settings::cableLabels[i] = s; + free(s); + }, false, true)); + menu->addChild(createMenuItem("Set color", "", [=]() { if (i >= settings::cableColors.size()) return; - NVGcolor newColor = selectColor(color); + NVGcolor newColor = color; + if (!selectColor(newColor)) + return; std::memcpy(&settings::cableColors[i], &newColor, sizeof(newColor)); }, false, true)); + menu->addChild(createMenuItem("New color above", "", [=]() { if (i >= settings::cableColors.size()) return; - settings::cableColors.insert(settings::cableColors.begin() + i, selectColor(color)); + NVGcolor newColor = color; + if (!selectColor(newColor)) + return; + settings::cableLabels.resize(settings::cableColors.size()); + settings::cableColors.insert(settings::cableColors.begin() + i, newColor); + settings::cableLabels.insert(settings::cableLabels.begin() + i, ""); }, false, true)); + menu->addChild(createMenuItem("New color below", "", [=]() { if (i >= settings::cableColors.size()) return; - settings::cableColors.insert(settings::cableColors.begin() + i + 1, selectColor(color)); + NVGcolor newColor = color; + if (!selectColor(newColor)) + return; + settings::cableLabels.resize(settings::cableColors.size()); + settings::cableColors.insert(settings::cableColors.begin() + i + 1, newColor); + settings::cableLabels.insert(settings::cableLabels.begin() + i + 1, ""); }, false, true)); + menu->addChild(createMenuItem("Move up", "", [=]() { if (i < 1 || i >= settings::cableColors.size()) return; + settings::cableLabels.resize(settings::cableColors.size()); std::swap(settings::cableColors[i], settings::cableColors[i - 1]); + std::swap(settings::cableLabels[i], settings::cableLabels[i - 1]); }, i < 1, true)); + menu->addChild(createMenuItem("Move down", "", [=]() { if (i + 1 >= settings::cableColors.size()) return; + settings::cableLabels.resize(settings::cableColors.size()); std::swap(settings::cableColors[i], settings::cableColors[i + 1]); + std::swap(settings::cableLabels[i], settings::cableLabels[i + 1]); }, i + 1 >= settings::cableColors.size())); + menu->addChild(createMenuItem("Delete", "", [=]() { if (i >= settings::cableColors.size()) return; + settings::cableLabels.resize(settings::cableColors.size()); settings::cableColors.erase(settings::cableColors.begin() + i); + settings::cableLabels.erase(settings::cableLabels.begin() + i); }, settings::cableColors.size() <= 1, true)); }); item->color = color; @@ -528,7 +567,7 @@ struct ViewButton : MenuButton { menu->addChild(createMenuItem("Restore factory colors", "", [=]() { if (!osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK_CANCEL, "Overwrite colors with factory defaults?")) return; - settings::cableColorsReset(); + settings::resetCables(); }, false, true)); })); diff --git a/src/app/PortWidget.cpp b/src/app/PortWidget.cpp index 87f6de3d..0b68aae5 100644 --- a/src/app/PortWidget.cpp +++ b/src/app/PortWidget.cpp @@ -263,8 +263,10 @@ void PortWidget::createContextMenu() { // New cable items for (size_t colorId = 0; colorId < settings::cableColors.size(); colorId++) { NVGcolor color = settings::cableColors[colorId]; - // Include extra leading spaces for the color circle - PortCreateCableItem* item = createMenuItem("New cable", "Click+drag"); + std::string label = get(settings::cableLabels, colorId); + if (label == "") + label = string::f("Color #%lld", (long long) (colorId + 1)); + PortCreateCableItem* item = createMenuItem(label, "Click+drag"); item->pw = this; item->color = color; item->colorId = colorId; diff --git a/src/settings.cpp b/src/settings.cpp index b964e8cf..c75bac99 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -55,6 +55,7 @@ bool skipLoadOnLaunch = false; std::list recentPatchPaths; bool cableAutoRotate = true; std::vector cableColors; +std::vector cableLabels; bool autoCheckUpdates = true; bool verifyHttpsCerts = true; bool showTipsOnLaunch = true; @@ -94,7 +95,7 @@ bool isModuleWhitelisted(const std::string& pluginSlug, const std::string& modul } -void cableColorsReset() { +void resetCables() { cableColors = { color::fromHexString("#f3374b"), // red color::fromHexString("#ffb437"), // yellow @@ -102,12 +103,14 @@ void cableColorsReset() { color::fromHexString("#3695ef"), // blue color::fromHexString("#8b4ade"), // purple }; + cableLabels.clear(); + cableLabels.resize(cableColors.size()); } void init() { settingsPath = asset::user("settings.json"); - cableColorsReset(); + resetCables(); } @@ -187,12 +190,18 @@ json_t* toJson() { json_object_set_new(rootJ, "recentPatchPaths", recentPatchPathsJ); json_t* cableColorsJ = json_array(); - for (NVGcolor cableColor : cableColors) { + for (const NVGcolor& cableColor : cableColors) { std::string colorStr = color::toHexString(cableColor); json_array_append_new(cableColorsJ, json_string(colorStr.c_str())); } json_object_set_new(rootJ, "cableColors", cableColorsJ); + json_t* cableLabelsJ = json_array(); + for (const std::string& cableLabel : cableLabels) { + json_array_append_new(cableLabelsJ, json_string(cableLabel.c_str())); + } + json_object_set_new(rootJ, "cableLabels", cableLabelsJ); + json_object_set_new(rootJ, "cableAutoRotate", json_boolean(cableAutoRotate)); json_object_set_new(rootJ, "autoCheckUpdates", json_boolean(autoCheckUpdates)); @@ -419,6 +428,16 @@ void fromJson(json_t* rootJ) { } } + cableLabels.clear(); + json_t* cableLabelsJ = json_object_get(rootJ, "cableLabels"); + if (cableLabelsJ) { + size_t i; + json_t* cableLabelJ; + json_array_foreach(cableLabelsJ, i, cableLabelJ) { + cableLabels.push_back(json_string_value(cableLabelJ)); + } + } + json_t* cableAutoRotateJ = json_object_get(rootJ, "cableAutoRotate"); if (cableAutoRotateJ) cableAutoRotate = json_boolean_value(cableAutoRotateJ);