You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
4.7KB

  1. /*
  2. * DISTRHO Cardinal Plugin
  3. * Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 3 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the LICENSE file.
  16. */
  17. /**
  18. * This file is partially based on VCVRack's ModuleWidget.cpp
  19. * Copyright (C) 2016-2021 VCV.
  20. *
  21. * This program is free software: you can redistribute it and/or
  22. * modify it under the terms of the GNU General Public License as
  23. * published by the Free Software Foundation; either version 3 of
  24. * the License, or (at your option) any later version.
  25. */
  26. #include "CardinalCommon.hpp"
  27. #include <regex>
  28. #include <app/ModuleWidget.hpp>
  29. #include <app/RackWidget.hpp>
  30. #include <app/Scene.hpp>
  31. #include <engine/Engine.hpp>
  32. #include <ui/MenuSeparator.hpp>
  33. #include <asset.hpp>
  34. #include <context.hpp>
  35. #include <helpers.hpp>
  36. #include <settings.hpp>
  37. #include <system.hpp>
  38. #undef ModuleWidget
  39. namespace rack {
  40. namespace app {
  41. static void CardinalModuleWidget__saveSelectionDialog(RackWidget* const w)
  42. {
  43. std::string selectionDir = asset::user("selections");
  44. system::createDirectories(selectionDir);
  45. async_dialog_filebrowser(true, "selection.vcvs", selectionDir.c_str(),
  46. #ifdef DISTRHO_OS_WASM
  47. "Save selection",
  48. #else
  49. "Save selection as...",
  50. #endif
  51. [w](char* pathC) {
  52. if (!pathC) {
  53. // No path selected
  54. return;
  55. }
  56. std::string path = pathC;
  57. std::free(pathC);
  58. // Automatically append .vcvs extension
  59. if (system::getExtension(path) != ".vcvs")
  60. path += ".vcvs";
  61. w->saveSelection(path);
  62. });
  63. }
  64. }
  65. }
  66. namespace patchUtils
  67. {
  68. using namespace rack;
  69. void appendSelectionContextMenu(ui::Menu* const menu)
  70. {
  71. app::RackWidget* const w = APP->scene->rack;
  72. int n = w->getSelected().size();
  73. menu->addChild(createMenuLabel(string::f("%d selected %s", n, n == 1 ? "module" : "modules")));
  74. // Enable alwaysConsume of menu items if the number of selected modules changes
  75. // Select all
  76. menu->addChild(createMenuItem("Select all", RACK_MOD_CTRL_NAME "+A", [w]() {
  77. w->selectAll();
  78. }, false, true));
  79. // Deselect
  80. menu->addChild(createMenuItem("Deselect", RACK_MOD_CTRL_NAME "+" RACK_MOD_SHIFT_NAME "+A", [w]() {
  81. w->deselectAll();
  82. }, n == 0, true));
  83. // Copy
  84. menu->addChild(createMenuItem("Copy", RACK_MOD_CTRL_NAME "+C", [w]() {
  85. w->copyClipboardSelection();
  86. }, n == 0));
  87. // Paste
  88. menu->addChild(createMenuItem("Paste", RACK_MOD_CTRL_NAME "+V", [w]() {
  89. w->pasteClipboardAction();
  90. }, false, true));
  91. // Save
  92. menu->addChild(createMenuItem(
  93. #ifdef DISTRHO_OS_WASM
  94. "Save selection",
  95. #else
  96. "Save selection as...",
  97. #endif
  98. "", [w]() {
  99. CardinalModuleWidget__saveSelectionDialog(w);
  100. }, n == 0));
  101. // Initialize
  102. menu->addChild(createMenuItem("Initialize", RACK_MOD_CTRL_NAME "+I", [w]() {
  103. w->resetSelectionAction();
  104. }, n == 0));
  105. // Randomize
  106. menu->addChild(createMenuItem("Randomize", RACK_MOD_CTRL_NAME "+R", [w]() {
  107. w->randomizeSelectionAction();
  108. }, n == 0));
  109. // Disconnect cables
  110. menu->addChild(createMenuItem("Disconnect cables", RACK_MOD_CTRL_NAME "+U", [w]() {
  111. w->disconnectSelectionAction();
  112. }, n == 0));
  113. // Bypass
  114. std::string bypassText = RACK_MOD_CTRL_NAME "+E";
  115. bool bypassed = (n > 0) && w->isSelectionBypassed();
  116. if (bypassed)
  117. bypassText += " " CHECKMARK_STRING;
  118. menu->addChild(createMenuItem("Bypass", bypassText, [w, bypassed]() {
  119. w->bypassSelectionAction(!bypassed);
  120. }, n == 0, true));
  121. // Duplicate
  122. menu->addChild(createMenuItem("Duplicate", RACK_MOD_CTRL_NAME "+D", [w]() {
  123. w->cloneSelectionAction(false);
  124. }, n == 0));
  125. // Duplicate with cables
  126. menu->addChild(createMenuItem("└ with cables", RACK_MOD_SHIFT_NAME "+" RACK_MOD_CTRL_NAME "+D", [w]() {
  127. w->cloneSelectionAction(true);
  128. }, n == 0));
  129. // Delete
  130. menu->addChild(createMenuItem("Delete", "Backspace/Delete", [w]() {
  131. w->deleteSelectionAction();
  132. }, n == 0, true));
  133. }
  134. }