@@ -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() { | ||||