How can I lay out components in Lemur?

I am trying to learn Lemur and I have found that some information is missing from the GitHub wiki. Specifically, the page on layouts is nearly empty. Is there some sort of other resource that I can learn the layouts from?

Ooops. Sorry about that. Those most have slipped past my radar.

BoxLayout you can probably just ignore. SpringGridLayout can easily cover all of its use-cases.

BorderLayout is pretty straight forward. With a Container with a BorderLayout you can specify a location for what you are adding: Position.North, Position.Center, etc… and it will place the component there. This is similar to Swing’s BorderLayout.

Container c = new Container(new BorderLayout());
c.addChild(new Label("Top"), Position.North);
c.addChild(new Label("Bottom"), Position.South);
...and so on...

SpringGridLayout is a little more complicated. Each item is added into a grid cell and then the rows and columns are sized based on the items in the cells. How the space is divided across the rows or columns is specified with the FillMode for that axis.
http://jmonkeyengine-contributions.github.io/Lemur/javadoc/Lemur/com/simsilica/lemur/FillMode.html

Whether the layout is row-major or column-major is also specified on the constructor. By default, a SpringGridLayout is row-major. Meaning a cell is row, column. Flipping the axes will make it column, row. But these are only notional anyway as the axes are in three-space… so you can even make one in x, z and so on.

Anyway, there are short-cuts so that you don’t always have to specify the rows or columns.

If we use a default SpringGridLayout that is row-major (first part of the cell coordinate is y axis) then the following code will build a grid explicitly:

Container c = new Container();  // spring grid layout by default depending on styling
c.addChild(new Label("Foo"), 0, 0);
c.addChild(new Label("Bar"), 1, 0);
c.addChild(new Label("Baz"), 2, 0);

Will put three labels in a column.

But… with short-cuts, that’s the same as:

Container c = new Container();  // spring grid layout by default depending on styling
c.addChild(new Label("Foo"));
c.addChild(new Label("Bar"));
c.addChild(new Label("Baz"));

By default, if no constraints are specified then it will increment the row and reset the column.

This also means you can do stuff like:

Container c = new Container();  // spring grid layout by default depending on styling
c.addChild(new Label("Foo:"));
c.addChild(new Label("123"), 1);
c.addChild(new Label("Bar:"));
c.addChild(new Label("456"), 1);
c.addChild(new Label("Baz:"));
c.addChild(new Label("789"), 1);

to make a two-column panel. When only one number is provided it is considered to be the ‘column’.

The above is the same as doing the following explicitly:

Container c = new Container();  // spring grid layout by default depending on styling
c.addChild(new Label("Foo:"), 0, 0);
c.addChild(new Label("123"), 0, 1);
c.addChild(new Label("Bar:"), 1, 0);
c.addChild(new Label("456"), 1, 1);
c.addChild(new Label("Baz:"), 2, 0);
c.addChild(new Label("789"), 2, 1);

The FillModes try to cover most of the sizing that one might want but eventually this class will be refactored to support a FillModel to allow the user to fully customized how the rows or columns are stretched. Then FillModes just become a set of default models. I haven’t gotten there yet but the existing FillModes cover 95% of use-cases I’d say. The others can sometimes be faked with nested panels… though I’ve also subclassed SpringGridLayout before, too.

Short of real documentation, I hope that helps a bit at least.

5 Likes

Thanks, that seems to make sense (although I probably won’t use the implied/implicit grid values). Is it able to function in a way like Swing’s SpringLayout? If so, where can I learn to use it that way? I suspect that it might as you mention the following in addition to it’s name:

SpringGridLayout is a bit similar to Swings GridBagLayout and SpringLayout. It’s just different, though.

I use the implicit values all the time because then I don’t have to reindex them all just to add a row or whatever. But you are welcome to do what you like. 9/10 times I’m just doing a single column or single row anyway and never specify the constraints at all.

Unlike Swing’s layouts, my layouts don’t have separate insets, anchor, etc… that’s up to the children to do as they like.

Are there any plans to support Swing layouts directly? If not, I’d like to request that feature as there are many more Swing layouts then one person could really create by themselves.

I mean, folks can create them. The layout model is a bit different and really in swing I only ever used two layouts in all of my years of swing development (BorderLayout and GridBagLayout). Once in a blue moon I might use BoxLayout or GridLayout but mostly not.

SpringGridLayout covers BoxLayout (which I already have as it was my first layout before I implemented SpringGrid). And SpringGridLayout can cover GridLayout to some extend with the right fill mode. There are not that many useful Swing layouts.

Swing uses an iterative layout method where there is a feedback loop as things get resized, the layout gets recalculated, the things get resized, etc… This is why things like getMininumSize() and getMaximumSize() are needed in Swing. When you try to get it to layout impossible things it just gives up.

Lemur went with a simpler approach. One pass to calculate size and one pass to layout. On the one hand, this is slightly less flexible. On the other hand, it is way simpler and way more predictable.

TL;DR: I have no personal plans to support other Swing layouts. Are there ones in particular that you had in mind?

I would really like the SpringLayout. I use it for nearly every swing
app I make. If you added something that just has a similar putConstraint
method, that would be perfect for my uses.

Also, I probably won’t but for reference would a pull request to add
swing layout support be accepted (assuming that code quality, etc. is good)?

Some swing layouts are just impossible to implement as swing’s model is just completely different.

What is it that SpringGridLayout lacks that you expect from SpringLayout?

I strongly prefer to setup a bunch of springs rather than using a grid. It feels significantly more intuitive to me. Does SpringGridLayout allow usage like the SpringLayout (ie. placing a bunch of springs between components as the sole way to lay them out)?

No.

I think a true spring layout may be hard to implement without an iterative layout approach. But if you want to try creating a SpringLayout then I’ll accept the patch.

@pspeed one day I will port MigLayout over to Lemur because … it’s the ONLY layout you will ever need :stuck_out_tongue: