| @@ -112,7 +112,6 @@ struct ModuleWidget : widget::OpaqueWidget { | |||
| /** Deletes `this` */ | |||
| void removeAction(); | |||
| void createContextMenu(); | |||
| void createSelectionContextMenu(); | |||
| INTERNAL math::Vec& dragOffset(); | |||
| INTERNAL bool& dragEnabled(); | |||
| @@ -4,6 +4,7 @@ | |||
| #include <app/common.hpp> | |||
| #include <widget/OpaqueWidget.hpp> | |||
| #include <widget/FramebufferWidget.hpp> | |||
| #include <ui/Menu.hpp> | |||
| #include <app/RailWidget.hpp> | |||
| #include <app/ModuleWidget.hpp> | |||
| #include <app/CableWidget.hpp> | |||
| @@ -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 | |||
| @@ -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; | |||
| @@ -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; | |||
| } | |||
| @@ -15,6 +15,7 @@ | |||
| #include <context.hpp> | |||
| #include <asset.hpp> | |||
| #include <patch.hpp> | |||
| #include <helpers.hpp> | |||
| 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(); | |||