Nested FlexBox items?

My advice: always use ‘++i’ rather than ‘i++’ if it’s possible.

1 Like

int i = 1 is right here ?

i do not deserve to keep my name

2 Likes

and always:

for (int i = 5; --i >= 0; )

rather than

for (int i = 0; i < 5; ++i)

if it’s possible…

1 Like

sure, sure

https://juce.com/doc/classComboBox#a37491da45f1cbb74e47f145e5664d8bf

newItemId an associated ID number that can be set or retrieved - see getSelectedId() and setSelectedId(). Note that this value can not be 0!

i see :confused:

This is where I’m at, to clarify the resized() and comboBoxChanged() methods now:

in the header, private section:

    ScopedPointer<PlaceHolder> footer;
    ScopedPointer<PlaceHolder> sequence;

in the constructor:

    addAndMakeVisible( footer = new PlaceHolder("footer", false) );
    addAndMakeVisible( sequence = new PlaceHolder("sequence", false ) );

and the revised resized() and comboBoxChanged()

void MainContentComponent::resized()
{
    FlexBox headerBox;
    {
        headerBox.items.add(FlexItem(allUsersList).withFlex(1.0).withMargin({2.0}) );
        addAndMakeVisible(allUsersList);
    }
    FlexBox contentBox;
    {
        FlexBox segmentBox;
        segmentBox.flexWrap = FlexBox::Wrap::wrap;
        segmentBox.flexDirection = FlexBox::Direction::row;
        {
            for( int i = 0; i < elements.size(); ++i ) {
                auto &newElement = *elements[i];
                DBG( "name: " + newElement.getName() );

                segmentBox.items.add( FlexItem( newElement ).withFlex(1.0).withMargin({2.0}));
            }
        }
        contentBox.items.add( FlexItem(segmentBox).withFlex(1.0).withMargin({2.0}) );
    }
    FlexBox selectedSequenceBox;
    {
        selectedSequenceBox.items.add( FlexItem( *sequence ).withFlex(1.0).withMargin({2.0}) );
    }
    FlexBox footerBox;
    {
        footerBox.items.add( FlexItem( *footer ).withFlex(1.0).withMargin({2.0}) );
    }
    FlexBox interface;

    interface.flexDirection = FlexBox::Direction::column;
    interface.items.add( FlexItem(headerBox).withFlex(0.5) );
    interface.items.add( FlexItem(contentBox).withFlex(1) );
    interface.items.add( FlexItem(selectedSequenceBox).withFlex(0.5) );
    interface.items.add( FlexItem(footerBox).withFlex(0.5) );

    interface.performLayout(getLocalBounds());
}
void MainContentComponent::comboBoxChanged(juce::ComboBox *comboBoxThatHasChanged) {
    if( comboBoxThatHasChanged == &allUsersList ) {
        DBG( "comboBoxChanged selectedID:" + String(allUsersList.getSelectedItemIndex()) );
        loadedSession = allUsersList.getSelectedItemIndex() + 1;
        elements.clear();
        for( int i = 0; i < loadedSession; ++i ) {
            DBG( "i: " + String(i) );
            elements.add( new PlaceHolder("segmentBox" + String(i+1), false) );
            auto &newElement = *elements[i];
            addAndMakeVisible( newElement );
        }
        resized();
    }
}

@jules we need your help lol. none of us, including @daniel or a few other folks in the #juce IRC channel on freenode can solve it.

ok, it seems that FlexBox::items::add does not like when you use blocks to control nesting. the following works perfectly when all of those scoping {} are removed:

void MainContentComponent::resized()
{
    FlexBox headerBox;
        headerBox.items.add(FlexItem(allUsersList).withFlex(1.0).withMargin({2.0}) );
        addAndMakeVisible(allUsersList);
    FlexBox contentBox;
        FlexBox segmentBox;
        segmentBox.flexWrap = FlexBox::Wrap::wrap;
        segmentBox.flexDirection = FlexBox::Direction::row;
            for( int i = 0; i < elements.size(); ++i ) {
                auto &newElement = *elements[i];
                DBG( "name: " + newElement.getName() );

                segmentBox.items.add( FlexItem( newElement ).withFlex(1.0).withMargin({2.0}));
            }
        contentBox.items.add( FlexItem(segmentBox).withFlex(1.0).withMargin({2.0}) );
    FlexBox selectedSequenceBox;
        selectedSequenceBox.items.add( FlexItem( *sequence ).withFlex(1.0).withMargin({2.0}) );
    FlexBox footerBox;
        footerBox.items.add( FlexItem( *footer ).withFlex(1.0).withMargin({2.0}) );
    FlexBox interface;

    interface.flexDirection = FlexBox::Direction::column;
    interface.items.add( FlexItem(headerBox).withFlex(0.5) );
    interface.items.add( FlexItem(contentBox).withFlex(1) );
    interface.items.add( FlexItem(selectedSequenceBox).withFlex(0.5) );
    interface.items.add( FlexItem(footerBox).withFlex(0.5) );

    interface.performLayout(getLocalBounds());
}

:clap:

Requesting that some addition to the FlexBox documentation be added that clarifies if you’re going to masterFlexBox.items.add( FlexItem( FlexBox& flexBoxToControl ) ), the flexBoxToControl needs to not go out of scope until masterFlexBox is out of scope.

FlexItem::FlexItem ( FlexBox & flexBoxToControl )

supposedly it is implied by the reference being used, but some of us (me) are dumb lol

2 Likes

i.e. not before performLayout was called.

When ading to Array items using add () one expects it’s lifetime to be dependant of the containing array, but since C++11 this seems different…

I always wondered, how add (ElementType && newElement) is different from add (ElementType & newElement) and how I can enforce the use of either…

The reference in the constructor to the Component has nothing to do with the lifetime in the FlexBox items container IMHO.

2 Likes

Wanted to chime in on this thread. I have a bunch of FlexItems I was able to consolidate into a for loop, and got burned big time when the FlexItem component pointers were mysteriously going out of scope.

Extra documentation, an explanation why this happens, or a workaround would be greatly appreciated!

Now off to copy/paste dozens of lines of code in my resized() method to manually unroll the loop…

I can’t see how to fix this problem without making everything reference counted, as multiple FlexItems could technically reference the same FlexBox. To be honest, the reference counting itself would not add so much overhead, however, the FlexItems would need to live on the heap rather than the stack which would throw memory allocations/de-allocations into the mix which may be a bit too much for some complex layouts.

For now, I’ve updated the documentation (will appear on develop shortly).

I was almost bitten by this. I would have though that the whole purpose of Flexbox is to have nested ones.
My rationale was to have FlexBox and FlexItem only defined in resized to avoid polluting the class with member data only used for the layout.

Like I have those labels and associated knob and would like to be able to iterate over those and place label on top of knobs.

People don’t use it like that ?

Maybe I should have a look at Grid instead

1 Like