diff options
author | Sven Gothel <[email protected]> | 2023-09-05 02:54:42 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2023-09-05 02:54:42 +0200 |
commit | ddd6cac8cc658ce542cb98e85f7d262f9917d37a (patch) | |
tree | 645516bebc945b5a853fd1ce54346d8abeb0235b /src/graphui | |
parent | f39a084c6a34a083698ca56e9122642e839234c2 (diff) |
GraphUI Layout: Fix BoxLayout scale, margin and padding; Add same padding behavior to BoxLayout and GridLayout.
For all:
- Padding is applied to each {@Shape} via {@link Shape#setPaddding(Padding)} if passed in constructor
BoxLayout:
- Optionally centered {@link Alignment.Bit#CenterHoriz horizontally}, {@link Alignment.Bit#CenterVert vertically} or {@link Alignment#Center both}.
- Optionally scaled to cell-size if given and {@link Alignment#Fill}
- Margin is ignored on dimension with center {@link Alignment}
- Not implemented {@link Alignment}: Top, Right, Bottom, Left
GridLayout:
- Optionally centered {@link Alignment.Bit#CenterHoriz horizontally}, {@link Alignment.Bit#CenterVert vertically} or {@link Alignment#Center both}.
- Optionally scaled to cell-size if given and {@link Alignment#Fill}
- 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.
- Not implemented {@link Alignment}: Top, Right, Bottom, Left
Changes to Group.Layout interface:
- Added preValidate(Shape) allowing to prepare the shape before validation, used to inject Padding
Changes to Margin:
- Removed the complex CENTER property and using Alignment in BoxLayout as well
Changes to BoxLayout:
- Using Alignment
+++
Tested via UILayoutBox01 and UILayoutGrid01,
try the tooltip by clicking on the group's description label.
Diffstat (limited to 'src/graphui')
4 files changed, 310 insertions, 186 deletions
diff --git a/src/graphui/classes/com/jogamp/graph/ui/Group.java b/src/graphui/classes/com/jogamp/graph/ui/Group.java index 6e181a0a1..b131e8863 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/Group.java +++ b/src/graphui/classes/com/jogamp/graph/ui/Group.java @@ -55,6 +55,9 @@ import jogamp.graph.ui.TreeTool; public class Group extends Shape implements Container { /** Layout for the GraphUI {@link Group}, called @ {@link Shape#validate(GL2ES2)} or {@link Shape#validate(GLProfile)}. */ public static interface Layout { + /** Prepare given {@link Shape} before {@link Shape#validate(GL2ES2) validation}, e.g. {@link Shape#setPaddding(Padding)}. */ + void preValidate(final Shape s); + /** * Performing the layout of {@link Group#getShapes()}, called @ {@link Shape#validate(GL2ES2)} or {@link Shape#validate(GLProfile)}. * <p> @@ -241,6 +244,7 @@ public class Group extends Shape implements Container { final PMVMatrix pmv = new PMVMatrix(); if( null != layouter ) { for(final Shape s : shapes) { + layouter.preValidate(s); if( null != gl ) { s.validate(gl); } else { 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 acd58d0ab..57a83b4e7 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/layout/BoxLayout.java +++ b/src/graphui/classes/com/jogamp/graph/ui/layout/BoxLayout.java @@ -32,6 +32,8 @@ import java.util.List; import com.jogamp.graph.ui.Group; import com.jogamp.graph.ui.Shape; import com.jogamp.opengl.math.FloatUtil; +import com.jogamp.opengl.math.Vec2f; +import com.jogamp.opengl.math.Vec3f; import com.jogamp.opengl.math.geom.AABBox; import com.jogamp.opengl.util.PMVMatrix; @@ -39,23 +41,70 @@ 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 + * <ul> + * <li>Optionally centered {@link Alignment.Bit#CenterHoriz horizontally}, {@link Alignment.Bit#CenterVert vertically} or {@link Alignment#Center both}.</li> + * <li>Optionally scaled to cell-size if given and {@link Alignment#Fill}</li> + * <li>Padding is applied to each {@Shape} via {@link Shape#setPaddding(Padding)} if passed in constructor</li> + * <li>Margin is ignored on dimension with center {@link Alignment}</li> + * <li>Not implemented {@link Alignment}: {@link Alignment.Bit#Top Top}, {@link Alignment.Bit#Right Right}, {@link Alignment.Bit#Bottom Bottom}, {@link Alignment.Bit#Left Left}</li> + * </ul> * </p> */ public class BoxLayout implements Group.Layout { - private final float cellWidth, cellHeight; + private final Vec2f cellSize; + private final Alignment alignment; private final Margin margin; private final Padding padding; private static final boolean TRACE_LAYOUT = false; + + /** + */ + public BoxLayout() { + this(0f, 0f, new Alignment(), new Margin(), null); + } + + /** + * + * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(Padding)} + */ public BoxLayout(final Padding padding) { - this(0f, 0f, new Margin(), padding); + this(0f, 0f, new Alignment(), new Margin(), padding); + } + + public BoxLayout(final float width, final float height) { + this(width, height, new Alignment(), new Margin(), null); + } + + /** + * + * @param width + * @param height + * @param alignment + */ + public BoxLayout(final float width, final float height, final Alignment alignment) { + this(width, height, alignment, new Margin(), null); } + + /** + * + * @param width + * @param height + * @param margin + */ public BoxLayout(final float width, final float height, final Margin margin) { - this(width, height, margin, new Padding()); + this(width, height, new Alignment(), margin, null); + } + + /** + * + * @param width + * @param height + * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(Padding)} + */ + public BoxLayout(final float width, final float height, final Padding padding) { + this(width, height, new Alignment(), new Margin(), padding); } /** @@ -63,22 +112,62 @@ public class BoxLayout implements Group.Layout { * @param width * @param height * @param margin - * @param padding + * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(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(width, height, new Alignment(), margin, padding); + } + + /** + * + * @param width + * @param height + * @param margin + */ + public BoxLayout(final float width, final float height, final Alignment alignment, final Margin margin) { + this(width, height, alignment, margin, null); + } + + /** + * + * @param width + * @param height + * @param alignment + * @param margin + * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(Padding)} + */ + public BoxLayout(final float width, final float height, final Alignment alignment, final Margin margin, final Padding padding) { + this.cellSize = new Vec2f(Math.max(0f, width), Math.max(0f, height)); + this.alignment = alignment; this.margin = margin; this.padding = padding; } - public Padding getPadding() { return padding; } + /** Returns the preset cell size */ + public Vec2f getCellSize() { return cellSize; } + /** Returns given {@link Alignment}. */ + public Alignment getAlignment() { return alignment; } + /** Returns given {@link Margin}. */ public Margin getMargin() { return margin; } + /** Returns given {@link Padding}, may be {@code null} if not given via constructor. */ + public Padding getPadding() { return padding; } + + @Override + public void preValidate(final Shape s) { + if( null != padding ) { + s.setPaddding(padding); + } + } @Override public void layout(final Group g, final AABBox box, final PMVMatrix pmv) { - final boolean hasCellWidth = !FloatUtil.isZero(cellWidth); - final boolean hasCellHeight = !FloatUtil.isZero(cellHeight); + final Vec3f zeroVec3 = new Vec3f(); + final boolean hasCellWidth = !FloatUtil.isZero(cellSize.x()); + final boolean hasCellHeight = !FloatUtil.isZero(cellSize.y()); + final boolean isCenteredHoriz = hasCellWidth && alignment.isSet(Alignment.Bit.CenterHoriz); + final boolean isCenteredVert = hasCellHeight && alignment.isSet(Alignment.Bit.CenterVert); + final boolean isScaled = alignment.isSet(Alignment.Bit.Fill) && ( hasCellWidth || hasCellHeight ); + final List<Shape> shapes = g.getShapes(); final AABBox sbox = new AABBox(); for(int i=0; i < shapes.size(); ++i) { @@ -90,48 +179,97 @@ public class BoxLayout implements Group.Layout { s.getBounds().transformMv(pmv, sbox); pmv.glPopMatrix(); - // adjust size and position (centered) - final float paddedWidth = sbox.getWidth() + padding.width(); - final float paddedHeight = sbox.getHeight() + padding.height(); - 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() && paddedHeight <= cellHeight2 ) { - y += padding.bottom; + final int x = 0, y = 0; + if( TRACE_LAYOUT ) { + System.err.println("bl("+i+").0: sbox "+sbox+", s "+s); } - final float dxh, dyh; - if( margin.isCenteredHoriz() ) { - dxh = 0.5f * ( cellWidth2 - paddedWidth ); // actual horiz-centered + + // IF isScaled: Uniform scale w/ lowest axis scale and center position on lower-scale axis + final float shapeWidthU = sbox.getWidth() + margin.width(); + final float shapeWidthU_LH = ( sbox.getWidth() * 0.5f ) + margin.left; // left-half + final float shapeHeightU = sbox.getHeight() + margin.height(); + final float shapeHeightU_BH = ( sbox.getHeight() * 0.5f ) + margin.bottom; // bottom-half + final float sxy; + float dxh = 0, dyh = 0; + if( isScaled ) { + // scaling to cell size, implies center (horiz + vert) + final float cellWidth2 = hasCellWidth ? cellSize.x() : shapeWidthU; + final float cellHeight2 = hasCellHeight ? cellSize.y() : shapeHeightU; + final float sx = cellWidth2 / shapeWidthU; + final float sy = cellHeight2/ shapeHeightU; + sxy = sx < sy ? sx : sy; + dxh += sxy * margin.left + shapeWidthU_LH * ( sx - sxy ); // adjustment for scale-axis + dyh += sxy * margin.bottom + shapeHeightU_BH * ( sy - sxy ); // ditto + if( TRACE_LAYOUT ) { + System.err.println("bl("+i+").s: "+sx+" x "+sy+" -> "+sxy+": +"+dxh+" / "+dyh+", U: s "+shapeWidthU+" x "+shapeHeightU+", sz "+cellWidth2+" x "+cellHeight2); + } } else { - dxh = 0; + sxy = 1; } - if( margin.isCenteredVert() ) { - dyh = 0.5f * ( cellHeight2 - paddedHeight ); // actual vert-centered - } else { - dyh = 0; + final float shapeWidthS = sxy * shapeWidthU; + final float shapeHeightS = sxy * shapeHeightU; + final float cellWidthS = hasCellWidth ? cellSize.x() : shapeWidthS; + final float cellHeightS = hasCellHeight ? cellSize.y() : shapeHeightS; + + if( !isScaled ) { + // Use half delta of net-size to center, margin is ignored when centering + final float shapeWidthS_H = sxy * sbox.getWidth() * 0.5f; + final float shapeHeightS_H = sxy * sbox.getHeight() * 0.5f; + final float cellWidthS_H = hasCellWidth ? cellSize.x() * 0.5f : shapeWidthS_H; + final float cellHeightS_H = hasCellHeight ? cellSize.y() * 0.5f : shapeHeightS_H; + if( isCenteredHoriz ) { + dxh += cellWidthS_H - shapeWidthS_H; // horiz-center + } else { + dxh += sxy * margin.left; + } + if( isCenteredVert ) { + dyh += cellHeightS_H - shapeHeightS_H; // vert-center + } else { + dyh += sxy * margin.bottom; + } } 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()); + System.err.println("bl("+i+").m: "+x+" / "+y+" + "+dxh+" / "+dyh+", sxy "+sxy+", S: s "+shapeWidthS+" x "+shapeHeightS+", sz "+cellWidthS+" x "+cellHeightS); } - s.move( x + dxh, y + dyh, 0f ); // center the scaled artifact - s.move( sbox.getLow().mul(-1f) ); // remove the bottom-left delta - // 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); + // Position and scale shape + { + // New shape position, relative to previous position + final float aX = x + dxh; + final float aY = y + dyh; + s.moveTo( aX, aY, s.getPosition().z() ); + + // remove the bottom-left delta + final Vec3f diffBL = new Vec3f(); + final AABBox sbox0 = s.getBounds(); + 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); + } + if( TRACE_LAYOUT ) { + System.err.println("bl("+i+").bl: sbox0 "+sbox0+", diffBL "+diffBL); + } + s.move( diffBL.scale(sxy) ); + + // resize bounds + box.resize( x, y, sbox.getMinZ()); + box.resize( x + cellWidthS, y + cellHeightS, sbox.getMaxZ()); + } + s.scale( sxy, sxy, 1f); + 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()); + System.err.println("bl("+i+").x: "+dxh+" / "+dyh+" -> "+s.getPosition()+", p3 "+shapeWidthS+" x "+shapeHeightS+", sz3 "+cellWidthS+" x "+cellHeightS+", box "+box.getWidth()+" x "+box.getHeight()); + System.err.println("bl("+i+").x: "+s); + System.err.println("bl("+i+").x: "+box); } } } @Override public String toString() { - return "Box[cell["+cellWidth+" x "+cellHeight+"], "+margin+", "+padding+"]"; + final String p_s = ( null == padding || padding.zeroSumSize() ) ? "" : ", "+padding.toString(); + final String m_s = margin.zeroSumSize() ? "" : ", "+margin.toString(); + return "Box[cell "+cellSize+", a "+alignment+m_s+p_s+"]"; } } 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 d4a976012..8f83678c1 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/layout/GridLayout.java +++ b/src/graphui/classes/com/jogamp/graph/ui/layout/GridLayout.java @@ -32,6 +32,7 @@ import java.util.List; import com.jogamp.graph.ui.Group; import com.jogamp.graph.ui.Shape; import com.jogamp.opengl.math.FloatUtil; +import com.jogamp.opengl.math.Vec2f; import com.jogamp.opengl.math.Vec3f; import com.jogamp.opengl.math.geom.AABBox; import com.jogamp.opengl.util.PMVMatrix; @@ -40,10 +41,15 @@ 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. - * - .. + * <ul> + * <li>Optionally centered {@link Alignment.Bit#CenterHoriz horizontally}, {@link Alignment.Bit#CenterVert vertically} or {@link Alignment#Center both}.</li> + * <li>Optionally scaled to cell-size if given and {@link Alignment#Fill}</li> + * <li>Padding is applied to each {@Shape} via {@link Shape#setPaddding(Padding)} if passed in constructor</li> + * <li>Without cell-size behaves like a grid bag using individual shape sizes including padding</li> + * <li>Can be filled in {@link Order#COLUMN} or {@link Order#ROW} major-order.</li> + * <li>Not implemented {@link Alignment}: {@link Alignment.Bit#Top Top}, {@link Alignment.Bit#Right Right}, {@link Alignment.Bit#Bottom Bottom}, {@link Alignment.Bit#Left Left}</li> + * <li>..</li> + * </ul> * </p> */ public class GridLayout implements Group.Layout { @@ -57,9 +63,10 @@ public class GridLayout implements Group.Layout { private final Order order; private final int col_limit; private final int row_limit; - private final float cellWidth, cellHeight; + private final Vec2f cellSize; private final Alignment alignment; private final Gap gap; + private final Padding padding; private int row_count, col_count; private static final boolean TRACE_LAYOUT = false; @@ -72,7 +79,7 @@ public class GridLayout implements Group.Layout { * @param alignment TODO */ 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()); + this(alignment, Math.max(1, column_limit), -1, cellWidth, cellHeight, new Gap(), null); } /** @@ -84,7 +91,20 @@ public class GridLayout implements Group.Layout { * @param gap */ 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); + this(alignment, Math.max(1, column_limit), -1, cellWidth, cellHeight, gap, null); + } + + /** + * Default layout order of {@link Group#getShapes()}} is {@link Order#COLUMN}. + * @param column_limit [1..inf) + * @param cellWidth + * @param cellHeight + * @param alignment TODO + * @param gap + * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(Padding)} + */ + public GridLayout(final int column_limit, final float cellWidth, final float cellHeight, final Alignment alignment, final Gap gap, final Padding padding) { + this(alignment, Math.max(1, column_limit), -1, cellWidth, cellHeight, gap, padding); } /** @@ -96,33 +116,64 @@ public class GridLayout implements Group.Layout { * @param row_limit [1..inf) */ 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); + this(alignment, -1, Math.max(1, row_limit), cellWidth, cellHeight, gap, null); } - private GridLayout(final Alignment alignment, final int column_limit, final int row_limit, final float cellWidth, final float cellHeight, final Gap gap) { + /** + * Default layout order of {@link Group#getShapes()}} is {@link Order#ROW}. + * @param cellWidth + * @param cellHeight + * @param alignment TODO + * @param gap + * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(Padding)} + * @param row_limit [1..inf) + */ + public GridLayout(final float cellWidth, final float cellHeight, final Alignment alignment, final Gap gap, final Padding padding, final int row_limit) { + this(alignment, -1, Math.max(1, row_limit), cellWidth, cellHeight, gap, padding); + } + + private GridLayout(final Alignment alignment, final int column_limit, final int row_limit, final float cellWidth, final float cellHeight, + final Gap gap, final Padding padding) { 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.cellSize = new Vec2f(Math.max(0f, cellWidth), Math.max(0f, cellHeight)); this.alignment = alignment; this.gap = gap; + this.padding = padding; row_count = 0; col_count = 0; } + /** Returns given {@link Order}. */ public Order getOrder() { return order; } + /** Returns column count after {@link #layout(Group, AABBox, PMVMatrix)}. */ public int getColumnCount() { return col_count; } + /** Returns row count after {@link #layout(Group, AABBox, PMVMatrix)}. */ public int getRowCount() { return row_count; } + /** Returns the preset cell size */ + public Vec2f getCellSize() { return cellSize; } + /** Returns given {@link Alignment}. */ + public Alignment getAlignment() { return alignment; } + /** Returns given {@link Gap}. */ public Gap getGap() { return gap; } + /** Returns given {@link Padding}, may be {@code null} if not given via constructor. */ + public Padding getPadding() { return padding; } + + @Override + public void preValidate(final Shape s) { + if( null != padding ) { + s.setPaddding(padding); + } + } @Override public void layout(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 hasCellWidth = !FloatUtil.isZero(cellSize.x()); + final boolean hasCellHeight = !FloatUtil.isZero(cellSize.y()); + final boolean isCenteredHoriz = hasCellWidth && alignment.isSet(Alignment.Bit.CenterHoriz); + final boolean isCenteredVert = hasCellHeight && alignment.isSet(Alignment.Bit.CenterVert); final boolean isScaled = alignment.isSet(Alignment.Bit.Fill) && ( hasCellWidth || hasCellHeight ); final List<Shape> shapes = g.getShapes(); if( Order.COLUMN == order ) { @@ -159,8 +210,8 @@ public class GridLayout implements Group.Layout { // 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 cellWidthU = hasCellWidth ? cellSize.x() : shapeWidthU; + final float cellHeightU = hasCellHeight ? cellSize.y() : shapeHeightU; final float sx = cellWidthU / shapeWidthU; final float sy = cellHeightU/ shapeHeightU; sxy = sx < sy ? sx : sy; @@ -169,8 +220,8 @@ public class GridLayout implements Group.Layout { } final float shapeWidthS = sxy*sbox.getWidth(); final float shapeHeightS = sxy*sbox.getHeight(); - final float cellWidthS = hasCellWidth ? cellWidth : shapeWidthS; - final float cellHeightS = hasCellHeight ? cellHeight : shapeHeightS; + final float cellWidthS = hasCellWidth ? cellSize.x() : shapeWidthS; + final float cellHeightS = hasCellHeight ? cellSize.y() : shapeHeightS; // bottom y_pos, top to bottom, to be subtracted from totalHeight final float y0 = y + cellHeightS; @@ -217,21 +268,9 @@ public class GridLayout implements Group.Layout { for(int i=0; i < shapes.size(); ++i) { final Shape s = shapes.get(i); final AABBox sbox = sboxes[i]; - final float zPos = sbox.getCenter().z(); - final Vec3f diffBL = new Vec3f(); - - { - final AABBox sbox0 = s.getBounds(); - 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); - } - } 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); + System.err.println("gl("+i+")["+col_i+"]["+row_i+"].0: sbox "+sbox+", s "+s); } // IF isScaled: Uniform scale w/ lowest axis scale and center position on lower-scale axis @@ -241,8 +280,8 @@ public class GridLayout implements Group.Layout { // 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 cellWidth2 = hasCellWidth ? cellSize.x() : shapeWidthU; + final float cellHeight2 = hasCellHeight ? cellSize.y() : shapeHeightU; final float sx = cellWidth2 / shapeWidthU; final float sy = cellHeight2/ shapeHeightU; sxy = sx < sy ? sx : sy; @@ -256,36 +295,52 @@ public class GridLayout implements Group.Layout { } final float shapeWidthS = sxy*sbox.getWidth(); final float shapeHeightS = sxy*sbox.getHeight(); - final float cellWidthS = hasCellWidth ? cellWidth : shapeWidthS; - final float cellHeightS = hasCellHeight ? cellHeight : shapeHeightS; + final float cellWidthS = hasCellWidth ? cellSize.x() : shapeWidthS; + final float cellHeightS = hasCellHeight ? cellSize.y() : shapeHeightS; y = totalHeight - y_pos[col_count * row_i + col_i]; if( isCenteredHoriz ) { - dxh += 0.5f * ( cellWidthS - shapeWidthS ); // actual horiz-centered + dxh += 0.5f * ( cellWidthS - shapeWidthS ); // horiz-center } if( isCenteredVert ) { - dyh += 0.5f * ( cellHeightS - shapeHeightS ); // actual vert-centered + dyh += 0.5f * ( cellHeightS - shapeHeightS ); // vert-center } 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); } + // Position and scale shape { // 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.moveTo( aX, aY, s.getPosition().z() ); + + // Remove the bottom-left delta + final Vec3f diffBL = new Vec3f(); + { + final AABBox sbox0 = s.getBounds(); + 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); + } + if( TRACE_LAYOUT ) { + System.err.println("gl("+i+")["+col_i+"]["+row_i+"].bl: sbox0 "+sbox0+", diffBL_ "+diffBL); + } + } + s.move( diffBL.scale(sxy) ); - // resize bounds including padding, excluding margin - box.resize( x, y, zPos); - box.resize( aX + cellWidthS, aY + cellHeightS, zPos); + // resize bounds + box.resize( x, y, sbox.getMinZ()); + box.resize( x + cellWidthS, y + cellHeightS, sbox.getMaxZ()); } 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); + System.err.println("gl("+i+")["+col_i+"]["+row_i+"].x: "+box); } if( i + 1 < shapes.size() ) { @@ -318,7 +373,9 @@ public class GridLayout implements Group.Layout { @Override public String toString() { - return "Grid["+col_count+"x"+row_count+", "+order+", cell["+cellWidth+" x "+cellHeight+", a "+alignment+"], "+gap+"]"; + final String p_s = ( null == padding || padding.zeroSumSize() ) ? "" : ", "+padding.toString(); + final String g_s = gap.zeroSumSize() ? "" : ", "+gap.toString(); + return "Grid["+col_count+"x"+row_count+", "+order+", cell "+cellSize+", a "+alignment+g_s+p_s+"]"; } } diff --git a/src/graphui/classes/com/jogamp/graph/ui/layout/Margin.java b/src/graphui/classes/com/jogamp/graph/ui/layout/Margin.java index 240053cb5..6e4bef169 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/layout/Margin.java +++ b/src/graphui/classes/com/jogamp/graph/ui/layout/Margin.java @@ -31,16 +31,14 @@ import com.jogamp.opengl.math.FloatUtil; /** * GraphUI CSS property Margin, space between or around elements and not included in the element's size. - * + * <p> * The CSS margin properties are used to create space around elements, outside of any defined borders. - * - * {@link Margin#CENTER} is mapped to `zero` while earmarking {@link #isCenteredHoriz()} and {@link #isCenteredVert()}. - * The container must be sized via its layout horizontally and/or vertically matching the centered axis, similar to CSS. + * </p> + * <p> + * Center alignment is defined via {@link Alignment} and {@link Margin} ignored on centered dimension. + * </p> */ public class Margin { - /** Auto margin value to horizontally and/or vertically center an element within its sized-layout container, value if {@link Float#NaN}. */ - public static final float CENTER = Float.NaN; - /** Top value */ public final float top; /** Right value */ @@ -50,20 +48,6 @@ public class Margin { /** Left value */ public final float left; - private final int bits; - static private final int CENTER_HORIZ = 1 << 0; - static private final int CENTER_VERT = 1 << 1; - static private int getBits(final float top, final float right, final float bottom, final float left) { - int b = 0; - if( FloatUtil.isEqual(CENTER, left) && FloatUtil.isEqual(CENTER, right) ) { - b |= CENTER_HORIZ; - } - if( FloatUtil.isEqual(CENTER, top) && FloatUtil.isEqual(CENTER, bottom) ) { - b |= CENTER_VERT; - } - return b; - } - /** * Ctor w/ zero values */ @@ -79,105 +63,46 @@ public class Margin { * @param left left value */ public Margin(final float top, final float right, final float bottom, final float left) { - this.bits = getBits(top, right, bottom, left); - if( isCenteredVert() ) { - this.top = 0; - this.bottom = 0; - } else { - this.top = top; - this.bottom = bottom; - } - if( isCenteredHoriz() ) { - this.right = 0; - this.left = 0; - } else { - this.right = right; - this.left = left; - } + this.top = top; + this.bottom = bottom; + this.right = right; + this.left = left; } /** * Ctor * @param top top value - * @param rl right and left value, use {@link #CENTER} to horizontally center the element in its container + * @param rl right and left value * @param bottom bottom value */ public Margin(final float top, final float rl, final float bottom) { - this.bits = getBits(top, rl, bottom, rl); - if( isCenteredVert() ) { - this.top = 0; - this.bottom = 0; - } else { - this.top = top; - this.bottom = bottom; - } - if( isCenteredHoriz() ) { - this.right = 0; - this.left = 0; - } else { - this.right = rl; - this.left = rl; - } + this.top = top; + this.bottom = bottom; + this.right = rl; + this.left = rl; } /** * Ctor - * @param tb top and bottom value, use {@link #CENTER} to vertically center the element in its container - * @param rl right and left value, use {@link #CENTER} to horizontally center the element in its container + * @param tb top and bottom value + * @param rl right and left value */ public Margin(final float tb, final float rl) { - this.bits = getBits(tb, rl, tb, rl); - if( isCenteredVert() ) { - this.top = 0; - this.bottom = 0; - } else { - this.top = tb; - this.bottom = tb; - } - if( isCenteredHoriz() ) { - this.right = 0; - this.left = 0; - } else { - this.right = rl; - this.left = rl; - } + this.top = tb; + this.bottom = tb; + this.right = rl; + this.left = rl; } /** * Ctor - * @param trbl top, right, bottom and left value, use {@link #CENTER} to horizontally and vertically center the element in its container. + * @param trbl top, right, bottom and left value */ public Margin(final float trbl) { - this.bits = getBits(trbl, trbl, trbl, trbl); - if( isCenteredVert() ) { - this.top = 0; - this.bottom = 0; - } else { - this.top = trbl; - this.bottom = trbl; - } - if( isCenteredHoriz() ) { - this.right = 0; - this.left = 0; - } else { - this.right = trbl; - this.left = trbl; - } - } - - /** Returns true if {@link #left} and {@link #right} is {@link #CENTER}. */ - public boolean isCenteredHoriz() { - return 0 != ( CENTER_HORIZ & bits ); - } - - /** Returns true if {@link #top} and {@link #bottom} is {@link #CENTER}. */ - public boolean isCenteredVert() { - return 0 != ( CENTER_VERT & bits ); - } - - /** Returns true if {@link #isCenteredHoriz()} and {@link #isCenteredVert()} is true, i.e. for horizontal and vertical center. */ - public boolean isCentered() { - return 0 != ( ( CENTER_VERT | CENTER_HORIZ ) & bits ); + this.top = trbl; + this.bottom = trbl; + this.right = trbl; + this.left = trbl; } /** Return width of horizontal values top + right. Zero if {@link #isCenteredHoriz()}. */ @@ -193,5 +118,5 @@ public class Margin { public boolean zeroSumSize() { return zeroSumWidth() && zeroSumHeight(); } @Override - public String toString() { return "Margin[t "+top+", r "+right+", b "+bottom+", l "+left+", ctr[h "+isCenteredHoriz()+", v "+isCenteredVert()+"]]"; } + public String toString() { return "Margin[t "+top+", r "+right+", b "+bottom+", l "+left+"]"; } } |