Save proportion (aspect ratio) when layouting in Lemur

I would like, for example, to have vertical layouted container where all inner panels are stretched horizontally but remaining it proportion (so stretched the same amount vertically). I’ve tried with:

new SpringGridLayout(Axis.Y, Axis.X, FillMode.None, FillMode.Even);

But, obviously, this isn’t working because of it is stretching it horziontally but doing nothing (None) vertically. So… I wonder if there is a way to do this or I should implement a new layout for this.

EDIT: I want to avoid adding a control to check if the size changed and so, set the preferredSize to match the stretching.

Same amount as what?

You mean you want the children to maintain their aspect ratio? Or?

Yep, just that.

The spring layout currently lays out the X and Y axes independently. You’d probably have to write a custom layout (maybe based on the BoxLayout) to get the behavior you want.

I kind of did it for the SpringGridLayout. I managed to achieve it for the sizes… but I have to change it now so it works with the positioning too xD:

    public void reshape(Vector3f pos, Vector3f size) {
        .....

        // Now we can process the actual children
        for( Map<Integer, Entry> r : children.values() ) {
            for( Entry e : r.values() ) {
                Vector3f offset = new Vector3f();
                addMajor(offset, rowOffsets[e.row]);
                addMinor(offset, colOffsets[e.col]);

               // applyProportions(e, offset);
                offset.y *= -1;
                e.setTranslation(pos.add(offset));

                Vector3f childSize = size.clone();
                setMajor(childSize, rowSizes[e.row]);
                setMinor(childSize, colSizes[e.col]);

                // Aspect ratio patch
                applyProportions(e, childSize);
                e.setSize(childSize);
            }
        }
    }

    private void applyProportions(Entry e, Vector3f childSize) {
        if(saveProportions) {
            Vector3f prefSize = e.getPreferredSize();
            if (mainFill != FillMode.None) {
                applyProportions(prefSize, childSize, mainAxis.index(), minorAxis.index());
            } else if (minorFill != FillMode.None) {
                applyProportions(prefSize, childSize, minorAxis.index(), mainAxis.index());
            }
        }
    }

    private void applyProportions(Vector3f prefSize, Vector3f newSize, int mainIndex, int minorIndex) {

        float prefMinor = prefSize.get(minorIndex);
        float prefMajor = prefSize.get(mainIndex);

        if(prefMinor == 0 && prefMajor == 0) {
            newSize.set(minorIndex, newSize.get(mainIndex));
        } else {
            newSize.set(minorIndex, prefMinor + prefMinor * (newSize.get(mainIndex) - prefMajor) / prefMajor);
        }
    }

It’s not more than a patch but… while it works :stuck_out_tongue:

EDIT: It works for the positioning too if a preferredSize is set on the layouted panels, but not if using no-preferred-sized ones (ie: filling with Even and no prefSize set)

BoxLayout is way closer to what you want already, though.

I never looked at it. The comment:

 *  stretched to fit the maximum component width.  This is similar
 *  to a single column or single row SpringGridLayout and in the
 *  future may be deprecated in lieu of that class.

just made me ignore that class :S

Well, somehow, I think I have SpringGridLayout patched and working. If someone is curious or want to use it, the modification is:

     public void reshape(Vector3f pos, Vector3f size) {
        ......... Original previous code ........

        float aspectOffset = 0;
        // Now we can process the actual children
        for( Map<Integer, Entry> r : children.values() ) {
            for( Entry e : r.values() ) {
                Vector3f offset = new Vector3f();
                Vector3f childSize = size.clone();


                // Sizing
                setMajor(childSize, rowSizes[e.row]);
                setMinor(childSize, colSizes[e.col]);

                // Aspect ratio patch
                aspectOffset += applyAspectRatio(e, childSize, offset, aspectOffset);

                e.setSize(childSize);
                // -----------------------------------------



                // Positioning
                addMajor(offset, rowOffsets[e.row]);
                addMinor(offset, colOffsets[e.col]);

                offset.y *= -1;
                e.setTranslation(pos.add(offset));
                // -----------------------------------------


            }
        }
    }

    private float applyAspectRatio(Entry e, Vector3f childSize, Vector3f offset, float aspectOffset) {
        if(saveAspectRatio) {
            Vector3f prefSize = e.getPreferredSize();
            if (mainFill != FillMode.None) {
                return applyAspectRatio(prefSize, childSize, offset, aspectOffset, mainAxis.index(), minorAxis.index());
            } else if (minorFill != FillMode.None) {
                return applyAspectRatio(prefSize, childSize, offset, aspectOffset, minorAxis.index(), mainAxis.index());
            }

        }

        return 0;
    }

    private float applyAspectRatio(Vector3f prefSize, Vector3f newSize, Vector3f offset, float aspectOffset, int mainIndex, int minorIndex) {

        float prefMinor = prefSize.get(minorIndex);
        float prefMajor = prefSize.get(mainIndex);

        float addedValue;

        if(prefMinor == 0 && prefMajor == 0) {
            addedValue = newSize.get(mainIndex);
        } else {
            addedValue = prefMinor * (newSize.get(mainIndex) - prefMajor) / prefMajor;
        }

        newSize.set(minorIndex, prefMinor + addedValue);
        offset.set(minorIndex, aspectOffset);

        return addedValue;
    }