diff --git a/include/app/ModuleWidget.hpp b/include/app/ModuleWidget.hpp index c3d5db2c..c6d4aa74 100644 --- a/include/app/ModuleWidget.hpp +++ b/include/app/ModuleWidget.hpp @@ -112,7 +112,6 @@ struct ModuleWidget : widget::OpaqueWidget { /** Deletes `this` */ void removeAction(); void createContextMenu(); - void createSelectionContextMenu(); INTERNAL math::Vec& dragOffset(); INTERNAL bool& dragEnabled(); diff --git a/include/app/RackWidget.hpp b/include/app/RackWidget.hpp index bf3c3196..cd6780c8 100644 --- a/include/app/RackWidget.hpp +++ b/include/app/RackWidget.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -70,6 +71,8 @@ struct RackWidget : widget::OpaqueWidget { void updateModuleOldPositions(); history::ComplexAction* getModuleDragAction(); + // Module selection methods + void updateModuleSelections(); void clearModuleSelections(); bool hasSelectedModules(); @@ -82,6 +85,7 @@ struct RackWidget : widget::OpaqueWidget { bool areSelectedModulesBypassed(); void deleteSelectedModulesAction(); bool requestSelectedModulePos(math::Vec delta); + void appendSelectionContextMenu(ui::Menu* menu); // Cable methods diff --git a/src/app/MenuBar.cpp b/src/app/MenuBar.cpp index af54e54b..f402747a 100644 --- a/src/app/MenuBar.cpp +++ b/src/app/MenuBar.cpp @@ -215,6 +215,11 @@ struct EditButton : MenuButton { disconnectCablesItem->text = "Clear cables"; menu->addChild(disconnectCablesItem); + if (APP->scene->rack->hasSelectedModules()) { + menu->addChild(new ui::MenuSeparator); + APP->scene->rack->appendSelectionContextMenu(menu); + } + menu->addChild(new ui::MenuSeparator); AllowCursorLockItem* allowCursorLockItem = new AllowCursorLockItem; diff --git a/src/app/ModuleWidget.cpp b/src/app/ModuleWidget.cpp index 30cd674b..de839607 100644 --- a/src/app/ModuleWidget.cpp +++ b/src/app/ModuleWidget.cpp @@ -389,7 +389,8 @@ void ModuleWidget::onButton(const ButtonEvent& e) { // Open context menu on right-click if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) { if (internal->selected) { - createSelectionContextMenu(); + ui::Menu* menu = createMenu(); + APP->scene->rack->appendSelectionContextMenu(menu); } else { createContextMenu(); @@ -1085,47 +1086,6 @@ void ModuleWidget::createContextMenu() { appendContextMenu(menu); } -void ModuleWidget::createSelectionContextMenu() { - ui::Menu* menu = createMenu(); - - int n = APP->scene->rack->getNumSelectedModules(); - menu->addChild(createMenuLabel(string::f("%d selected %s", n, n == 1 ? "module" : "modules"))); - - // Deselect - menu->addChild(createMenuItem("Deselect", "", [=]() { - APP->scene->rack->clearModuleSelections(); - })); - - // Initialize - menu->addChild(createMenuItem("Initialize", RACK_MOD_CTRL_NAME "+I", [=]() { - APP->scene->rack->resetSelectedModulesAction(); - })); - - // Randomize - menu->addChild(createMenuItem("Randomize", RACK_MOD_CTRL_NAME "+R", [=]() { - APP->scene->rack->randomizeSelectedModulesAction(); - })); - - // Disconnect cables - menu->addChild(createMenuItem("Disconnect cables", RACK_MOD_CTRL_NAME "+U", [=]() { - APP->scene->rack->disconnectSelectedModulesAction(); - })); - - // Bypass - std::string bypassText = RACK_MOD_CTRL_NAME "+E"; - bool bypassed = APP->scene->rack->areSelectedModulesBypassed(); - if (bypassed) - bypassText += " " CHECKMARK_STRING; - menu->addChild(createMenuItem("Bypass", bypassText, [=]() { - APP->scene->rack->bypassSelectedModulesAction(!bypassed); - })); - - // Delete - menu->addChild(createMenuItem("Delete", "Backspace/Delete", [=]() { - APP->scene->rack->deleteSelectedModulesAction(); - })); -} - math::Vec& ModuleWidget::dragOffset() { return internal->dragOffset; } diff --git a/src/app/RackWidget.cpp b/src/app/RackWidget.cpp index 48b0542d..c4a732f2 100644 --- a/src/app/RackWidget.cpp +++ b/src/app/RackWidget.cpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace rack { @@ -828,6 +829,45 @@ bool RackWidget::requestSelectedModulePos(math::Vec delta) { return true; } +void RackWidget::appendSelectionContextMenu(ui::Menu* menu) { + int n = getNumSelectedModules(); + menu->addChild(createMenuLabel(string::f("%d selected %s", n, n == 1 ? "module" : "modules"))); + + // Deselect + menu->addChild(createMenuItem("Deselect", "", [=]() { + clearModuleSelections(); + })); + + // Initialize + menu->addChild(createMenuItem("Initialize", RACK_MOD_CTRL_NAME "+I", [=]() { + resetSelectedModulesAction(); + })); + + // Randomize + menu->addChild(createMenuItem("Randomize", RACK_MOD_CTRL_NAME "+R", [=]() { + randomizeSelectedModulesAction(); + })); + + // Disconnect cables + menu->addChild(createMenuItem("Disconnect cables", RACK_MOD_CTRL_NAME "+U", [=]() { + disconnectSelectedModulesAction(); + })); + + // Bypass + std::string bypassText = RACK_MOD_CTRL_NAME "+E"; + bool bypassed = areSelectedModulesBypassed(); + if (bypassed) + bypassText += " " CHECKMARK_STRING; + menu->addChild(createMenuItem("Bypass", bypassText, [=]() { + bypassSelectedModulesAction(!bypassed); + })); + + // Delete + menu->addChild(createMenuItem("Delete", "Backspace/Delete", [=]() { + deleteSelectedModulesAction(); + })); +} + void RackWidget::clearCables() { incompleteCable = NULL; internal->cableContainer->clearChildren();