I’ve trying to work out why my nested FlexBox layout is not working as I expect. I pulled out the essentials and created a PIP.
If I ignore the ButtonGroup::flexBox
and use it’s buttonBox
instead, all works as expected. But nesting it into another FlexBox results in a) the buttons not appearing and b) a crash when resizing the window, on juce::Point::setXY
, with some crazy x and y values.
Anyone have a clue as to what I’ve missed here?
/*******************************************************************************
The block below describes the properties of this PIP. A PIP is a short snippet
of code that can be read by the Projucer and used to generate a JUCE project.
BEGIN_JUCE_PIP_METADATA
name: NestedFlexbox
description: Demo to show an issue with nested FlexBoxes
dependencies: juce_core, juce_data_structures, juce_events, juce_graphics, juce_gui_basics
exporters: vs2017, vs2019, xcode_mac
moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1
type: Component
mainClass: MyComponent
END_JUCE_PIP_METADATA
*******************************************************************************/
#pragma once
//==============================================================================
class MyComponent : public Component
{
public:
//==============================================================================
MyComponent()
{
addAndMakeVisible (button1);
addAndMakeVisible (button2);
addAndMakeVisible (button3);
addAndMakeVisible (button4);
addAndMakeVisible (button5);
addAndMakeVisible (group1Label);
addAndMakeVisible (group2Label);
flexBox.flexDirection = FlexBox::Direction::row;
flexBox.alignContent = FlexBox::AlignContent::stretch;
flexBox.alignItems = FlexBox::AlignItems::stretch;
//==============================================================================
buttonGroups.push_back({group1Label, {button1, button2, button3}});
buttonGroups.push_back({group2Label, {button4, button5}});
//==============================================================================
for (auto& buttonGroup : buttonGroups)
{
auto groupWidth = (buttonGroup.buttonBox.items.size() * (buttonWidth + buttonMargin));
flexBox.items.add (FlexItem (buttonGroup.flexBox) // <-- changing this to .buttonBox works
.withMargin (buttonGroupMargin)
.withWidth (groupWidth)
.withFlex (1, 0));
}
setSize (600, 400);
}
~MyComponent()
{
}
//==============================================================================
void paint (Graphics& g) override
{
// (Our component is opaque, so we must completely fill the background with a solid colour)
g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));
}
void resized() override
{
flexBox.performLayout (getLocalBounds().toFloat());
}
private:
//==============================================================================
struct ButtonGroup
{
ButtonGroup (Label& label, std::vector<std::reference_wrapper<TextButton>> buttons)
: label (label)
{
buttonBox.flexDirection = FlexBox::Direction::row;
buttonBox.alignContent = FlexBox::AlignContent::center;
buttonBox.alignItems = FlexBox::AlignItems::center;
flexBox.flexDirection = FlexBox::Direction::column;
flexBox.alignContent = FlexBox::AlignContent::stretch;
//flexBox.alignItems = FlexBox::AlignItems::center;
for (auto button : buttons)
{
buttonBox.items.add (FlexItem (button)
.withHeight (buttonHeight)
.withFlex (0, 0, buttonWidth)
.withMargin (buttonMargin));
}
flexBox.items.add (FlexItem (buttonBox)
.withWidth (200)
.withHeight (50)
.withFlex (0.5));
flexBox.items.add (FlexItem (label)
.withFlex (0.5));
}
Label& label;
FlexBox buttonBox, flexBox;
};
static constexpr int buttonHeight = 24;
static constexpr int buttonWidth = 45;
static constexpr int buttonMargin = 3;
static constexpr int buttonGroupMargin = 10;
FlexBox flexBox;
std::vector<ButtonGroup> buttonGroups;
TextButton button1 { "A" };
TextButton button2 { "B" };
TextButton button3 { "C" };
TextButton button4 { "X" };
TextButton button5 { "Y" };
Label group1Label { "Group1", "Group 1" };
Label group2Label { "Group2", "Group 2" };
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MyComponent)
};