Resizing window


#1

I have a resizing window ( juce::DocumentWindow ). When I resize this window I would like to have the components inside move & resize using simple rules ( for example: [Stick to left upper] or [ keep all borders fixed to parent ] or [ stick to bottom left ]. I’m would like to set these for all components so I can resize the window automatically. This is something I’m used to use when I was using Cocoa & its integrated Interface Builder.

At this moment I’m completely lost on how to do this automatically in JUCE. As far as I understand I have to write a method Component::resized() to every Component which does the reposition by hand or by semi-by-hand using RelativeRectangle. This could be fine as long as I can have the previous bounds ( before the resize ) of the parent Component so I can write a generic resize/reposition method. I could not find a reliable way on how to get te previous bounds of the component.

All is seemingly quite complex for the simple reposition rules I want. Is there something I’m missing in JUCE how to accomplish this ?

I would expect something like: (other arguments are very well possible )

enum eResizeAction
{
none,
stickTo_TopLeft,
stickTo_TopRight,
stickTo_BottomLeft,
stickTo_BottomRight,
stickTo_AllSides,
// and some more, as long we keep only simple actions
};

void Component::setResizeBehaviour( eResizeAction resizeAction );

Thanks


#2

Hi jankoen,

I have the same problem, I'm looking for an elegant way to implement dynamic positioning of components in the screen.

I was expecting to find an anchor property (like in Windows Form) or some layout managers (like in Java Swing), but I cannot find anything about this functionality.

Did you find something about or could anyone help me?

Thank you.


#3


#4

Hi!

I've just been looking - again! - at using Juce for new iOS & Android apps.


Clearly, these need to scale well on different screens.

So, fixed positioning and fixed sizing simply doesn't cut the mustard.

However, Juce doesn't seem to have a layout system.

That said, of course a simple solution would be to have a screen configured such that it could simply, where required, automatically reposition and re-size all elements from their original values, to scale to the current screen size.

 

As a quick experiment, I've done this in my "resizable master component" .h file:

    bool mbSetSizesYet;
    Rectangle<float> mOriginalSize;
    std::vector< float> mComponentOriginalPositionX;
    std::vector< float> mComponentOriginalPositionY;
    std::vector< float> mComponentOriginalWidth;
    std::vector< float> mComponentOriginalHeight;


And this in the .cpp file...:
 

void ResizingGuiComponent::resized()
{
    textButton->setBounds (32, 32, 150, 24);
    groupComponent->setBounds (48, 144, 200, 150);
    comboBox->setBounds (288, 72, 150, 24);
    treeView->setBounds (376, 208, 150, 150);
    textEditor->setBounds (40, 88, 150, 24);
    //[UserResized] Add your own custom resize handling here..
// Note the code above, is the fixing size/position code always put there by the Introjucer!
  if (mbSetSizesYet == false)
  {
    // Capture the initial component size and position information...
    mbSetSizesYet = true;

    // TODO - do this with NamedValueSet ...?

    mOriginalSize = Rectangle<float>(getWidth(), getHeight());

    int lChildComponentCount = this->getNumChildComponents();
    int i;
    for (i = 0; i < lChildComponentCount; i++) {
      Component *lpChildComponent = getChildComponent(i);
      float lfX = lpChildComponent->getX();
      float lfY = lpChildComponent->getY();
      float lfWidth = lpChildComponent->getWidth();
      float lfHeight = lpChildComponent->getHeight();
      printf("%d, x=%g,y=%g,w=%g,h=%g\n", i, lfX, lfY, lfWidth, lfHeight);
      mComponentOriginalPositionX.push_back(lfX);
      mComponentOriginalPositionY.push_back(lfY);
      mComponentOriginalWidth.push_back(lfWidth);
      mComponentOriginalHeight.push_back(lfHeight);

      lfX = mComponentOriginalPositionX[i];
      lfY = mComponentOriginalPositionY[i];
      lfWidth = mComponentOriginalWidth[i];
      lfHeight = mComponentOriginalHeight[i];
      printf("CHECK: %d, x=%g,y=%g,w=%g,h=%g\n", i, lfX, lfY, lfWidth, lfHeight);
    }
  }
  else
  {
    // Re-size and re-position!
    float lfXScale = ((float)getWidth()) / mOriginalSize.getWidth();
    float lfYScale = ((float)getHeight()) / mOriginalSize.getHeight();

    int lChildComponentCount = this->getNumChildComponents();
    int i;
    for (i = 0; i < lChildComponentCount; i++) {
      Component *lpChildComponent = getChildComponent(i);

      float lfX = mComponentOriginalPositionX[i] * lfXScale;
      float lfY = mComponentOriginalPositionY[i] * lfYScale;
      float lfWidth = mComponentOriginalWidth[i] * lfXScale;
      float lfHeight = mComponentOriginalHeight[i] * lfYScale;
      printf("RESIZE: %d, x=%g,y=%g,w=%g,h=%g\n", i, lfX, lfY, lfWidth, lfHeight);
      lpChildComponent->setBounds(lfX, lfY, lfWidth, lfHeight);
    }
  }
    //[/UserResized]
}

 

Anyhow! The question is: has anybody out there in Juce land got a better solution than this?

 

Jules - have you got any bright ideas?! :)


