diff options
author | Sven Gothel <[email protected]> | 2023-09-16 15:38:21 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2023-09-16 15:38:21 +0200 |
commit | e5de90b67efe8e8ca518159b3a73295d751764c1 (patch) | |
tree | 49b751489dda73b510e4db37abed6b8824ec0372 | |
parent | 1e55d2a6a157cb9d70f7a879cc9a9bc97db5413d (diff) |
GraphUI BoxLayout: Margin is only ignored for center Alignment w/o Fill scale. {Box,Grid}Layout: Always remove Bottom-Left delta and refine API doc of incl scale behavior
GraphUI BoxLayout: Margin is only ignored for center Alignment w/o Fill scale.
Margin outside of a shape is not scaled and hence must be considered
when using Fill scale.
{Box,Grid}Layout: Always remove Bottom-Left delta
Previously we were only dropping the negative extend.
However, since our scale and center algo uses the AABBox width and height,
which excludes the bottom-left delta, we have to drop such offset.
TODO: Otherwise, we would need adjust for the bottom-left extend
when NOT centering for each direction!
This might be a useful enhancement in case one likes to drop
shapes as-is w/o centering.
{Box,Grid}Layout: Refine API doc of incl scale behavior
6 files changed, 114 insertions, 102 deletions
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBox01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBox01.java index 70db5d696..cef57d503 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBox01.java +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBox01.java @@ -346,7 +346,15 @@ public class UILayoutBox01 { groups.add(g); } ++id; + nextPos.setX( nextPos.x() + sxy * cellGap ); + + if( true ) { + final Group g = fillDemoGroup(new Group( new BoxLayout( 1f, 1f, Alignment.FillCenter, margin, null ) ), + reqGLP, scene, zEps, sxy, nextPos, font, id, dragZoomRotateListener); + groups.add(g); + } nextPos.set(0, nextPos.y() + sxy * cellGap, 0); + ++id; // // 3. Row @@ -385,7 +393,7 @@ public class UILayoutBox01 { ++id; if( true ) { - final Group g = fillDemoGroup(new Group( new BoxLayout( 1f, 1f, Alignment.Fill, new Margin(), padding ) ), + final Group g = fillDemoGroup(new Group( new BoxLayout( 1f, 1f, Alignment.Fill, margin, padding ) ), reqGLP, scene, zEps, sxy, nextPos, font, id, dragZoomRotateListener); groups.add(g); } @@ -393,7 +401,7 @@ public class UILayoutBox01 { ++id; if( true ) { - final Group g = fillDemoGroup(new Group( new BoxLayout( 1f, 1f, Alignment.Fill, margin, padding ) ), + final Group g = fillDemoGroup(new Group( new BoxLayout( 1f, 1f, Alignment.FillCenter, margin, padding ) ), reqGLP, scene, zEps, sxy, nextPos, font, id, dragZoomRotateListener); groups.add(g); } 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 d8c6f8605..36671d32a 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/layout/Alignment.java +++ b/src/graphui/classes/com/jogamp/graph/ui/layout/Alignment.java @@ -55,14 +55,14 @@ public final class Alignment { /** Top alignment. */ Top ( ( 1 << 3 ) ), + /** Scale object to parent size, e.g. fill {@link GridLayout} or {@link BoxLayout} cell size. */ + Fill ( ( 1 << 4 ) ), + /** Horizontal center alignment. */ - CenterHoriz ( ( 1 << 4 ) ), + CenterHoriz ( ( 1 << 5 ) ), /** Vertical center alignment. */ - CenterVert ( ( 1 << 5 ) ), - - /** Scale object to parent size, e.g. fill {@link GridLayout} or {@link BoxLayout} cell size. */ - Fill ( ( 1 << 15 ) ); + CenterVert ( ( 1 << 6 ) ); Bit(final int v) { value = v; } public final int value; 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 57a83b4e7..340060e02 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/layout/BoxLayout.java +++ b/src/graphui/classes/com/jogamp/graph/ui/layout/BoxLayout.java @@ -44,8 +44,8 @@ import com.jogamp.opengl.util.PMVMatrix; * <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>{@link Padding} is applied to each {@Shape} via {@link Shape#setPaddding(Padding)} if passed in constructor and is scaled if {@link Alignment.Bit#Fill}</li> + * <li>{@link Margin} is applied unscaled if used and ignored with only center {@link Alignment} w/o {@link Alignment.Bit#Fill} scale</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> @@ -53,8 +53,8 @@ import com.jogamp.opengl.util.PMVMatrix; public class BoxLayout implements Group.Layout { private final Vec2f cellSize; private final Alignment alignment; - private final Margin margin; - private final Padding padding; + private final Margin margin; // unscaled + private final Padding padding; // scaled private static final boolean TRACE_LAYOUT = false; @@ -67,77 +67,88 @@ public class BoxLayout implements Group.Layout { /** * - * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(Padding)} + * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(Padding)} and is scaled if {@link Alignment.Bit#Fill} */ public BoxLayout(final Padding 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); + public BoxLayout(final float cellWidth, final float cellHeight) { + this(cellWidth, cellHeight, new Alignment(), new Margin(), null); } /** * - * @param width - * @param height + * @param cellWidth + * @param cellHeight * @param alignment */ - public BoxLayout(final float width, final float height, final Alignment alignment) { - this(width, height, alignment, new Margin(), null); + public BoxLayout(final float cellWidth, final float cellHeight, final Alignment alignment) { + this(cellWidth, cellHeight, alignment, new Margin(), null); } /** * - * @param width - * @param height - * @param margin + * @param cellWidth + * @param cellHeight + * @param margin {@link Margin} is applied unscaled and ignored with only center {@link Alignment} w/o {@link Alignment.Bit#Fill} scale */ - public BoxLayout(final float width, final float height, final Margin margin) { - this(width, height, new Alignment(), margin, null); + public BoxLayout(final float cellWidth, final float cellHeight, final Margin margin) { + this(cellWidth, cellHeight, new Alignment(), margin, null); } /** * - * @param width - * @param height - * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(Padding)} + * @param cellWidth + * @param cellHeight + * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(Padding)} and is scaled if {@link Alignment.Bit#Fill} */ - public BoxLayout(final float width, final float height, final Padding padding) { - this(width, height, new Alignment(), new Margin(), padding); + public BoxLayout(final float cellWidth, final float cellHeight, final Padding padding) { + this(cellWidth, cellHeight, new Alignment(), new Margin(), padding); } /** * - * @param width - * @param height - * @param margin - * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(Padding)} + * @param cellWidth + * @param cellHeight + * @param margin {@link Margin} is applied unscaled and ignored with only center {@link Alignment} w/o {@link Alignment.Bit#Fill} scale + * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(Padding)} and is scaled if {@link Alignment.Bit#Fill} */ - public BoxLayout(final float width, final float height, final Margin margin, final Padding padding) { - this(width, height, new Alignment(), margin, padding); + public BoxLayout(final float cellWidth, final float cellHeight, final Margin margin, final Padding padding) { + this(cellWidth, cellHeight, new Alignment(), margin, padding); } /** * - * @param width - * @param height - * @param margin + * @param cellWidth + * @param cellHeight + * @param margin {@link Margin} is applied unscaled */ - public BoxLayout(final float width, final float height, final Alignment alignment, final Margin margin) { - this(width, height, alignment, margin, null); + public BoxLayout(final float cellWidth, final float cellHeight, final Alignment alignment, final Margin margin) { + this(cellWidth, cellHeight, alignment, margin, null); } /** * - * @param width - * @param height + * @param cellWidth + * @param cellHeight * @param alignment - * @param margin - * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(Padding)} + * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(Padding)} and is scaled if {@link Alignment.Bit#Fill} */ - 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)); + public BoxLayout(final float cellWidth, final float cellHeight, final Alignment alignment, final Padding padding) { + this(cellWidth, cellHeight, alignment, new Margin(), padding); + } + + /** + * + * @param cellWidth + * @param cellHeight + * @param alignment + * @param margin {@link Margin} is applied unscaled and ignored with only center {@link Alignment} w/o {@link Alignment.Bit#Fill} scale + * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(Padding)} and is scaled if {@link Alignment.Bit#Fill} + */ + public BoxLayout(final float cellWidth, final float cellHeight, final Alignment alignment, final Margin margin, final Padding padding) { + this.cellSize = new Vec2f(Math.max(0f, cellWidth), Math.max(0f, cellHeight)); this.alignment = alignment; this.margin = margin; this.padding = padding; @@ -185,21 +196,26 @@ public class BoxLayout implements Group.Layout { } // 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 shapeWidthU = sbox.getWidth(); + final float shapeHeightU = sbox.getHeight(); 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; + // scaling to cell size + final float cellWidth2 = hasCellWidth ? cellSize.x() - margin.width() : shapeWidthU; + final float cellHeight2 = hasCellHeight ? cellSize.y() - margin.height() : 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( isCenteredHoriz ) { + dxh += shapeWidthU * ( sx - sxy ) * 0.5f; // horiz-center (adjustment for scale-axis) + } + if( isCenteredVert ) { + dyh += shapeHeightU * ( sy - sxy ) * 0.5f; // vert-center (adjustment for scale-axis) + } + dyh += margin.bottom; + dxh += margin.left; if( TRACE_LAYOUT ) { System.err.println("bl("+i+").s: "+sx+" x "+sy+" -> "+sxy+": +"+dxh+" / "+dyh+", U: s "+shapeWidthU+" x "+shapeHeightU+", sz "+cellWidth2+" x "+cellHeight2); } @@ -212,22 +228,19 @@ public class BoxLayout implements Group.Layout { 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; + // Center w/o scale and ignoring margin (not scaled) if( isCenteredHoriz ) { - dxh += cellWidthS_H - shapeWidthS_H; // horiz-center + dxh += 0.5f * ( cellWidthS - shapeWidthS ); // horiz-center } else { - dxh += sxy * margin.left; + dxh += margin.left; } if( isCenteredVert ) { - dyh += cellHeightS_H - shapeHeightS_H; // vert-center + dyh += 0.5f * ( cellHeightS - shapeHeightS ); // vert-center } else { - dyh += sxy * margin.bottom; + dyh += margin.bottom; } } + if( TRACE_LAYOUT ) { System.err.println("bl("+i+").m: "+x+" / "+y+" + "+dxh+" / "+dyh+", sxy "+sxy+", S: s "+shapeWidthS+" x "+shapeHeightS+", sz "+cellWidthS+" x "+cellHeightS); } @@ -238,16 +251,12 @@ public class BoxLayout implements Group.Layout { 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); - } + // Remove the bottom-left delta + final Vec3f diffBL = new Vec3f(s.getBounds().getLow()); + diffBL.setZ(0); + diffBL.scale(s.getScale()).scale(-1f); if( TRACE_LAYOUT ) { - System.err.println("bl("+i+").bl: sbox0 "+sbox0+", diffBL "+diffBL); + System.err.println("bl("+i+").bl: sbox0 "+s.getBounds()+", diffBL_ "+diffBL); } s.move( diffBL.scale(sxy) ); diff --git a/src/graphui/classes/com/jogamp/graph/ui/layout/Gap.java b/src/graphui/classes/com/jogamp/graph/ui/layout/Gap.java index 35174a87d..61d93c03c 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/layout/Gap.java +++ b/src/graphui/classes/com/jogamp/graph/ui/layout/Gap.java @@ -30,7 +30,7 @@ package com.jogamp.graph.ui.layout; import com.jogamp.opengl.math.FloatUtil; /** - * GraphUI CSS property Gap, spaceing between (grid) cells not belonging to the element. + * GraphUI CSS property Gap, spacing between (grid) cells not belonging to the element. * <p> * The CSS gap property defines the size of the gap between the rows and columns in a grid layout. * </p> 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 8f83678c1..50f847df4 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/layout/GridLayout.java +++ b/src/graphui/classes/com/jogamp/graph/ui/layout/GridLayout.java @@ -44,8 +44,9 @@ import com.jogamp.opengl.util.PMVMatrix; * <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>{@link Padding} is applied to each {@Shape} via {@link Shape#setPaddding(Padding)} if passed in constructor and is scaled if {@link Alignment.Bit#Fill}</li> + * <li>Without cell-size behaves like a grid bag using individual shape sizes including {@link Padding}</li> + * <li>{@link Gap} is applied unscaled if used.</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> @@ -66,7 +67,7 @@ public class GridLayout implements Group.Layout { private final Vec2f cellSize; private final Alignment alignment; private final Gap gap; - private final Padding padding; + private final Padding padding; // scaled! private int row_count, col_count; private static final boolean TRACE_LAYOUT = false; @@ -88,7 +89,7 @@ public class GridLayout implements Group.Layout { * @param cellWidth * @param cellHeight * @param alignment TODO - * @param gap + * @param gap {@link Gap} is applied unscaled */ 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, null); @@ -100,8 +101,8 @@ public class GridLayout implements Group.Layout { * @param cellWidth * @param cellHeight * @param alignment TODO - * @param gap - * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(Padding)} + * @param gap {@link Gap} is applied unscaled + * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(Padding)} and is scaled if {@link Alignment.Bit#Fill} */ 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); @@ -112,7 +113,7 @@ public class GridLayout implements Group.Layout { * @param cellWidth * @param cellHeight * @param alignment TODO - * @param gap + * @param gap {@link Gap} is applied unscaled * @param row_limit [1..inf) */ public GridLayout(final float cellWidth, final float cellHeight, final Alignment alignment, final Gap gap, final int row_limit) { @@ -124,8 +125,8 @@ public class GridLayout implements Group.Layout { * @param cellWidth * @param cellHeight * @param alignment TODO - * @param gap - * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(Padding)} + * @param gap {@link Gap} is applied unscaled + * @param padding {@link Padding} applied to each {@Shape} via {@link Shape#setPaddding(Padding)} and is scaled if {@link Alignment.Bit#Fill} * @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) { @@ -205,11 +206,11 @@ public class GridLayout implements Group.Layout { pmv.glPopMatrix(); final AABBox sbox = sboxes[i]; + final float shapeWidthU = sbox.getWidth(); + final float shapeHeightU = sbox.getHeight(); final float sxy; if( isScaled ) { // scaling to cell size - final float shapeWidthU = sbox.getWidth(); - final float shapeHeightU = sbox.getHeight(); final float cellWidthU = hasCellWidth ? cellSize.x() : shapeWidthU; final float cellHeightU = hasCellHeight ? cellSize.y() : shapeHeightU; final float sx = cellWidthU / shapeWidthU; @@ -218,8 +219,8 @@ public class GridLayout implements Group.Layout { } else { sxy = 1; } - final float shapeWidthS = sxy*sbox.getWidth(); - final float shapeHeightS = sxy*sbox.getHeight(); + final float shapeWidthS = sxy * shapeWidthU; + final float shapeHeightS = sxy * shapeHeightU; final float cellWidthS = hasCellWidth ? cellSize.x() : shapeWidthS; final float cellHeightS = hasCellHeight ? cellSize.y() : shapeHeightS; @@ -274,12 +275,12 @@ public class GridLayout implements Group.Layout { } // IF isScaled: Uniform scale w/ lowest axis scale and center position on lower-scale axis + final float shapeWidthU = sbox.getWidth(); + final float shapeHeightU = sbox.getHeight(); 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 ? cellSize.x() : shapeWidthU; final float cellHeight2 = hasCellHeight ? cellSize.y() : shapeHeightU; final float sx = cellWidth2 / shapeWidthU; @@ -293,8 +294,8 @@ public class GridLayout implements Group.Layout { } else { sxy = 1; } - final float shapeWidthS = sxy*sbox.getWidth(); - final float shapeHeightS = sxy*sbox.getHeight(); + final float shapeWidthS = sxy * shapeWidthU; + final float shapeHeightS = sxy * shapeHeightU; final float cellWidthS = hasCellWidth ? cellSize.x() : shapeWidthS; final float cellHeightS = hasCellHeight ? cellSize.y() : shapeHeightS; @@ -317,17 +318,11 @@ public class GridLayout implements Group.Layout { 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); - } + final Vec3f diffBL = new Vec3f(s.getBounds().getLow()); + diffBL.setZ(0); + diffBL.scale(s.getScale()).scale(-1f); + if( TRACE_LAYOUT ) { + System.err.println("gl("+i+")["+col_i+"]["+row_i+"].bl: sbox0 "+s.getBounds()+", diffBL_ "+diffBL); } s.move( diffBL.scale(sxy) ); 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 6e4bef169..72d366ae2 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/layout/Margin.java +++ b/src/graphui/classes/com/jogamp/graph/ui/layout/Margin.java @@ -35,7 +35,7 @@ import com.jogamp.opengl.math.FloatUtil; * The CSS margin properties are used to create space around elements, outside of any defined borders. * </p> * <p> - * Center alignment is defined via {@link Alignment} and {@link Margin} ignored on centered dimension. + * Center alignment is defined via {@link Alignment} and {@link Margin} ignored with only center {@link Alignment} w/o {@link Alignment.Bit#Fill} scale. * </p> */ public class Margin { |