Overriding drawLinearSliderBackground

Hi,

So I’m taking a swing at custom sliders by overriding the LookAndFeel_V3 methods for sliders. I was able to successfully override drawLinearSlider but drawLinearSliderBackground frustrates me.

I’m overriding this function in my otherLookAndFeel class and instantiating it/ using it with timelineSlider.setLookAndFeel (&otherLookAndFeel);

Again, drawLinearSlider works but drawLinearSliderBackground doesn’t. Is there something I’m missing with instantiation or with timelineSlider.setLookAndFeel

My otherLookandFeel class:

class OtherLookAndFeel : public LookAndFeel_V3
{
public:    
    OtherLookAndFeel()
    {
        setColour (Slider::thumbColourId, Colours::green);
    }
    void drawLinearSlider (Graphics& g,
                            int x, int y, int w, int h,
                            float sliderPos, float minSliderPos, float maxSliderPos,
                            const Slider::SliderStyle style,
                            Slider& slider) override
    {
         g.fillAll (slider.findColour (Slider::backgroundColourId));

         if (style == Slider::LinearBar)
         {
             g.setColour (slider.findColour (Slider::thumbColourId));
             g.fillRect (x, y, (int) sliderPos - x, h);

             g.setColour (slider.findColour (Slider::textBoxTextColourId).withMultipliedAlpha (0.5f));
             g.drawRect (x, y, (int) sliderPos - x, h);
         }
         else
         {
             g.setColour (slider.findColour (Slider::trackColourId)
                                .withMultipliedAlpha (slider.isEnabled() ? 1.0f : 0.3f));
             x = x-8;
             w = w+16;
             
             if (slider.isHorizontal())
             {
                 g.fillRect (x, y + roundToInt (h * 0.6f),
                             w, roundToInt (h * 0.2f));
             }
             else
             {
                 g.fillRect (x + roundToInt (w * 0.5f - jmin (3.0f, w * 0.1f)), y,
                             jmin (4, roundToInt (w * 0.2f)), h);
             }

             float alpha = 0.35f;

             if (slider.isEnabled())
                 alpha = slider.isMouseOverOrDragging() ? 1.0f : 0.7f;

             const Colour fill (slider.findColour (Slider::thumbColourId).withAlpha (alpha));
             const Colour outline (Colours::black.withAlpha (slider.isEnabled() ? 0.7f : 0.35f));

             if (style == Slider::LinearHorizontal || style == Slider::ThreeValueHorizontal)
             {
                 drawTriangle (g, sliderPos, y + h * 0.9f,
                               sliderPos - 7.0f, y + h * 0.2f,
                               sliderPos + 7.0f, y + h * 0.2f,
                               fill, outline);
             }
         }
     }
    
    void drawLinearSliderBackground (Graphics& g, int x, int y, int width, int height,
                                                     float /*sliderPos*/,
                                                     float /*minSliderPos*/,
                                                     float /*maxSliderPos*/,
                                                     const Slider::SliderStyle /*style*/, Slider& slider) override
    {
        
        const float sliderRadius = (float) (getSliderThumbRadius (slider) + 20);

        const Colour trackColour (Colours:: red);
        const Colour gradCol1 (trackColour.overlaidWith (Colour (slider.isEnabled() ? 0x13000000 : 0x09000000)));
        const Colour gradCol2 (trackColour.overlaidWith (Colour (0x06000000)));
        Path indent;

        if (slider.isHorizontal())
        {
            auto iy = y + height * 0.5f - sliderRadius * 0.5f;

            g.setGradientFill (ColourGradient::vertical (gradCol1, iy, gradCol2, iy + sliderRadius));

            indent.addRoundedRectangle (x - sliderRadius * 0.5f, iy, width + sliderRadius, sliderRadius, 5.0f);
        }
        else
        {
            auto ix = x + width * 0.5f - sliderRadius * 0.5f;

            g.setGradientFill (ColourGradient::horizontal (gradCol1, ix, gradCol2, ix + sliderRadius));

            indent.addRoundedRectangle (ix, y - sliderRadius * 0.5f, sliderRadius, height + sliderRadius, 5.0f);
        }

        g.fillPath (indent);

        g.setColour (trackColour.contrasting (0.5f));
        g.strokePath (indent, PathStrokeType (0.5f));
    }
    
};

When you say drawLinearSliderBackground doesn’t work, what do you mean? Does it get called for the slider in question? Or does it not behave as expected?

The virtual function drawLinearSliderBackground does not get overrided ie. it’s never called. I’ve tried changing the params float /*sliderPos*/, float /*minSliderPos*/, float /*maxSliderPos*/ (uncommenting them) but that didn’t work either.

The code in drawLinearSlider that calls the drawLinearSliderBackground function first checks the slider style:

if (style == Slider::LinearBar || style == Slider::LinearBarVertical)
{
    ...
}
else
{
    drawLinearSliderBackground(...);
    ...
}

So, perhaps your Slider has the type LinearBar or LinearBarVertical? In that case, you’d need to put your code in drawLinearSlider itself, not in drawLinearSliderBackground.

Oh, I see you overrode drawLinearSlider. Looking at that code, you never call drawLinearSliderBackground. That’s where the base class calls that function from. So if you don’t call it, it will never get called.

1 Like

Ah, I see what you mean. I removed the call to drawLinearBackground in my attempt to keep my code clean and simple. Thank you!

1 Like