aspose file tools*
The moose likes Swing / AWT / SWT and the fly likes Liquid LayoutManager Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "Liquid LayoutManager" Watch "Liquid LayoutManager" New topic
Author

Liquid LayoutManager

Federico Tomassetti
Greenhorn

Joined: Mar 13, 2011
Posts: 7
Hi,
I want to implement a LayoutManager which places contained elements one after the others in a row (horizontal, then I will write also a vertical version of the same LayoutManager).
I use widgets which resizes themselves, and I need when an element is resized to move the widgets after it so that they do not overlap or there is no gap between them.
I want the container to resize accordingly to the size needed by its contents.

Example:
My container has three widgets of width 200, 100 and 50 pixel.
I want the container to be 350px wide and the first element to be placed at (0,0), the second at (200,0) and the third at (300) (I am ignoring insets for the sake of simplicity).

Then the second widget is shrinked at 70px. I want the container to resize at 320px, and the widgets to be relocated at:
1° (0,0)
2° (200,0)
3° (270,0)

I implemented getPreferredSize and getMinimumSize to return the desired dimension but I am unsure about resizing the container inside the LayoutManager. Shouldn't the container's container call getPreferredSize and honor that?

Suggestions?
Darryl Burke
Bartender

Joined: May 03, 2008
Posts: 4543
    
    5

Suggestions?

Calling revalidate() on the container's container should fix it.

To get better help sooner, post a SSCCE (Short, Self Contained, Compilable and Executable) example that demonstrates the problem.

luck, db
There are no new questions, but there may be new answers.
Federico Tomassetti
Greenhorn

Joined: Mar 13, 2011
Posts: 7
The Container parent is a Container and it has not the method revalidate. I tried with validate and I obtained a StackOverflowException.

This is the LayoutManager:


This is the superclass:


(I omit the superclass' superclass, it does not contains anything important for the context).

I wrote a test for the LayoutManager:


If you need I can attach the code.
Federico Tomassetti
Greenhorn

Joined: Mar 13, 2011
Posts: 7
I missed a couple more lines of code:
Rob Camick
Ranch Hand

Joined: Jun 13, 2009
Posts: 2182
    
    7
I think you are making your code too complex. A layout manager doesn't worry about the parent. A layout manager just gets the preferred size of the child components and then attempts to lay out the components in the space allocated to the container. When you pack() the frame all components will be painted and layed out at their preferred sizes.

The layout manager you describe is just like the FlowLayout, except you also need the ability for vertical layout. In case you are interested the Relative Layout does exactly what you require. The code is more complex than you need because it also supports the "relative resizing" of components. You can use the class if you like or maybe you can look at the code to try to understand how it works.
Federico Tomassetti
Greenhorn

Joined: Mar 13, 2011
Posts: 7
Probably my code is more complex that it should, but I am javing trouble because of widgets which resize dinamically. It seems that all layouts are designed for static widgets, whichhave their size set at the beginning of time and remain unaltered for the life of the application. Having a dynamic layout I need to ensure to have enough space allocated. I am not that happy with this approach but I don't know another way. Any suggestion would be really appreciated.

RelativeLayout seems not to do what I need, it gives space proportionally, I need all the widgets to assume their preferredSize.
FlowLayout do not resize the panel to be large as required by the contents.
I need the panel to have a size depending from its content, not on the decision of its own container. I realize this could be a violation of the way LayoutManager are designed to be used and I would like to find a better way.
Rob Camick
Ranch Hand

Joined: Jun 13, 2009
Posts: 2182
    
    7
RelativeLayout seems not to do what I need, it gives space proportionally, I need all the widgets to assume their preferredSize.


This is the way RelativeLayout works when you DON'T specify any relative contraints. Search the blog for where I mention FlowLayout.

FlowLayout do not resize the panel to be large as required by the contents.


That is not the way layout managers work. That is the job of the pack() method. If you want all components to fit at their preferred size then you add all the components to the panel, add the panel to the frame and then pack() the frame. If you make a visible component smaller in size, then you can just revalidate() and repaint() the parent panel and the components will be layed out properly. If you make the component larger, then you need to pack() the frame to make sure space is available for all components.

I need the panel to have a size depending from its content,


That is what the pack() method is for.

Assume you create a panel with 10 components and each component is defined with a preferrid size of (50, 50). So the preferred size of the panel is (500, 50). Now if you create a frame and give it a size of (200, 200), then your components won't show. The frame size overrides the preferred size of the panel. That is why you use the pack() method. The pack() method will recursively call all components to get their preferred sizes so that all components will be displayed at their preferred size.

If the panel doesn't get the space requested then it has to decide how to paint the component. Some layout mangers will attempt to scale components so they are visible, some will just truncate the last components.
Federico Tomassetti
Greenhorn

Joined: Mar 13, 2011
Posts: 7
Yes, I would definitely a pack method but I would need it for any container, instead pack it is available just for java.awt.Window and subclasses. Of course I could call it on the window and having all the containers re-layouted but it could be too much expensive.
In some situations I need to use LOTS of widgets, at the beginning I was using SWT and I had to switch to Swing because the number of widgets is limited in SWT (one widget -> one O.S. handle, because they are "real" widgets managed by the O.S.) so I would like to avoid to call pack on the whole window.
Moreover I am building a system in which elements will be provided by different sources, so I want my container to act in the same way also when its parent use a strange layout or not layout at all. I.e. when the parent of my container has layout==null while layouting the container I set its size to its preferredSize because its parent is not doing its job.
Rob Camick
Ranch Hand

Joined: Jun 13, 2009
Posts: 2182
    
    7
I would definitely a pack method but I would need it for any container


That is exactly what layout managers do. They calculate the preferred size of a given panel based on the components added to the panel. However this preferred size is only a recommendation. A panel cannot force its parent panel to allocate all the requested space because there may simply not be enough space available. I gave you a simple example of this where you have a frame with one panel.

You still have not explained why a FlowLayout (or a BoxLayout or the RelativeLayout) does not meet your requirements. Post a simple SSCCE that demonstrates the case where it doesn't work.
Federico Tomassetti
Greenhorn

Joined: Mar 13, 2011
Posts: 7
Thank you, I had to ponder a little bit on what you explained to me.

I can not use FlowLayout for different reasons:
1) It is ok for the horizontal layouting but I need two LayoutManager: one Horizontal, one Vertical.
2) I need to use special rules for alignment which depends on characteristics very specific to my application

