Bug in Projucer GUI editor: objects positioned relative to other elements are not handled in resized()


#1

I have the following Projucer GUI Component:

<JUCER_COMPONENT documentType="Component" className="Test" componentName="" parentClasses="public Component"
                 constructorParams="" variableInitialisers="" snapPixels="8" snapActive="1"
                 snapShown="1" overlayOpacity="0.33" fixedSize="1" initialWidth="200"
                 initialHeight="200">
  <BACKGROUND backgroundColour="ff323e44"/>
  <GROUPCOMPONENT name="new group" id="e69593baec37af" memberName="groupComponent"
                  virtualName="" explicitFocusOrder="0" pos="8 8 16M 16M" title="group"/>
  <TEXTBUTTON name="new button" id="b9e37873949b898d" memberName="textButton"
              virtualName="" explicitFocusOrder="0" pos="16 144 150 24" posRelativeX="e69593baec37af"
              posRelativeY="e69593baec37af" buttonText="new button" connectedEdges="0"
              needsCallback="1" radioGroupId="0"/>
</JUCER_COMPONENT>

The gist is, that the textButton is positioned relative to groupComponent.

Observed:
The Projucer generated the following resize() code:

void Test::resized()
{
    //[UserPreResize] Add your own custom resize code here..
    //[/UserPreResize]

    groupComponent->setBounds (8, 8, getWidth() - 16, getHeight() - 16);
    //[UserResized] Add your own custom resize handling here..
    //[/UserResized]
}

the code for positioning the textButton is omitted entirely.

Expected:

the generated resized() function contains code to position the textButton as well. This used to work in earlier versions. Also the Projucer positions the components as one would expect.

I’m on 717cc49382fd8fd97dcfe080c75be60d573d4e5b, macOS


#2

This is a known limitation, unfortunately there are no plans to add functionality to it, see this thread:

There are too many different ways to layout a GUI, there are the FlexBox and Grid methods around now.

I wish I had better news here, maybe one day the priorities change again…


#3

the forum seems to get a post about the editor not doing something correctly once or twice a month. How long would it take to strip it out of ProJucer? a day, maybe? Is that on the todo list by chance @daniel?


#4

Lads, I’m getting that you’re trying to get rid of the GUI editor. But this used to work in the past - so someone broke it along the way. Just try it with 5.2.0.

PS.: I don’t get why anybody would prefer to check-adjust-recompile-rinse-repeat over pseudo-WYSIWYG.

PPS.:

5.2.0 generates:

textButton->setBounds (8 + 16, 8 + 128, 150, 24);

which is indeed not correct as it ignores the fact that the parent might have been dynamically positioned. snap!


#5

There are legacy project still using this feature. What would you gain by having it removed?


#6

you’d write your GUIs using dynamic resizing via flexbox or grid.


#7

setBounds is relative to the parent. that textButton will always be 8+16 units away from the parent’s left edge…


#8

True, put the generated code in 5.2.0 does also ignore the parents dynamic X if the parent is positioned as ‘absolute distance from right of parent’.


#9

What’s your workflow? In my experience the re-compile times make layout via code a pain.


#10

say that again?


#11

image
(group now sticks to the right)

in this case the X of the textButton depends on the X of the group which depends on the width of the whole component. And the code that the Projucer of 5.2.0 generates does not take this into account.


#12

There is the JUCE_LIVE_CONSTANT class for editing values while the application is running, which is very useful for getting those fine details just right!


#13

yeah, that’s the only way to develop your GUI’s really. it doesn’t work for ios or android tho, because those are always fullscreen apps, and the LiveConstant appears in its own window


#14

That still requires you to tag all the places you want to adjust beforehand. And when you’re done you need to remove JUCE_LIVE_CONSTANT again because otherwise the list can get a little overwhelming. I do use it for tweaking stuff in paint() though.


#15

Hey Daniel, IMHO this is still a regression to earlier versions (5.2.0) and I’d appreciate if someone could have a look. I have now two projects with borked UI.


#16

My apologies, I missed this most important line. I thought you were referring to the fact, that there is no dynamic resizing.

I am not working on the Projucer, it is probably something @ed95 would know best…


#17

This is the commit after which the resized() behaviour is different, and AFAICT it’s fixing an actual bug in the layout code. Perhaps your code just worked before with the broken behaviour and is actually incorrect although I’m not totally clear what your expected behaviour is - can you provide a bit more info and perhaps some screenshots?


#18

That’s cool, I wasn’t aware, that the Projucer actually can generate formulas in the resized() method. I loaded the code you posted, and indeed it is missing the line for resized() for textButton.
However, when I looked in the GUI editor, I realised, that the width and height for your textButton is set to “absolute”. Once you change it to “Subtract from width of parent”, it works again…
I don’t know, why it would behave differently in 5.2.0 though.


#19

Wow. How did you dig that up so fast?

Essentially I’d like the generated code to behave the same as the cmd+t preview in the Projucer.

this bit of code appears to decide if a bit of resizing-code goes into the constructor or into resized(). What appears to be missing here is a check if the RelativePositionedRectangle is positioned relative to the ‘parent’ (i.e. root) or relative to some other component.

Here’s another example:

<JUCER_COMPONENT documentType="Component" className="Test" componentName="" parentClasses="public Component"
                 constructorParams="" variableInitialisers="" snapPixels="8" snapActive="1"
                 snapShown="1" overlayOpacity="0.33" fixedSize="1" initialWidth="128"
                 initialHeight="64">
  <BACKGROUND backgroundColour="ff323e44"/>
  <TEXTBUTTON name="new button" id="7128704c3d25d451" memberName="a" virtualName=""
              explicitFocusOrder="0" pos="50% 0 24 24" buttonText="a" connectedEdges="0"
              needsCallback="1" radioGroupId="0"/>
  <TEXTBUTTON name="new button" id="c8980fa8501603ff" memberName="b" virtualName=""
              explicitFocusOrder="0" pos="24 32 24 24" posRelativeX="7128704c3d25d451"
              buttonText="b" connectedEdges="0" needsCallback="1" radioGroupId="0"/>
</JUCER_COMPONENT>

image

here are the generated lines:

a->setBounds (proportionOfWidth (0.5f), 0, 24, 24); // in resized()
b->setBounds (proportionOfWidth (0.5f) + 24, 32, 24, 24); // in constructor

obviously the second line should also be in resized(), as it depends on the width of the parent.


#20

I think the RelativePositionedRectangle::isPositionAbsolute() returns a true, when it shouldn’t.
It doesn’t take absoluteFromParentTopLeft into account, when the parent itself is relative.