horizont/Source/Knob.cpp

81 lines
3.2 KiB
C++
Raw Normal View History

2026-08-10 12:55:02 +02:00
#include "Knob.h"
Knob::Knob (const juce::String& title,
juce::AudioProcessorValueTreeState& apvts,
const juce::String& paramID,
float defaultValue,
std::function<juce::String (float)> formatFn,
const juce::String& tooltip)
: format (std::move (formatFn))
{
nameLabel.setText (title, juce::dontSendNotification);
nameLabel.setJustificationType (juce::Justification::centred);
nameLabel.setFont (juce::Font (juce::FontOptions (11.0f, juce::Font::bold)));
nameLabel.setColour (juce::Label::textColourId, juce::Colour (0xFFB8CCCC));
nameLabel.setInterceptsMouseClicks (false, false);
addAndMakeVisible (nameLabel);
valueLabel.setJustificationType (juce::Justification::centred);
valueLabel.setFont (juce::Font (juce::FontOptions (11.0f, juce::Font::bold)));
valueLabel.setColour (juce::Label::textColourId, juce::Colour (0xFF3CE0C8));
valueLabel.setInterceptsMouseClicks (false, false);
addAndMakeVisible (valueLabel);
slider.setSliderStyle (juce::Slider::RotaryHorizontalVerticalDrag);
slider.setTextBoxStyle (juce::Slider::NoTextBox, true, 0, 0);
slider.setDoubleClickReturnValue (true, defaultValue);
slider.setWantsKeyboardFocus (true);
slider.setScrollWheelEnabled (true);
slider.setTooltip (tooltip);
slider.onValueChange = [this] { updateValueLabel(); };
addAndMakeVisible (slider);
attachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment> (apvts, paramID, slider);
updateValueLabel();
}
void Knob::setScaleFactor (float scale)
{
scaleFactor = scale;
resized();
}
void Knob::updateValueLabel()
{
valueLabel.setText (format (slider.getValue()), juce::dontSendNotification);
}
void Knob::paint (juce::Graphics& g)
{
auto b = slider.getBounds().toFloat();
auto shadow = b.translated (0.0f, b.getHeight() * 0.05f).expanded (b.getWidth() * 0.05f);
auto shadowCentre = shadow.getCentre().withY (shadow.getCentre().getY() + b.getHeight() * 0.4f);
auto grad = juce::ColourGradient (juce::Colour (0x60000000), shadowCentre,
juce::Colour (0x00000000), shadowCentre.translated (shadow.getWidth() * 0.7f, 0.0f),
true);
grad.addColour (0.55f, juce::Colour (0x20000000));
g.setGradientFill (grad);
g.fillEllipse (shadow);
}
void Knob::resized()
{
auto bounds = getLocalBounds();
const float s = scaleFactor;
const int nameH = juce::roundToInt (18.0f * s);
const int valueH = juce::roundToInt (16.0f * s);
const int maxKnobSize = juce::roundToInt (84.0f * s);
auto nameArea = bounds.removeFromTop (nameH);
auto valueArea = bounds.removeFromBottom (valueH);
nameLabel.setBounds (nameArea);
valueLabel.setBounds (valueArea);
nameLabel.setFont (juce::Font (juce::FontOptions (juce::roundToInt (11.0f * s), juce::Font::bold)));
valueLabel.setFont (juce::Font (juce::FontOptions (juce::roundToInt (11.0f * s), juce::Font::bold)));
const int knobSize = jmin (bounds.getWidth(), bounds.getHeight(), maxKnobSize);
slider.setBounds (bounds.getCentreX() - knobSize / 2, bounds.getCentreY() - knobSize / 2, knobSize, knobSize);
}