diff options
author | Sven Gothel <[email protected]> | 2023-04-29 03:13:01 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2023-04-29 03:13:01 +0200 |
commit | a9c76153fd9a472679c1fc85189f6d4ecda7979e (patch) | |
tree | 6ee96a4605b725da15dff3ef8a52cf7d4d1dffbc /src/graphui/classes/com/jogamp/graph/ui | |
parent | 0b7559a6f5f92dd4af9b80bc2a24b8b1d6140bfe (diff) |
GraphUI Working GridLayout w/ and w/o cell-size and alignment; Added BoxLayout.
Diffstat (limited to 'src/graphui/classes/com/jogamp/graph/ui')
3 files changed, 369 insertions, 56 deletions
diff --git a/src/graphui/classes/com/jogamp/graph/ui/layout/Alignment.java b/src/graphui/classes/com/jogamp/graph/ui/layout/Alignment.java index b43de332c..544ae3f26 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/layout/Alignment.java +++ b/src/graphui/classes/com/jogamp/graph/ui/layout/Alignment.java @@ -39,6 +39,8 @@ public final class Alignment { public static final Alignment Center = new Alignment(Alignment.Bit.Center); /** {@link Bit#Fill} alignment constant. */ public static final Alignment Fill = new Alignment(Alignment.Bit.Fill.value); + /** {@link Bit#Fill} and {@link Bit#Center} alignment constant. */ + public static final Alignment FillCenter = new Alignment(Alignment.Bit.Fill.value | Alignment.Bit.Center.value); public enum Bit { /** Left alignment. */ diff --git a/src/graphui/classes/com/jogamp/graph/ui/layout/BoxLayout.java b/src/graphui/classes/com/jogamp/graph/ui/layout/BoxLayout.java index 6f6e610f6..acd58d0ab 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/layout/BoxLayout.java +++ b/src/graphui/classes/com/jogamp/graph/ui/layout/BoxLayout.java @@ -39,16 +39,17 @@ import com.jogamp.opengl.util.PMVMatrix; * GraphUI Stack {@link Group.Layout}. * <p> * A stack of {@link Shape}s - * - size kept unscaled - * - position depends on {@Link Padding} and {@link Margin} - * - *cell* size can be set + * - Size kept unscaled + * - Position depends on {@Link Padding} and {@link Margin} + * - Cell size can be set * </p> */ public class BoxLayout implements Group.Layout { private final float cellWidth, cellHeight; private final Margin margin; private final Padding padding; - private final float borderThickness; + + private static final boolean TRACE_LAYOUT = false; public BoxLayout(final Padding padding) { this(0f, 0f, new Margin(), padding); @@ -56,12 +57,19 @@ public class BoxLayout implements Group.Layout { public BoxLayout(final float width, final float height, final Margin margin) { this(width, height, margin, new Padding()); } + + /** + * + * @param width + * @param height + * @param margin + * @param padding + */ public BoxLayout(final float width, final float height, final Margin margin, final Padding padding) { this.cellWidth = Math.max(0f, width); this.cellHeight = Math.max(0f, height); this.margin = margin; this.padding = padding; - this.borderThickness = 0f; } public Padding getPadding() { return padding; } @@ -75,6 +83,8 @@ public class BoxLayout implements Group.Layout { final AABBox sbox = new AABBox(); for(int i=0; i < shapes.size(); ++i) { final Shape s = shapes.get(i); + + // measure size pmv.glPushMatrix(); s.setTransform(pmv); s.getBounds().transformMv(pmv, sbox); @@ -83,34 +93,39 @@ public class BoxLayout implements Group.Layout { // adjust size and position (centered) final float paddedWidth = sbox.getWidth() + padding.width(); final float paddedHeight = sbox.getHeight() + padding.height(); - final float marginedWidth = paddedWidth + margin.width(); - final float marginedHeight = paddedHeight + margin.height(); - final float cellWidth2 = hasCellWidth ? cellWidth : marginedWidth; - final float cellHeight2 = hasCellHeight ? cellHeight : marginedHeight; - final float x, y; - if( margin.isCenteredHoriz() || hasCellWidth && sbox.getWidth() + padding.width() + margin.width() > cellWidth2 ) { - x = 0; - } else { - x = margin.left + padding.left; + final float cellWidth2 = hasCellWidth ? cellWidth : paddedWidth; + final float cellHeight2 = hasCellHeight ? cellHeight : paddedHeight; + float x = margin.left; + float y = margin.bottom; + if( !margin.isCenteredHoriz() && paddedWidth <= cellWidth2 ) { + x += padding.left; } - if( margin.isCenteredVert() || hasCellHeight && sbox.getHeight() + padding.height() + margin.height() > cellHeight2 ) { - y = 0; - } else { - y = margin.bottom + padding.bottom; + if( !margin.isCenteredVert() && paddedHeight <= cellHeight2 ) { + y += padding.bottom; } - float dxh = 0, dyh = 0; + final float dxh, dyh; if( margin.isCenteredHoriz() ) { - dxh += 0.5f * ( cellWidth2 - paddedWidth ); // actual horiz-centered + dxh = 0.5f * ( cellWidth2 - paddedWidth ); // actual horiz-centered + } else { + dxh = 0; } if( margin.isCenteredVert() ) { - dyh += 0.5f * ( cellHeight2 - paddedHeight ); // actual vert-centered + dyh = 0.5f * ( cellHeight2 - paddedHeight ); // actual vert-centered + } else { + dyh = 0; } - System.err.println("["+i+"].m: "+x+" / "+y+" + "+dxh+" / "+dyh+", p "+paddedWidth+" x "+paddedHeight+", sz "+cellWidth2+" x "+cellHeight2+", box "+box.getWidth()+" x "+box.getHeight()); - s.moveTo( x + dxh, y + dyh, 0f ); // center the scaled artifact + if( TRACE_LAYOUT ) { + System.err.println("bl["+i+"].0: @ "+s.getPosition()+", sbox "+sbox); + System.err.println("bl["+i+"].m: "+x+" / "+y+" + "+dxh+" / "+dyh+", p "+paddedWidth+" x "+paddedHeight+", sz "+cellWidth2+" x "+cellHeight2+", box "+box.getWidth()+" x "+box.getHeight()); + } + s.move( x + dxh, y + dyh, 0f ); // center the scaled artifact s.move( sbox.getLow().mul(-1f) ); // remove the bottom-left delta - box.resize( x + cellWidth2 + padding.right, y + cellHeight2 + padding.top, 0); - box.resize( x - padding.left, y - padding.bottom, 0); - System.err.println("["+i+"].x: "+x+" / "+y+" + "+dxh+" / "+dyh+" -> "+s.getPosition()+", p "+paddedWidth+" x "+paddedHeight+", sz "+cellWidth2+" x "+cellHeight2+", box "+box.getWidth()+" x "+box.getHeight()); + // resize bounds including padding, excluding margin + box.resize( x + sbox.getWidth() + padding.right, y + sbox.getHeight() + padding.top, 0); + box.resize( x - padding.left, y - padding.bottom, 0); + if( TRACE_LAYOUT ) { + System.err.println("bl["+i+"].x: "+x+" / "+y+" + "+dxh+" / "+dyh+" -> "+s.getPosition()+", p "+paddedWidth+" x "+paddedHeight+", sz "+cellWidth2+" x "+cellHeight2+", box "+box.getWidth()+" x "+box.getHeight()); + } } } diff --git a/src/graphui/classes/com/jogamp/graph/ui/layout/GridLayout.java b/src/graphui/classes/com/jogamp/graph/ui/layout/GridLayout.java index d5ba8e289..acc82208f 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/layout/GridLayout.java +++ b/src/graphui/classes/com/jogamp/graph/ui/layout/GridLayout.java @@ -29,14 +29,22 @@ package com.jogamp.graph.ui.layout; import java.util.List; -import com.jogamp.graph.ui.GraphShape; import com.jogamp.graph.ui.Group; import com.jogamp.graph.ui.Shape; +import com.jogamp.opengl.math.FloatUtil; +import com.jogamp.opengl.math.Vec3f; import com.jogamp.opengl.math.geom.AABBox; import com.jogamp.opengl.util.PMVMatrix; /** * GraphUI Grid {@link Group.Layout}. + * <p> + * A grid of {@link Shape}s + * - Optional cell-size with {@link Alignment#Fill} and or {@link Alignment#Center} + * - Without cell-size behaves like a grid bag using individual shape sizes including padding + * - Can be filled in {@link Order#COLUMN} or {@link Order#ROW} major-order. + * - .. + * </p> */ public class GridLayout implements Group.Layout { /** Layout order for {@link Group#getShapes()}} after population. */ @@ -50,18 +58,21 @@ public class GridLayout implements Group.Layout { private final int col_limit; private final int row_limit; private final float cellWidth, cellHeight; - private final Padding padding; + private final Alignment alignment; + private final Gap gap; private int row_count, col_count; + private static final boolean TRACE_LAYOUT = false; /** * Default layout order of {@link Group#getShapes()}} is {@link Order#COLUMN}. * @param column_limit [1..inf) * @param cellWidth * @param cellHeight + * @param alignment TODO */ - public GridLayout(final int column_limit, final float cellWidth, final float cellHeight) { - this(Math.max(1, column_limit), -1, cellWidth, cellHeight, new Padding()); + public GridLayout(final int column_limit, final float cellWidth, final float cellHeight, final Alignment alignment) { + this(alignment, Math.max(1, column_limit), -1, cellWidth, cellHeight, new Gap()); } /** @@ -69,30 +80,33 @@ public class GridLayout implements Group.Layout { * @param column_limit [1..inf) * @param cellWidth * @param cellHeight - * @param padding + * @param alignment TODO + * @param gap */ - public GridLayout(final int column_limit, final float cellWidth, final float cellHeight, final Padding padding) { - this(Math.max(1, column_limit), -1, cellWidth, cellHeight, padding); + public GridLayout(final int column_limit, final float cellWidth, final float cellHeight, final Alignment alignment, final Gap gap) { + this(alignment, Math.max(1, column_limit), -1, cellWidth, cellHeight, gap); } /** * Default layout order of {@link Group#getShapes()}} is {@link Order#ROW}. * @param cellWidth * @param cellHeight - * @param padding + * @param alignment TODO + * @param gap * @param row_limit [1..inf) */ - public GridLayout(final float cellWidth, final float cellHeight, final Padding padding, final int row_limit) { - this(-1, Math.max(1, row_limit), cellWidth, cellHeight, padding); + public GridLayout(final float cellWidth, final float cellHeight, final Alignment alignment, final Gap gap, final int row_limit) { + this(alignment, -1, Math.max(1, row_limit), cellWidth, cellHeight, gap); } - private GridLayout(final int column_limit, final int row_limit, final float cellWidth, final float cellHeight, final Padding padding) { + private GridLayout(final Alignment alignment, final int column_limit, final int row_limit, final float cellWidth, final float cellHeight, final Gap gap) { this.order = 0 < column_limit ? Order.COLUMN : Order.ROW; this.col_limit = column_limit; this.row_limit = row_limit; this.cellWidth = cellWidth; this.cellHeight = cellHeight; - this.padding = padding;; + this.alignment = alignment; + this.gap = gap; row_count = 0; col_count = 0; } @@ -100,9 +114,226 @@ public class GridLayout implements Group.Layout { public Order getOrder() { return order; } public int getColumnCount() { return col_count; } public int getRowCount() { return row_count; } + public Gap getGap() { return gap; } @Override public void layout(final Group g, final AABBox box, final PMVMatrix pmv) { + layout1(g, box, pmv); + } + private void layout1(final Group g, final AABBox box, final PMVMatrix pmv) { + final Vec3f zeroVec3 = new Vec3f(); + final boolean hasCellWidth = !FloatUtil.isZero(cellWidth); + final boolean hasCellHeight = !FloatUtil.isZero(cellHeight); + final boolean isCenteredHoriz = hasCellWidth && alignment.isSet(Alignment.Bit.Center); + final boolean isCenteredVert = hasCellHeight && alignment.isSet(Alignment.Bit.Center); + final boolean isScaled = alignment.isSet(Alignment.Bit.Fill) && ( hasCellWidth || hasCellHeight ); + final List<Shape> shapes = g.getShapes(); + if( Order.COLUMN == order ) { + row_count = (int) Math.ceil( (double)shapes.size() / (double)col_limit ); + col_count = col_limit; + } else { // Order.ROW_MAJOR == order + row_count = row_limit; + col_count = (int) Math.ceil( (double)shapes.size() / (double)row_limit ); + } + if( TRACE_LAYOUT ) { + System.err.println("gl.00: "+order+", "+col_count+" x "+row_count+", a "+alignment+", shapes "+shapes.size()+", "+gap); + } + int col_i = 0, row_i = 0; + float x=0, y=0; + float totalWidth=-Float.MAX_VALUE, totalHeight=-Float.MAX_VALUE; + final AABBox[] sboxes = new AABBox[shapes.size()]; + final Vec3f[] diffBLs = new Vec3f[shapes.size()]; + final float[] y_pos = new float[col_count * row_count]; // y_bottom = totalHeight - y_pos[..] + + // Pass-1: Determine totalHeight, while collect sbox and y_pos + for(int i=0; i < shapes.size(); ++i) { + final Shape s = shapes.get(i); + // measure size + pmv.glPushMatrix(); + s.setTransform(pmv); + { + final AABBox sbox0 = s.getBounds(); + sboxes[i] = sbox0.transformMv(pmv, new AABBox()); + + final Vec3f diffBL = new Vec3f(); + if( !diffBL.set( sbox0.getLow().x(), sbox0.getLow().y(), 0).min( zeroVec3 ).isZero() ) { + // pmv.mulMvMatVec3f(diffBL).scale(-1f, -1f, 0f); + final Vec3f ss = s.getScale(); + diffBL.scale(-1f*ss.x(), -1f*ss.y(), 0f); + } + diffBLs[i] = diffBL; + } + pmv.glPopMatrix(); + final AABBox sbox = sboxes[i]; + + final float sxy; + if( isScaled ) { + // scaling to cell size + final float shapeWidthU = sbox.getWidth(); + final float shapeHeightU = sbox.getHeight(); + final float cellWidthU = hasCellWidth ? cellWidth : shapeWidthU; + final float cellHeightU = hasCellHeight ? cellHeight : shapeHeightU; + final float sx = cellWidthU / shapeWidthU; + final float sy = cellHeightU/ shapeHeightU; + sxy = sx < sy ? sx : sy; + } else { + sxy = 1; + } + final float shapeWidthS = sxy*sbox.getWidth(); + final float shapeHeightS = sxy*sbox.getHeight(); + final float cellWidthS = hasCellWidth ? cellWidth : shapeWidthS; + final float cellHeightS = hasCellHeight ? cellHeight : shapeHeightS; + + // bottom y_pos, top to bottom, to be subtracted from totalHeight + final float y0 = y + cellHeightS; + final float x1 = x + cellWidthS; + totalHeight = Math.max(totalHeight, y0); + totalWidth = Math.max(totalWidth, x1); + y_pos[col_count * row_i + col_i] = y0; + if( TRACE_LAYOUT ) { + System.err.println("gl.00: y("+i+")["+col_i+"]["+row_i+"]: "+y0+", ["+cellWidthS+" x "+cellHeightS+"]"); + } + + // position for next cell + if( i + 1 < shapes.size() ) { + if( Order.COLUMN == order ) { + if( col_i + 1 == col_count ) { + col_i = 0; + row_i++; + x = 0; + y += cellHeightS + gap.height(); + } else { + col_i++; + x += cellWidthS + gap.width(); + } + } else { // Order.ROW_MAJOR == order + if( row_i + 1 == row_count ) { + row_i = 0; + col_i++; + y = 0; + x += cellWidthS + gap.width(); + } else { + row_i++; + y += cellHeightS + gap.height(); + } + } + } + } + if( TRACE_LAYOUT ) { + System.err.println("gl[__].00: Total "+totalWidth+" / "+totalHeight); + } + + // Pass-2: Layout + row_i = 0; col_i = 0; + x = 0; y = 0; + for(int i=0; i < shapes.size(); ++i) { + final Shape s = shapes.get(i); + final AABBox sbox = sboxes[i]; + final Vec3f diffBL = diffBLs[i]; + final float zPos = sbox.getCenter().z(); + + if( TRACE_LAYOUT ) { + System.err.println("gl("+i+")["+col_i+"]["+row_i+"].0: "+s); + System.err.println("gl("+i+")["+col_i+"]["+row_i+"].0: sbox "+sbox+", diffBL "+diffBL); + } + + // IF isScaled: Uniform scale w/ lowest axis scale and center position on lower-scale axis + final float sxy; + float dxh = 0, dyh = 0; + if( isScaled ) { + // scaling to cell size + final float shapeWidthU = sbox.getWidth(); + final float shapeHeightU = sbox.getHeight(); + final float cellWidth2 = hasCellWidth ? cellWidth : shapeWidthU; + final float cellHeight2 = hasCellHeight ? cellHeight : shapeHeightU; + final float sx = cellWidth2 / shapeWidthU; + final float sy = cellHeight2/ shapeHeightU; + sxy = sx < sy ? sx : sy; + dxh += shapeWidthU * ( sx - sxy ) * 0.5f; // adjustment for scale-axis + dyh += shapeHeightU * ( sy - sxy ) * 0.5f; // ditto + if( TRACE_LAYOUT ) { + System.err.println("gl("+i+")["+col_i+"]["+row_i+"].s: "+sx+" x "+sy+" -> "+sxy+": +"+dxh+" / "+dyh+", U: s "+shapeWidthU+" x "+shapeHeightU+", sz "+cellWidth2+" x "+cellHeight2); + } + } else { + sxy = 1; + } + final float shapeWidthS = sxy*sbox.getWidth(); + final float shapeHeightS = sxy*sbox.getHeight(); + final float cellWidthS = hasCellWidth ? cellWidth : shapeWidthS; + final float cellHeightS = hasCellHeight ? cellHeight : shapeHeightS; + + y = totalHeight - y_pos[col_count * row_i + col_i]; + + if( isCenteredHoriz ) { + dxh += 0.5f * ( cellWidthS - shapeWidthS ); // actual horiz-centered + } + if( isCenteredVert ) { + dyh += 0.5f * ( cellHeightS - shapeHeightS ); // actual vert-centered + } + if( TRACE_LAYOUT ) { + System.err.println("gl("+i+")["+col_i+"]["+row_i+"].m: "+x+" / "+y+" + "+dxh+" / "+dyh+", S: s "+shapeWidthS+" x "+shapeHeightS+", sz "+cellWidthS+" x "+cellHeightS); + } + { + // New shape position, relative to previous position + final float aX = x + dxh; + final float aY = y + dyh; + s.moveTo( aX, aY, 0f ); + s.move( diffBL.scale(sxy) ); // remove the bottom-left delta + + // resize bounds including padding, excluding margin + box.resize( x, y, zPos); + box.resize( aX + cellWidthS, aY + cellHeightS, zPos); + } + s.scale( sxy, sxy, 1f); + + if( TRACE_LAYOUT ) { + System.err.println("gl("+i+")["+col_i+"]["+row_i+"].x: "+x+" / "+y+" + "+dxh+" / "+dyh+" -> "+s.getPosition()+", p3 "+shapeWidthS+" x "+shapeHeightS+", sz3 "+cellWidthS+" x "+cellHeightS+", box "+box.getWidth()+" x "+box.getHeight()); + System.err.println("gl("+i+")["+col_i+"]["+row_i+"].x: "+s); + } + + if( i + 1 < shapes.size() ) { + // position for next cell + if( Order.COLUMN == order ) { + if( col_i + 1 == col_count ) { + col_i = 0; + row_i++; + x = 0; + } else { + col_i++; + x += cellWidthS + gap.width(); + } + } else { // Order.ROW_MAJOR == order + if( row_i + 1 == row_count ) { + row_i = 0; + col_i++; + y = 0; + x += cellWidthS + gap.width(); + } else { + row_i++; + } + } + } + } + if( TRACE_LAYOUT ) { + System.err.println("gl.xx: "+box); + } + } + + /** + * A fast path layout for set cellWidth > 0 && cellHeight > 0, + * w/o consideration of individual shape height. + */ + @SuppressWarnings("unused") + private void layout0(final Group g, final AABBox box, final PMVMatrix pmv) { + final Vec3f zeroVec3 = new Vec3f(); + final boolean hasCellWidth = !FloatUtil.isZero(cellWidth); + final boolean hasCellHeight = !FloatUtil.isZero(cellHeight); + if( !hasCellWidth || !hasCellHeight ) { + throw new IllegalArgumentException(toString()); + } + final boolean isCenteredHoriz = hasCellWidth && alignment.isSet(Alignment.Bit.Center); + final boolean isCenteredVert = hasCellHeight && alignment.isSet(Alignment.Bit.Center); + final boolean isScaled = alignment.isSet(Alignment.Bit.Fill) && ( hasCellWidth || hasCellHeight ); final List<Shape> shapes = g.getShapes(); if( Order.COLUMN == order ) { row_count = (int) Math.ceil( (double)shapes.size() / (double)col_limit ); @@ -111,40 +342,102 @@ public class GridLayout implements Group.Layout { row_count = row_limit; col_count = (int) Math.ceil( (double)shapes.size() / (double)row_limit ); } + if( TRACE_LAYOUT ) { + System.err.println("gl.00: "+row_count+" x "+col_count+", "+box); + } int col_i = 0, row_i = 0; final AABBox sbox = new AABBox(); - for(final Shape s : shapes) { + final Vec3f diffBL = new Vec3f(); + for(int i=0; i < shapes.size(); ++i) { + final Shape s = shapes.get(i); + // measure size pmv.glPushMatrix(); s.setTransform(pmv); - s.getBounds().transformMv(pmv, sbox); + { + final AABBox sbox0 = s.getBounds(); + sbox0.transformMv(pmv, sbox); + + if( !diffBL.set( sbox0.getLow().x(), sbox0.getLow().y(), 0).min( zeroVec3 ).isZero() ) { + // pmv.mulMvMatVec3f(diffBL).scale(-1f, -1f, 0f); + final Vec3f ss = s.getScale(); + diffBL.scale(-1f*ss.x(), -1f*ss.y(), 0f); + } + } pmv.glPopMatrix(); + final float zPos = sbox.getCenter().z(); + + if( TRACE_LAYOUT ) { + System.err.println("gl["+i+"].0: "+s); + System.err.println("gl["+i+"].0: sbox "+sbox+", diffBL "+diffBL); + } + + // IF hasCell{Width|Height}: Uniform scale w/ lowest axis scale and center position on lower-scale axis + final float sxy; + float dxh = 0, dyh = 0; + if( isScaled ) { + // scaling to cell size + final float shapeWidthU = sbox.getWidth(); + final float shapeHeightU = sbox.getHeight(); + final float cellWidthU = hasCellWidth ? cellWidth : shapeWidthU; + final float cellHeightU = hasCellHeight ? cellHeight : shapeHeightU; + final float sx = cellWidthU / shapeWidthU; + final float sy = cellHeightU/ shapeHeightU; + sxy = sx < sy ? sx : sy; + dxh += shapeWidthU * ( sx - sxy ) * 0.5f; // adjustment for scale-axis + dyh += shapeHeightU * ( sy - sxy ) * 0.5f; // ditto + if( TRACE_LAYOUT ) { + System.err.println("gl["+i+"].s: "+sx+" x "+sy+" -> "+sxy+": +"+dxh+" / "+dyh+", U: s "+shapeWidthU+" x "+shapeHeightU+", sz "+cellWidthU+" x "+cellHeightU); + } + } else { + sxy = 1; + } + final float shapeWidthS = sxy*sbox.getWidth(); + final float shapeHeightS = sxy*sbox.getHeight(); + final float cellWidthS = hasCellWidth ? cellWidth : shapeWidthS; + final float cellHeightS = hasCellHeight ? cellHeight : shapeHeightS; - // adjust size and position (centered) - final float x = ( ( col_i ) * ( cellWidth + padding.width() ) ) + padding.left; - final float y = ( ( row_count - row_i - 1 ) * ( cellHeight + padding.height() ) ) + padding.bottom; - final float sx = cellWidth / sbox.getWidth(); - final float sy = cellHeight/ sbox.getHeight(); - final float sxy = sx < sy ? sx : sy; - final float dxh = sbox.getWidth() * ( sx - sxy ) * 0.5f; - final float dyh = sbox.getHeight() * ( sy - sxy ) * 0.5f; - s.moveTo( x + dxh, y + dyh, 0f ); // center the scaled artifact - s.move( sbox.getLow().mul(-1f*sxy) ); // remove the bottom-left delta + final float x = ( ( col_i ) * ( cellWidthS + gap.width() ) ); + final float y = ( ( row_count - row_i - 1 ) * ( cellHeightS + gap.height() ) ); + + if( isCenteredHoriz ) { + dxh += 0.5f * ( cellWidthS - shapeWidthS ); // actual horiz-centered + } + if( isCenteredVert ) { + dyh += 0.5f * ( cellHeightS - shapeHeightS ); // actual vert-centered + } + if( TRACE_LAYOUT ) { + System.err.println("gl["+i+"].m: "+x+" / "+y+" + "+dxh+" / "+dyh+", S: s "+shapeWidthS+" x "+shapeHeightS+", sz "+cellWidthS+" x "+cellHeightS+", box "+box.getWidth()+" x "+box.getHeight()); + } + { + // New shape position, relative to previous position + final float aX = x + dxh; + final float aY = y + dyh; + s.moveTo( aX, aY, 0f ); + s.move( diffBL.scale(sxy) ); // remove the bottom-left delta + // s.move( sbox.getLow().mul(-1f) ); // remove the bottom-left delta + + // resize bounds including padding, excluding margin + box.resize( aX, aY, zPos); + box.resize( aX + cellWidthS, aY + cellHeightS, zPos); + } s.scale( sxy, sxy, 1f); - box.resize( x + cellWidth + padding.right, y + cellHeight + padding.top, 0); - box.resize( x - padding.left, y - padding.bottom, 0); - // System.err.println("["+row_i+"]["+col_i+"]: "+x+" / "+y+", sxy "+sxy+", d[xy]h "+dxh+" x "+dyh+", "+sbox); + + if( TRACE_LAYOUT ) { + System.err.println("gl["+i+"].x: "+x+" / "+y+" + "+dxh+" / "+dyh+" -> "+s.getPosition()+", p3 "+shapeWidthS+" x "+shapeHeightS+", sz3 "+cellWidthS+" x "+cellHeightS+", box "+box.getWidth()+" x "+box.getHeight()); + System.err.println("gl["+i+"].x: "+s); + } // position for next cell if( Order.COLUMN == order ) { - if( col_i + 1 == col_limit ) { + if( col_i + 1 == col_count ) { col_i = 0; row_i++; } else { col_i++; } } else { // Order.ROW_MAJOR == order - if( row_i + 1 == row_limit ) { + if( row_i + 1 == row_count ) { row_i = 0; col_i++; } else { @@ -152,11 +445,14 @@ public class GridLayout implements Group.Layout { } } } + if( TRACE_LAYOUT ) { + System.err.println("gl.xx: "+box); + } } @Override public String toString() { - return "Grid["+row_count+"x"+col_count+", "+order+", cell["+cellWidth+" x "+cellHeight+"], "+padding+"]"; + return "Grid["+col_count+"x"+row_count+", "+order+", cell["+cellWidth+" x "+cellHeight+", a "+alignment+"], "+gap+"]"; } } |