| @@ -29,6 +29,7 @@ struct PortWidget : OpaqueWidget { | |||
| void onDragDrop(const event::DragDrop &e) override; | |||
| void onDragEnter(const event::DragEnter &e) override; | |||
| void onDragLeave(const event::DragLeave &e) override; | |||
| void setHovered(); | |||
| }; | |||
| @@ -37,7 +37,6 @@ | |||
| #include "ui/IconButton.hpp" | |||
| #include "ui/ChoiceButton.hpp" | |||
| #include "ui/RadioButton.hpp" | |||
| #include "ui/WindowWidget.hpp" | |||
| #include "ui/ProgressBar.hpp" | |||
| #include "app/AudioWidget.hpp" | |||
| @@ -13,45 +13,14 @@ struct Button : OpaqueWidget { | |||
| /** Optional, owned. Tracks the pressed state of the button.*/ | |||
| 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 { | |||
| 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; | |||
| 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; | |||
| 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 { | |||
| 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 { | |||
| MenuEntry() { | |||
| box.size = math::Vec(0, BND_WIDGET_HEIGHT); | |||
| } | |||
| MenuEntry(); | |||
| }; | |||
| @@ -1,7 +1,6 @@ | |||
| #pragma once | |||
| #include "ui/common.hpp" | |||
| #include "ui/MenuEntry.hpp" | |||
| #include "app.hpp" | |||
| namespace rack { | |||
| @@ -10,17 +9,8 @@ namespace rack { | |||
| struct MenuLabel : MenuEntry { | |||
| 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 { | |||
| 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 { | |||
| 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 | |||
| #include "ui/common.hpp" | |||
| #include "widgets/Widget.hpp" | |||
| #include "ui/Quantity.hpp" | |||
| namespace rack { | |||
| @@ -8,20 +10,9 @@ namespace rack { | |||
| struct ProgressBar : virtual Widget { | |||
| 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 | |||
| #include "widgets/OpaqueWidget.hpp" | |||
| #include "ui/common.hpp" | |||
| #include "widgets/OpaqueWidget.hpp" | |||
| #include "ui/Quantity.hpp" | |||
| namespace rack { | |||
| @@ -10,49 +11,12 @@ struct RadioButton : OpaqueWidget { | |||
| BNDwidgetState state = BND_DEFAULT; | |||
| 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; | |||
| 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) | |||
| 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) { | |||
| @@ -110,17 +107,7 @@ void PortWidget::onDragEnter(const event::DragEnter &e) { | |||
| if (!originPort) | |||
| 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) { | |||
| @@ -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 | |||
| @@ -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 | |||