Adding context menu modes to your module

Suppose you need to add a setting with 3 modes to your context menu. Here’s what I do, so I’m posting it here for others’ reference.

In MyModule:

	int mode = 0;

	...

	void onReset() override {
		mode = 0;
	}

	void onRandomize() override {
		// It's usually not a good idea to randomize modes, because
		// users might not know how to switch back, but I'm including
		// this for completeness.
		mode = random::u32() % 3;
	}

	...

	json_t* dataToJson() override {
		json_t* rootJ = json_object();
		json_object_set_new(rootJ, "mode", json_integer(mode));
		return rootJ;
	}

	void dataFromJson(json_t* rootJ) override {
		json_t* modeJ = json_object_get(rootJ, "mode");
		if (modeJ)
			mode = json_integer_value(modeJ);
	}

In MyModuleWidget:

	void appendContextMenu(Menu* menu) override {
		MyModule* module = dynamic_cast<MyModule*>(this->module);

		menu->addChild(new MenuEntry);
		menu->addChild(createMenuLabel("Mode"));

		struct ModeItem : MenuItem {
			MyModule* module;
			int mode;
			void onAction(const event::Action& e) override {
				module->mode = mode;
			}
		};

		std::string modeNames[3] = {"Mode 1", "Mode 2", "Mode 3"};
		for (int i = 0; i < 3; i++) {
			ModeItem* modeItem = createMenuItem<ModeItem>(modeNames[i]);
			modeItem->rightText = CHECKMARK(module->mode == i);
			modeItem->module = module;
			modeItem->mode = i;
			menu->addChild(modeItem);
		}
	}

Result: 2019-09-23-003631_1600x900_scrot

12 Likes

Thanks, now boogie bay has selectable voltage ranges. How do I best get at MyModule mode from MyModuleWidget step()? Do I have to do the dynamic cast thing or is there another way?

I tend to keep a pointer to it in my ModuleWidget:

struct JackDanceModuleWidget : ModuleWidget {
    JackDanceModuleWidget(JackDanceModule* module) {
        setModule(module);
        _module = module;
    }

    void step() override {
        if (_module) ...
    }

    JackDanceModule* _module;
};

It’s arguably redundant because of ModuleWidget::module, but it means I have a pointer of the right type without casting.

1 Like

This is a great example, Andrew, thanks! It would be very nice to pull it into the Developer documentation page at some point.

The huge number of open source plugins is sort of a developers manual.

2 Likes