Resizing two components at once

I want to horizontally resize two components at once using the mouse so that as one grows the other shrinks. It seems that there are several tools available for doing this, and I want to know what the best one is.

  1. ConcertinaPanel. This is exactly what I’m trying to achieve, except I want to do it horizontally. From what I can tell, it only works vertically. Is that right?
  2. ResizableEdgeComponent. I first tried this, but found that it only resizes one component. It might be possible to force the other component to respond to the first one, but this seems dodgy. I assume that this is a dead-end.
  3. StretchableLayoutManager. This seems to be the right tool for the job, and in fact I’ve almost got it working. However, poking around on this forum, I see that it has sort of been replaced by…
  4. Grid. This seems like the most modern layout tool around, but I haven’t been able to find a method for manually resizing components–it seems to be entirely automated. Am I right about this, or does Grid in fact offer a way to manually resize two components at once?

I really appreciate the amount of work that has gone into layout techniques in JUCE!

How about just a draggable thin component in your parent class that can actually move and does it all?

struct MyDraggableComp : public Component //literally from the ComponentDragger docs
    ComponentDragger myDragger;
    void mouseDown (const MouseEvent& e)
        myDragger.startDraggingComponent (this, e);
    void mouseDrag (const MouseEvent& e)
        myDragger.dragComponent (this, e, nullptr);
    void paint(Graphics& g) override 
        //make it look good/functional
struct Foo : public Component
    MyWidget leftSide;
    MyWidget rightSide;
    MyDraggableComp draggableResizer;
        addAndMakeVisible( draggableResizer );
    void mouseDrag (const MouseEvent& e) override
    void resized() override 
        draggableResizer.setSize( 5, getHeight() ); //
        auto x = draggableResizer.getX();
        auto xr = draggableResizer.getRight();
        leftSide.setBounds(0,0, x, getHeight() );
        rightSide.setBounds( xr, 0, getWidth() - xr, getHeight() );

I hadn’t considered this, but I’m fairly committed to using one of the the layout managers that is already implemented, as it should scale better (ie. because in fact there are more than two windows that I want to resize). I’m pretty sure that either StretchableLayoutManager or Grid will be perfect for my task–I’m just trying to figure out which one is preferable. Grid seems to be the one that people generally prefer, but can it deal with manual resizing? If I could get a yes or a no here, it would help me a lot.

just try it and see.

if it sucks and doesn’t do what you want, try the other one.

if that also sucks, roll your own solution.

1 Like

@matkatmusic, you’re absolutely right, tinkering is the best way to learn. However I’ve never used CSS grids before, and since there are a lot of people on this forum with greater experience than I, I thought that the answer might be close at hand.

Anyway, I’ve got StretchableLayoutManager and StretchableLayoutResizerBar working fairly well now. However, I’ve run into a peculiar new problem that it enlarges correctly when I drag it right, but fails to shrink again when I drag it left. Can anyone think what the problem might be here? Here’s the relevant section of code:

class MainComponent
    StretchableLayoutManager horizontalLayout;
    int componentCounter;
    std::unique_ptr<StretchableLayoutResizerBar> resizeBar;
    SidePanelComponent sidePanelComponent;
    TabHolder tabHolder;

    std::vector<Component*> arrayOfComponentPointers;
        addComponentWithLayout(&sidePanelComponent, -0.0, -1.0, -0.20);
        resizeBar = std::make_unique<StretchableLayoutResizerBar>(&horizontalLayout, componentCounter + 1, true);
        addComponentWithLayout(resizeBar.get(), 5.0, 5.0, 5.0);
        addComponentWithLayout(&tabHolder, -0.0, -1.0, -0.80);

    void addComponentWithLayout(Component* componentToAdd, double min, double max, double pref)
        horizontalLayout.setItemLayout(componentCounter++, min, max, pref);

    void resized()
        horizontalLayout.layOutComponents(, componentCounter, 0, 0, getWidth(), getHeight(), false, true); }

Edit: in case anyone else faces the same issue, the problem was with line resizeBar = std::make_unique<StretchableLayoutResizerBar>(&horizontalLayout, componentCounter + 1, true);. The componentCounter argument should have been specified on its its own without the +1.

Grid has no mouse resizing support, it’s just a rule based geometry manager.

@Xenakios thanks for the input. This confirms what I thought.

While I’m here, I’d like to ask another question about Grid. Is is possible to use Grid for layout of a dynamic number of rows/columns? From what I can tell, the TrackInfo() method shown in the tutorial only works if you know the number of rows & columns before hand.

From the documentation :

Container that handles geometry for grid layouts 
(fixed columns and rows) using a set of declarative rules.

However, I suppose you can recreate the Grid object as needed when the number of components you need changes.

yeah, create your grid in the resized() function on the stack, and just call resized() whenever you drag your thing that adjusts the component sizes. same process for flexbox…

Hi all

I’ve made a lot of progress with this over the past couple of weeks, but have run into new dilemmas.

Executive summary:
Is it possible to cast a pointer to a C-style array of class X to a pointer to a C-style array of class Y?

Currently I’m using StretchableLayoutManager to lay out an indefinite number of components. My resized() function looks something like this:

    void resized() override
          m_layoutManager.layOutComponents (, componentCount, 0, 0, getWidth(), getHeight(), myOrientation, true);
    }  //                                       ^^

where myVector stores pointers to all of the Components that the Manager will lay out.

But having a stray vector full of pointers to dynamically created components is exactly what everyone tells you not to do. So I thought it would be safer to use a ReferenceCountedArray instead, and to share those Components with their original owners.

So I tried this:

    void resized() override
          m_layoutManager.layOutComponents (myRefCountedArray.getRawDataPointer(), componentCount, 0, 0, getWidth(), getHeight(), myOrientation, true);
    }    //                                      ^^

But this one fails to get off the ground, because I can’t add Components (which are not ReferenceCountedObjects to myRefCountedArray. The class I’m working with is both a Component and a ReferenceCountedObject, but it doesn’t seem to help. StretchableLayoutManager needs a C-style array of Components, but the array cannot hold Components if they are to be reference counted.

So, is it possible to take the pointer that myRefCountedArray.getRawDataPointer() returns and cast it to a pointer of type Component[] ?

store all of your components in an OwnedArray<Component>

struct Foo
    OwnedArray<Component> components;
    void resized() override
        m_layoutManager.layOutComponents( components.getRawDataPointer(), etc )

Why do you feel you need to use a ReferenceCountedArray? Are you sharing your components in some weird fashion?

This is exactly the discussion I’m having over here: [solved] Why is my ReferenceCountedObject asserting?.

I had started out with an OwnedArray, and decided to try out ReferenceCountedArray because it seemed like it might be safer. But now I’m wondering if shared pointers are actually overkill in this instance, as you suggest.