Browse Source

Refactor ParamWidget and ModuleWidget. Add context menu to ParamWidget on right-click.

tags/v1.0.0
Andrew Belt 6 years ago
parent
commit
f73dae1384
5 changed files with 412 additions and 340 deletions
  1. +25
    -17
      include/app/ModuleWidget.hpp
  2. +3
    -0
      include/app/ParamWidget.hpp
  3. +2
    -0
      include/window.hpp
  4. +273
    -274
      src/app/ModuleWidget.cpp
  5. +109
    -49
      src/app/ParamWidget.cpp

+ 25
- 17
include/app/ModuleWidget.hpp View File

@@ -30,16 +30,34 @@ struct ModuleWidget : OpaqueWidget {
}
~ModuleWidget();

void draw(NVGcontext *vg) override;
void drawShadow(NVGcontext *vg);

void onHover(const event::Hover &e) override;
void onButton(const event::Button &e) override;
void onHoverKey(const event::HoverKey &e) override;
void onDragStart(const event::DragStart &e) override;
void onDragEnd(const event::DragEnd &e) override;
void onDragMove(const event::DragMove &e) override;

/** Associates this ModuleWidget with the Module
Transfers ownership
*/
void setModule(Module *module);

/** Convenience functions for adding special widgets (calls addChild()) */
void addInput(PortWidget *input);
void addOutput(PortWidget *output);
void addParam(ParamWidget *param);
void setPanel(std::shared_ptr<SVG> svg);

/** Overriding these is deprecated.
Use Module::dataToJson() and dataFromJson() instead
*/
virtual json_t *toJson();
virtual void fromJson(json_t *rootJ);

/** Serializes/unserializes the module state */
void copyClipboard();
void pasteClipboard();
void load(std::string filename);
@@ -50,33 +68,23 @@ struct ModuleWidget : OpaqueWidget {
/** Disconnects cables from all ports
Called when the user clicks Disconnect Cables in the context menu.
*/
virtual void disconnect();
void disconnect();
/** Resets the parameters of the module and calls the Module's randomize().
Called when the user clicks Initialize in the context menu.
*/
virtual void reset();
/** Deprecated */
virtual void initialize() final {}
void reset();
/** Randomizes the parameters of the module and calls the Module's randomize().
Called when the user clicks Randomize in the context menu.
*/
virtual void randomize();
/** Do not subclass this to add context menu entries. Use appendContextMenu() instead */
virtual Menu *createContextMenu();
void randomize();

void removeAction();
void bypassAction();
void createContextMenu();
/** Override to add context menu entries to your subclass.
It is recommended to add a blank MenuEntry first for spacing.
*/
virtual void appendContextMenu(Menu *menu) {}

void draw(NVGcontext *vg) override;
void drawShadow(NVGcontext *vg);

void onHover(const event::Hover &e) override;
void onButton(const event::Button &e) override;
void onHoverKey(const event::HoverKey &e) override;
void onDragStart(const event::DragStart &e) override;
void onDragEnd(const event::DragEnd &e) override;
void onDragMove(const event::DragMove &e) override;
};




+ 3
- 0
include/app/ParamWidget.hpp View File

@@ -23,6 +23,9 @@ struct ParamWidget : OpaqueWidget {

/** For legacy patch loading */
void fromJson(json_t *rootJ);
void createParamField();
void createContextMenu();
void resetAction();
};




+ 2
- 0
include/window.hpp View File

@@ -20,6 +20,8 @@ Use this instead of GLFW_MOD_CONTROL, since Cmd should be used on Mac in place o
#define WINDOW_MOD_CTRL GLFW_MOD_CONTROL
#define WINDOW_MOD_CTRL_NAME "Ctrl"
#endif
#define WINDOW_MOD_SHIFT_NAME "Shift"
#define WINDOW_MOD_ALT_NAME "Alt"

