Resizing two components at once

gui
#1

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!

0 Likes

#2

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;
    Foo()
    {
        addAndMakeVisible(leftSide);
        addAndMakeVisible(rightSide);
        addAndMakeVisible( draggableResizer );
        draggableResizer.addMouseListener(this);
    }
    void mouseDrag (const MouseEvent& e) override
    {
        resized();
    }
    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() );
    }
};
0 Likes

#3

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.

0 Likes

#4

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

#5

@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
{
private:
    StretchableLayoutManager horizontalLayout;
    int componentCounter;
    std::unique_ptr<StretchableLayoutResizerBar> resizeBar;
    SidePanelComponent sidePanelComponent;
    TabHolder tabHolder;

    std::vector<Component*> arrayOfComponentPointers;
    
public:
    MainComponent()
    {
        addComponentWithLayout(&sidePanelComponent, -0.0, -1.0, -0.20);
        StretchableLayoutResizeBar
        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);
    }

private:
    void addComponentWithLayout(Component* componentToAdd, double min, double max, double pref)
    {
        addAndMakeVisible(componentToAdd);
        arrayOfComponentPointers.push_back(componentToAdd);
        horizontalLayout.setItemLayout(componentCounter++, min, max, pref);
    }

    void resized()
    {
        horizontalLayout.layOutComponents(arrayOfComponentPointers.data(), 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.

0 Likes

#6

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

0 Likes

#7

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

0 Likes

#8

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.

0 Likes

#9

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.

0 Likes

#10

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…

0 Likes