Rectangle.removeFromSide behaviour feels not right (Solved)

Hi, I’m just starting to learn the Juce with the help of youtube videos. I got to the point of manipulating the placement for dials. I’ve done game development and worked with GUI coding before.
I like the approach for resizing like it’s in drawing apps - resize from reference/ origin point.
But this is the first time I see that type method sets the object itself on top of returning the remainder. Because I expect to return the value of change and that’s it.
With current methods, it’s needed to use many Rectangle objects in a place where it could be simple calculations done around one object. For example putting sliders in corners I could use single Rectangle using this same manipulations:
dial1.setBounds(area.removeFromTop(area.getHeight() * 0.5).removeFromLeft(area.getWidth() * 0.5));
In current situation it needs at least n/2 rectangles for each dial.

Maybe you could add some more examples of what you mean, for example more complete code that shows the approach of how it works today (use many Rectangle objects) vs the same code, but how you would like it to work.

1 Like

Sorry don’t know how to post code so here’s PasteBin.

void MainComponent::resized()
    Rectangle<int> top = getLocalBounds();
    Rectangle<int> bottom = top.removeFromTop(top.getHeight() * 0.5);
    dial1.setBounds(top.removeFromLeft(top.getWidth() * 0.5));
    dial3.setBounds(bottom.removeFromLeft(bottom.getWidth() * 0.5));

//Proposed - that using removeFromSide doesn't change caller object
//Maybe alternative method?
void MainComponent::resized()
    Rectangle<int> area = getLocalBounds();
	int h = area.getHeight();
	int w = area.getWidth();
    dial1.setBounds(area.removeFromTop(h * 0.5).removeFromLeft(w * 0.5));
    dial2.setBounds(area.removeFromTop(h * 0.5).removeFromRight(w * 0.5));
    dial3.setBounds(area.removeFromBottom(h * 0.5).removeFromLeft(w * 0.5));
    dial4.setBounds(area.removeFromBottom(h * 0.5).removeFromRight(w * 0.5));

The idea is to cover a whole area with UI elements. The four methods removeFromLeft/Top/Right/Bottom split the area in two parts: the removed one, which is returned, and the remainder, which is the rectangle itself.

This makes it very easy, usually I only need one rectangle:

void resized() override
    auto area = getLocalBounds();
    int h = area.getHeight() / 4;
    dial1.setBounds (area.removeFromTop (h));
    dial2.setBounds (area.removeFromTop (h));
    dial3.setBounds (area.removeFromTop (h));
    dial4.setBounds (area);

For nesting I often use additional rectangles:

void resized() override
    auto area = getLocalBounds();

    header.setBounds (area.removeFromTop (h));

    auto buttonArea = area.removeFromTop (30);
    button1.setBounds (buttonArea.removeFromLeft (80));
    button2.setBounds (buttonArea.removeFromLeft (80));
    button3.setBounds (buttonArea.removeFromLeft (80));

    auto dialArea = area.removeFromTop (80);
    dial1.setBounds (dialArea.removeFromLeft (60));
    dial2.setBounds (dialArea.removeFromLeft (60));
    dial3.setBounds (dialArea.removeFromLeft (60));
    dial4.setBounds (dialArea.removeFromLeft (60));

…and so on.

btw. to post code, start with three back ticks ``` on a separate line and end the block again with three back ticks on a separate line

EDIT about your example:
By chaining two removeFromXYZ() calls in one setBounds(), you will leave areas unused. I don’t think that is what you want. But I haven’t understood your code in full, might be a mistake on my end.

Thanks, I updated my comment. In current situation chaining will leave holes because it changes caller object. And that’s what I’m proposing, to have method that doesn’t change caller object, allowing reuse of one object and chaining methods.
It just clicked just now that it’s pretty easy to change source code method. I’ll try my hands to create alternative, but dunno if changes are permament.
Basically change it like this in source and it works like I wanted :smiley: :

    Rectangle removeFromTop (ValueType amountToRemove) noexcept
        const Rectangle r (pos.x, pos.y, w, jmin (amountToRemove, h));
        //pos.y += r.h; h -= r.h;
        return r;

That command you are looking for actually exists, e.g. withTrimmedLeft (x)

Returns a version of this rectangle with the given amount removed from its left-hand edge.


Oh! Didn’t see it there. I’m sorry for the situation!
And thank you for pointing it out.