Pete


#5

The way I tend to do layout these days is with Rectangle objects, and the removeFromLeft/Right/Top/Bottom methods - have a search for any of those and you'll find plenty of example code of what I mean.

Essentially, you start with a rectangle that covers your parent component, and chop bits off it to use for the sub-components, which is a bit like the way you might define a grid-layout, and is dramatically easier than dealing with the x, y, w, h for each component individually.

I've recently been pondering ways in which I could make a more formal set of classes to do this job, and to do so in such a way that I could also apply the same trick I used for JUCE_LIVE_CONSTANT, and make the layout code live-editable at runtime.


#6

Hi Jules!

Yeah, I tried using Rectangles, but there was a weird bug where the X/Y values weren't saved properly, as as a quick hack I separated the values out to x/y/width/height values, which worked enough to prove the principle!

 

Back to the main point-in-hand: this sort of approach is *critical* (can't say it stronger than that!) on mobile, because:

- every "screen" must be able to adapt to launching on an un-planned-for screen size (100s of different combinations on Android, and iOS has iPhone/iPad/Retinal/non-Retinal/Portrait/Landscape)

- every "screen" must be able to re-layout automtically in response to rotation events

- really, you don't want to have to write your own auto-resizing code for this - ideally, the Intro Jucer should be capable of creating code that does this automatically. And furthermore, should be able to auto-show you how it'd look on iPhone landscape/portrait, iPod landscape/portrait, and a selection of common Android layouts.

- we approach all apps these days from a "mobile first" perspective, as you might imagine. :)

- a couple of things would make this easier; for example, if auto-resizing combo boxes, don't make them too deep etc.

 

In Noatikl/Mixtikl, our own widgeting system handles all this "out of the box" through an automatic rubber-banding a bit like I outlined above. But really, I'd *love* to use Juce to replace my widgeting system, as then I'd get the nice Jucer GUI design integration etc. :-D

 

Separate point - but can't seem to add ListBox components in the Introjucer GUI...? Driving me potty, that. :)

 

Best wishes,

 

Pete


#7

Well, as you know I've spent years trying to invent a good GUI design tool, and never managed to find a killer design (except maybe the projucer) - that's why I'm really only keeping the introjucer GUI editor as a backwards-compatibility thing, until I can figure out a better plan.

The problem with GUI tools is that they're only any use for static layouts, and as soon as you need anything with , you have to do it all by hand. That's why I think the best plan will be for some kind of live editor that's integrated into your actual running app, so that even if you have non-static components, they can still be handled.


#8

Hi Jules,

Well, it seems that if you introduced a layout system, with Intro Jucer aware of that - you'd pretty much have a solution?

Anyhow, I appreciate that you won't have time to spend to look at it really!

Any idea if you could fix the ListBox component not being supported directly?

I must admit that ProJucer had slipped my mind - it has been a very big project for you!!! - have you got a pointer to the latest public info on ProJucer..?! :)

Best wishes as always,

Pete


#9

The middle of a tracktion pre-release panic is not a good time to request additions to the GUI designer!

And sadly the projucer has been dormant for a while.. Hope to eventually have time to revive it in the future.


#10

No worries, Jules. Rap more soon I hope :)

Pete