aboutsummaryrefslogtreecommitdiffstats
path: root/src/graphui
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-09-05 02:54:42 +0200
committerSven Gothel <[email protected]>2023-09-05 02:54:42 +0200
commitddd6cac8cc658ce542cb98e85f7d262f9917d37a (patch)
tree645516bebc945b5a853fd1ce54346d8abeb0235b /src/graphui
parentf39a084c6a34a083698ca56e9122642e839234c2 (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')
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/Group.java4
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/layout/BoxLayout.java220
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/layout/GridLayout.java145
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/layout/Margin.java127
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+"]"; }
}