| @@ -261,11 +261,16 @@ struct MenuOverlay : OpaqueWidget { | |||||
| }; | }; | ||||
| struct Menu : OpaqueWidget { | struct Menu : OpaqueWidget { | ||||
| Menu *parentMenu = NULL; | |||||
| Menu *childMenu = NULL; | |||||
| Menu() { | Menu() { | ||||
| box.size = Vec(0, 0); | box.size = Vec(0, 0); | ||||
| } | } | ||||
| ~Menu(); | |||||
| // Resizes menu and calls addChild() | // Resizes menu and calls addChild() | ||||
| void pushChild(Widget *child); | void pushChild(Widget *child); | ||||
| void setChildMenu(Menu *menu); | |||||
| void fit(); | void fit(); | ||||
| void step(); | void step(); | ||||
| void draw(NVGcontext *vg); | void draw(NVGcontext *vg); | ||||
| @@ -291,8 +296,9 @@ struct MenuItem : MenuEntry { | |||||
| float computeMinWidth(NVGcontext *vg); | float computeMinWidth(NVGcontext *vg); | ||||
| void draw(NVGcontext *vg); | void draw(NVGcontext *vg); | ||||
| virtual Menu *createChildMenu() {return NULL;} | |||||
| void onMouseEnter(); | void onMouseEnter(); | ||||
| void onMouseLeave() ; | |||||
| void onMouseLeave(); | |||||
| void onDragDrop(Widget *origin); | void onDragDrop(Widget *origin); | ||||
| }; | }; | ||||
| @@ -366,6 +366,22 @@ struct AddModuleMenuItem : MenuItem { | |||||
| } | } | ||||
| }; | }; | ||||
| struct AddPluginMenuItem : MenuItem { | |||||
| Plugin *plugin; | |||||
| Vec modulePos; | |||||
| Menu *createChildMenu() { | |||||
| Menu *menu = new Menu(); | |||||
| for (Model *model : plugin->models) { | |||||
| AddModuleMenuItem *item = new AddModuleMenuItem(); | |||||
| item->text = model->name; | |||||
| item->model = model; | |||||
| item->modulePos = modulePos; | |||||
| menu->pushChild(item); | |||||
| } | |||||
| return menu; | |||||
| } | |||||
| }; | |||||
| void RackWidget::onMouseDownOpaque(int button) { | void RackWidget::onMouseDownOpaque(int button) { | ||||
| if (button == 1) { | if (button == 1) { | ||||
| Vec modulePos = gMousePos.minus(getAbsolutePos()); | Vec modulePos = gMousePos.minus(getAbsolutePos()); | ||||
| @@ -375,14 +391,11 @@ void RackWidget::onMouseDownOpaque(int button) { | |||||
| menuLabel->text = "Add Module"; | menuLabel->text = "Add Module"; | ||||
| menu->pushChild(menuLabel); | menu->pushChild(menuLabel); | ||||
| for (Plugin *plugin : gPlugins) { | for (Plugin *plugin : gPlugins) { | ||||
| for (Model *model : plugin->models) { | |||||
| AddModuleMenuItem *item = new AddModuleMenuItem(); | |||||
| item->text = model->name; | |||||
| item->rightText = model->plugin->name; | |||||
| item->model = model; | |||||
| item->modulePos = modulePos; | |||||
| menu->pushChild(item); | |||||
| } | |||||
| AddPluginMenuItem *item = new AddPluginMenuItem(); | |||||
| item->text = plugin->name; | |||||
| item->plugin = plugin; | |||||
| item->modulePos = modulePos; | |||||
| menu->pushChild(item); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -3,12 +3,30 @@ | |||||
| namespace rack { | namespace rack { | ||||
| Menu::~Menu() { | |||||
| setChildMenu(NULL); | |||||
| } | |||||
| void Menu::pushChild(Widget *child) { | void Menu::pushChild(Widget *child) { | ||||
| child->box.pos = Vec(0, box.size.y); | child->box.pos = Vec(0, box.size.y); | ||||
| addChild(child); | addChild(child); | ||||
| box.size.y += child->box.size.y; | box.size.y += child->box.size.y; | ||||
| } | } | ||||
| void Menu::setChildMenu(Menu *menu) { | |||||
| if (childMenu) { | |||||
| if (childMenu->parent) | |||||
| childMenu->parent->removeChild(childMenu); | |||||
| delete childMenu; | |||||
| childMenu = NULL; | |||||
| } | |||||
| if (menu) { | |||||
| childMenu = menu; | |||||
| assert(parent); | |||||
| parent->addChild(childMenu); | |||||
| } | |||||
| } | |||||
| void Menu::fit() { | void Menu::fit() { | ||||
| // Try to fit into the parent's box | // Try to fit into the parent's box | ||||
| if (parent) | if (parent) | ||||
| @@ -22,6 +22,15 @@ void MenuItem::draw(NVGcontext *vg) { | |||||
| void MenuItem::onMouseEnter() { | void MenuItem::onMouseEnter() { | ||||
| state = BND_HOVER; | state = BND_HOVER; | ||||
| // Try to create child menu | |||||
| Menu *childMenu = createChildMenu(); | |||||
| if (childMenu) { | |||||
| childMenu->box.pos = parent->box.pos.plus(box.getTopRight()); | |||||
| Menu *parentMenu = dynamic_cast<Menu*>(parent); | |||||
| assert(parentMenu); | |||||
| parentMenu->setChildMenu(childMenu); | |||||
| } | |||||
| } | } | ||||
| void MenuItem::onMouseLeave() { | void MenuItem::onMouseLeave() { | ||||