#include "ScatterPanel.h" ScatterPanel::ScatterPanel() { titleLabel.setText ("SCATTER", juce::dontSendNotification); titleLabel.setJustificationType (juce::Justification::centredLeft); titleLabel.setColour (juce::Label::textColourId, InstaGrainLookAndFeel::textPrimary); addAndMakeVisible (titleLabel); setupKnob (posScatterKnob, posScatLabel, "Pos"); setupKnob (sizeScatterKnob, sizeScatLabel, "Size"); setupKnob (pitchScatterKnob, pitchScatLabel, "Pitch"); setupKnob (panScatterKnob, panScatLabel, "Pan"); directionBox.addItem ("Forward", 1); directionBox.addItem ("Reverse", 2); directionBox.addItem ("PingPong", 3); directionBox.setSelectedId (1); addAndMakeVisible (directionBox); dirLabel.setText ("Direction", juce::dontSendNotification); dirLabel.setJustificationType (juce::Justification::centred); dirLabel.setColour (juce::Label::textColourId, InstaGrainLookAndFeel::textSecondary); addAndMakeVisible (dirLabel); freezeButton.setButtonText ("Freeze"); addAndMakeVisible (freezeButton); freezeLabel.setText ("Freeze", juce::dontSendNotification); freezeLabel.setJustificationType (juce::Justification::centred); freezeLabel.setColour (juce::Label::textColourId, InstaGrainLookAndFeel::textSecondary); addAndMakeVisible (freezeLabel); } void ScatterPanel::setupKnob (juce::Slider& knob, juce::Label& label, const juce::String& name) { knob.setSliderStyle (juce::Slider::RotaryHorizontalVerticalDrag); knob.setTextBoxStyle (juce::Slider::TextBoxBelow, false, 50, 14); knob.setRange (0.0, 1.0); knob.setValue (0.0); knob.getProperties().set (InstaGrainLookAndFeel::knobTypeProperty, "dark"); addAndMakeVisible (knob); label.setText (name, juce::dontSendNotification); label.setJustificationType (juce::Justification::centred); label.setColour (juce::Label::textColourId, InstaGrainLookAndFeel::textSecondary); addAndMakeVisible (label); } void ScatterPanel::resized() { auto bounds = getLocalBounds().reduced (4); titleLabel.setBounds (bounds.removeFromTop (20)); // Top row: 4 knobs int knobW = bounds.getWidth() / 4; int knobH = (bounds.getHeight() - 30) * 2 / 3; auto topRow = bounds.removeFromTop (knobH); juce::Slider* knobs[] = { &posScatterKnob, &sizeScatterKnob, &pitchScatterKnob, &panScatterKnob }; juce::Label* labels[] = { &posScatLabel, &sizeScatLabel, &pitchScatLabel, &panScatLabel }; for (int i = 0; i < 4; ++i) { auto col = topRow.removeFromLeft (knobW); knobs[i]->setBounds (col.reduced (2)); labels[i]->setBounds (col.getX(), col.getBottom() - 2, col.getWidth(), 16); } // Bottom row: Direction combo + Freeze toggle auto botRow = bounds.reduced (2); int halfW = botRow.getWidth() / 2; auto dirArea = botRow.removeFromLeft (halfW); dirLabel.setBounds (dirArea.removeFromTop (14)); directionBox.setBounds (dirArea.reduced (4, 2)); auto freezeArea = botRow; freezeLabel.setBounds (freezeArea.removeFromTop (14)); freezeButton.setBounds (freezeArea.reduced (4, 2)); } void ScatterPanel::paint (juce::Graphics& g) { auto bounds = getLocalBounds().toFloat(); g.setColour (InstaGrainLookAndFeel::bgMedium.withAlpha (0.5f)); g.fillRoundedRectangle (bounds, 4.0f); g.setColour (InstaGrainLookAndFeel::bgLight.withAlpha (0.3f)); g.drawRoundedRectangle (bounds, 4.0f, 1.0f); }