| @@ -3,6 +3,8 @@ Tip: Use `git checkout v0.4.0` for example to check out any previous version men | |||||
| ### dev | ### dev | ||||
| - Automatically scroll when dragging cables to the edge of the screen | |||||
| - Audible Instruments | - Audible Instruments | ||||
| - Added Low CPU mode to Braids for draft-quality rendering | - Added Low CPU mode to Braids for draft-quality rendering | ||||
| @@ -288,7 +288,6 @@ struct Menu : OpaqueWidget { | |||||
| // Resizes menu and calls addChild() | // Resizes menu and calls addChild() | ||||
| void pushChild(Widget *child); | void pushChild(Widget *child); | ||||
| void setChildMenu(Menu *menu); | void setChildMenu(Menu *menu); | ||||
| void fit(); | |||||
| void step() override; | void step() override; | ||||
| void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
| bool onScrollOpaque(Vec scrollRel) override; | bool onScrollOpaque(Vec scrollRel) override; | ||||
| @@ -300,7 +299,7 @@ struct MenuEntry : OpaqueWidget { | |||||
| MenuEntry() { | MenuEntry() { | ||||
| box.size = Vec(0, BND_WIDGET_HEIGHT); | box.size = Vec(0, BND_WIDGET_HEIGHT); | ||||
| } | } | ||||
| virtual float computeMinWidth(NVGcontext *vg); | |||||
| void step() override; | |||||
| }; | }; | ||||
| struct MenuLabel : MenuEntry { | struct MenuLabel : MenuEntry { | ||||
| @@ -308,9 +307,7 @@ struct MenuLabel : MenuEntry { | |||||
| }; | }; | ||||
| struct MenuItem : MenuEntry { | struct MenuItem : MenuEntry { | ||||
| float computeMinWidth(NVGcontext *vg) override; | |||||
| void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
| virtual Menu *createChildMenu() {return NULL;} | virtual Menu *createChildMenu() {return NULL;} | ||||
| void onMouseEnter() override; | void onMouseEnter() override; | ||||
| void onDragDrop(Widget *origin) override; | void onDragDrop(Widget *origin) override; | ||||
| @@ -453,6 +453,25 @@ struct AddManufacturerMenuItem : MenuItem { | |||||
| } | } | ||||
| }; | }; | ||||
| struct SearchModuleField : TextField { | |||||
| void onTextChange() override { | |||||
| Menu *parentMenu = getAncestorOfType<Menu>(); | |||||
| assert(parentMenu); | |||||
| for (Widget *w : parentMenu->children) { | |||||
| AddManufacturerMenuItem *a = dynamic_cast<AddManufacturerMenuItem*>(w); | |||||
| if (!a) | |||||
| continue; | |||||
| if (a->manufacturerName == text) { | |||||
| a->visible = true; | |||||
| } | |||||
| else { | |||||
| a->visible = false; | |||||
| } | |||||
| } | |||||
| } | |||||
| }; | |||||
| 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()); | ||||
| @@ -460,11 +479,14 @@ void RackWidget::onMouseDownOpaque(int button) { | |||||
| menu->pushChild(construct<MenuLabel>(&MenuLabel::text, "Add module")); | menu->pushChild(construct<MenuLabel>(&MenuLabel::text, "Add module")); | ||||
| /* | |||||
| // TODO make functional | // TODO make functional | ||||
| TextField *searchField = construct<TextField>(); | |||||
| TextField *searchField = construct<SearchModuleField>(); | |||||
| searchField->box.size.x = 100.0; | |||||
| menu->pushChild(searchField); | menu->pushChild(searchField); | ||||
| // Focus search field | // Focus search field | ||||
| gFocusedWidget = searchField; | gFocusedWidget = searchField; | ||||
| */ | |||||
| // Collect manufacturer names | // Collect manufacturer names | ||||
| std::set<std::string> manufacturerNames; | std::set<std::string> manufacturerNames; | ||||
| @@ -27,35 +27,27 @@ void Menu::setChildMenu(Menu *menu) { | |||||
| } | } | ||||
| } | } | ||||
| void Menu::fit() { | |||||
| void Menu::step() { | |||||
| // Try to fit into the parent's box | // Try to fit into the parent's box | ||||
| if (parent) | if (parent) | ||||
| box = box.clamp(Rect(Vec(0, 0), parent->box.size)); | box = box.clamp(Rect(Vec(0, 0), parent->box.size)); | ||||
| } | |||||
| void Menu::step() { | |||||
| fit(); | |||||
| Widget::step(); | Widget::step(); | ||||
| } | |||||
| void Menu::draw(NVGcontext *vg) { | |||||
| // Resize the width to the widest child | // Resize the width to the widest child | ||||
| for (Widget *child : children) { | for (Widget *child : children) { | ||||
| MenuEntry *menuEntry = dynamic_cast<MenuEntry*>(child); | |||||
| if (!menuEntry) | |||||
| continue; | |||||
| float width = menuEntry->computeMinWidth(vg); | |||||
| if (width > box.size.x) { | |||||
| box.size.x = width; | |||||
| if (child->box.size.x > box.size.x) { | |||||
| box.size.x = child->box.size.x; | |||||
| } | } | ||||
| } | } | ||||
| // Resize widths of children | // Resize widths of children | ||||
| for (Widget *child : children) { | for (Widget *child : children) { | ||||
| child->box.size.x = box.size.x; | child->box.size.x = box.size.x; | ||||
| } | } | ||||
| } | |||||
| void Menu::draw(NVGcontext *vg) { | |||||
| bndMenuBackground(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE); | bndMenuBackground(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE); | ||||
| Widget::draw(vg); | Widget::draw(vg); | ||||
| } | } | ||||
| @@ -65,7 +57,6 @@ bool Menu::onScrollOpaque(Vec scrollRel) { | |||||
| return true; | return true; | ||||
| if (!parent->box.contains(box)) | if (!parent->box.contains(box)) | ||||
| box.pos = box.pos.plus(scrollRel); | box.pos = box.pos.plus(scrollRel); | ||||
| fit(); | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -1,12 +1,17 @@ | |||||
| #include "widgets.hpp" | #include "widgets.hpp" | ||||
| #include "gui.hpp" | |||||
| namespace rack { | namespace rack { | ||||
| float MenuEntry::computeMinWidth(NVGcontext *vg) { | |||||
| void MenuEntry::step() { | |||||
| // Add 10 more pixels because Retina measurements are sometimes too small | // Add 10 more pixels because Retina measurements are sometimes too small | ||||
| return bndLabelWidth(vg, -1, text.c_str()) + 10.0; | |||||
| const float rightPadding = 10.0; | |||||
| // HACK use gVg from the gui. | |||||
| // All this does is inspect the font, so it shouldn't modify gVg and should work when called from a FramebufferWidget for example. | |||||
| box.size.x = bndLabelWidth(gVg, -1, text.c_str()) + bndLabelWidth(gVg, -1, rightText.c_str()) + rightPadding; | |||||
| Widget::step(); | |||||
| } | } | ||||
| @@ -4,12 +4,8 @@ | |||||
| namespace rack { | namespace rack { | ||||
| #define RIGHT_PADDING 10.0 | |||||
| #define BND_LABEL_FONT_SIZE 13 | #define BND_LABEL_FONT_SIZE 13 | ||||
| float MenuItem::computeMinWidth(NVGcontext *vg) { | |||||
| return MenuEntry::computeMinWidth(vg) + RIGHT_PADDING + bndLabelWidth(vg, -1, rightText.c_str()); | |||||
| } | |||||
| void MenuItem::draw(NVGcontext *vg) { | void MenuItem::draw(NVGcontext *vg) { | ||||
| // Get state | // Get state | ||||