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