It looks like I got the basic principle for my flexible FlexBox GUI working. Here is what it currently looks like:
If you expand the window horizontally, the two groups will go onto one row together. Ie. Flexbox.
Here is the full code (single file css):
/*
==============================================================================
This file was auto-generated and contains the startup code for a PIP.
==============================================================================
*/
#include "../JuceLibraryCode/JuceHeader.h"
///============================
///BEGINNING OF USUAL PROJECT HEADER
#pragma once
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 LabeledGroup : public GroupComponent
{
public:
LabeledGroup(const String& name)
{
setText(name);
setTextLabelPosition(Justification::centredTop);
addAndMakeVisible(dummy1);
addAndMakeVisible(dummy2);
addAndMakeVisible(dummy3);
addAndMakeVisible(dummy4);
}
void resized() override
{
//setBounds(getLocalBounds().reduced(10));
FlexBox knobBox1;
knobBox1.flexWrap = FlexBox::Wrap::wrap;
knobBox1.justifyContent = FlexBox::JustifyContent::flexStart;
knobBox1.alignContent = FlexBox::AlignContent::flexStart;
Array<LabeledSlider*> knobs1;
knobs1.add(&dummy1, &dummy2, &dummy3, &dummy4);
for (auto *k : knobs1)
knobBox1.items.add(FlexItem(*k).withMinHeight(80.0f).withMinWidth(80.0f).withFlex(1));
FlexBox fb1;
fb1.flexDirection = FlexBox::Direction::column;
fb1.items.add(FlexItem(knobBox1).withFlex(2.5));
fb1.performLayout(getLocalBounds().reduced(15).toFloat());
}
private:
LabeledSlider dummy1{ "Dummy 1" };
LabeledSlider dummy2{ "Dummy 2" };
LabeledSlider dummy3{ "Dummy 3" };
LabeledSlider dummy4{ "Dummy 4" };
};
//==============================================================================
//MAINCONTENTCOMPONENT
//==============================================================================
class MainContentComponent : public Component
{
public:
MainContentComponent()
{
addAndMakeVisible(group1);
addAndMakeVisible(group2);
level.slider.setRange(0.0, 1.0);
level.slider.setNumDecimalPlacesToDisplay(1);
level.slider.onValueChange = [this] { targetLevel = (float)level.slider.getValue(); };
addAndMakeVisible(level);
setSize(600, 600);
}
~MainContentComponent()
{
// shutdownAudio();
}
void resized() override
{
//group1.setBounds(getLocalBounds().expanded(10));
//group2.setBounds(getLocalBounds().expanded(10));
FlexBox groupBox1;
groupBox1.flexWrap = FlexBox::Wrap::wrap;
groupBox1.justifyContent = FlexBox::JustifyContent::flexStart;
groupBox1.alignContent = FlexBox::AlignContent::flexStart;
Array<LabeledGroup*> groups1array;
groups1array.add(&group1, &group2);
for (auto *g : groups1array)
groupBox1.items.add(FlexItem(*g).withMinHeight(100.0f).withMinWidth(350.0f).withFlex(3).withMargin(5));
FlexBox fb1;
fb1.flexDirection = FlexBox::Direction::column;
fb1.items.add(FlexItem(groupBox1).withFlex(3));
fb1.performLayout(getLocalBounds().toFloat());
}
private:
float currentLevel = 0.1f, targetLevel = 0.1f;
LabeledGroup group1{ "Group 1" };
LabeledGroup group2{ "Group 2" };
LabeledSlider level{ "Level" };
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MainContentComponent)
};
///============================
///BEGINNING OF USUAL MAIN.CPP
class Application : public JUCEApplication
{
public:
Application() {}
const String getApplicationName() override { return "SineSynthTutorial"; }
const String getApplicationVersion() override { return "3.0.0"; }
void initialise(const String&) override { mainWindow.reset(new MainWindow("SineSynthTutorial", new MainContentComponent(), *this)); }
void shutdown() override { mainWindow = nullptr; }
private:
class MainWindow : public DocumentWindow
{
public:
MainWindow(const String& name, Component* c, JUCEApplication& a)
: DocumentWindow(name, Desktop::getInstance().getDefaultLookAndFeel()
.findColour(ResizableWindow::backgroundColourId),
DocumentWindow::allButtons),
app(a)
{
setUsingNativeTitleBar(true);
setContentOwned(c, true);
#if JUCE_ANDROID || JUCE_IOS
setFullScreen(true);
#else
setResizable(true, false);
setResizeLimits(300, 250, 10000, 10000);
centreWithSize(getWidth(), getHeight());
#endif
setVisible(true);
}
void closeButtonPressed() override
{
app.systemRequestedQuit();
}
private:
JUCEApplication & app;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MainWindow)
};
std::unique_ptr<MainWindow> mainWindow;
};
//==============================================================================
START_JUCE_APPLICATION(Application)
The problem is I am declaring variables three times directly inside the class definition for LaeledGroup:
addAndMakeVisible(dummy1);
addAndMakeVisible(dummy2);
addAndMakeVisible(dummy3);
addAndMakeVisible(dummy4);
knobs1.add(&dummy1, &dummy2, &dummy3, &dummy4);
LabeledSlider dummy1{ "Dummy 1" };
LabeledSlider dummy2{ "Dummy 2" };
LabeledSlider dummy3{ "Dummy 3" };
LabeledSlider dummy4{ "Dummy 4" };
I need a way of replacing these three portions to references to arrays or vectors, that I can then specify for each object of LabeledGroup, so each LabeledGroup can be generated with its own number and names of knobs accordingly (from its own arrays).
I have tried this many times with arrays and vectors but I do not seem to be succeeding. Can anyone help?
I’m getting much closer to my goal! Just need some help with the vector/array references . . .
Thanks.


