| @@ -29,6 +29,7 @@ struct PortWidget : OpaqueWidget { | |||||
| void onDragDrop(const event::DragDrop &e) override; | void onDragDrop(const event::DragDrop &e) override; | ||||
| void onDragEnter(const event::DragEnter &e) override; | void onDragEnter(const event::DragEnter &e) override; | ||||
| void onDragLeave(const event::DragLeave &e) override; | void onDragLeave(const event::DragLeave &e) override; | ||||
| void setHovered(); | |||||
| }; | }; | ||||
| @@ -37,7 +37,6 @@ | |||||
| #include "ui/IconButton.hpp" | #include "ui/IconButton.hpp" | ||||
| #include "ui/ChoiceButton.hpp" | #include "ui/ChoiceButton.hpp" | ||||
| #include "ui/RadioButton.hpp" | #include "ui/RadioButton.hpp" | ||||
| #include "ui/WindowWidget.hpp" | |||||
| #include "ui/ProgressBar.hpp" | #include "ui/ProgressBar.hpp" | ||||
| #include "app/AudioWidget.hpp" | #include "app/AudioWidget.hpp" | ||||
| @@ -13,45 +13,14 @@ struct Button : OpaqueWidget { | |||||
| /** Optional, owned. Tracks the pressed state of the button.*/ | /** Optional, owned. Tracks the pressed state of the button.*/ | ||||
| Quantity *quantity = NULL; | Quantity *quantity = NULL; | ||||
| Button() { | |||||
| box.size.y = BND_WIDGET_HEIGHT; | |||||
| } | |||||
| ~Button() { | |||||
| if (quantity) | |||||
| delete quantity; | |||||
| } | |||||
| void draw(NVGcontext *vg) override { | |||||
| bndToolButton(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str()); | |||||
| } | |||||
| void onEnter(const event::Enter &e) override { | |||||
| state = BND_HOVER; | |||||
| } | |||||
| void onLeave(const event::Leave &e) override { | |||||
| state = BND_DEFAULT; | |||||
| } | |||||
| void onDragStart(const event::DragStart &e) override { | |||||
| state = BND_ACTIVE; | |||||
| if (quantity) | |||||
| quantity->setMax(); | |||||
| } | |||||
| void onDragEnd(const event::DragEnd &e) override { | |||||
| state = BND_HOVER; | |||||
| if (quantity) | |||||
| quantity->setMin(); | |||||
| } | |||||
| void onDragDrop(const event::DragDrop &e) override { | |||||
| if (e.origin == this) { | |||||
| event::Action eAction; | |||||
| onAction(eAction); | |||||
| } | |||||
| } | |||||
| Button(); | |||||
| ~Button(); | |||||
| void draw(NVGcontext *vg) override; | |||||
| void onEnter(const event::Enter &e) override; | |||||
| void onLeave(const event::Leave &e) override; | |||||
| void onDragStart(const event::DragStart &e) override; | |||||
| void onDragEnd(const event::DragEnd &e) override; | |||||
| void onDragDrop(const event::DragDrop &e) override; | |||||
| }; | }; | ||||
| @@ -7,9 +7,7 @@ namespace rack { | |||||
| struct ChoiceButton : Button { | struct ChoiceButton : Button { | ||||
| void draw(NVGcontext *vg) override { | |||||
| bndChoiceButton(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str()); | |||||
| } | |||||
| void draw(NVGcontext *vg) override; | |||||
| }; | }; | ||||
| @@ -12,22 +12,8 @@ struct IconButton : Button { | |||||
| FramebufferWidget *fw; | FramebufferWidget *fw; | ||||
| SVGWidget *sw; | SVGWidget *sw; | ||||
| IconButton() { | |||||
| box.size.x = BND_TOOL_WIDTH; | |||||
| fw = new FramebufferWidget; | |||||
| fw->oversample = 2; | |||||
| addChild(fw); | |||||
| sw = new SVGWidget; | |||||
| sw->box.pos = math::Vec(2, 2); | |||||
| fw->addChild(sw); | |||||
| } | |||||
| void setSVG(std::shared_ptr<SVG> svg) { | |||||
| sw->setSVG(svg); | |||||
| fw->dirty = true; | |||||
| } | |||||
| IconButton(); | |||||
| void setSVG(std::shared_ptr<SVG> svg); | |||||
| }; | }; | ||||
| @@ -18,31 +18,8 @@ struct Label : virtual Widget { | |||||
| NVGcolor color; | NVGcolor color; | ||||
| Alignment alignment = LEFT_ALIGNMENT; | Alignment alignment = LEFT_ALIGNMENT; | ||||
| Label() { | |||||
| box.size.y = BND_WIDGET_HEIGHT; | |||||
| fontSize = 13; | |||||
| color = bndGetTheme()->regularTheme.textColor; | |||||
| } | |||||
| void draw(NVGcontext *vg) override { | |||||
| // TODO | |||||
| // Custom font sizes do not work with right or center alignment | |||||
| float x; | |||||
| switch (alignment) { | |||||
| default: | |||||
| case LEFT_ALIGNMENT: { | |||||
| x = 0.0; | |||||
| } break; | |||||
| case RIGHT_ALIGNMENT: { | |||||
| x = box.size.x - bndLabelWidth(vg, -1, text.c_str()); | |||||
| } break; | |||||
| case CENTER_ALIGNMENT: { | |||||
| x = (box.size.x - bndLabelWidth(vg, -1, text.c_str())) / 2.0; | |||||
| } break; | |||||
| } | |||||
| bndIconLabelValue(vg, x, 0.0, box.size.x, box.size.y, -1, color, BND_LEFT, fontSize, text.c_str(), NULL); | |||||
| } | |||||
| Label(); | |||||
| void draw(NVGcontext *vg) override; | |||||
| }; | }; | ||||
| @@ -7,21 +7,7 @@ namespace rack { | |||||
| struct List : OpaqueWidget { | struct List : OpaqueWidget { | ||||
| void step() override { | |||||
| Widget::step(); | |||||
| // Set positions of children | |||||
| box.size.y = 0.0; | |||||
| for (Widget *child : children) { | |||||
| if (!child->visible) | |||||
| continue; | |||||
| // Increment height, set position of child | |||||
| child->box.pos = math::Vec(0.0, box.size.y); | |||||
| box.size.y += child->box.size.y; | |||||
| // Resize width of child | |||||
| child->box.size.x = box.size.x; | |||||
| } | |||||
| } | |||||
| void step() override; | |||||
| }; | }; | ||||
| @@ -7,9 +7,7 @@ namespace rack { | |||||
| struct MenuEntry : OpaqueWidget { | struct MenuEntry : OpaqueWidget { | ||||
| MenuEntry() { | |||||
| box.size = math::Vec(0, BND_WIDGET_HEIGHT); | |||||
| } | |||||
| MenuEntry(); | |||||
| }; | }; | ||||
| @@ -1,7 +1,6 @@ | |||||
| #pragma once | #pragma once | ||||
| #include "ui/common.hpp" | #include "ui/common.hpp" | ||||
| #include "ui/MenuEntry.hpp" | #include "ui/MenuEntry.hpp" | ||||
| #include "app.hpp" | |||||
| namespace rack { | namespace rack { | ||||
| @@ -10,17 +9,8 @@ namespace rack { | |||||
| struct MenuLabel : MenuEntry { | struct MenuLabel : MenuEntry { | ||||
| std::string text; | std::string text; | ||||
| void draw(NVGcontext *vg) override { | |||||
| bndMenuLabel(vg, 0.0, 0.0, box.size.x, box.size.y, -1, text.c_str()); | |||||
| } | |||||
| void step() override { | |||||
| // Add 10 more pixels because Retina measurements are sometimes too small | |||||
| const float rightPadding = 10.0; | |||||
| // HACK use app()->window->vg from the window. | |||||
| box.size.x = bndLabelWidth(app()->window->vg, -1, text.c_str()) + rightPadding; | |||||
| Widget::step(); | |||||
| } | |||||
| void draw(NVGcontext *vg) override; | |||||
| void step() override; | |||||
| }; | }; | ||||
| @@ -7,19 +7,8 @@ namespace rack { | |||||
| struct MenuSeparator : MenuEntry { | struct MenuSeparator : MenuEntry { | ||||
| MenuSeparator() { | |||||
| box.size.y = BND_WIDGET_HEIGHT / 2; | |||||
| } | |||||
| void draw(NVGcontext *vg) override { | |||||
| nvgBeginPath(vg); | |||||
| const float margin = 8.0; | |||||
| nvgMoveTo(vg, margin, box.size.y / 2.0); | |||||
| nvgLineTo(vg, box.size.x - margin, box.size.y / 2.0); | |||||
| nvgStrokeWidth(vg, 1.0); | |||||
| nvgStrokeColor(vg, color::alpha(bndGetTheme()->menuTheme.textColor, 0.25)); | |||||
| nvgStroke(vg); | |||||
| } | |||||
| MenuSeparator(); | |||||
| void draw(NVGcontext *vg) override; | |||||
| }; | }; | ||||
| @@ -7,12 +7,7 @@ namespace rack { | |||||
| struct PasswordField : TextField { | struct PasswordField : TextField { | ||||
| void draw(NVGcontext *vg) override { | |||||
| std::string textTmp = text; | |||||
| text = std::string(textTmp.size(), '*'); | |||||
| TextField::draw(vg); | |||||
| text = textTmp; | |||||
| } | |||||
| void draw(NVGcontext *vg) override; | |||||
| }; | }; | ||||
| @@ -1,5 +1,7 @@ | |||||
| #pragma once | #pragma once | ||||
| #include "ui/common.hpp" | #include "ui/common.hpp" | ||||
| #include "widgets/Widget.hpp" | |||||
| #include "ui/Quantity.hpp" | |||||
| namespace rack { | namespace rack { | ||||
| @@ -8,20 +10,9 @@ namespace rack { | |||||
| struct ProgressBar : virtual Widget { | struct ProgressBar : virtual Widget { | ||||
| Quantity *quantity = NULL; | Quantity *quantity = NULL; | ||||
| ProgressBar() { | |||||
| box.size.y = BND_WIDGET_HEIGHT; | |||||
| } | |||||
| ~ProgressBar() { | |||||
| if (quantity) | |||||
| delete quantity; | |||||
| } | |||||
| void draw(NVGcontext *vg) override { | |||||
| float progress = quantity ? quantity->getScaledValue() : 0.f; | |||||
| std::string text = quantity ? quantity->getString() : ""; | |||||
| bndSlider(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_ALL, BND_DEFAULT, progress, text.c_str(), NULL); | |||||
| } | |||||
| ProgressBar(); | |||||
| ~ProgressBar(); | |||||
| void draw(NVGcontext *vg) override; | |||||
| }; | }; | ||||
| @@ -1,6 +1,7 @@ | |||||
| #pragma once | #pragma once | ||||
| #include "widgets/OpaqueWidget.hpp" | |||||
| #include "ui/common.hpp" | #include "ui/common.hpp" | ||||
| #include "widgets/OpaqueWidget.hpp" | |||||
| #include "ui/Quantity.hpp" | |||||
| namespace rack { | namespace rack { | ||||
| @@ -10,49 +11,12 @@ struct RadioButton : OpaqueWidget { | |||||
| BNDwidgetState state = BND_DEFAULT; | BNDwidgetState state = BND_DEFAULT; | ||||
| Quantity *quantity = NULL; | Quantity *quantity = NULL; | ||||
| RadioButton() { | |||||
| box.size.y = BND_WIDGET_HEIGHT; | |||||
| } | |||||
| ~RadioButton() { | |||||
| if (quantity) | |||||
| delete quantity; | |||||
| } | |||||
| void draw(NVGcontext *vg) override { | |||||
| std::string label; | |||||
| if (quantity) | |||||
| label = quantity->getLabel(); | |||||
| bndRadioButton(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, label.c_str()); | |||||
| } | |||||
| void onEnter(const event::Enter &e) override { | |||||
| if (state != BND_ACTIVE) | |||||
| state = BND_HOVER; | |||||
| } | |||||
| void onLeave(const event::Leave &e) override { | |||||
| if (state != BND_ACTIVE) | |||||
| state = BND_DEFAULT; | |||||
| } | |||||
| void onDragDrop(const event::DragDrop &e) override { | |||||
| if (e.origin == this) { | |||||
| if (state == BND_ACTIVE) { | |||||
| state = BND_HOVER; | |||||
| if (quantity) | |||||
| quantity->setMin(); | |||||
| } | |||||
| else { | |||||
| state = BND_ACTIVE; | |||||
| if (quantity) | |||||
| quantity->setMax(); | |||||
| } | |||||
| event::Action eAction; | |||||
| onAction(eAction); | |||||
| } | |||||
| } | |||||
| RadioButton(); | |||||
| ~RadioButton(); | |||||
| void draw(NVGcontext *vg) override; | |||||
| void onEnter(const event::Enter &e) override; | |||||
| void onLeave(const event::Leave &e) override; | |||||
| void onDragDrop(const event::DragDrop &e) override; | |||||
| }; | }; | ||||
| @@ -15,44 +15,13 @@ struct Slider : OpaqueWidget { | |||||
| BNDwidgetState state = BND_DEFAULT; | BNDwidgetState state = BND_DEFAULT; | ||||
| Quantity *quantity = NULL; | Quantity *quantity = NULL; | ||||
| Slider() { | |||||
| box.size.y = BND_WIDGET_HEIGHT; | |||||
| } | |||||
| ~Slider() { | |||||
| if (quantity) | |||||
| delete quantity; | |||||
| } | |||||
| void draw(NVGcontext *vg) override { | |||||
| float progress = quantity ? quantity->getScaledValue() : 0.f; | |||||
| std::string text = quantity ? quantity->getString() : ""; | |||||
| bndSlider(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, progress, text.c_str(), NULL); | |||||
| } | |||||
| void onDragStart(const event::DragStart &e) override { | |||||
| state = BND_ACTIVE; | |||||
| app()->window->cursorLock(); | |||||
| } | |||||
| void onDragMove(const event::DragMove &e) override { | |||||
| if (quantity) { | |||||
| quantity->moveScaledValue(SLIDER_SENSITIVITY * e.mouseDelta.x); | |||||
| } | |||||
| } | |||||
| void onDragEnd(const event::DragEnd &e) override { | |||||
| state = BND_DEFAULT; | |||||
| app()->window->cursorUnlock(); | |||||
| } | |||||
| void onButton(const event::Button &e) override { | |||||
| if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) { | |||||
| if (quantity) | |||||
| quantity->reset(); | |||||
| } | |||||
| e.consume(this); | |||||
| } | |||||
| Slider(); | |||||
| ~Slider(); | |||||
| void draw(NVGcontext *vg) override; | |||||
| void onDragStart(const event::DragStart &e) override; | |||||
| void onDragMove(const event::DragMove &e) override; | |||||
| void onDragEnd(const event::DragEnd &e) override; | |||||
| void onButton(const event::Button &e) override; | |||||
| }; | }; | ||||
| @@ -1,13 +0,0 @@ | |||||
| #pragma once | |||||
| #include "widgets/OpaqueWidget.hpp" | |||||
| #include "ui/common.hpp" | |||||
| namespace rack { | |||||
| struct WindowOverlay : OpaqueWidget { | |||||
| }; | |||||
| } // namespace rack | |||||
| @@ -1,23 +0,0 @@ | |||||
| #pragma once | |||||
| #include "widgets/OpaqueWidget.hpp" | |||||
| #include "ui/common.hpp" | |||||
| namespace rack { | |||||
| struct WindowWidget : OpaqueWidget { | |||||
| std::string title; | |||||
| void draw(NVGcontext *vg) override { | |||||
| bndNodeBackground(vg, 0.0, 0.0, box.size.x, box.size.y, BND_DEFAULT, -1, title.c_str(), bndGetTheme()->backgroundColor); | |||||
| Widget::draw(vg); | |||||
| } | |||||
| void onDragMove(const event::DragMove &e) override { | |||||
| box.pos = box.pos.plus(e.mouseDelta); | |||||
| } | |||||
| }; | |||||
| } // namespace rack | |||||
| @@ -99,10 +99,7 @@ void PortWidget::onDragDrop(const event::DragDrop &e) { | |||||
| if (!originPort) | if (!originPort) | ||||
| return; | return; | ||||
| // Fake onDragEnter because onDragLeave is triggered immediately before this one | |||||
| event::DragEnter eDragEnter; | |||||
| eDragEnter.origin = e.origin; | |||||
| onDragEnter(eDragEnter); | |||||
| setHovered(); | |||||
| } | } | ||||
| void PortWidget::onDragEnter(const event::DragEnter &e) { | void PortWidget::onDragEnter(const event::DragEnter &e) { | ||||
| @@ -110,17 +107,7 @@ void PortWidget::onDragEnter(const event::DragEnter &e) { | |||||
| if (!originPort) | if (!originPort) | ||||
| return; | return; | ||||
| // Reject ports if this is an input port and something is already plugged into it | |||||
| if (type == INPUT) { | |||||
| CableWidget *topCable = app()->scene->rackWidget->cableContainer->getTopCable(this); | |||||
| if (topCable) | |||||
| return; | |||||
| } | |||||
| CableWidget *activeCable = app()->scene->rackWidget->cableContainer->activeCable; | |||||
| if (activeCable) { | |||||
| (type == INPUT ? activeCable->hoveredInputPort : activeCable->hoveredOutputPort) = this; | |||||
| } | |||||
| setHovered(); | |||||
| } | } | ||||
| void PortWidget::onDragLeave(const event::DragLeave &e) { | void PortWidget::onDragLeave(const event::DragLeave &e) { | ||||
| @@ -134,5 +121,19 @@ void PortWidget::onDragLeave(const event::DragLeave &e) { | |||||
| } | } | ||||
| } | } | ||||
| void PortWidget::setHovered() { | |||||
| // Reject ports if this is an input port and something is already plugged into it | |||||
| if (type == INPUT) { | |||||
| CableWidget *topCable = app()->scene->rackWidget->cableContainer->getTopCable(this); | |||||
| if (topCable) | |||||
| return; | |||||
| } | |||||
| CableWidget *activeCable = app()->scene->rackWidget->cableContainer->activeCable; | |||||
| if (activeCable) { | |||||
| (type == INPUT ? activeCable->hoveredInputPort : activeCable->hoveredOutputPort) = this; | |||||
| } | |||||
| } | |||||
| } // namespace rack | } // namespace rack | ||||
| @@ -0,0 +1,48 @@ | |||||
| #include "ui/Button.hpp" | |||||
| namespace rack { | |||||
| Button::Button() { | |||||
| box.size.y = BND_WIDGET_HEIGHT; | |||||
| } | |||||
| Button::~Button() { | |||||
| if (quantity) | |||||
| delete quantity; | |||||
| } | |||||
| void Button::draw(NVGcontext *vg) { | |||||
| bndToolButton(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str()); | |||||
| } | |||||
| void Button::onEnter(const event::Enter &e) { | |||||
| state = BND_HOVER; | |||||
| } | |||||
| void Button::onLeave(const event::Leave &e) { | |||||
| state = BND_DEFAULT; | |||||
| } | |||||
| void Button::onDragStart(const event::DragStart &e) { | |||||
| state = BND_ACTIVE; | |||||
| if (quantity) | |||||
| quantity->setMax(); | |||||
| } | |||||
| void Button::onDragEnd(const event::DragEnd &e) { | |||||
| state = BND_HOVER; | |||||
| if (quantity) | |||||
| quantity->setMin(); | |||||
| } | |||||
| void Button::onDragDrop(const event::DragDrop &e) { | |||||
| if (e.origin == this) { | |||||
| event::Action eAction; | |||||
| onAction(eAction); | |||||
| } | |||||
| } | |||||
| } // namespace rack | |||||
| @@ -0,0 +1,12 @@ | |||||
| #include "ui/ChoiceButton.hpp" | |||||
| namespace rack { | |||||
| void ChoiceButton::draw(NVGcontext *vg) { | |||||
| bndChoiceButton(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str()); | |||||
| } | |||||
| } // namespace rack | |||||
| @@ -0,0 +1,25 @@ | |||||
| #include "ui/IconButton.hpp" | |||||
| namespace rack { | |||||
| IconButton::IconButton() { | |||||
| box.size.x = BND_TOOL_WIDTH; | |||||
| fw = new FramebufferWidget; | |||||
| fw->oversample = 2; | |||||
| addChild(fw); | |||||
| sw = new SVGWidget; | |||||
| sw->box.pos = math::Vec(2, 2); | |||||
| fw->addChild(sw); | |||||
| } | |||||
| void IconButton::setSVG(std::shared_ptr<SVG> svg) { | |||||
| sw->setSVG(svg); | |||||
| fw->dirty = true; | |||||
| } | |||||
| } // namespace rack | |||||
| @@ -0,0 +1,34 @@ | |||||
| #include "ui/Label.hpp" | |||||
| namespace rack { | |||||
| Label::Label() { | |||||
| box.size.y = BND_WIDGET_HEIGHT; | |||||
| fontSize = 13; | |||||
| color = bndGetTheme()->regularTheme.textColor; | |||||
| } | |||||
| void Label::draw(NVGcontext *vg) { | |||||
| // TODO | |||||
| // Custom font sizes do not work with right or center alignment | |||||
| float x; | |||||
| switch (alignment) { | |||||
| default: | |||||
| case LEFT_ALIGNMENT: { | |||||
| x = 0.0; | |||||
| } break; | |||||
| case RIGHT_ALIGNMENT: { | |||||
| x = box.size.x - bndLabelWidth(vg, -1, text.c_str()); | |||||
| } break; | |||||
| case CENTER_ALIGNMENT: { | |||||
| x = (box.size.x - bndLabelWidth(vg, -1, text.c_str())) / 2.0; | |||||
| } break; | |||||
| } | |||||
| bndIconLabelValue(vg, x, 0.0, box.size.x, box.size.y, -1, color, BND_LEFT, fontSize, text.c_str(), NULL); | |||||
| } | |||||
| } // namespace rack | |||||
| @@ -0,0 +1,24 @@ | |||||
| #include "ui/List.hpp" | |||||
| namespace rack { | |||||
| void List::step() { | |||||
| Widget::step(); | |||||
| // Set positions of children | |||||
| box.size.y = 0.0; | |||||
| for (Widget *child : children) { | |||||
| if (!child->visible) | |||||
| continue; | |||||
| // Increment height, set position of child | |||||
| child->box.pos = math::Vec(0.0, box.size.y); | |||||
| box.size.y += child->box.size.y; | |||||
| // Resize width of child | |||||
| child->box.size.x = box.size.x; | |||||
| } | |||||
| } | |||||
| } // namespace rack | |||||
| @@ -0,0 +1,12 @@ | |||||
| #include "ui/MenuEntry.hpp" | |||||
| namespace rack { | |||||
| MenuEntry::MenuEntry() { | |||||
| box.size = math::Vec(0, BND_WIDGET_HEIGHT); | |||||
| } | |||||
| } // namespace rack | |||||
| @@ -0,0 +1,21 @@ | |||||
| #include "ui/MenuLabel.hpp" | |||||
| #include "app.hpp" | |||||
| namespace rack { | |||||
| void MenuLabel::draw(NVGcontext *vg) { | |||||
| bndMenuLabel(vg, 0.0, 0.0, box.size.x, box.size.y, -1, text.c_str()); | |||||
| } | |||||
| void MenuLabel::step() { | |||||
| // Add 10 more pixels because Retina measurements are sometimes too small | |||||
| const float rightPadding = 10.0; | |||||
| // HACK use app()->window->vg from the window. | |||||
| box.size.x = bndLabelWidth(app()->window->vg, -1, text.c_str()) + rightPadding; | |||||
| Widget::step(); | |||||
| } | |||||
| } // namespace rack | |||||
| @@ -0,0 +1,22 @@ | |||||
| #include "ui/MenuSeparator.hpp" | |||||
| namespace rack { | |||||
| MenuSeparator::MenuSeparator() { | |||||
| box.size.y = BND_WIDGET_HEIGHT / 2; | |||||
| } | |||||
| void MenuSeparator::draw(NVGcontext *vg) { | |||||
| nvgBeginPath(vg); | |||||
| const float margin = 8.0; | |||||
| nvgMoveTo(vg, margin, box.size.y / 2.0); | |||||
| nvgLineTo(vg, box.size.x - margin, box.size.y / 2.0); | |||||
| nvgStrokeWidth(vg, 1.0); | |||||
| nvgStrokeColor(vg, color::alpha(bndGetTheme()->menuTheme.textColor, 0.25)); | |||||
| nvgStroke(vg); | |||||
| } | |||||
| } // namespace rack | |||||
| @@ -0,0 +1,15 @@ | |||||
| #include "ui/PasswordField.hpp" | |||||
| namespace rack { | |||||
| void PasswordField::draw(NVGcontext *vg) { | |||||
| std::string textTmp = text; | |||||
| text = std::string(textTmp.size(), '*'); | |||||
| TextField::draw(vg); | |||||
| text = textTmp; | |||||
| } | |||||
| } // namespace rack | |||||
| @@ -0,0 +1,23 @@ | |||||
| #include "ui/ProgressBar.hpp" | |||||
| namespace rack { | |||||
| ProgressBar::ProgressBar() { | |||||
| box.size.y = BND_WIDGET_HEIGHT; | |||||
| } | |||||
| ProgressBar::~ProgressBar() { | |||||
| if (quantity) | |||||
| delete quantity; | |||||
| } | |||||
| void ProgressBar::draw(NVGcontext *vg) { | |||||
| float progress = quantity ? quantity->getScaledValue() : 0.f; | |||||
| std::string text = quantity ? quantity->getString() : ""; | |||||
| bndSlider(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_ALL, BND_DEFAULT, progress, text.c_str(), NULL); | |||||
| } | |||||
| } // namespace rack | |||||
| @@ -0,0 +1,52 @@ | |||||
| #include "ui/RadioButton.hpp" | |||||
| namespace rack { | |||||
| RadioButton::RadioButton() { | |||||
| box.size.y = BND_WIDGET_HEIGHT; | |||||
| } | |||||
| RadioButton::~RadioButton() { | |||||
| if (quantity) | |||||
| delete quantity; | |||||
| } | |||||
| void RadioButton::draw(NVGcontext *vg) { | |||||
| std::string label; | |||||
| if (quantity) | |||||
| label = quantity->getLabel(); | |||||
| bndRadioButton(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, label.c_str()); | |||||
| } | |||||
| void RadioButton::onEnter(const event::Enter &e) { | |||||
| if (state != BND_ACTIVE) | |||||
| state = BND_HOVER; | |||||
| } | |||||
| void RadioButton::onLeave(const event::Leave &e) { | |||||
| if (state != BND_ACTIVE) | |||||
| state = BND_DEFAULT; | |||||
| } | |||||
| void RadioButton::onDragDrop(const event::DragDrop &e) { | |||||
| if (e.origin == this) { | |||||
| if (state == BND_ACTIVE) { | |||||
| state = BND_HOVER; | |||||
| if (quantity) | |||||
| quantity->setMin(); | |||||
| } | |||||
| else { | |||||
| state = BND_ACTIVE; | |||||
| if (quantity) | |||||
| quantity->setMax(); | |||||
| } | |||||
| event::Action eAction; | |||||
| onAction(eAction); | |||||
| } | |||||
| } | |||||
| } // namespace rack | |||||
| @@ -0,0 +1,47 @@ | |||||
| #include "ui/Slider.hpp" | |||||
| namespace rack { | |||||
| Slider::Slider() { | |||||
| box.size.y = BND_WIDGET_HEIGHT; | |||||
| } | |||||
| Slider::~Slider() { | |||||
| if (quantity) | |||||
| delete quantity; | |||||
| } | |||||
| void Slider::draw(NVGcontext *vg) { | |||||
| float progress = quantity ? quantity->getScaledValue() : 0.f; | |||||
| std::string text = quantity ? quantity->getString() : ""; | |||||
| bndSlider(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, progress, text.c_str(), NULL); | |||||
| } | |||||
| void Slider::onDragStart(const event::DragStart &e) { | |||||
| state = BND_ACTIVE; | |||||
| app()->window->cursorLock(); | |||||
| } | |||||
| void Slider::onDragMove(const event::DragMove &e) { | |||||
| if (quantity) { | |||||
| quantity->moveScaledValue(SLIDER_SENSITIVITY * e.mouseDelta.x); | |||||
| } | |||||
| } | |||||
| void Slider::onDragEnd(const event::DragEnd &e) { | |||||
| state = BND_DEFAULT; | |||||
| app()->window->cursorUnlock(); | |||||
| } | |||||
| void Slider::onButton(const event::Button &e) { | |||||
| if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) { | |||||
| if (quantity) | |||||
| quantity->reset(); | |||||
| } | |||||
| e.consume(this); | |||||
| } | |||||
| } // namespace rack | |||||