/** Filters actual mod keys from the mod flags.
Use this if you don't care about GLFW_MOD_CAPS_LOCK and GLFW_MOD_NUM_LOCK.


+ 273
- 274
src/app/ModuleWidget.cpp View File

@@ -15,10 +15,267 @@
namespace rack {


struct ModuleDisconnectItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleDisconnectItem() {
text = "Disconnect cables";
rightText = WINDOW_MOD_CTRL_NAME "+U";
}
void onAction(const event::Action &e) override {
moduleWidget->disconnect();
}
};

struct ModuleResetItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleResetItem() {
text = "Initialize";
rightText = WINDOW_MOD_CTRL_NAME "+I";
}
void onAction(const event::Action &e) override {
moduleWidget->reset();
}
};

struct ModuleRandomizeItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleRandomizeItem() {
text = "Randomize";
rightText = WINDOW_MOD_CTRL_NAME "+R";
}
void onAction(const event::Action &e) override {
moduleWidget->randomize();
}
};

struct ModuleCopyItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleCopyItem() {
text = "Copy preset";
rightText = WINDOW_MOD_CTRL_NAME "+C";
}
void onAction(const event::Action &e) override {
moduleWidget->copyClipboard();
}
};

struct ModulePasteItem : MenuItem {
ModuleWidget *moduleWidget;
ModulePasteItem() {
text = "Paste preset";
rightText = WINDOW_MOD_CTRL_NAME "+V";
}
void onAction(const event::Action &e) override {
moduleWidget->pasteClipboard();
}
};

struct ModuleSaveItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleSaveItem() {
text = "Save preset as";
}
void onAction(const event::Action &e) override {
moduleWidget->saveDialog();
}
};

struct ModuleLoadItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleLoadItem() {
text = "Load preset";
}
void onAction(const event::Action &e) override {
moduleWidget->loadDialog();
}
};

struct ModuleCloneItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleCloneItem() {
text = "Duplicate";
rightText = WINDOW_MOD_CTRL_NAME "+D";
}
void onAction(const event::Action &e) override {
app()->scene->rackWidget->cloneModule(moduleWidget);
}
};

struct ModuleBypassItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleBypassItem() {
text = "Bypass";
}
void step() override {
rightText = WINDOW_MOD_CTRL_NAME "+E";
if (!moduleWidget->module)
return;
if (moduleWidget->module->bypass)
rightText = CHECKMARK_STRING " " + rightText;
}
void onAction(const event::Action &e) override {
moduleWidget->bypassAction();
}
};

struct ModuleDeleteItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleDeleteItem() {
text = "Delete";
rightText = "Backspace/Delete";
}
void onAction(const event::Action &e) override {
moduleWidget->removeAction();
}
};


ModuleWidget::~ModuleWidget() {
setModule(NULL);
}

void ModuleWidget::draw(NVGcontext *vg) {
if (module && module->bypass) {
nvgGlobalAlpha(vg, 0.5);
}
// nvgScissor(vg, 0, 0, box.size.x, box.size.y);
Widget::draw(vg);

// Power meter
if (module && settings::powerMeter) {
nvgBeginPath(vg);
nvgRect(vg,
0, box.size.y - 20,
65, 20);
nvgFillColor(vg, nvgRGBAf(0, 0, 0, 0.75));
nvgFill(vg);

std::string cpuText = string::f("%.2f ÎĽs", module->cpuTime * 1e6f);
bndLabel(vg, 2.0, box.size.y - 20.0, INFINITY, INFINITY, -1, cpuText.c_str());

float p = math::clamp(module->cpuTime / app()->engine->getSampleTime(), 0.f, 1.f);
nvgBeginPath(vg);
nvgRect(vg,
0, (1.f - p) * box.size.y,
5, p * box.size.y);
nvgFillColor(vg, nvgRGBAf(1, 0, 0, 1.0));
nvgFill(vg);
}

// nvgResetScissor(vg);
}

void ModuleWidget::drawShadow(NVGcontext *vg) {
nvgBeginPath(vg);
float r = 20; // Blur radius
float c = 20; // Corner radius
math::Vec b = math::Vec(-10, 30); // Offset from each corner
nvgRect(vg, b.x - r, b.y - r, box.size.x - 2*b.x + 2*r, box.size.y - 2*b.y + 2*r);
NVGcolor shadowColor = nvgRGBAf(0, 0, 0, 0.2);
NVGcolor transparentColor = nvgRGBAf(0, 0, 0, 0);
nvgFillPaint(vg, nvgBoxGradient(vg, b.x, b.y, box.size.x - 2*b.x, box.size.y - 2*b.y, c, r, shadowColor, transparentColor));
nvgFill(vg);
}

void ModuleWidget::onHover(const event::Hover &e) {
OpaqueWidget::onHover(e);

// Instead of checking key-down events, delete the module even if key-repeat hasn't fired yet and the cursor is hovering over the widget.
if (glfwGetKey(app()->window->win, GLFW_KEY_DELETE) == GLFW_PRESS || glfwGetKey(app()->window->win, GLFW_KEY_BACKSPACE) == GLFW_PRESS) {
if ((app()->window->getMods() & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
removeAction();
e.consume(NULL);
return;
}
}
}

void ModuleWidget::onButton(const event::Button &e) {
OpaqueWidget::onButton(e);

if (e.getConsumed() == this) {
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) {
createContextMenu();
}
}
}

void ModuleWidget::onHoverKey(const event::HoverKey &e) {
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
switch (e.key) {
case GLFW_KEY_I: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
reset();
e.consume(this);
}
} break;
case GLFW_KEY_R: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
randomize();
e.consume(this);
}
} break;
case GLFW_KEY_C: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
copyClipboard();
e.consume(this);
}
} break;
case GLFW_KEY_V: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
pasteClipboard();
e.consume(this);
}
} break;
case GLFW_KEY_D: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
app()->scene->rackWidget->cloneModule(this);
e.consume(this);
}
} break;
case GLFW_KEY_U: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
disconnect();
e.consume(this);
}
} break;
case GLFW_KEY_E: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
bypassAction();
e.consume(this);
}
} break;
}
}

if (!e.getConsumed())
OpaqueWidget::onHoverKey(e);
}

void ModuleWidget::onDragStart(const event::DragStart &e) {
oldPos = box.pos;
dragPos = app()->scene->rackWidget->lastMousePos.minus(box.pos);
}

void ModuleWidget::onDragEnd(const event::DragEnd &e) {
if (!box.pos.isEqual(oldPos)) {
// Push ModuleMove history action
history::ModuleMove *h = new history::ModuleMove;
h->moduleId = module->id;
h->oldPos = oldPos;
h->newPos = box.pos;
app()->history->push(h);
}
}

void ModuleWidget::onDragMove(const event::DragMove &e) {
if (!settings::lockModules) {
math::Rect newBox = box;
newBox.pos = app()->scene->rackWidget->lastMousePos.minus(dragPos);
app()->scene->rackWidget->requestModuleBoxNearest(this, newBox);
}
}

void ModuleWidget::setModule(Module *module) {
if (this->module) {
delete this->module;
@@ -244,15 +501,6 @@ void ModuleWidget::saveDialog() {
save(pathStr);
}

void ModuleWidget_bypassAction(ModuleWidget *moduleWidget) {
// Push ModuleBypass history action
history::ModuleBypass *h = new history::ModuleBypass;
h->bypass = !moduleWidget->module->bypass;
h->moduleId = moduleWidget->module->id;
app()->history->push(h);
h->redo();
}

void ModuleWidget::disconnect() {
for (PortWidget *input : inputs) {
app()->scene->rackWidget->cableContainer->removeAllCables(input);
@@ -274,282 +522,35 @@ void ModuleWidget::randomize() {
}
}

void ModuleWidget::draw(NVGcontext *vg) {
if (module && module->bypass) {
nvgGlobalAlpha(vg, 0.5);
}
// nvgScissor(vg, 0, 0, box.size.x, box.size.y);
Widget::draw(vg);

// Power meter
if (module && settings::powerMeter) {
nvgBeginPath(vg);
nvgRect(vg,
0, box.size.y - 20,
65, 20);
nvgFillColor(vg, nvgRGBAf(0, 0, 0, 0.75));
nvgFill(vg);

std::string cpuText = string::f("%.2f ÎĽs", module->cpuTime * 1e6f);
bndLabel(vg, 2.0, box.size.y - 20.0, INFINITY, INFINITY, -1, cpuText.c_str());

float p = math::clamp(module->cpuTime / app()->engine->getSampleTime(), 0.f, 1.f);
nvgBeginPath(vg);
nvgRect(vg,
0, (1.f - p) * box.size.y,
5, p * box.size.y);
nvgFillColor(vg, nvgRGBAf(1, 0, 0, 1.0));
nvgFill(vg);
}

// nvgResetScissor(vg);
}

void ModuleWidget::drawShadow(NVGcontext *vg) {
nvgBeginPath(vg);
float r = 20; // Blur radius
float c = 20; // Corner radius
math::Vec b = math::Vec(-10, 30); // Offset from each corner
nvgRect(vg, b.x - r, b.y - r, box.size.x - 2*b.x + 2*r, box.size.y - 2*b.y + 2*r);
NVGcolor shadowColor = nvgRGBAf(0, 0, 0, 0.2);
NVGcolor transparentColor = nvgRGBAf(0, 0, 0, 0);
nvgFillPaint(vg, nvgBoxGradient(vg, b.x, b.y, box.size.x - 2*b.x, box.size.y - 2*b.y, c, r, shadowColor, transparentColor));
nvgFill(vg);
}

static void ModuleWidget_removeAction(ModuleWidget *moduleWidget) {
void ModuleWidget::removeAction() {
history::ComplexAction *complexAction = new history::ComplexAction;

// Push ModuleRemove history action
history::ModuleRemove *moduleRemove = new history::ModuleRemove;
moduleRemove->model = moduleWidget->model;
moduleRemove->moduleId = moduleWidget->module->id;
moduleRemove->pos = moduleWidget->box.pos;
moduleRemove->moduleJ = moduleWidget->toJson();
moduleRemove->model = model;
moduleRemove->moduleId = module->id;
moduleRemove->pos = box.pos;
moduleRemove->moduleJ = toJson();
complexAction->push(moduleRemove);

app()->history->push(complexAction);

app()->scene->rackWidget->removeModule(moduleWidget);
delete moduleWidget;
}

void ModuleWidget::onHover(const event::Hover &e) {
OpaqueWidget::onHover(e);

// Instead of checking key-down events, delete the module even if key-repeat hasn't fired yet and the cursor is hovering over the widget.
if (glfwGetKey(app()->window->win, GLFW_KEY_DELETE) == GLFW_PRESS || glfwGetKey(app()->window->win, GLFW_KEY_BACKSPACE) == GLFW_PRESS) {
if ((app()->window->getMods() & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
ModuleWidget_removeAction(this);
e.consume(NULL);
return;
}
}
}

void ModuleWidget::onButton(const event::Button &e) {
OpaqueWidget::onButton(e);

if (e.getConsumed() == this) {
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) {
createContextMenu();
}
}
}

void ModuleWidget::onHoverKey(const event::HoverKey &e) {
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
switch (e.key) {
case GLFW_KEY_I: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
reset();
e.consume(this);
}
} break;
case GLFW_KEY_R: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
randomize();
e.consume(this);
}
} break;
case GLFW_KEY_C: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
copyClipboard();
e.consume(this);
}
} break;
case GLFW_KEY_V: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
pasteClipboard();
e.consume(this);
}
} break;
case GLFW_KEY_D: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
app()->scene->rackWidget->cloneModule(this);
e.consume(this);
}
} break;
case GLFW_KEY_U: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
disconnect();
e.consume(this);
}
} break;
case GLFW_KEY_E: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
ModuleWidget_bypassAction(this);
e.consume(this);
}
} break;
}
}

if (!e.getConsumed())
OpaqueWidget::onHoverKey(e);
}

void ModuleWidget::onDragStart(const event::DragStart &e) {
oldPos = box.pos;
dragPos = app()->scene->rackWidget->lastMousePos.minus(box.pos);
app()->scene->rackWidget->removeModule(this);
delete this;
}

void ModuleWidget::onDragEnd(const event::DragEnd &e) {
if (!box.pos.isEqual(oldPos)) {
// Push ModuleMove history action
history::ModuleMove *h = new history::ModuleMove;
h->moduleId = module->id;
h->oldPos = oldPos;
h->newPos = box.pos;
app()->history->push(h);
}
}

void ModuleWidget::onDragMove(const event::DragMove &e) {
if (!settings::lockModules) {
math::Rect newBox = box;
newBox.pos = app()->scene->rackWidget->lastMousePos.minus(dragPos);
app()->scene->rackWidget->requestModuleBoxNearest(this, newBox);
}
void ModuleWidget::bypassAction() {
// Push ModuleBypass history action
history::ModuleBypass *h = new history::ModuleBypass;
h->bypass = !module->bypass;
h->moduleId = module->id;
app()->history->push(h);
h->redo();
}


struct ModuleDisconnectItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleDisconnectItem() {
text = "Disconnect cables";
rightText = WINDOW_MOD_CTRL_NAME "+U";
}
void onAction(const event::Action &e) override {
moduleWidget->disconnect();
}
};

struct ModuleResetItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleResetItem() {
text = "Initialize";
rightText = WINDOW_MOD_CTRL_NAME "+I";
}
void onAction(const event::Action &e) override {
moduleWidget->reset();
}
};

struct ModuleRandomizeItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleRandomizeItem() {
text = "Randomize";
rightText = WINDOW_MOD_CTRL_NAME "+R";
}
void onAction(const event::Action &e) override {
moduleWidget->randomize();
}
};

struct ModuleCopyItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleCopyItem() {
text = "Copy preset";
rightText = WINDOW_MOD_CTRL_NAME "+C";
}
void onAction(const event::Action &e) override {
moduleWidget->copyClipboard();
}
};

struct ModulePasteItem : MenuItem {
ModuleWidget *moduleWidget;
ModulePasteItem() {
text = "Paste preset";
rightText = WINDOW_MOD_CTRL_NAME "+V";
}
void onAction(const event::Action &e) override {
moduleWidget->pasteClipboard();
}
};

struct ModuleSaveItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleSaveItem() {
text = "Save preset as";
}
void onAction(const event::Action &e) override {
moduleWidget->saveDialog();
}
};

struct ModuleLoadItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleLoadItem() {
text = "Load preset";
}
void onAction(const event::Action &e) override {
moduleWidget->loadDialog();
}
};

struct ModuleCloneItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleCloneItem() {
text = "Duplicate";
rightText = WINDOW_MOD_CTRL_NAME "+D";
}
void onAction(const event::Action &e) override {
app()->scene->rackWidget->cloneModule(moduleWidget);
}
};

struct ModuleBypassItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleBypassItem() {
text = "Bypass";
}
void step() override {
rightText = WINDOW_MOD_CTRL_NAME "+E";
if (!moduleWidget->module)
return;
if (moduleWidget->module->bypass)
rightText = CHECKMARK_STRING " " + rightText;
}
void onAction(const event::Action &e) override {
ModuleWidget_bypassAction(moduleWidget);
}
};

struct ModuleDeleteItem : MenuItem {
ModuleWidget *moduleWidget;
ModuleDeleteItem() {
text = "Delete";
rightText = "Backspace/Delete";
}
void onAction(const event::Action &e) override {
ModuleWidget_removeAction(moduleWidget);
}
};

Menu *ModuleWidget::createContextMenu() {
void ModuleWidget::createContextMenu() {
Menu *menu = createMenu();
assert(model);

MenuLabel *menuLabel = new MenuLabel;
menuLabel->text = model->plugin->name + " " + model->name + " " + model->plugin->version;
@@ -596,8 +597,6 @@ Menu *ModuleWidget::createContextMenu() {
menu->addChild(deleteItem);

appendContextMenu(menu);

return menu;
}



+ 109
- 49
src/app/ParamWidget.cpp View File

@@ -7,6 +7,7 @@
#include "settings.hpp"
#include "random.hpp"
#include "history.hpp"
#include "helpers.hpp"


namespace rack {
@@ -18,6 +19,7 @@ struct ParamField : TextField {
void step() override {
// Keep selected
app()->event->setSelected(this);
TextField::step();
}

void setParamWidget(ParamWidget *paramWidget) {
@@ -61,6 +63,48 @@ struct ParamField : TextField {
};


struct ParamTooltip : Tooltip {
ParamWidget *paramWidget;

void step() override {
if (paramWidget->paramQuantity) {
// Quantity string
text = paramWidget->paramQuantity->getString();
// Param description
std::string description = paramWidget->paramQuantity->getParam()->description;
if (!description.empty())
text += "\n" + description;
}
// Position at bottom-right of parameter
box.pos = paramWidget->getAbsoluteOffset(box.size).round();
}
};


struct ParamResetItem : MenuItem {
ParamWidget *paramWidget;
ParamResetItem() {
text = "Initialize";
rightText = WINDOW_MOD_ALT_NAME "+click";
}
void onAction(const event::Action &e) override {
paramWidget->resetAction();
}
};


struct ParamFieldItem : MenuItem {
ParamWidget *paramWidget;
ParamFieldItem() {
text = "Enter value";
rightText = WINDOW_MOD_SHIFT_NAME "+click";
}
void onAction(const event::Action &e) override {
paramWidget->createParamField();
}
};


ParamWidget::~ParamWidget() {
if (paramQuantity)
delete paramQuantity;
@@ -77,19 +121,6 @@ void ParamWidget::step() {
}
}

if (tooltip) {
if (paramQuantity) {
// Quantity string
tooltip->text = paramQuantity->getString();
// Param description
std::string description = paramQuantity->getParam()->description;
if (!description.empty())
tooltip->text += "\n" + description;
}
// Position at bottom-right of parameter
tooltip->box.pos = getAbsoluteOffset(box.size).round();
}

OpaqueWidget::step();
}

@@ -109,48 +140,22 @@ void ParamWidget::draw(NVGcontext *vg) {
// }
}

void ParamWidget::fromJson(json_t *rootJ) {
json_t *valueJ = json_object_get(rootJ, "value");
if (valueJ) {
if (paramQuantity)
paramQuantity->setValue(json_number_value(valueJ));
}
}

void ParamWidget::onButton(const event::Button &e) {
// Right click to reset
// Right click to open context menu
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT && (e.mods & WINDOW_MOD_MASK) == 0) {
if (paramQuantity && paramQuantity->isBounded()) {
float oldValue = paramQuantity->getValue();
paramQuantity->reset();
float newValue = paramQuantity->getValue();
createContextMenu();
e.consume(this);
}

if (oldValue != newValue) {
// Push ParamChange history action
history::ParamChange *h = new history::ParamChange;
h->moduleId = paramQuantity->module->id;
h->paramId = paramQuantity->paramId;
h->oldValue = oldValue;
h->newValue = newValue;
app()->history->push(h);
}
}
// Here's another way of doing it, but either works.
// paramQuantity->getParam()->reset();
// Alt-click to reset
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT && (e.mods & WINDOW_MOD_MASK) == GLFW_MOD_ALT) {
resetAction();
e.consume(this);
}

// Shift-click to open value entry
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT && (e.mods & WINDOW_MOD_MASK) == GLFW_MOD_SHIFT) {
// Create ParamField
MenuOverlay *overlay = new MenuOverlay;
app()->scene->addChild(overlay);

ParamField *paramField = new ParamField;
paramField->box.size.x = 100;
paramField->box.pos = getAbsoluteOffset(box.size).round();
paramField->setParamWidget(this);
overlay->addChild(paramField);
createParamField();
e.consume(this);
}

@@ -160,8 +165,10 @@ void ParamWidget::onButton(const event::Button &e) {

void ParamWidget::onEnter(const event::Enter &e) {
if (settings::paramTooltip && !tooltip) {
tooltip = new Tooltip;
app()->scene->addChild(tooltip);
ParamTooltip *paramTooltip = new ParamTooltip;
paramTooltip->paramWidget = this;
app()->scene->addChild(paramTooltip);
tooltip = paramTooltip;
}
}

@@ -173,5 +180,58 @@ void ParamWidget::onLeave(const event::Leave &e) {
}
}

void ParamWidget::fromJson(json_t *rootJ) {
json_t *valueJ = json_object_get(rootJ, "value");
if (valueJ) {
if (paramQuantity)
paramQuantity->setValue(json_number_value(valueJ));
}
}

void ParamWidget::createParamField() {
// Create ParamField
MenuOverlay *overlay = new MenuOverlay;
app()->scene->addChild(overlay);

ParamField *paramField = new ParamField;
paramField->box.size.x = 100;
paramField->box.pos = getAbsoluteOffset(box.size).round();
paramField->setParamWidget(this);
overlay->addChild(paramField);
}

void ParamWidget::createContextMenu() {
Menu *menu = createMenu();

ParamResetItem *resetItem = new ParamResetItem;
resetItem->paramWidget = this;
menu->addChild(resetItem);

ParamFieldItem *fieldItem = new ParamFieldItem;
fieldItem->paramWidget = this;
menu->addChild(fieldItem);
}

void ParamWidget::resetAction() {
if (paramQuantity && paramQuantity->isBounded()) {
float oldValue = paramQuantity->getValue();
paramQuantity->reset();
float newValue = paramQuantity->getValue();

if (oldValue != newValue) {
// Push ParamChange history action
history::ParamChange *h = new history::ParamChange;
h->moduleId = paramQuantity->module->id;
h->paramId = paramQuantity->paramId;
h->oldValue = oldValue;
h->newValue = newValue;
app()->history->push(h);
}

// Here's another way of doing it, but either works.
// paramQuantity->getParam()->reset();
}
}


} // namespace rack

Loading…
Cancel
Save