Seems I need to show code to explain. Just copy the getSliderLayout() and reduce the returned bounds when the variable localBounds
is calculated (and some fixes when setting the textBox, because it assumes x and y to be 0)
In the drawRotarySlider you can simply draw your decorations around.
// == constructor ==
MainComponent::MainComponent()
{
setLookAndFeel(&lookAndFeel);
addAndMakeVisible(gain);
addAndMakeVisible(pan);
gain.getProperties().set("title", "Gain");
pan.getProperties().set("title", "Pan");
setSize (600, 400);
}
// == LookAndFeel ==
#pragma once
#include <juce_gui_basics/juce_gui_basics.h>
class DecoLookAndFeel : public juce::LookAndFeel_V2
{
public:
static constexpr auto kDecoSpace = 20;
DecoLookAndFeel() = default;
void drawRotarySlider (juce::Graphics& g, int x, int y, int width, int height,
float sliderPosProportional, float rotaryStartAngle, float rotaryEndAngle,
juce::Slider& slider) override
{
juce::LookAndFeel_V2::drawRotarySlider(g, x, y, width, height, sliderPosProportional, rotaryStartAngle, rotaryEndAngle, slider);
auto title = slider.getProperties()["title"].toString();
auto bounds = slider.getLocalBounds();
auto textColour = slider.findColour(juce::Slider::textBoxTextColourId);
g.setColour(textColour);
{
const juce::Graphics::ScopedSaveState save (g);
juce::GlyphArrangement arrangement;
arrangement.addFittedText(g.getCurrentFont(), title, bounds.getX(), bounds.getY(), bounds.getWidth(), kDecoSpace, juce::Justification::centred, 1);
g.excludeClipRegion(arrangement.getBoundingBox(0, title.length(), true).toNearestIntEdges().expanded(3, 3));
g.drawRoundedRectangle(bounds.toFloat().reduced(10.0f), 10.0f, 3.0f);
}
g.drawFittedText (title, bounds.withHeight(kDecoSpace), juce::Justification::centred, 1);
}
juce::Slider::SliderLayout getSliderLayout (juce::Slider& slider) override
{
// 1. compute the actually visible textBox size from the slider textBox size and some additional constraints
int minXSpace = 0;
int minYSpace = 0;
auto textBoxPos = slider.getTextBoxPosition();
if (textBoxPos == juce::Slider::TextBoxLeft || textBoxPos == juce::Slider::TextBoxRight)
minXSpace = 30;
else
minYSpace = 15;
auto localBounds = slider.getLocalBounds().reduced(kDecoSpace); // <== Reduce the slider layout here to make space for your decorations
auto textBoxWidth = std::clamp(localBounds.getWidth() - minXSpace, 0, slider.getTextBoxWidth());
auto textBoxHeight = std::clamp(localBounds.getHeight() - minYSpace, 0, slider.getTextBoxHeight());
juce::Slider::SliderLayout layout;
// 2. set the textBox bounds
if (textBoxPos != juce::Slider::NoTextBox)
{
if (slider.isBar())
{
layout.textBoxBounds = localBounds;
}
else
{
layout.textBoxBounds.setWidth (textBoxWidth);
layout.textBoxBounds.setHeight (textBoxHeight);
if (textBoxPos == juce::Slider::TextBoxLeft) layout.textBoxBounds.setX (localBounds.getX());
else if (textBoxPos == juce::Slider::TextBoxRight) layout.textBoxBounds.setX (localBounds.getRight() - textBoxWidth);
else /* above or below -> centre horizontally */ layout.textBoxBounds.setX (localBounds.getCentreX() - textBoxWidth / 2);
if (textBoxPos == juce::Slider::TextBoxAbove) layout.textBoxBounds.setY (localBounds.getY());
else if (textBoxPos == juce::Slider::TextBoxBelow) layout.textBoxBounds.setY (localBounds.getBottom() - textBoxHeight);
else /* left or right -> centre vertically */ layout.textBoxBounds.setY (localBounds.getCentreY() - textBoxHeight / 2);
}
}
// 3. set the slider bounds
layout.sliderBounds = localBounds;
if (slider.isBar())
{
layout.sliderBounds.reduce (1, 1); // bar border
}
else
{
if (textBoxPos == juce::Slider::TextBoxLeft) layout.sliderBounds.removeFromLeft (textBoxWidth);
else if (textBoxPos == juce::Slider::TextBoxRight) layout.sliderBounds.removeFromRight (textBoxWidth);
else if (textBoxPos == juce::Slider::TextBoxAbove) layout.sliderBounds.removeFromTop (textBoxHeight);
else if (textBoxPos == juce::Slider::TextBoxBelow) layout.sliderBounds.removeFromBottom (textBoxHeight);
const int thumbIndent = getSliderThumbRadius (slider);
if (slider.isHorizontal()) layout.sliderBounds.reduce (thumbIndent, 0);
else if (slider.isVertical()) layout.sliderBounds.reduce (0, thumbIndent);
}
return layout;
}
};