Trying to get a "GroupComponent" around a slider and linked label - What am I doing wrong?

Well I got a simple FlexBox implementation going now thanks to you daniel and this thread.

Here is the code, which is again the header code from the SineSynth Tutorial modified, and stealing some bits from the FlexBox tutorial:

class LabeledSlider : public GroupComponent

{
    public:
    LabeledSlider (const String& name)
    {
        setText (name);
        setTextLabelPosition (Justification::centredTop);
        addAndMakeVisible (slider);
    }
    
    void resized() override
    {
        slider.setBounds (getLocalBounds().reduced (10));
    }
    
    Slider slider 
    { 
        Slider::RotaryHorizontalVerticalDrag, Slider::TextBoxBelow 
    };
    

};



class MainContentComponent : public AudioAppComponent
{
public:
    MainContentComponent()
	
    {
    addAndMakeVisible(frequency);
    addAndMakeVisible(level);
	addAndMakeVisible(dummy1);
	addAndMakeVisible(dummy2);
	addAndMakeVisible(dummy3);
	addAndMakeVisible(dummy4);
	addAndMakeVisible(dummy5);
	addAndMakeVisible(dummy6);
	addAndMakeVisible(dummy7);
	addAndMakeVisible(dummy8);
	addAndMakeVisible(dummy9);

    frequency.slider.setRange (20.0, 20000.0);
    frequency.slider.setSkewFactorFromMidPoint (500.0);
    frequency.slider.setNumDecimalPlacesToDisplay (1);
    frequency.slider.setValue(currentFrequency, dontSendNotification);
    frequency.slider.onValueChange = [this] { targetFrequency = frequency.slider.getValue(); };
	frequency.slider.setTextBoxStyle(Slider::TextBoxBelow, false, 100, 20);
	frequency.slider.setRange(50.0, 5000.0);
	frequency.slider.setSkewFactorFromMidPoint(500.0);
	frequency.slider.setNumDecimalPlacesToDisplay(1);

    level.slider.setRange (0.0, 1.0);
    level.slider.onValueChange = [this] { targetLevel = (float) level.slider.getValue(); };

    setSize (600, 600);
    setAudioChannels (0, 2); // no inputs, two outputs
    }

    ~MainContentComponent()
    {
        shutdownAudio();
    }

    void resized() override
    {
			
		//==============================================================================
		FlexBox knobBox;
		knobBox.flexWrap = FlexBox::Wrap::wrap;
		knobBox.justifyContent = FlexBox::JustifyContent::flexStart;
		knobBox.alignContent = FlexBox::AlignContent::flexStart;

		Array<LabeledSlider*> knobs;
		knobs.add(&frequency, &level, &dummy1, &dummy2, &dummy3, &dummy4, &dummy5, &dummy6, &dummy7, &dummy8, &dummy9);

		for (auto* k : knobs)
			knobBox.items.add(FlexItem(*k).withMinHeight(80.0f).withMinWidth(80.0f).withFlex(1));

		//==============================================================================
		FlexBox fb;
		fb.flexDirection = FlexBox::Direction::column;
		fb.items.add(FlexItem(knobBox).withFlex(2.5));
		fb.performLayout(getLocalBounds().toFloat());
	

    }

    inline void updateAngleDelta()
    {
        auto cyclesPerSample = currentFrequency / currentSampleRate;
        angleDelta = cyclesPerSample * 2.0 * MathConstants<double>::pi;
    }

    void prepareToPlay (int, double sampleRate) override
    {
        currentSampleRate = sampleRate;
        updateAngleDelta();
    }

    void releaseResources() override {}

    void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override
    {
        auto* leftBuffer  = bufferToFill.buffer->getWritePointer (0, bufferToFill.startSample);
        auto* rightBuffer = bufferToFill.buffer->getWritePointer (1, bufferToFill.startSample);

        auto localTargetFrequency = targetFrequency;

        if (targetFrequency != currentFrequency)
        {
            auto frequencyIncrement = (targetFrequency - currentFrequency) / bufferToFill.numSamples;

            for (auto sample = 0; sample < bufferToFill.numSamples; ++sample)
            {
                auto currentSample = (float) std::sin (currentAngle);
                currentFrequency += frequencyIncrement;
                updateAngleDelta();
                currentAngle += angleDelta;
                leftBuffer[sample]  = currentSample;
                rightBuffer[sample] = currentSample;
            }

            currentFrequency = localTargetFrequency;
        }
        else
        {
            for (auto sample = 0; sample < bufferToFill.numSamples; ++sample)
            {
                auto currentSample = (float) std::sin (currentAngle);
                currentAngle += angleDelta;
                leftBuffer[sample]  = currentSample;
                rightBuffer[sample] = currentSample;
            }
        }

        auto localTargetLevel = targetLevel;
        bufferToFill.buffer->applyGainRamp (bufferToFill.startSample, bufferToFill.numSamples, currentLevel, localTargetLevel);
        currentLevel = localTargetLevel;
	}

private:
	double currentSampleRate = 0.0, currentAngle = 0.0, angleDelta = 0.0;
	double currentFrequency = 500.0, targetFrequency = 500.0;
	float currentLevel = 0.1f, targetLevel = 0.1f;
	int rotaryDiam = 100;

	LabeledSlider frequency{ "Frequency" };
	LabeledSlider level{ "Level" };
	LabeledSlider dummy1{ "Dummy 1" };
	LabeledSlider dummy2{ "Dummy 2" };
	LabeledSlider dummy3{ "Dummy 3" };
	LabeledSlider dummy4{ "Dummy 4" };
	LabeledSlider dummy5{ "Dummy 5" };
	LabeledSlider dummy6{ "Dummy 6" };
	LabeledSlider dummy7{ "Dummy 7" };
	LabeledSlider dummy8{ "Dummy 8" };
	LabeledSlider dummy9{ "Dummy 9" };


    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
};

This creates this result:

Now I have two follow up questions:

1) Automating the Array?
Currently to add a knob, I must enter it in three spaces of MainContentComponent: (i) Create it as an object under Private, (ii) addAndMakeVisible under Public, and (iii) Add it to the Array under “void resized()” in Public.

This is acceptable, but is there any more efficient way to do it? Is there any way to automate step (iii) and somehow have all “labeledSlider” objects automatically added to the array in the order they’re declared?

This would help with efficiency and reduce potential error on projects with many knobs as I have planned.

2) Left Justifying the FlexBox?
In the screencap of my FlexBox test, the 3rd row which only has three knobs (vs. four knobs for the other rows) is stretched horizontally, so the three LabeledSlider objects on this row are different width from the rest.

Is there any way to prevent this and force the FlexBox process to assign the least (or equal) amount of space needed to all Items? Ie. So they all look the same?

I tried to force left justification instead of stretching with:

FlexBox knobBox;
	knobBox.flexWrap = FlexBox::Wrap::wrap;
	knobBox.justifyContent = FlexBox::JustifyContent::flexStart;
	knobBox.alignContent = FlexBox::AlignContent::flexStart;

But it didn’t work as you can see, as it’s still stretching each row individually to fit the full width. Any fix?

Thanks again. Getting there. :slight_smile: