commit ba923d458c30856f8d46ff96f873606f028afb88
parent e998c7fe673adf8a3156e382bf83f7f75b0c7089
Author: Matt Demanett <matt@demanett.net>
Date: Sun, 17 Nov 2019 01:50:47 -0500
Refactor context menus; turn option groups into submenus.
Diffstat:
18 files changed, 222 insertions(+), 578 deletions(-)
diff --git a/src/AD.cpp b/src/AD.cpp
@@ -166,35 +166,22 @@ struct ADWidget : ModuleWidget {
addChild(createLight<SmallLight<GreenLight>>(linearLightPosition, module, AD::LINEAR_LIGHT));
}
- struct InvertMenuItem : MenuItem {
- AD* _module;
-
- InvertMenuItem(AD* module, const char* label, int offset)
- : _module(module)
- {
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- if (_module->_invert < 0.0f) {
- _module->_invert = 1.0f;
- }
- else {
- _module->_invert = -1.0f;
- }
- }
-
- void step() override {
- MenuItem::step();
- rightText = _module->_invert == -1.0f ? "✔" : "";
- }
- };
-
void appendContextMenu(Menu* menu) override {
AD* m = dynamic_cast<AD*>(module);
assert(m);
menu->addChild(new MenuLabel());
- menu->addChild(new InvertMenuItem(m, "Invert output", -1));
+ menu->addChild(new OptionMenuItem(
+ "Invert output",
+ [m]() { return m->_invert == -1.0f; },
+ [m]() {
+ if (m->_invert < 0.0f) {
+ m->_invert = 1.0f;
+ }
+ else {
+ m->_invert = -1.0f;
+ }
+ }
+ ));
}
};
diff --git a/src/ADSR.cpp b/src/ADSR.cpp
@@ -144,35 +144,22 @@ struct ADSRWidget : ModuleWidget {
addChild(createLight<SmallLight<GreenLight>>(linearLightPosition, module, ADSR::LINEAR_LIGHT));
}
- struct InvertMenuItem : MenuItem {
- ADSR* _module;
-
- InvertMenuItem(ADSR* module, const char* label, int offset)
- : _module(module)
- {
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- if (_module->_invert < 0.0f) {
- _module->_invert = 1.0f;
- }
- else {
- _module->_invert = -1.0f;
- }
- }
-
- void step() override {
- MenuItem::step();
- rightText = _module->_invert == -1.0f ? "✔" : "";
- }
- };
-
void appendContextMenu(Menu* menu) override {
ADSR* m = dynamic_cast<ADSR*>(module);
assert(m);
menu->addChild(new MenuLabel());
- menu->addChild(new InvertMenuItem(m, "Invert output", -1));
+ menu->addChild(new OptionMenuItem(
+ "Invert output",
+ [m]() { return m->_invert == -1.0f; },
+ [m]() {
+ if (m->_invert < 0.0f) {
+ m->_invert = 1.0f;
+ }
+ else {
+ m->_invert = -1.0f;
+ }
+ }
+ ));
}
};
diff --git a/src/AddrSeq.cpp b/src/AddrSeq.cpp
@@ -157,27 +157,17 @@ struct AddrSeqWidget : AddressableSequenceModuleWidget {
addChild(createLight<SmallLight<GreenLight>>(out8LightPosition, module, AddrSeq::OUT8_LIGHT));
}
- struct RangeMenuItem : MenuItem {
- AddrSeq* _module;
- float _offset, _scale;
-
- RangeMenuItem(AddrSeq* module, const char* label, float offset, float scale)
- : _module(module)
- , _offset(offset)
- , _scale(scale)
- {
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_rangeOffset = _offset;
- _module->_rangeScale = _scale;
- }
-
- void step() override {
- MenuItem::step();
- rightText = (_module->_rangeOffset == _offset && _module->_rangeScale == _scale) ? "✔" : "";
- }
+ struct RangeOptionMenuItem : OptionMenuItem {
+ RangeOptionMenuItem(AddrSeq* module, const char* label, float offset, float scale)
+ : OptionMenuItem(
+ label,
+ [=]() { return module->_rangeOffset == offset && module->_rangeScale == scale; },
+ [=]() {
+ module->_rangeOffset = offset;
+ module->_rangeScale = scale;
+ }
+ )
+ {}
};
void appendContextMenu(Menu* menu) override {
@@ -185,15 +175,16 @@ struct AddrSeqWidget : AddressableSequenceModuleWidget {
AddrSeq* m = dynamic_cast<AddrSeq*>(module);
assert(m);
- menu->addChild(new MenuLabel());
- menu->addChild(new RangeMenuItem(m, "Range: +/-10V", 0.0f, 10.0f));
- menu->addChild(new RangeMenuItem(m, "Range: +/-5V", 0.0f, 5.0f));
- menu->addChild(new RangeMenuItem(m, "Range: +/-3V", 0.0f, 3.0f));
- menu->addChild(new RangeMenuItem(m, "Range: +/-1V", 0.0f, 1.0f));
- menu->addChild(new RangeMenuItem(m, "Range: 0V-10V", 1.0f, 5.0f));
- menu->addChild(new RangeMenuItem(m, "Range: 0V-5V", 1.0f, 2.5f));
- menu->addChild(new RangeMenuItem(m, "Range: 0V-3V", 1.0f, 1.5f));
- menu->addChild(new RangeMenuItem(m, "Range: 0V-1V", 1.0f, 0.5f));
+ OptionsMenuItem* mi = new OptionsMenuItem("Range");
+ mi->addItem(RangeOptionMenuItem(m, "+/-10V", 0.0f, 10.0f));
+ mi->addItem(RangeOptionMenuItem(m, "+/-5V", 0.0f, 5.0f));
+ mi->addItem(RangeOptionMenuItem(m, "+/-3V", 0.0f, 3.0f));
+ mi->addItem(RangeOptionMenuItem(m, "+/-1V", 0.0f, 1.0f));
+ mi->addItem(RangeOptionMenuItem(m, "0V-10V", 1.0f, 5.0f));
+ mi->addItem(RangeOptionMenuItem(m, "0V-5V", 1.0f, 2.5f));
+ mi->addItem(RangeOptionMenuItem(m, "0V-3V", 1.0f, 1.5f));
+ mi->addItem(RangeOptionMenuItem(m, "0V-1V", 1.0f, 0.5f));
+ menu->addChild(mi);
}
};
diff --git a/src/Analyzer.cpp b/src/Analyzer.cpp
@@ -153,34 +153,15 @@ struct AnalyzerWidget : ModuleWidget {
addChild(createLight<SmallLight<GreenLight>>(windowKaiserLightPosition, module, Analyzer::WINDOW_KAISER_LIGHT));
}
- struct RangeDbMenuItem : MenuItem {
- Analyzer* _module;
- const float _rangeDb;
-
- RangeDbMenuItem(Analyzer* module, const char* label, float rangeDb)
- : _module(module)
- , _rangeDb(rangeDb)
- {
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_rangeDb = _rangeDb;
- }
-
- void step() override {
- MenuItem::step();
- rightText = _module->_rangeDb == _rangeDb ? "✔" : "";
- }
- };
-
void appendContextMenu(Menu* menu) override {
Analyzer* a = dynamic_cast<Analyzer*>(module);
assert(a);
menu->addChild(new MenuLabel());
- menu->addChild(new RangeDbMenuItem(a, "Amplitude: to -60dB", 80.0f));
- menu->addChild(new RangeDbMenuItem(a, "Amplitude: to -120dB", 140.0f));
+ OptionsMenuItem* mi = new OptionsMenuItem("Amplitude range");
+ mi->addItem(OptionMenuItem("To -60dB", [a]() { return a->_rangeDb == 80.0f; }, [a]() { a->_rangeDb = 80.0f; }));
+ mi->addItem(OptionMenuItem("To -120dB", [a]() { return a->_rangeDb == 140.0f; }, [a]() { a->_rangeDb = 140.0f; }));
+ menu->addChild(mi);
}
};
diff --git a/src/AnalyzerXL.cpp b/src/AnalyzerXL.cpp
@@ -173,143 +173,50 @@ struct AnalyzerXLWidget : ModuleWidget {
addInput(createInput<Port24>(signalhInputPosition, module, AnalyzerXL::SIGNALH_INPUT));
}
- struct RangeMenuItem : MenuItem {
- AnalyzerXL* _module;
- const float _range;
+ void appendContextMenu(Menu* menu) override {
+ AnalyzerXL* a = dynamic_cast<AnalyzerXL*>(module);
+ assert(a);
- RangeMenuItem(AnalyzerXL* module, const char* label, float range)
- : _module(module)
- , _range(range)
+ menu->addChild(new MenuLabel());
{
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_range = _range;
+ OptionsMenuItem* mi = new OptionsMenuItem("Frequency range");
+ mi->addItem(OptionMenuItem("Lower 25%", [a]() { return a->_range == -0.75f; }, [a]() { a->_range = -0.75f; }));
+ mi->addItem(OptionMenuItem("Lower 50%", [a]() { return a->_range == -0.5f; }, [a]() { a->_range = -0.5f; }));
+ mi->addItem(OptionMenuItem("Full", [a]() { return a->_range == 0.0f; }, [a]() { a->_range = 0.0f; }));
+ mi->addItem(OptionMenuItem("Upper 50%", [a]() { return a->_range == 0.5f; }, [a]() { a->_range = 0.5f; }));
+ mi->addItem(OptionMenuItem("Upper 25%", [a]() { return a->_range == 0.75f; }, [a]() { a->_range = 0.75f; }));
+ menu->addChild(mi);
}
-
- void step() override {
- MenuItem::step();
- rightText = _module->_range == _range ? "✔" : "";
- }
- };
-
- struct RangeDbMenuItem : MenuItem {
- AnalyzerXL* _module;
- const float _rangeDb;
-
- RangeDbMenuItem(AnalyzerXL* module, const char* label, float rangeDb)
- : _module(module)
- , _rangeDb(rangeDb)
{
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_rangeDb = _rangeDb;
+ OptionsMenuItem* mi = new OptionsMenuItem("Amplitude range");
+ mi->addItem(OptionMenuItem("To -60dB", [a]() { return a->_rangeDb == 80.0f; }, [a]() { a->_rangeDb = 80.0f; }));
+ mi->addItem(OptionMenuItem("To -120dB", [a]() { return a->_rangeDb == 140.0f; }, [a]() { a->_rangeDb = 140.0f; }));
+ menu->addChild(mi);
}
-
- void step() override {
- MenuItem::step();
- rightText = _module->_rangeDb == _rangeDb ? "✔" : "";
- }
- };
-
- struct SmoothMenuItem : MenuItem {
- AnalyzerXL* _module;
- const float _smooth;
-
- SmoothMenuItem(AnalyzerXL* module, const char* label, float smooth)
- : _module(module)
- , _smooth(smooth)
{
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_smooth = _smooth;
+ OptionsMenuItem* mi = new OptionsMenuItem("Smoothing");
+ mi->addItem(OptionMenuItem("None", [a]() { return a->_smooth == 0.0f; }, [a]() { a->_smooth = 0.0f; }));
+ mi->addItem(OptionMenuItem("10ms", [a]() { return a->_smooth == 0.01f; }, [a]() { a->_smooth = 0.01f; }));
+ mi->addItem(OptionMenuItem("50ms", [a]() { return a->_smooth == 0.05f; }, [a]() { a->_smooth = 0.05f; }));
+ mi->addItem(OptionMenuItem("100ms", [a]() { return a->_smooth == 0.1f; }, [a]() { a->_smooth = 0.1f; }));
+ mi->addItem(OptionMenuItem("250ms", [a]() { return a->_smooth == 0.25f; }, [a]() { a->_smooth = 0.25f; }));
+ mi->addItem(OptionMenuItem("500ms", [a]() { return a->_smooth == 0.5f; }, [a]() { a->_smooth = 0.5f; }));
+ menu->addChild(mi);
}
-
- void step() override {
- MenuItem::step();
- rightText = _module->_smooth == _smooth ? "✔" : "";
- }
- };
-
- struct QualityMenuItem : MenuItem {
- AnalyzerXL* _module;
- const AnalyzerCore::Quality _quality;
-
- QualityMenuItem(AnalyzerXL* module, const char* label, AnalyzerCore::Quality quality)
- : _module(module)
- , _quality(quality)
{
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_quality = _quality;
- }
-
- void step() override {
- MenuItem::step();
- rightText = _module->_quality == _quality ? "✔" : "";
+ OptionsMenuItem* mi = new OptionsMenuItem("Quality");
+ mi->addItem(OptionMenuItem("Good", [a]() { return a->_quality == AnalyzerCore::QUALITY_GOOD; }, [a]() { a->_quality = AnalyzerCore::QUALITY_GOOD; }));
+ mi->addItem(OptionMenuItem("High", [a]() { return a->_quality == AnalyzerCore::QUALITY_HIGH; }, [a]() { a->_quality = AnalyzerCore::QUALITY_HIGH; }));
+ mi->addItem(OptionMenuItem("Ultra", [a]() { return a->_quality == AnalyzerCore::QUALITY_ULTRA; }, [a]() { a->_quality = AnalyzerCore::QUALITY_ULTRA; }));
+ menu->addChild(mi);
}
- };
-
- struct WindowMenuItem : MenuItem {
- AnalyzerXL* _module;
- const AnalyzerCore::Window _window;
-
- WindowMenuItem(AnalyzerXL* module, const char* label, AnalyzerCore::Window window)
- : _module(module)
- , _window(window)
{
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_window = _window;
- }
-
- void step() override {
- MenuItem::step();
- rightText = _module->_window == _window ? "✔" : "";
+ OptionsMenuItem* mi = new OptionsMenuItem("Window");
+ mi->addItem(OptionMenuItem("Kaiser", [a]() { return a->_window == AnalyzerCore::WINDOW_KAISER; }, [a]() { a->_window = AnalyzerCore::WINDOW_KAISER; }));
+ mi->addItem(OptionMenuItem("Hamming", [a]() { return a->_window == AnalyzerCore::WINDOW_HAMMING; }, [a]() { a->_window = AnalyzerCore::WINDOW_HAMMING; }));
+ mi->addItem(OptionMenuItem("None", [a]() { return a->_window == AnalyzerCore::WINDOW_NONE; }, [a]() { a->_window = AnalyzerCore::WINDOW_NONE; }));
+ menu->addChild(mi);
}
- };
-
- void appendContextMenu(Menu* menu) override {
- AnalyzerXL* a = dynamic_cast<AnalyzerXL*>(module);
- assert(a);
-
- menu->addChild(new MenuLabel());
- menu->addChild(new RangeMenuItem(a, "Frequency: lower 25%", -0.75f));
- menu->addChild(new RangeMenuItem(a, "Frequency: lower 50%", -0.5f));
- menu->addChild(new RangeMenuItem(a, "Frequency: full", 0.0f));
- menu->addChild(new RangeMenuItem(a, "Frequency: upper 50%", 0.5f));
- menu->addChild(new RangeMenuItem(a, "Frequency: upper 25%", 0.75f));
-
- menu->addChild(new MenuLabel());
- menu->addChild(new RangeDbMenuItem(a, "Amplitude: to -60dB", 80.0f));
- menu->addChild(new RangeDbMenuItem(a, "Amplitude: to -120dB", 140.0f));
-
- menu->addChild(new MenuLabel());
- menu->addChild(new SmoothMenuItem(a, "Smooth: none", 0.0f));
- menu->addChild(new SmoothMenuItem(a, "Smooth: 10ms", 0.01f));
- menu->addChild(new SmoothMenuItem(a, "Smooth: 50ms", 0.05f));
- menu->addChild(new SmoothMenuItem(a, "Smooth: 100ms", 0.1f));
- menu->addChild(new SmoothMenuItem(a, "Smooth: 250ms", 0.25f));
- menu->addChild(new SmoothMenuItem(a, "Smooth: 500ms", 0.5f));
-
- menu->addChild(new MenuLabel());
- menu->addChild(new QualityMenuItem(a, "Quality: good", AnalyzerCore::QUALITY_GOOD));
- menu->addChild(new QualityMenuItem(a, "Quality: high", AnalyzerCore::QUALITY_HIGH));
- menu->addChild(new QualityMenuItem(a, "Quality: ultra", AnalyzerCore::QUALITY_ULTRA));
-
- menu->addChild(new MenuLabel());
- menu->addChild(new WindowMenuItem(a, "Window: Kaiser", AnalyzerCore::WINDOW_KAISER));
- menu->addChild(new WindowMenuItem(a, "Window: Hamming", AnalyzerCore::WINDOW_HAMMING));
- menu->addChild(new WindowMenuItem(a, "Window: none", AnalyzerCore::WINDOW_NONE));
}
};
diff --git a/src/FMOp.cpp b/src/FMOp.cpp
@@ -326,30 +326,11 @@ struct FMOpWidget : ModuleWidget {
addChild(createLight<SmallLight<GreenLight>>(envToDepthLightPosition, module, FMOp::ENV_TO_DEPTH_LIGHT));
}
- struct LinearLevelMenuItem : MenuItem {
- FMOp* _module;
-
- LinearLevelMenuItem(FMOp* module, const char* label)
- : _module(module)
- {
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_linearLevel = !_module->_linearLevel;
- }
-
- void step() override {
- MenuItem::step();
- rightText = _module->_linearLevel ? "✔" : "";
- }
- };
-
void appendContextMenu(Menu* menu) override {
FMOp* fmop = dynamic_cast<FMOp*>(module);
assert(fmop);
menu->addChild(new MenuLabel());
- menu->addChild(new LinearLevelMenuItem(fmop, "Linear level response"));
+ menu->addChild(new BoolOptionMenuItem("Linear level response", [fmop]() { return &fmop->_linearLevel; }));
}
};
diff --git a/src/Manual.cpp b/src/Manual.cpp
@@ -32,7 +32,9 @@ void Manual::processChannel(const ProcessArgs& args, int _c) {
struct ManualWidget : TriggerOnLoadModuleWidget {
static constexpr int hp = 3;
- ManualWidget(Manual* module) {
+ ManualWidget(Manual* module)
+ : TriggerOnLoadModuleWidget("Trigger on load")
+ {
setModule(module);
box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT);
@@ -70,13 +72,6 @@ struct ManualWidget : TriggerOnLoadModuleWidget {
addOutput(createOutput<Port24>(out7OutputPosition, module, Manual::OUT7_OUTPUT));
addOutput(createOutput<Port24>(out8OutputPosition, module, Manual::OUT8_OUTPUT));
}
-
- void appendContextMenu(Menu* menu) override {
- TriggerOnLoadModule* m = dynamic_cast<TriggerOnLoadModule*>(module);
- assert(m);
- menu->addChild(new MenuLabel());
- menu->addChild(new TriggerOnLoadMenuItem(m, "Trigger on load"));
- }
};
Model* modelManual = bogaudio::createModel<Manual, ManualWidget>("Bogaudio-Manual", "MANUAL", "Button controlled gates / triggers", "Utility");
diff --git a/src/Mix4.cpp b/src/Mix4.cpp
@@ -190,36 +190,17 @@ struct Mix4Widget : ModuleWidget {
addParam(slider);
}
- struct PolySpreadMenuItem : MenuItem {
- Mix4* _module;
- int _offset;
-
- PolySpreadMenuItem(Mix4* module, const char* label, int offset)
- : _module(module)
- , _offset(offset)
- {
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_polyChannelOffset = _offset;
- }
-
- void step() override {
- MenuItem::step();
- rightText = _module->_polyChannelOffset == _offset ? "✔" : "";
- }
- };
-
void appendContextMenu(Menu* menu) override {
Mix4* m = dynamic_cast<Mix4*>(module);
assert(m);
menu->addChild(new MenuLabel());
- menu->addChild(new PolySpreadMenuItem(m, "Input 1 poly spread: none", -1));
- menu->addChild(new PolySpreadMenuItem(m, "Input 1 poly spread: channels 1-4", 0));
- menu->addChild(new PolySpreadMenuItem(m, "Input 1 poly spread: channels 5-8", 4));
- menu->addChild(new PolySpreadMenuItem(m, "Input 1 poly spread: channels 9-12", 4));
- menu->addChild(new PolySpreadMenuItem(m, "Input 1 poly spread: channels 13-16", 4));
+ OptionsMenuItem* mi = new OptionsMenuItem("Input 1 poly spread");
+ mi->addItem(OptionMenuItem("None", [m]() { return m->_polyChannelOffset == -1; }, [m]() { m->_polyChannelOffset = -1; }));
+ mi->addItem(OptionMenuItem("Channels 1-4", [m]() { return m->_polyChannelOffset == 0; }, [m]() { m->_polyChannelOffset = 0; }));
+ mi->addItem(OptionMenuItem("Channels 5-8", [m]() { return m->_polyChannelOffset == 4; }, [m]() { m->_polyChannelOffset = 4; }));
+ mi->addItem(OptionMenuItem("Channels 9-12", [m]() { return m->_polyChannelOffset == 8; }, [m]() { m->_polyChannelOffset = 8; }));
+ mi->addItem(OptionMenuItem("Channels 13-16", [m]() { return m->_polyChannelOffset == 12; }, [m]() { m->_polyChannelOffset = 12; }));
+ menu->addChild(mi);
}
};
diff --git a/src/Mix8.cpp b/src/Mix8.cpp
@@ -242,34 +242,15 @@ struct Mix8Widget : ModuleWidget {
addParam(slider);
}
- struct PolySpreadMenuItem : MenuItem {
- Mix8* _module;
- int _offset;
-
- PolySpreadMenuItem(Mix8* module, const char* label, int offset)
- : _module(module)
- , _offset(offset)
- {
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_polyChannelOffset = _offset;
- }
-
- void step() override {
- MenuItem::step();
- rightText = _module->_polyChannelOffset == _offset ? "✔" : "";
- }
- };
-
void appendContextMenu(Menu* menu) override {
Mix8* m = dynamic_cast<Mix8*>(module);
assert(m);
menu->addChild(new MenuLabel());
- menu->addChild(new PolySpreadMenuItem(m, "Input 1 poly spread: none", -1));
- menu->addChild(new PolySpreadMenuItem(m, "Input 1 poly spread: channels 1-8", 0));
- menu->addChild(new PolySpreadMenuItem(m, "Input 1 poly spread: channels 9-16", 8));
+ OptionsMenuItem* mi = new OptionsMenuItem("Input 1 poly spread");
+ mi->addItem(OptionMenuItem("None", [m]() { return m->_polyChannelOffset == -1; }, [m]() { m->_polyChannelOffset = -1; }));
+ mi->addItem(OptionMenuItem("Channels 1-8", [m]() { return m->_polyChannelOffset == 0; }, [m]() { m->_polyChannelOffset = 0; }));
+ mi->addItem(OptionMenuItem("Channels 9-16", [m]() { return m->_polyChannelOffset == 8; }, [m]() { m->_polyChannelOffset = 8; }));
+ menu->addChild(mi);
}
};
diff --git a/src/Noise.cpp b/src/Noise.cpp
@@ -91,41 +91,21 @@ struct NoiseWidget : ModuleWidget {
addOutput(createOutput<Port24>(absOutputPosition, module, Noise::ABS_OUTPUT));
}
- struct ChannelMenuItemX : MenuItem {
+ struct ChannelsMenuItem : MenuItem {
Noise* _module;
- int _channels;
- ChannelMenuItemX(Noise* module, const char* label, int channels)
- : _module(module)
- , _channels(channels)
- {
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_noiseChannels = _channels;
- }
-
- void step() override {
- MenuItem::step();
- this->rightText = _module->_noiseChannels == _channels ? "✔" : "";
- }
- };
-
- struct ChannelsMenuItemX : MenuItem {
- Noise* _module;
-
- ChannelsMenuItemX(Noise* module, const char* label) : _module(module) {
+ ChannelsMenuItem(Noise* module, const char* label) : _module(module) {
this->text = label;
}
Menu* createChildMenu() override {
Menu* menu = new Menu;
- menu->addChild(new ChannelMenuItemX(_module, "Monophonic", 1));
+ Noise* m = _module;
+ menu->addChild(new OptionMenuItem("Monophonic", [m]() { return m->_noiseChannels == 1; }, [m]() { m->_noiseChannels = 1; }));
for (int i = 2; i <= BGModule::maxChannels; i++) {
char s[10];
snprintf(s, 10, "%d", i);
- menu->addChild(new ChannelMenuItemX(_module, s, i));
+ menu->addChild(new OptionMenuItem(s, [m, i]() { return m->_noiseChannels == i; }, [m, i]() { m->_noiseChannels = i; }));
}
return menu;
}
@@ -143,7 +123,7 @@ struct NoiseWidget : ModuleWidget {
assert(m);
menu->addChild(new MenuLabel());
- menu->addChild(new ChannelsMenuItemX(m, "Polyphony channels"));
+ menu->addChild(new ChannelsMenuItem(m, "Polyphony channels"));
}
};
diff --git a/src/SampleHold.cpp b/src/SampleHold.cpp
@@ -191,67 +191,43 @@ struct SampleHoldWidget : ModuleWidget {
addChild(createLight<SmallLight<GreenLight>>(invert2LightPosition, module, SampleHold::INVERT2_LIGHT));
}
- struct NoiseTypeMenuItem : MenuItem {
- SampleHold* _module;
- SampleHold::NoiseType _noiseType;
-
- NoiseTypeMenuItem(SampleHold* module, const char* label, SampleHold::NoiseType noiseType)
- : _module(module)
- , _noiseType(noiseType)
- {
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_noiseType = _noiseType;
- }
-
- void step() override {
- MenuItem::step();
- rightText = _module->_noiseType == _noiseType ? "✔" : "";
- }
- };
-
- struct RangeMenuItem : MenuItem {
- SampleHold* _module;
- float _offset, _scale;
-
- RangeMenuItem(SampleHold* module, const char* label, float offset, float scale)
- : _module(module)
- , _offset(offset)
- , _scale(scale)
- {
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_rangeOffset = _offset;
- _module->_rangeScale = _scale;
- }
-
- void step() override {
- MenuItem::step();
- rightText = (_module->_rangeOffset == _offset && _module->_rangeScale == _scale) ? "✔" : "";
- }
+ struct RangeOptionMenuItem : OptionMenuItem {
+ RangeOptionMenuItem(SampleHold* module, const char* label, float offset, float scale)
+ : OptionMenuItem(
+ label,
+ [=]() { return module->_rangeOffset == offset && module->_rangeScale == scale; },
+ [=]() {
+ module->_rangeOffset = offset;
+ module->_rangeScale = scale;
+ }
+ )
+ {}
};
void appendContextMenu(Menu* menu) override {
SampleHold* m = dynamic_cast<SampleHold*>(module);
assert(m);
menu->addChild(new MenuLabel());
- menu->addChild(new NoiseTypeMenuItem(m, "Normal noise: blue", SampleHold::BLUE_NOISE_TYPE));
- menu->addChild(new NoiseTypeMenuItem(m, "Normal noise: white", SampleHold::WHITE_NOISE_TYPE));
- menu->addChild(new NoiseTypeMenuItem(m, "Normal noise: pink", SampleHold::PINK_NOISE_TYPE));
- menu->addChild(new NoiseTypeMenuItem(m, "Normal noise: red", SampleHold::RED_NOISE_TYPE));
- menu->addChild(new MenuLabel());
- menu->addChild(new RangeMenuItem(m, "Normal range: +/-10V", 0.0f, 10.0f));
- menu->addChild(new RangeMenuItem(m, "Normal range: +/-5V", 0.0f, 5.0f));
- menu->addChild(new RangeMenuItem(m, "Normal range: +/-3V", 0.0f, 3.0f));
- menu->addChild(new RangeMenuItem(m, "Normal range: +/-1V", 0.0f, 1.0f));
- menu->addChild(new RangeMenuItem(m, "Normal range: 0V-10V", 1.0f, 5.0f));
- menu->addChild(new RangeMenuItem(m, "Normal range: 0V-5V", 1.0f, 2.5f));
- menu->addChild(new RangeMenuItem(m, "Normal range: 0V-3V", 1.0f, 1.5f));
- menu->addChild(new RangeMenuItem(m, "Normal range: 0V-1V", 1.0f, 0.5f));
+ {
+ OptionsMenuItem* mi = new OptionsMenuItem("Normal noise");
+ mi->addItem(OptionMenuItem("Blue", [m]() { return m->_noiseType == SampleHold::BLUE_NOISE_TYPE; }, [m]() { m->_noiseType = SampleHold::BLUE_NOISE_TYPE; }));
+ mi->addItem(OptionMenuItem("White", [m]() { return m->_noiseType == SampleHold::WHITE_NOISE_TYPE; }, [m]() { m->_noiseType = SampleHold::WHITE_NOISE_TYPE; }));
+ mi->addItem(OptionMenuItem("Pink", [m]() { return m->_noiseType == SampleHold::PINK_NOISE_TYPE; }, [m]() { m->_noiseType = SampleHold::PINK_NOISE_TYPE; }));
+ mi->addItem(OptionMenuItem("Red", [m]() { return m->_noiseType == SampleHold::RED_NOISE_TYPE; }, [m]() { m->_noiseType = SampleHold::RED_NOISE_TYPE; }));
+ menu->addChild(mi);
+ }
+ {
+ OptionsMenuItem* mi = new OptionsMenuItem("Normal range");
+ mi->addItem(RangeOptionMenuItem(m, "+/-10V", 0.0f, 10.0f));
+ mi->addItem(RangeOptionMenuItem(m, "+/-5V", 0.0f, 5.0f));
+ mi->addItem(RangeOptionMenuItem(m, "+/-3V", 0.0f, 3.0f));
+ mi->addItem(RangeOptionMenuItem(m, "+/-1V", 0.0f, 1.0f));
+ mi->addItem(RangeOptionMenuItem(m, "0V-10V", 1.0f, 5.0f));
+ mi->addItem(RangeOptionMenuItem(m, "0V-5V", 1.0f, 2.5f));
+ mi->addItem(RangeOptionMenuItem(m, "0V-3V", 1.0f, 1.5f));
+ mi->addItem(RangeOptionMenuItem(m, "0V-1V", 1.0f, 0.5f));
+ menu->addChild(mi);
+ }
}
};
diff --git a/src/UMix.cpp b/src/UMix.cpp
@@ -122,50 +122,12 @@ struct UMixWidget : ModuleWidget {
addOutput(createOutput<Port24>(outOutputPosition, module, UMix::OUT_OUTPUT));
}
- struct AverageMenuItem : MenuItem {
- UMix* _module;
-
- AverageMenuItem(UMix* module, const char* label)
- : _module(module)
- {
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_sum = !_module->_sum;
- }
-
- void step() override {
- MenuItem::step();
- rightText = !_module->_sum ? "✔" : "";
- }
- };
-
- struct CVModeMenuItem : MenuItem {
- UMix* _module;
-
- CVModeMenuItem(UMix* module, const char* label)
- : _module(module)
- {
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_cvMode = !_module->_cvMode;
- }
-
- void step() override {
- MenuItem::step();
- rightText = _module->_cvMode ? "✔" : "";
- }
- };
-
void appendContextMenu(Menu* menu) override {
- UMix* umix = dynamic_cast<UMix*>(module);
- assert(umix);
+ UMix* m = dynamic_cast<UMix*>(module);
+ assert(m);
menu->addChild(new MenuLabel());
- menu->addChild(new AverageMenuItem(umix, "Average"));
- menu->addChild(new CVModeMenuItem(umix, "CV mode"));
+ menu->addChild(new OptionMenuItem("Average", [m]() { return !m->_sum; }, [m]() { m->_sum = !m->_sum; }));
+ menu->addChild(new BoolOptionMenuItem("CV mode", [m]() { return &m->_cvMode; }));
}
};
diff --git a/src/Walk2.cpp b/src/Walk2.cpp
@@ -485,79 +485,26 @@ struct Walk2Widget : ModuleWidget {
addOutput(createOutput<Port24>(distanceOutputPosition, module, Walk2::DISTANCE_OUTPUT));
}
- struct ZoomOutMenuItem : MenuItem {
- Walk2* _module;
- const bool _zoomOut;
+ void appendContextMenu(Menu* menu) override {
+ Walk2* m = dynamic_cast<Walk2*>(module);
+ assert(m);
- ZoomOutMenuItem(Walk2* module, const char* label, bool zoomOut)
- : _module(module)
- , _zoomOut(zoomOut)
+ menu->addChild(new MenuLabel());
{
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_zoomOut = _zoomOut;
- }
-
- void step() override {
- MenuItem::step();
- rightText = _module->_zoomOut == _zoomOut ? "✔" : "";
- }
- };
-
- struct GridMenuItem : MenuItem {
- Walk2* _module;
-
- GridMenuItem(Walk2* module, const char* label) : _module(module) {
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_drawGrid = !_module->_drawGrid;
- }
-
- void step() override {
- MenuItem::step();
- rightText = _module->_drawGrid ? "✔" : "";
+ OptionsMenuItem* mi = new OptionsMenuItem("Display range");
+ mi->addItem(OptionMenuItem("+/-5V", [m]() { return m->_zoomOut == false; }, [m]() { m->_zoomOut = false; }));
+ mi->addItem(OptionMenuItem("+/-10V", [m]() { return m->_zoomOut == true; }, [m]() { m->_zoomOut = true; }));
+ menu->addChild(mi);
}
- };
-
- struct ColorMenuItem : MenuItem {
- Walk2* _module;
- const Walk2::TraceColor _color;
-
- ColorMenuItem(Walk2* module, const char* label, Walk2::TraceColor color)
- : _module(module)
- , _color(color)
+ menu->addChild(new BoolOptionMenuItem("Show grid", [m]() { return &m->_drawGrid; }));
{
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_traceColor = _color;
- }
-
- void step() override {
- MenuItem::step();
- rightText = _module->_traceColor == _color ? "✔" : "";
+ OptionsMenuItem* mi = new OptionsMenuItem("Trace color");
+ mi->addItem(OptionMenuItem("Green", [m]() { return m->_traceColor == Walk2::GREEN_TRACE_COLOR; }, [m]() { m->_traceColor = Walk2::GREEN_TRACE_COLOR; }));
+ mi->addItem(OptionMenuItem("Orange", [m]() { return m->_traceColor == Walk2::ORANGE_TRACE_COLOR; }, [m]() { m->_traceColor = Walk2::ORANGE_TRACE_COLOR; }));
+ mi->addItem(OptionMenuItem("Red", [m]() { return m->_traceColor == Walk2::RED_TRACE_COLOR; }, [m]() { m->_traceColor = Walk2::RED_TRACE_COLOR; }));
+ mi->addItem(OptionMenuItem("Blue", [m]() { return m->_traceColor == Walk2::BLUE_TRACE_COLOR; }, [m]() { m->_traceColor = Walk2::BLUE_TRACE_COLOR; }));
+ menu->addChild(mi);
}
- };
-
- void appendContextMenu(Menu* menu) override {
- Walk2* w = dynamic_cast<Walk2*>(module);
- assert(w);
-
- menu->addChild(new MenuLabel());
- menu->addChild(new ZoomOutMenuItem(w, "Display range: +/-5V", false));
- menu->addChild(new ZoomOutMenuItem(w, "Display range: +/-10V", true));
- menu->addChild(new MenuLabel());
- menu->addChild(new GridMenuItem(w, "Show grid"));
- menu->addChild(new MenuLabel());
- menu->addChild(new ColorMenuItem(w, "Trace color: green", Walk2::GREEN_TRACE_COLOR));
- menu->addChild(new ColorMenuItem(w, "Trace color: orange", Walk2::ORANGE_TRACE_COLOR));
- menu->addChild(new ColorMenuItem(w, "Trace color: red", Walk2::RED_TRACE_COLOR));
- menu->addChild(new ColorMenuItem(w, "Trace color: blue", Walk2::BLUE_TRACE_COLOR));
}
};
diff --git a/src/addressable_sequence.hpp b/src/addressable_sequence.hpp
@@ -37,50 +37,12 @@ struct AddressableSequenceModule : BGModule {
};
struct AddressableSequenceModuleWidget : ModuleWidget {
- struct SelectOnClockMenuItem : MenuItem {
- AddressableSequenceModule* _module;
-
- SelectOnClockMenuItem(AddressableSequenceModule* module, const char* label)
- : _module(module)
- {
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_selectOnClock = !_module->_selectOnClock;
- }
-
- void step() override {
- MenuItem::step();
- rightText = _module->_selectOnClock ? "✔" : "";
- }
- };
-
- struct TriggeredSelectMenuItem : MenuItem {
- AddressableSequenceModule* _module;
-
- TriggeredSelectMenuItem(AddressableSequenceModule* module, const char* label)
- : _module(module)
- {
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_triggeredSelect = !_module->_triggeredSelect;
- }
-
- void step() override {
- MenuItem::step();
- rightText = _module->_triggeredSelect ? "✔" : "";
- }
- };
-
void appendContextMenu(Menu* menu) override {
AddressableSequenceModule* m = dynamic_cast<AddressableSequenceModule*>(module);
assert(m);
menu->addChild(new MenuLabel());
- menu->addChild(new SelectOnClockMenuItem(m, "Select on clock mode"));
- menu->addChild(new TriggeredSelectMenuItem(m, "Triggered select mode"));
+ menu->addChild(new BoolOptionMenuItem("Select on clock mode", [m]() { return &m->_selectOnClock; }));
+ menu->addChild(new BoolOptionMenuItem("Triggered select mode", [m]() { return &m->_triggeredSelect; }));
}
};
diff --git a/src/bogaudio.hpp b/src/bogaudio.hpp
@@ -10,6 +10,7 @@
#include "rack.hpp"
#include "module.hpp"
+#include "menu.hpp"
#include "param_quantities.hpp"
#include "rack_overrides.hpp"
#include "widgets.hpp"
diff --git a/src/disable_output_limit.hpp b/src/disable_output_limit.hpp
@@ -12,30 +12,11 @@ struct DisableOutputLimitModule : BGModule {
};
struct DisableOutputLimitModuleWidget : ModuleWidget {
- struct DisableOutputLimitMenuItem : MenuItem {
- DisableOutputLimitModule* _module;
-
- DisableOutputLimitMenuItem(DisableOutputLimitModule* module, const char* label)
- : _module(module)
- {
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_disableOutputLimit = !_module->_disableOutputLimit;
- }
-
- void step() override {
- MenuItem::step();
- rightText = _module->_disableOutputLimit ? "✔" : "";
- }
- };
-
void appendContextMenu(Menu* menu) override {
- DisableOutputLimitModule* dolm = dynamic_cast<DisableOutputLimitModule*>(module);
- assert(dolm);
+ DisableOutputLimitModule* m = dynamic_cast<DisableOutputLimitModule*>(module);
+ assert(m);
menu->addChild(new MenuLabel());
- menu->addChild(new DisableOutputLimitMenuItem(dolm, "Disable output limit"));
+ menu->addChild(new BoolOptionMenuItem("Disable output limit", [m]() { return &m->_disableOutputLimit; }));
}
};
diff --git a/src/menu.hpp b/src/menu.hpp
@@ -0,0 +1,57 @@
+#pragma once
+
+#include "rack.hpp"
+
+using namespace rack;
+
+namespace bogaudio {
+
+struct OptionMenuItem : MenuItem {
+ std::function<bool()> _check;
+ std::function<void()> _set;
+
+ OptionMenuItem(const char* label, std::function<bool()> check, std::function<void()> set)
+ : _check(check)
+ , _set(set)
+ {
+ this->text = label;
+ }
+
+ void onAction(const event::Action& e) override {
+ _set();
+ }
+
+ void step() override {
+ MenuItem::step();
+ rightText = _check() ? "✔" : "";
+ }
+};
+
+struct BoolOptionMenuItem : OptionMenuItem {
+ BoolOptionMenuItem(const char* label, std::function<bool*()> get)
+ : OptionMenuItem(label, [=]() { return *(get()); }, [=]() { bool* b = get(); *b = !*b; })
+ {}
+};
+
+struct OptionsMenuItem : MenuItem {
+ std::vector<OptionMenuItem> _items;
+
+ OptionsMenuItem(const char* label) {
+ this->text = label;
+ this->rightText = "▸";
+ }
+
+ void addItem(const OptionMenuItem& item) {
+ _items.push_back(item);
+ }
+
+ Menu* createChildMenu() override {
+ Menu* menu = new Menu;
+ for (const OptionMenuItem& item : _items) {
+ menu->addChild(new OptionMenuItem(item));
+ }
+ return menu;
+ }
+};
+
+} // namespace bogaudio
diff --git a/src/trigger_on_load.hpp b/src/trigger_on_load.hpp
@@ -17,30 +17,17 @@ struct TriggerOnLoadModule : BGModule {
};
struct TriggerOnLoadModuleWidget : ModuleWidget {
- struct TriggerOnLoadMenuItem : MenuItem {
- TriggerOnLoadModule* _module;
+ std::string _menuItemLabel;
- TriggerOnLoadMenuItem(TriggerOnLoadModule* module, const char* label)
- : _module(module)
- {
- this->text = label;
- }
-
- void onAction(const event::Action& e) override {
- _module->_triggerOnLoad = !_module->_triggerOnLoad;
- }
-
- void step() override {
- MenuItem::step();
- rightText = _module->_triggerOnLoad ? "✔" : "";
- }
- };
+ TriggerOnLoadModuleWidget(const char* menuItemLabel = "Resume loop on load")
+ : _menuItemLabel(menuItemLabel)
+ {}
void appendContextMenu(Menu* menu) override {
TriggerOnLoadModule* m = dynamic_cast<TriggerOnLoadModule*>(module);
assert(m);
menu->addChild(new MenuLabel());
- menu->addChild(new TriggerOnLoadMenuItem(m, "Resume loop on load"));
+ menu->addChild(new BoolOptionMenuItem(_menuItemLabel.c_str(), [m]() { return &m->_triggerOnLoad; }));
}
};