| @@ -18,10 +18,6 @@ struct ParamWidget : widget::OpaqueWidget { | |||
| engine::Module* module = NULL; | |||
| int paramId = -1; | |||
| ui::Tooltip* tooltip = NULL; | |||
| /** For triggering the Change event. `*/ | |||
| float lastValue = NAN; | |||
| ParamWidget(); | |||
| ~ParamWidget(); | |||
| /** Configures ParamQuantity properties based on the type of ParamWidget. | |||
| @@ -20,8 +20,6 @@ struct PortWidget : widget::OpaqueWidget { | |||
| engine::Port::Type type = engine::Port::INPUT; | |||
| int portId = -1; | |||
| ui::Tooltip* tooltip = NULL; | |||
| MultiLightWidget* plugLight; | |||
| PortWidget(); | |||
| @@ -22,9 +22,9 @@ struct SvgSlider : app::SliderKnob { | |||
| SvgSlider(); | |||
| void setBackgroundSvg(std::shared_ptr<Svg> svg); | |||
| void setHandleSvg(std::shared_ptr<Svg> svg); | |||
| void onChange(const ChangeEvent& e) override; | |||
| void setHandlePos(math::Vec minHandlePos, math::Vec maxHandlePos); | |||
| void setHandlePosCentered(math::Vec minHandlePosCentered, math::Vec maxHandlePosCentered); | |||
| void onChange(const ChangeEvent& e) override; | |||
| DEPRECATED void setBackgroundSVG(std::shared_ptr<Svg> svg) { | |||
| setBackgroundSvg(svg); | |||
| @@ -152,28 +152,44 @@ engine::ParamQuantity* ParamWidget::getParamQuantity() { | |||
| return module->paramQuantities[paramId]; | |||
| } | |||
| ParamWidget::ParamWidget() {} | |||
| ParamWidget::~ParamWidget() {} | |||
| struct ParamWidget::Internal { | |||
| ui::Tooltip* tooltip = NULL; | |||
| /** For triggering the Change event. `*/ | |||
| float lastValue = NAN; | |||
| }; | |||
| ParamWidget::ParamWidget() { | |||
| internal = new Internal; | |||
| } | |||
| ParamWidget::~ParamWidget() { | |||
| delete internal; | |||
| } | |||
| void ParamWidget::createTooltip() { | |||
| if (!settings::tooltips) | |||
| return; | |||
| if (this->tooltip) | |||
| if (internal->tooltip) | |||
| return; | |||
| if (!module) | |||
| return; | |||
| ParamTooltip* tooltip = new ParamTooltip; | |||
| tooltip->paramWidget = this; | |||
| APP->scene->addChild(tooltip); | |||
| this->tooltip = tooltip; | |||
| internal->tooltip = tooltip; | |||
| } | |||
| void ParamWidget::destroyTooltip() { | |||
| if (!tooltip) | |||
| if (!internal->tooltip) | |||
| return; | |||
| APP->scene->removeChild(tooltip); | |||
| delete tooltip; | |||
| tooltip = NULL; | |||
| APP->scene->removeChild(internal->tooltip); | |||
| delete internal->tooltip; | |||
| internal->tooltip = NULL; | |||
| } | |||
| void ParamWidget::step() { | |||
| @@ -181,16 +197,17 @@ void ParamWidget::step() { | |||
| if (pq) { | |||
| float value = pq->getSmoothValue(); | |||
| // Dispatch change event when the ParamQuantity value changes | |||
| if (value != lastValue) { | |||
| if (value != internal->lastValue) { | |||
| ChangeEvent eChange; | |||
| onChange(eChange); | |||
| lastValue = value; | |||
| internal->lastValue = value; | |||
| } | |||
| } | |||
| Widget::step(); | |||
| } | |||
| void ParamWidget::draw(const DrawArgs& args) { | |||
| Widget::draw(args); | |||
| @@ -210,6 +227,7 @@ void ParamWidget::draw(const DrawArgs& args) { | |||
| } | |||
| } | |||
| void ParamWidget::onButton(const ButtonEvent& e) { | |||
| OpaqueWidget::onButton(e); | |||
| @@ -229,18 +247,22 @@ void ParamWidget::onButton(const ButtonEvent& e) { | |||
| } | |||
| } | |||
| void ParamWidget::onDoubleClick(const DoubleClickEvent& e) { | |||
| resetAction(); | |||
| } | |||
| void ParamWidget::onEnter(const EnterEvent& e) { | |||
| createTooltip(); | |||
| } | |||
| void ParamWidget::onLeave(const LeaveEvent& e) { | |||
| destroyTooltip(); | |||
| } | |||
| void ParamWidget::createContextMenu() { | |||
| ui::Menu* menu = createMenu(); | |||
| @@ -300,6 +322,7 @@ void ParamWidget::createContextMenu() { | |||
| appendContextMenu(menu); | |||
| } | |||
| void ParamWidget::resetAction() { | |||
| engine::ParamQuantity* pq = getParamQuantity(); | |||
| if (pq && pq->resetEnabled && pq->isBounded()) { | |||
| @@ -74,7 +74,13 @@ struct PlugLight : MultiLightWidget { | |||
| }; | |||
| struct PortWidget::Internal { | |||
| ui::Tooltip* tooltip = NULL; | |||
| }; | |||
| PortWidget::PortWidget() { | |||
| internal = new Internal; | |||
| plugLight = new PlugLight; | |||
| } | |||
| @@ -86,6 +92,7 @@ PortWidget::~PortWidget() { | |||
| // HACK | |||
| if (module) | |||
| APP->scene->rack->clearCablesOnPort(this); | |||
| delete internal; | |||
| } | |||
| engine::Port* PortWidget::getPort() { | |||
| @@ -109,22 +116,22 @@ engine::PortInfo* PortWidget::getPortInfo() { | |||
| void PortWidget::createTooltip() { | |||
| if (!settings::tooltips) | |||
| return; | |||
| if (this->tooltip) | |||
| if (internal->tooltip) | |||
| return; | |||
| if (!module) | |||
| return; | |||
| PortTooltip* tooltip = new PortTooltip; | |||
| tooltip->portWidget = this; | |||
| APP->scene->addChild(tooltip); | |||
| this->tooltip = tooltip; | |||
| internal->tooltip = tooltip; | |||
| } | |||
| void PortWidget::destroyTooltip() { | |||
| if (!tooltip) | |||
| if (!internal->tooltip) | |||
| return; | |||
| APP->scene->removeChild(tooltip); | |||
| delete tooltip; | |||
| tooltip = NULL; | |||
| APP->scene->removeChild(internal->tooltip); | |||
| delete internal->tooltip; | |||
| internal->tooltip = NULL; | |||
| } | |||
| void PortWidget::step() { | |||
| @@ -34,27 +34,37 @@ void SvgSlider::setHandleSvg(std::shared_ptr<Svg> svg) { | |||
| } | |||
| void SvgSlider::onChange(const ChangeEvent& e) { | |||
| engine::ParamQuantity* pq = getParamQuantity(); | |||
| if (pq) { | |||
| // Interpolate handle position | |||
| float v = math::rescale(pq->getSmoothValue(), pq->getMinValue(), pq->getMaxValue(), 0.f, 1.f); | |||
| handle->box.pos = minHandlePos.crossfade(maxHandlePos, v); | |||
| fb->setDirty(); | |||
| } | |||
| ParamWidget::onChange(e); | |||
| } | |||
| void SvgSlider::setHandlePos(math::Vec minHandlePos, math::Vec maxHandlePos) { | |||
| this->minHandlePos = minHandlePos; | |||
| this->maxHandlePos = maxHandlePos; | |||
| // Dispatch ChangeEvent since the handle position changed | |||
| ChangeEvent eChange; | |||
| onChange(eChange); | |||
| } | |||
| void SvgSlider::setHandlePosCentered(math::Vec minHandlePosCentered, math::Vec maxHandlePosCentered) { | |||
| this->minHandlePos = minHandlePosCentered.minus(handle->box.size.div(2)); | |||
| this->maxHandlePos = maxHandlePosCentered.minus(handle->box.size.div(2)); | |||
| setHandlePos( | |||
| minHandlePosCentered.minus(handle->box.size.div(2)), | |||
| maxHandlePosCentered.minus(handle->box.size.div(2)) | |||
| ); | |||
| } | |||
| void SvgSlider::onChange(const ChangeEvent& e) { | |||
| // Default position is max value | |||
| float v = 1.f; | |||
| engine::ParamQuantity* pq = getParamQuantity(); | |||
| if (pq) { | |||
| v = math::rescale(pq->getSmoothValue(), pq->getMinValue(), pq->getMaxValue(), 0.f, 1.f); | |||
| } | |||
| // Interpolate handle position | |||
| handle->box.pos = minHandlePos.crossfade(maxHandlePos, v); | |||
| fb->setDirty(); | |||
| ParamWidget::onChange(e); | |||
| } | |||