I did as you suggested and I am no more trying to resize the container inside the LayoutManager. Now my LayoutManagers just try to places components using the space available.
So I moved the request for more space in a subclass of Panel. Have you advices on this implementation? Do you think it is the right place to do that?

The idea is that the DynamicPanel just before trying to places its components verify if its need for space is different from the previous time. If it is it asks its own parent to layout again, in this way the parent of the panel reconsiders how much space give to the panel. Then the panel layout its components. Note that the panel is not checking if its actual size is equals to its preferredsize because its parent has to decide how much space it can received, instead it checks if its need (the pref. size) its changed.


Rob Camick
Ranch Hand

Joined: Jun 13, 2009
Posts: 2182
    
    7
I can not use FlowLayout for different reasons:


I know that. I know that it doesn't support vertical layout. I asked for a simple demo that shows why it doesn't work in a horizontal example so I can better understand the problem. I also suggested two other layouts which do support horizontal/vertical layout.

The idea is that the DynamicPanel just before trying to places its components verify if its need for space is different from the previous time.


That is NOT the way layout management works. The spaces requirements for a layout do not just randomly change. They change if you add another component to the panel or if a property of your component changes. For examle, when using a JLabel and you change the text, the preferred size of the component may change. In the first case you need to invoke revalidate() on the parent panel. In the second you invoke revalidate() on the component.

I still don't understand your problem. Layout manager is a top down design. The top component keeps asking the child components how much space they need and then lays out the components properly. A child component can't just demand its parent container needs more space because the space may not be available so each layout manager needs to determine the best way to allocate space.

You still have not posted a SSCCE (did you click on the link to understand what a SSCCE is?). One of us does not understand what the other is saying so it is looking like this thread will not get resolved without a SSCCE. Even then I can't guarantee a solution, but at least we will hopefully understand the problem better.
Federico Tomassetti
Greenhorn

Joined: Mar 13, 2011
Posts: 7
Of course I read what a SSCCE is. I was trying to provide concise and clear information. I failed and I am sorry with that but it was not due to lazyness.

I would proceed by steps. First step: I have a hierarchy of containers and inside the deepest there is a component. Changing the minimum and preferred size of the component and calling validate I would expect the container to be resized. It doesn't happen:


It probably does not happen because the container has not enough space. So what should I do every time I resize a component, callind directly validate on the frame?
Rob Camick
Ranch Hand

Joined: Jun 13, 2009
Posts: 2182
    
    7
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Liquid LayoutManager