summaryrefslogtreecommitdiffstats
path: root/src/graphui/classes/com/jogamp/graph/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphui/classes/com/jogamp/graph/ui')
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/layout/Alignment.java2
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/layout/BoxLayout.java67
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/layout/GridLayout.java356
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+"]";
}
}