Slider Construction - Too Verbose!

Hi, I have a long list of Sliders in my PluginEditor Constructor all with very similar properties, see below:

    // POD Sliders
    // -----------
    addAndMakeVisible(driveSlider);
    driveSlider.setLookAndFeel(&rotaryLookAndFeel);
    driveSlider.setSliderStyle(juce::Slider::SliderStyle::Rotary);
    driveSlider.setTextBoxStyle(juce::Slider::TextBoxBelow, true, 44, 20);
    driveSlider.setRange(0, 127, 1);
    driveSlider.setValue(64);
    ampModelGroup.addChildComponent(driveSlider);

    addAndMakeVisible(drive2Slider);
    drive2Slider.setLookAndFeel(&rotaryLookAndFeel);
    drive2Slider.setSliderStyle(juce::Slider::SliderStyle::Rotary);
    drive2Slider.setTextBoxStyle(juce::Slider::TextBoxBelow, true, 44, 20);
    drive2Slider.setRange(0, 127, 1);
    drive2Slider.setValue(64);
    ampModelGroup.addChildComponent(drive2Slider);

    addAndMakeVisible(bassSlider);
    bassSlider.setLookAndFeel(&rotaryLookAndFeel);
    bassSlider.setSliderStyle(juce::Slider::SliderStyle::Rotary);
    bassSlider.setTextBoxStyle(juce::Slider::TextBoxBelow, true, 44, 20);
    bassSlider.setRange(0, 127, 1);
    bassSlider.setValue(64);
    ampModelGroup.addChildComponent(bassSlider);

    addAndMakeVisible(midSlider);
    midSlider.setLookAndFeel(&rotaryLookAndFeel);
    midSlider.setSliderStyle(juce::Slider::SliderStyle::Rotary);
    midSlider.setTextBoxStyle(juce::Slider::TextBoxBelow, true, 44, 20);
    midSlider.setRange(0, 127, 1);
    midSlider.setValue(64);
    ampModelGroup.addChildComponent(midSlider);

I already have a Custom LookAndFeel working, but how do I move some of the common stuff like:

    driveSlider.setSliderStyle(juce::Slider::SliderStyle::Rotary);
    driveSlider.setTextBoxStyle(juce::Slider::TextBoxBelow, true, 44, 20);
    driveSlider.setRange(0, 127, 1);
    driveSlider.setValue(64);

out into the LookAndFeel Class?

I tried moving it out into the LookAndFeel Constructor like:

class RotaryLookAndFeel  : public juce::LookAndFeel_V4
{
public:
    RotaryLookAndFeel()
    {
        // Slider Colours
        // --------------
        setColour(juce::Slider::thumbColourId, juce::Colours::silver);
        setColour(juce::Slider::rotarySliderOutlineColourId, juce::Colour(darkerMainColourId));     // The unfilled part of the Rotary
        setColour(juce::Slider::rotarySliderFillColourId, juce::Colour(lighterMainColourId));       // The filled part of the Rotary

        setColour(juce::Slider::textBoxTextColourId, juce::Colours::white);
        setColour(juce::Slider::textBoxOutlineColourId, juce::Colour(transparentColourId));

        juce::Slider::SliderStyle::Rotary;
        juce::Slider::TextBoxBelow, true, 44, 20;
        setRange(0, 127, 1);
        setValue(64);
    }

But I’m not getting very far, must be doing something wrong? Just looking to get rid of all the repetitive code in the PluginEditor!!!

Just declare a function to handle the repetitive aspects?

void MainComponent::setupSlider(Slider& slider)
{
    addAndMakeVisible(slider);
    slider.setLookAndFeel(&rotaryLookAndFeel);
    slider.setSliderStyle(juce::Slider::SliderStyle::Rotary);
    slider.setTextBoxStyle(juce::Slider::TextBoxBelow, true, 44, 20);
    slider.setRange(0, 127, 1);
    slider.setValue(64);
    ampModelGroup.addChildComponent(slider);
}

Use:
    setupSlider(driveSlider);    
    setupSlider(drive2Slider);
    setupSlider(bassSlider);
    setupSlider(midSlider);

...etc.
2 Likes

You can go one further and throw all the sliders into a temporary vector and then use a range based for loop and hit them all in one line. I do this kind of thing in a constructor, with the config function as a lambda.

3 Likes

That all sounds good, I’ll give it a go, thanks!

I use a similar approach, but instead of it being a separate function, I would declare your setupSlider as a lambda inside the constructor

I like the following pattern:

for (auto* slider : { &driveSlider, &drive2Slider, &bassSlider, &midSlider })
{
    addAndMakeVisible(*slider);
    slider->setLookAndFeel(&rotaryLookAndFeel);
    slider->setSliderStyle(juce::Slider::SliderStyle::Rotary);
    slider->setTextBoxStyle(juce::Slider::TextBoxBelow, true, 44, 20);
    slider->setRange(0, 127, 1);
    slider->setValue(64);
    ampModelGroup.addChildComponent(*slider);
}
3 Likes

Another approach that isn’t mentioned yet is to subclass juce::Slider and set these properties in the constructor of your subclass.

2 Likes

That’s the approach I’d typically take.

There’s also the Builder pattern. If you add some default parameters you can then still customise some sliders if needed.

std::unqiue_ptr<juce::Slider> gainSlider = SliderBuilder{}
                                             .withName ("Gain")
                                             .build();
std::unqiue_ptr<juce::Slider> cutoffSlider = SliderBuilder{}
                                               .withName ("Cutoff")
                                               .withRange (20, 20000)
                                               .build();

Or just use parameter attachments to have most things set up on the slider for you.

1 Like

A few more suggestions:

  • SliderType and TextBoxPosition can be set in the declaration in the header already
  • Range and Value come from SliderAttachment, if you use them (as stated before, if it is a plugin at all)
  • addAndMakeVisible and addChildComponent are redundant, you can call ampModelGroup.addAndMakeVisible (driveSlider); directly
  • If they all use the same LookAndFeel, you can set it to the parent. If you inherit your rotaryLookAndFeel and set that to the parent, all other widgets simply use the functions of the base class
private:
    juce::Slider driveSlider { juce::Slider::SliderStyle::Rotary, juce::Slider::TextBoxBelow };

And N.B. prefer composition over inheritance (opposed to kerfuffle)

1 Like

if you wanna make plugins you don’t need to touch most Slider functions manually anyway because you use parameter attachments to connect them with the parameters in the processor

You know it’s C++ when everyone has a different way of solving the same problem :joy:

4 Likes

5 Likes