Hi,
I am trying to implement a reversible slider adapter, using the Slider::proportionOfLengthToValue and Slider::valueToProportionOfLength methods.
When reversed, the slider should slide from max to min instead of min to max.
I only managed to get this working with rotary sliders, though.
Linear sliders behave quite strangely on extreme values: they jump back to the other side.
Is there something I missed there?
template < class ConcreteSlider = Slider >
class ReversibleSlider : public ConcreteSlider
{
public:
using ConcreteSlider::getMinimum;
using ConcreteSlider::getMaximum;
using ConcreteSlider::repaint;
public:
ReversibleSlider (const String& componentName) :
Slider(componentName),
reversed(false)
{}
~ ReversibleSlider () {}
public:
void setReverse (bool shouldBeReversed)
{
if (reversed != shouldBeReversed)
{
reversed = shouldBeReversed;
repaint();
}
}
public: // Slider
double proportionOfLengthToValue (double proportion)
{
double ret = 0;
if (reversed)
ret = getMaximum() + getMinimum() - ConcreteSlider::proportionOfLengthToValue(proportion);
else
ret = ConcreteSlider::proportionOfLengthToValue(proportion);
Logger::outputDebugPrintf(T("proportionOfLengthToValue(%f) == %f"), proportion, ret);
return ret;
}
double valueToProportionOfLength (double value)
{
double ret = 0;
if (reversed)
ret = jlimit(0., 1., 1.0 - ConcreteSlider::valueToProportionOfLength(value));
else
ret = ConcreteSlider::valueToProportionOfLength(value);
Logger::outputDebugPrintf(T("valueToProportionOfLength(%f) == %f"), value, ret);
return ret;
}
private:
bool reversed;
};
class ReversibleSliderTestComponent :
public Component,
public ButtonListener,
public ComboBoxListener,
public SliderListener
{
public:
ReversibleSliderTestComponent ()
{
addAndMakeVisible(reverseButton = new ToggleButton("Reversed"));
reverseButton->addButtonListener(this);
addAndMakeVisible(styleComboBox = new ComboBox("styleComboBox"));
styleComboBox->addListener(this);
struct StyleData
{
Slider::SliderStyle id;
const char* name;
}
styles [] =
{
{ Slider::LinearHorizontal, "LinearHorizontal" },
{ Slider::LinearVertical, "LinearVertical" },
{ Slider::LinearBar, "LinearBar" },
{ Slider::Rotary, "Rotary" },
{ Slider::RotaryHorizontalDrag, "RotaryHorizontalDrag" },
{ Slider::RotaryVerticalDrag, "RotaryVerticalDrag" },
{ Slider::IncDecButtons, "IncDecButtons" },
{ Slider::TwoValueHorizontal, "TwoValueHorizontal" },
{ Slider::TwoValueVertical, "TwoValueVertical" },
{ Slider::ThreeValueHorizontal, "ThreeValueHorizontal" },
{ Slider::ThreeValueVertical, "ThreeValueVertical" }
};
size_t stylesSize = sizeof(styles) / sizeof(StyleData);
for (size_t i = 0; i < stylesSize; ++i)
styleComboBox->addItem(styles[i].name, toId(styles[i].id));
addAndMakeVisible(reversibleSlider = new ReversibleSlider<>("reversibleSlider"));
reversibleSlider->setSliderStyle(Slider::Rotary);
reversibleSlider->addListener(this);
}
public: // Component
virtual void resized ()
{
reverseButton->setBoundsRelative(0.f, 0.f, 0.5f, 0.5f);
styleComboBox->setBoundsRelative(0.5f, 0.f, 0.5f, 0.5f);
reversibleSlider->setBoundsRelative(0.f, 0.5f, 1.f, 0.5f);
}
public: // ButtonListener
virtual void buttonClicked(Button* button)
{
if (button == reverseButton)
reversibleSlider->setReverse(reverseButton->getToggleState());
}
public: // ComboBoxListener
virtual void comboBoxChanged (ComboBox* comboBox)
{
if (comboBox = styleComboBox)
reversibleSlider->setSliderStyle(toSliderStyle(styleComboBox->getSelectedId()));
}
public: // SliderListener
virtual void sliderValueChanged(Slider* slider)
{
if (slider == reversibleSlider)
Logger::outputDebugString(String("Slider: ") << slider->getValue());
}
private:
static int toId (Slider::SliderStyle style)
{
return style + 1;
}
static Slider::SliderStyle toSliderStyle (int id)
{
return static_cast<Slider::SliderStyle>(id - 1);
}
private:
ToggleButton* reverseButton;
ComboBox* styleComboBox;
ReversibleSlider<Slider>* reversibleSlider;
};