Custom selection menu, so we can use async dialogs
Closes #85 Signed-off-by: falkTX <falktx@falktx.com>
This commit is contained in:
parent
2de11d4a24
commit
df6df767a4
3 changed files with 156 additions and 16 deletions
|
@ -19,6 +19,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
namespace rack
|
||||||
|
{
|
||||||
|
namespace ui {
|
||||||
|
struct Menu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace patchUtils
|
namespace patchUtils
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -28,5 +35,6 @@ void loadTemplateDialog();
|
||||||
void revertDialog();
|
void revertDialog();
|
||||||
void saveDialog(const std::string& path);
|
void saveDialog(const std::string& path);
|
||||||
void saveAsDialog();
|
void saveAsDialog();
|
||||||
|
void appendSelectionContextMenu(rack::ui::Menu* menu);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,9 +31,12 @@
|
||||||
#include <plugin/Model.hpp>
|
#include <plugin/Model.hpp>
|
||||||
#undef ModuleWidget
|
#undef ModuleWidget
|
||||||
|
|
||||||
|
#include "CardinalCommon.hpp"
|
||||||
|
|
||||||
#include <app/Scene.hpp>
|
#include <app/Scene.hpp>
|
||||||
#include <engine/Engine.hpp>
|
#include <engine/Engine.hpp>
|
||||||
#include <ui/MenuSeparator.hpp>
|
#include <ui/MenuSeparator.hpp>
|
||||||
|
#include <asset.hpp>
|
||||||
#include <context.hpp>
|
#include <context.hpp>
|
||||||
#include <helpers.hpp>
|
#include <helpers.hpp>
|
||||||
#include <system.hpp>
|
#include <system.hpp>
|
||||||
|
@ -133,31 +136,31 @@ static void CardinalModuleWidget__createContextMenu(ModuleWidget* const w,
|
||||||
menu->addChild(createMenuLabel(model->plugin->brand));
|
menu->addChild(createMenuLabel(model->plugin->brand));
|
||||||
|
|
||||||
// Info
|
// Info
|
||||||
menu->addChild(createSubmenuItem("Info", "", [=](ui::Menu* menu) {
|
menu->addChild(createSubmenuItem("Info", "", [model](ui::Menu* menu) {
|
||||||
model->appendContextMenu(menu);
|
model->appendContextMenu(menu);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Preset
|
// Preset
|
||||||
menu->addChild(createSubmenuItem("Preset", "", [=](ui::Menu* menu) {
|
menu->addChild(createSubmenuItem("Preset", "", [weakThis](ui::Menu* menu) {
|
||||||
menu->addChild(createMenuItem("Copy", RACK_MOD_CTRL_NAME "+C", [=]() {
|
menu->addChild(createMenuItem("Copy", RACK_MOD_CTRL_NAME "+C", [weakThis]() {
|
||||||
if (!weakThis)
|
if (!weakThis)
|
||||||
return;
|
return;
|
||||||
weakThis->copyClipboard();
|
weakThis->copyClipboard();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
menu->addChild(createMenuItem("Paste", RACK_MOD_CTRL_NAME "+V", [=]() {
|
menu->addChild(createMenuItem("Paste", RACK_MOD_CTRL_NAME "+V", [weakThis]() {
|
||||||
if (!weakThis)
|
if (!weakThis)
|
||||||
return;
|
return;
|
||||||
weakThis->pasteClipboardAction();
|
weakThis->pasteClipboardAction();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
menu->addChild(createMenuItem("Open", "", [=]() {
|
menu->addChild(createMenuItem("Open", "", [weakThis]() {
|
||||||
if (!weakThis)
|
if (!weakThis)
|
||||||
return;
|
return;
|
||||||
CardinalModuleWidget__loadDialog(weakThis);
|
CardinalModuleWidget__loadDialog(weakThis);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
menu->addChild(createMenuItem("Save as", "", [=]() {
|
menu->addChild(createMenuItem("Save as", "", [weakThis]() {
|
||||||
if (!weakThis)
|
if (!weakThis)
|
||||||
return;
|
return;
|
||||||
CardinalModuleWidget__saveDialog(weakThis);
|
CardinalModuleWidget__saveDialog(weakThis);
|
||||||
|
@ -177,21 +180,21 @@ static void CardinalModuleWidget__createContextMenu(ModuleWidget* const w,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
menu->addChild(createMenuItem("Initialize", RACK_MOD_CTRL_NAME "+I", [=]() {
|
menu->addChild(createMenuItem("Initialize", RACK_MOD_CTRL_NAME "+I", [weakThis]() {
|
||||||
if (!weakThis)
|
if (!weakThis)
|
||||||
return;
|
return;
|
||||||
weakThis->resetAction();
|
weakThis->resetAction();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Randomize
|
// Randomize
|
||||||
menu->addChild(createMenuItem("Randomize", RACK_MOD_CTRL_NAME "+R", [=]() {
|
menu->addChild(createMenuItem("Randomize", RACK_MOD_CTRL_NAME "+R", [weakThis]() {
|
||||||
if (!weakThis)
|
if (!weakThis)
|
||||||
return;
|
return;
|
||||||
weakThis->randomizeAction();
|
weakThis->randomizeAction();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Disconnect cables
|
// Disconnect cables
|
||||||
menu->addChild(createMenuItem("Disconnect cables", RACK_MOD_CTRL_NAME "+U", [=]() {
|
menu->addChild(createMenuItem("Disconnect cables", RACK_MOD_CTRL_NAME "+U", [weakThis]() {
|
||||||
if (!weakThis)
|
if (!weakThis)
|
||||||
return;
|
return;
|
||||||
weakThis->disconnectAction();
|
weakThis->disconnectAction();
|
||||||
|
@ -202,28 +205,28 @@ static void CardinalModuleWidget__createContextMenu(ModuleWidget* const w,
|
||||||
bool bypassed = module && module->isBypassed();
|
bool bypassed = module && module->isBypassed();
|
||||||
if (bypassed)
|
if (bypassed)
|
||||||
bypassText += " " CHECKMARK_STRING;
|
bypassText += " " CHECKMARK_STRING;
|
||||||
menu->addChild(createMenuItem("Bypass", bypassText, [=]() {
|
menu->addChild(createMenuItem("Bypass", bypassText, [weakThis, bypassed]() {
|
||||||
if (!weakThis)
|
if (!weakThis)
|
||||||
return;
|
return;
|
||||||
weakThis->bypassAction(!bypassed);
|
weakThis->bypassAction(!bypassed);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Duplicate
|
// Duplicate
|
||||||
menu->addChild(createMenuItem("Duplicate", RACK_MOD_CTRL_NAME "+D", [=]() {
|
menu->addChild(createMenuItem("Duplicate", RACK_MOD_CTRL_NAME "+D", [weakThis]() {
|
||||||
if (!weakThis)
|
if (!weakThis)
|
||||||
return;
|
return;
|
||||||
weakThis->cloneAction(false);
|
weakThis->cloneAction(false);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Duplicate with cables
|
// Duplicate with cables
|
||||||
menu->addChild(createMenuItem("└ with cables", RACK_MOD_SHIFT_NAME "+" RACK_MOD_CTRL_NAME "+D", [=]() {
|
menu->addChild(createMenuItem("└ with cables", RACK_MOD_SHIFT_NAME "+" RACK_MOD_CTRL_NAME "+D", [weakThis]() {
|
||||||
if (!weakThis)
|
if (!weakThis)
|
||||||
return;
|
return;
|
||||||
weakThis->cloneAction(true);
|
weakThis->cloneAction(true);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Delete
|
// Delete
|
||||||
menu->addChild(createMenuItem("Delete", "Backspace/Delete", [=]() {
|
menu->addChild(createMenuItem("Delete", "Backspace/Delete", [weakThis]() {
|
||||||
if (!weakThis)
|
if (!weakThis)
|
||||||
return;
|
return;
|
||||||
weakThis->removeAction();
|
weakThis->removeAction();
|
||||||
|
@ -232,6 +235,50 @@ static void CardinalModuleWidget__createContextMenu(ModuleWidget* const w,
|
||||||
w->appendContextMenu(menu);
|
w->appendContextMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void CardinalModuleWidget__loadSelectionDialog(RackWidget* const w)
|
||||||
|
{
|
||||||
|
std::string selectionDir = asset::user("selections");
|
||||||
|
system::createDirectories(selectionDir);
|
||||||
|
|
||||||
|
async_dialog_filebrowser(false, selectionDir.c_str(), "Import selection", [w](char* pathC) {
|
||||||
|
if (!pathC) {
|
||||||
|
// No path selected
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
w->loadSelection(pathC);
|
||||||
|
}
|
||||||
|
catch (Exception& e) {
|
||||||
|
async_dialog_message(e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::free(pathC);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CardinalModuleWidget__saveSelectionDialog(RackWidget* const w)
|
||||||
|
{
|
||||||
|
std::string selectionDir = asset::user("selections");
|
||||||
|
system::createDirectories(selectionDir);
|
||||||
|
|
||||||
|
async_dialog_filebrowser(true, selectionDir.c_str(), "Save selection as", [w](char* pathC) {
|
||||||
|
if (!pathC) {
|
||||||
|
// No path selected
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string path = pathC;
|
||||||
|
std::free(pathC);
|
||||||
|
|
||||||
|
// Automatically append .vcvs extension
|
||||||
|
if (system::getExtension(path) != ".vcvs")
|
||||||
|
path += ".vcvs";
|
||||||
|
|
||||||
|
w->saveSelection(path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void CardinalModuleWidget::onButton(const ButtonEvent& e)
|
void CardinalModuleWidget::onButton(const ButtonEvent& e)
|
||||||
{
|
{
|
||||||
bool selected = APP->scene->rack->isSelected(this);
|
bool selected = APP->scene->rack->isSelected(this);
|
||||||
|
@ -239,8 +286,7 @@ void CardinalModuleWidget::onButton(const ButtonEvent& e)
|
||||||
if (selected) {
|
if (selected) {
|
||||||
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) {
|
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) {
|
||||||
ui::Menu* menu = createMenu();
|
ui::Menu* menu = createMenu();
|
||||||
// TODO customize this one too
|
patchUtils::appendSelectionContextMenu(menu);
|
||||||
APP->scene->rack->appendSelectionContextMenu(menu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e.consume(this);
|
e.consume(this);
|
||||||
|
@ -270,3 +316,89 @@ void CardinalModuleWidget::onButton(const ButtonEvent& e)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace patchUtils
|
||||||
|
{
|
||||||
|
|
||||||
|
using namespace rack;
|
||||||
|
|
||||||
|
void appendSelectionContextMenu(ui::Menu* const menu)
|
||||||
|
{
|
||||||
|
app::RackWidget* const w = APP->scene->rack;
|
||||||
|
|
||||||
|
int n = w->getSelected().size();
|
||||||
|
menu->addChild(createMenuLabel(string::f("%d selected %s", n, n == 1 ? "module" : "modules")));
|
||||||
|
|
||||||
|
// Enable alwaysConsume of menu items if the number of selected modules changes
|
||||||
|
|
||||||
|
// Select all
|
||||||
|
menu->addChild(createMenuItem("Select all", RACK_MOD_CTRL_NAME "+A", [w]() {
|
||||||
|
w->selectAll();
|
||||||
|
}, false, true));
|
||||||
|
|
||||||
|
// Deselect
|
||||||
|
menu->addChild(createMenuItem("Deselect", RACK_MOD_CTRL_NAME "+" RACK_MOD_SHIFT_NAME "+A", [w]() {
|
||||||
|
w->deselectAll();
|
||||||
|
}, n == 0, true));
|
||||||
|
|
||||||
|
// Copy
|
||||||
|
menu->addChild(createMenuItem("Copy", RACK_MOD_CTRL_NAME "+C", [w]() {
|
||||||
|
w->copyClipboardSelection();
|
||||||
|
}, n == 0));
|
||||||
|
|
||||||
|
// Paste
|
||||||
|
menu->addChild(createMenuItem("Paste", RACK_MOD_CTRL_NAME "+V", [w]() {
|
||||||
|
w->pasteClipboardAction();
|
||||||
|
}, false, true));
|
||||||
|
|
||||||
|
// Load
|
||||||
|
menu->addChild(createMenuItem("Import selection", "", [w]() {
|
||||||
|
CardinalModuleWidget__loadSelectionDialog(w);
|
||||||
|
}, false, true));
|
||||||
|
|
||||||
|
// Save
|
||||||
|
menu->addChild(createMenuItem("Save selection as", "", [w]() {
|
||||||
|
CardinalModuleWidget__saveSelectionDialog(w);
|
||||||
|
}, n == 0));
|
||||||
|
|
||||||
|
// Initialize
|
||||||
|
menu->addChild(createMenuItem("Initialize", RACK_MOD_CTRL_NAME "+I", [w]() {
|
||||||
|
w->resetSelectionAction();
|
||||||
|
}, n == 0));
|
||||||
|
|
||||||
|
// Randomize
|
||||||
|
menu->addChild(createMenuItem("Randomize", RACK_MOD_CTRL_NAME "+R", [w]() {
|
||||||
|
w->randomizeSelectionAction();
|
||||||
|
}, n == 0));
|
||||||
|
|
||||||
|
// Disconnect cables
|
||||||
|
menu->addChild(createMenuItem("Disconnect cables", RACK_MOD_CTRL_NAME "+U", [w]() {
|
||||||
|
w->disconnectSelectionAction();
|
||||||
|
}, n == 0));
|
||||||
|
|
||||||
|
// Bypass
|
||||||
|
std::string bypassText = RACK_MOD_CTRL_NAME "+E";
|
||||||
|
bool bypassed = (n > 0) && w->isSelectionBypassed();
|
||||||
|
if (bypassed)
|
||||||
|
bypassText += " " CHECKMARK_STRING;
|
||||||
|
menu->addChild(createMenuItem("Bypass", bypassText, [w, bypassed]() {
|
||||||
|
w->bypassSelectionAction(!bypassed);
|
||||||
|
}, n == 0, true));
|
||||||
|
|
||||||
|
// Duplicate
|
||||||
|
menu->addChild(createMenuItem("Duplicate", RACK_MOD_CTRL_NAME "+D", [w]() {
|
||||||
|
w->cloneSelectionAction(false);
|
||||||
|
}, n == 0));
|
||||||
|
|
||||||
|
// Duplicate with cables
|
||||||
|
menu->addChild(createMenuItem("└ with cables", RACK_MOD_SHIFT_NAME "+" RACK_MOD_CTRL_NAME "+D", [w]() {
|
||||||
|
w->cloneSelectionAction(true);
|
||||||
|
}, n == 0));
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
menu->addChild(createMenuItem("Delete", "Backspace/Delete", [w]() {
|
||||||
|
w->deleteSelectionAction();
|
||||||
|
}, n == 0, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -235,7 +235,7 @@ struct EditButton : MenuButton {
|
||||||
|
|
||||||
menu->addChild(new ui::MenuSeparator);
|
menu->addChild(new ui::MenuSeparator);
|
||||||
|
|
||||||
APP->scene->rack->appendSelectionContextMenu(menu);
|
patchUtils::appendSelectionContextMenu(menu);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue