summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--make/scripts/tests.sh3
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java28
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBox01.java (renamed from src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo12.java)161
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutGrid01.java503
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03.java2
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03b.java48
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo11.java5
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java48
-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
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/FontViewListener01.java5
12 files changed, 1072 insertions, 156 deletions
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index f30de91fd..847704e46 100644
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -1032,8 +1032,9 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.demos.graph.ui.UISceneDemo03b $*
#testnoawt com.jogamp.opengl.demos.graph.ui.UISceneDemo10 $*
#testnoawt com.jogamp.opengl.demos.graph.ui.UISceneDemo11 $*
-testnoawt com.jogamp.opengl.demos.graph.ui.UISceneDemo12 $*
#testnoawt com.jogamp.opengl.demos.graph.ui.UISceneDemo20 $*
+testnoawt com.jogamp.opengl.demos.graph.ui.UILayoutGrid01 $*
+#testnoawt com.jogamp.opengl.demos.graph.ui.UILayoutBox01 $*
#testnoawt com.jogamp.opengl.demos.graph.ui.FontView01 $*
#testnoawt com.jogamp.opengl.test.junit.graph.TestTextRendererNEWT21 $*
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java
index 8803fbf14..a8d82fcc4 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java
@@ -40,8 +40,9 @@ import com.jogamp.graph.font.FontScale;
import com.jogamp.graph.ui.Group;
import com.jogamp.graph.ui.Scene;
import com.jogamp.graph.ui.Shape;
+import com.jogamp.graph.ui.layout.Alignment;
+import com.jogamp.graph.ui.layout.Gap;
import com.jogamp.graph.ui.layout.GridLayout;
-import com.jogamp.graph.ui.layout.Padding;
import com.jogamp.graph.ui.shapes.GlyphShape;
import com.jogamp.graph.ui.shapes.Label;
import com.jogamp.graph.ui.shapes.Rectangle;
@@ -62,11 +63,11 @@ import com.jogamp.opengl.util.Animator;
* This may become a little font viewer application, having FontForge as its role model.
*/
public class FontView01 {
- private static float gridWidth = 2/3f;
+ private static float GlyphGridWidth = 2/3f;
static GraphUIDemoArgs options = new GraphUIDemoArgs(1280, 720, Region.VBAA_RENDERING_BIT);
public static void main(final String[] args) throws IOException {
- float mmPerCell = 10f;
+ float mmPerCell = 8f;
String fontfilename = null;
int gridCols = -1;
int gridRows = -1;
@@ -153,15 +154,16 @@ public class FontView01 {
System.err.println("mmPerCell "+mmPerCell);
}
if( 0 >= gridCols ) {
- gridCols = (int)( ( window.getSurfaceWidth() * gridWidth / ppmm[0] ) / mmPerCell );
+ gridCols = (int)( ( window.getSurfaceWidth() * GlyphGridWidth / ppmm[0] ) / mmPerCell );
}
if( 0 >= gridRows ) {
gridRows = (int)( ( window.getSurfaceHeight() / ppmm[1] ) / mmPerCell );
}
final int cellCount = gridCols * gridRows;
+
final float gridSize = gridCols > gridRows ? 1f/gridCols : 1f/gridRows;
System.err.println("Grid "+gridCols+" x "+gridRows+", "+cellCount+" cells, gridSize "+gridSize);
- final Group mainGrid = new Group(new GridLayout(gridCols, gridSize, gridSize, new Padding(gridSize*0.05f, gridSize*0.05f)));
+ final Group mainGrid = new Group(new GridLayout(gridCols, gridSize, gridSize, Alignment.Fill, new Gap(gridSize*0.10f)));
final Group glyphCont = new Group();
{
@@ -175,7 +177,7 @@ public class FontView01 {
glyphInfo.setColor(0.1f, 0.1f, 0.1f, 1.0f);
infoCont.addShape(glyphInfo);
}
- final Group infoGrid = new Group(new GridLayout(1/2f, 1/2f, new Padding(1/2f*0.005f, 1/2f*0.005f), 2));
+ final Group infoGrid = new Group(new GridLayout(1/2f, 1/2f, Alignment.Fill, new Gap(1/2f*0.01f), 2));
infoGrid.addShape(glyphCont);
infoGrid.addShape(infoCont);
@@ -243,19 +245,19 @@ public class FontView01 {
final AABBox sceneBox = scene.getBounds();
System.err.println("SceneBox "+sceneBox);
final AABBox mainGridBox = mainGrid.getBounds();
- final float sgxy;
- if( mainGridBox.getWidth() > mainGridBox.getHeight() ) {
- sgxy = sceneBox.getWidth() * gridWidth / mainGridBox.getWidth();
- } else {
- sgxy = sceneBox.getHeight() / mainGridBox.getHeight();
+ final float sxy;
+ {
+ final float sx = sceneBox.getWidth() * GlyphGridWidth / mainGridBox.getWidth();
+ final float sy = sceneBox.getHeight() / mainGridBox.getHeight();
+ sxy = sx < sy ? sx : sy;
}
- mainGrid.scale(sgxy, sgxy, 1f);
+ mainGrid.scale(sxy, sxy, 1f);
mainGrid.moveTo(sceneBox.getMinX(), sceneBox.getMinY(), 0f);
scene.addShape(mainGrid); // late add at correct position and size
System.err.println("Grid "+mainGrid);
System.err.println("Grid "+mainGrid.getLayout());
System.err.println("Grid[0] "+mainGrid.getShapes().get(0));
- final float rightWidth = sceneBox.getWidth() * ( 1f - gridWidth );
+ final float rightWidth = sceneBox.getWidth() * ( 1f - GlyphGridWidth );
{
final float icScale = sceneBox.getHeight();
infoGrid.validate(reqGLP);
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo12.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBox01.java
index 4a0fa9a90..754614ed4 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo12.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBox01.java
@@ -36,14 +36,15 @@ import com.jogamp.graph.font.FontSet;
import com.jogamp.graph.ui.Group;
import com.jogamp.graph.ui.Scene;
import com.jogamp.graph.ui.Shape;
+import com.jogamp.graph.ui.Scene.PMVMatrixSetup;
import com.jogamp.graph.ui.layout.BoxLayout;
-import com.jogamp.graph.ui.layout.GridLayout;
import com.jogamp.graph.ui.layout.Margin;
import com.jogamp.graph.ui.layout.Padding;
import com.jogamp.graph.ui.shapes.Button;
import com.jogamp.graph.ui.shapes.Label;
import com.jogamp.graph.ui.shapes.Rectangle;
import com.jogamp.graph.ui.shapes.BaseButton;
+import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.opengl.GLWindow;
@@ -51,19 +52,58 @@ import com.jogamp.opengl.GL;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.demos.graph.ui.util.GraphUIDemoArgs;
+import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.Recti;
+import com.jogamp.opengl.math.Vec3f;
import com.jogamp.opengl.math.geom.AABBox;
import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.PMVMatrix;
/**
- * Res independent {@link Shape}s in a {@link Group} using a {@link GridLayout}, contained within a Scene attached to GLWindow.
+ * Res independent {@link Shape}s in a {@link Group} using a {@link BoxLayout}, contained within a Scene attached to GLWindow.
* <p>
* Pass '-keep' to main-function to keep running after animation,
* then user can test Shape drag-move and drag-resize w/ 1-pointer.
* </p>
*/
-public class UISceneDemo12 {
+public class UILayoutBox01 {
static GraphUIDemoArgs options = new GraphUIDemoArgs(1280, 720, Region.VBAA_RENDERING_BIT);
+ /**
+ * Our PMVMatrixSetup:
+ * - gluPerspective like Scene's default
+ * - no normal scale to 1, keep a longer distance to near plane for rotation effects. We scale Shapes
+ */
+ public static class MyPMVMatrixSetup implements PMVMatrixSetup {
+ static float Z_DIST = -1f;
+ @Override
+ public void set(final PMVMatrix pmv, final Recti viewport) {
+ final float ratio = (float)viewport.width()/(float)viewport.height();
+ pmv.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmv.glLoadIdentity();
+ pmv.gluPerspective(Scene.DEFAULT_ANGLE, ratio, Scene.DEFAULT_ZNEAR, Scene.DEFAULT_ZFAR);
+ pmv.glTranslatef(0f, 0f, Z_DIST); // Scene.DEFAULT_SCENE_DIST);
+
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmv.glLoadIdentity();
+ }
+
+ @Override
+ public void setPlaneBox(final AABBox planeBox, final PMVMatrix pmv, final Recti viewport) {
+ final float orthoDist = -Z_DIST; // Scene.DEFAULT_SCENE_DIST;
+ final Vec3f obj00Coord = new Vec3f();
+ final Vec3f obj11Coord = new Vec3f();
+
+ Scene.winToPlaneCoord(pmv, viewport, Scene.DEFAULT_ZNEAR, Scene.DEFAULT_ZFAR, viewport.x(), viewport.y(), orthoDist, obj00Coord);
+ Scene.winToPlaneCoord(pmv, viewport, Scene.DEFAULT_ZNEAR, Scene.DEFAULT_ZFAR, viewport.width(), viewport.height(), orthoDist, obj11Coord);
+
+ planeBox.setSize( obj00Coord, obj11Coord );
+ }
+ };
+
+ static final boolean reLayout = false;
+
public static void main(final String[] args) throws IOException {
if( 0 != args.length ) {
final int[] idx = { 0 };
@@ -90,11 +130,11 @@ public class UISceneDemo12 {
final GLWindow window = GLWindow.create(caps);
window.setSize(options.surface_width, options.surface_height);
- window.setTitle(UISceneDemo12.class.getSimpleName()+": "+window.getSurfaceWidth()+" x "+window.getSurfaceHeight());
+ window.setTitle(UILayoutBox01.class.getSimpleName()+": "+window.getSurfaceWidth()+" x "+window.getSurfaceHeight());
window.addWindowListener(new WindowAdapter() {
@Override
public void windowResized(final WindowEvent e) {
- window.setTitle(UISceneDemo12.class.getSimpleName()+": "+window.getSurfaceWidth()+" x "+window.getSurfaceHeight());
+ window.setTitle(UILayoutBox01.class.getSimpleName()+": "+window.getSurfaceWidth()+" x "+window.getSurfaceHeight());
}
@Override
public void windowDestroyNotify(final WindowEvent e) {
@@ -104,6 +144,7 @@ public class UISceneDemo12 {
final Scene scene = new Scene();
+ scene.setPMVMatrixSetup(new MyPMVMatrixSetup());
scene.setClearParams(new float[] { 1f, 1f, 1f, 1f}, GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
scene.setFrustumCullingEnabled(true);
scene.attachInputListenerTo(window);
@@ -114,6 +155,23 @@ public class UISceneDemo12 {
animator.setUpdateFPSFrames(1*60, null); // System.err);
animator.add(window);
animator.start();
+
+ /**
+ * We can share this instance w/ all UI elements,
+ * since only mouse action / gesture is complete for a single one (press, drag, released and click).
+ */
+ final Shape.MouseGestureAdapter dragZoomRotateListener = new Shape.MouseGestureAdapter() {
+ @Override
+ public void mouseWheelMoved(final MouseEvent e) {
+ final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment();
+ final Shape shape = shapeEvent.shape;
+ final Vec3f rot = new Vec3f(e.getRotation()).scale( FloatUtil.PI / 180.0f );
+ // swap axis for onscreen rotation matching natural feel
+ final float tmp = rot.x(); rot.setX( rot.y() ); rot.setY( tmp );
+ shape.getRotation().rotateByEuler( rot.scale( 2f ) );
+ }
+ };
+
//
// Resolution independent, no screen size
//
@@ -123,16 +181,17 @@ public class UISceneDemo12 {
final AABBox sceneBox = scene.getBounds();
System.err.println("SceneBox "+sceneBox);
- final float sxy = 1/8f;
+ final float sxy = 1/8f * sceneBox.getWidth();
float nextPos = 0;
final Group groupA0 = new Group(new BoxLayout( new Padding(0.15f, 0.15f) ) );
{
groupA0.addShape( new BaseButton(options.renderModes, 0.70f, 0.70f).setCorner(0f).setInteractive(false).setColor(0, 1, 0, 1) );
- groupA0.addShape( new Button(options.renderModes, font, "stack1", 0.50f, 0.50f/2f).setCorner(0f).setDragAndResizeable(false) );
- groupA0.addShape( new Label(options.renderModes, font, 0.70f/4f, "pajq").setDragAndResizeable(false).setColor(0, 0, 1, 1) );
+ groupA0.addShape( new Button(options.renderModes, font, "stack-0", 0.50f, 0.50f/2f).setCorner(0f).setDragAndResizeable(false) );
+ groupA0.addShape( new Label(options.renderModes, font, 0.70f/4f, "A0 pajq").setDragAndResizeable(false).setColor(0, 0, 1, 1) );
}
groupA0.setInteractive(true);
+ groupA0.addMouseListener(dragZoomRotateListener);
groupA0.scale(sxy, sxy, 1);
groupA0.moveTo(sceneBox.getLow()).move(nextPos, 0, 0);
groupA0.validate(reqGLP);
@@ -145,11 +204,13 @@ public class UISceneDemo12 {
final Group groupA1 = new Group(new BoxLayout( 1f, 1f, new Margin(0.05f, 0.05f), new Padding(0.10f, 0.10f) ) );
{
- groupA1.addShape( new BaseButton(options.renderModes, 0.70f, 0.70f).setCorner(0f).setInteractive(false).setColor(0, 1, 0, 1) );
- groupA1.addShape( new Button(options.renderModes, font, "stack2", 0.50f, 0.50f/2f).setCorner(0f).setDragAndResizeable(false) );
- groupA1.addShape( new Label(options.renderModes, font, 0.70f/4f, "pajq").setDragAndResizeable(false).setColor(0, 0, 1, 1) );
+ // groupA1.addShape( new BaseButton(options.renderModes, 0.70f, 0.70f).setCorner(0f).setInteractive(false).setColor(0, 1, 0, 1) );
+ groupA1.addShape( new BaseButton(options.renderModes | Region.COLORCHANNEL_RENDERING_BIT, 0.70f, 0.70f).setCorner(0f).setInteractive(false).setColor(0, 1, 0, 1)
+ .setBorder(0.01f).setPaddding(new Padding(0.0f)) );
+ groupA1.addShape( new Button(options.renderModes, font, "stack-1", 0.50f, 0.50f/2f).setCorner(0f).addMouseListener(dragZoomRotateListener) );
+ groupA1.addShape( new Label(options.renderModes, font, 0.70f/4f, "A1 pajq").setDragAndResizeable(false).setColor(0, 0, 1, 1) );
}
- groupA1.setInteractive(true);
+ // groupA1.setInteractive(true);
groupA1.scale(sxy, sxy, 1);
groupA1.moveTo(sceneBox.getLow()).move(nextPos, 0, 0);
groupA1.validate(reqGLP);
@@ -157,14 +218,20 @@ public class UISceneDemo12 {
System.err.println("Group-A1 Layout "+groupA1.getLayout());
groupA1.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
scene.addShape(groupA1);
- scene.addShape( new Rectangle(options.renderModes, 1f, 1f, 0.01f).scale(sxy, sxy, 1).moveTo(sceneBox.getLow()).move(nextPos, 0, 0).setInteractive(false).setColor(0, 0, 0, 1) );
+ // scene.addShape( new Rectangle(options.renderModes, 1f, 1f, 0.01f).scale(sxy, sxy, 1).moveTo(sceneBox.getLow()).move(nextPos, 0, 0).setInteractive(false).setColor(0, 0, 0, 1) );
+ scene.addShape( new Button(options.renderModes, font, "stack-1b", 0.50f, 0.50f/2f).setCorner(0f)
+ .scale(sxy, sxy, 1f).moveTo(sceneBox.getLow()).move(nextPos, groupA1.getScaledHeight(), 0)
+ .addMouseListener(dragZoomRotateListener) );
+
nextPos += groupA1.getScaledWidth() * 1.5f;
final Group groupA2 = new Group(new BoxLayout( 1f, 1f, new Margin(0.10f, Margin.CENTER), new Padding(0.05f, 0) ) );
{
- groupA2.addShape( new BaseButton(options.renderModes, 0.70f, 0.70f).setCorner(0f).setInteractive(false).setColor(0, 1, 0, 1) );
- groupA2.addShape( new Button(options.renderModes, font, "stack3", 0.50f, 0.50f/2f).setCorner(0f).setDragAndResizeable(false) );
- groupA2.addShape( new Label(options.renderModes, font, 0.70f/4f, "pajq").setDragAndResizeable(false).setColor(0, 0, 1, 1) );
+ // groupA2.addShape( new BaseButton(options.renderModes, 0.70f, 0.70f).setCorner(0f).setInteractive(false).setColor(0, 1, 0, 1) );
+ groupA2.addShape( new BaseButton(options.renderModes | Region.COLORCHANNEL_RENDERING_BIT, 0.70f, 0.70f).setCorner(0f).setInteractive(false).setColor(0, 1, 0, 1)
+ .setBorder(0.01f).setPaddding(new Padding(0.0f)).setBorderColor(1, 0, 0, 1) );
+ groupA2.addShape( new Button(options.renderModes, font, "stack-2", 0.50f, 0.50f/2f).setCorner(0f).setDragAndResizeable(false) );
+ groupA2.addShape( new Label(options.renderModes, font, 0.70f/4f, "A2 pajq").setDragAndResizeable(false).setColor(0, 0, 1, 1) );
}
groupA2.setInteractive(true);
groupA2.scale(sxy, sxy, 1);
@@ -174,48 +241,58 @@ public class UISceneDemo12 {
System.err.println("Group-A2 Layout "+groupA2.getLayout());
groupA2.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
scene.addShape(groupA2);
- scene.addShape( new Rectangle(options.renderModes, 1f, 1f, 0.01f).scale(sxy, sxy, 1).moveTo(sceneBox.getLow()).move(nextPos, 0, 0).setInteractive(false).setColor(0, 0, 0, 1) );
+ // scene.addShape( new Rectangle(options.renderModes, 1f, 1f, 0.01f).scale(sxy, sxy, 1).moveTo(sceneBox.getLow()).move(nextPos, 0, 0).setInteractive(false).setColor(0, 0, 0, 1) );
nextPos += groupA2.getScaledWidth() * 1.5f;
- final Group groupA3 = new Group(new BoxLayout( 1f, 1f, new Margin(Margin.CENTER) ) );
+ final Group groupA3 = new Group(new BoxLayout( 1f, 1f, new Margin(0.10f, Margin.CENTER), new Padding(0.05f, 0f) ) );
{
- groupA3.addShape( new BaseButton(options.renderModes, 0.70f, 0.70f).setCorner(0f).setInteractive(false).setColor(0, 1, 0, 1) );
- groupA3.addShape( new Button(options.renderModes, font, "stack4", 0.50f, 0.50f/2f).setCorner(0f).setDragAndResizeable(false) );
- groupA3.addShape( new Label(options.renderModes, font, 0.70f/4f, "pajq").setDragAndResizeable(false).setColor(0, 0, 1, 1) );
+ // groupA3.addShape( new BaseButton(options.renderModes, 0.70f, 0.70f).setCorner(0f).setInteractive(false).setColor(0, 1, 0, 1) );
+ groupA3.addShape( new BaseButton(options.renderModes | Region.COLORCHANNEL_RENDERING_BIT, 0.70f, 0.70f).setCorner(0f).setInteractive(false).setColor(0, 1, 0, 1)
+ .setBorder(0.01f).setPaddding(new Padding(0.0f)).setBorderColor(0, 0, 1, 1) );
+ groupA3.addShape( new Button(options.renderModes, font, "stack-3", 0.50f, 0.50f/2f).setCorner(0f).setDragAndResizeable(false) );
+ groupA3.addShape( new Label(options.renderModes, font, 0.70f/4f, "A3 pajq").setDragAndResizeable(false).setColor(0, 0, 1, 1) );
}
- groupA3.setInteractive(true);
groupA3.scale(sxy, sxy, 1);
groupA3.moveTo(sceneBox.getLow()).move(nextPos, 0, 0);
groupA3.validate(reqGLP);
- System.err.println("Group-A1 "+groupA3);
- System.err.println("Group-A1 Layout "+groupA3.getLayout());
+ System.err.println("Group-A3 "+groupA3);
+ System.err.println("Group-A3 Layout "+groupA3.getLayout());
groupA3.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
scene.addShape(groupA3);
- scene.addShape( new Rectangle(options.renderModes, 1f, 1f, 0.01f).scale(sxy, sxy, 1).moveTo(sceneBox.getLow()).move(nextPos, 0, 0).setInteractive(false).setColor(0, 0, 0, 1) );
+ // scene.addShape( new Rectangle(options.renderModes, 1f, 1f, 0.01f).scale(sxy, sxy, 1).moveTo(sceneBox.getLow()).move(nextPos, 0, 0).setInteractive(false).setColor(0, 0, 0, 1) );
nextPos += groupA3.getScaledWidth() * 1.5f;
+ final Group groupA4 = new Group(new BoxLayout( 1f, 1f, new Margin(Margin.CENTER), new Padding(0.0f, 0f) ) );
+ {
+ // groupA4.addShape( new BaseButton(options.renderModes, 0.70f, 0.70f).setCorner(0f).setInteractive(false).setColor(0, 1, 0, 1) );
+ groupA4.addShape( new BaseButton(options.renderModes | Region.COLORCHANNEL_RENDERING_BIT, 0.70f, 0.70f).setCorner(0f).setInteractive(false).setColor(0, 1, 0, 1)
+ .setBorder(0.01f).setPaddding(new Padding(0.0f)).setBorderColor(0f, 0f, 0f, 1) );
+ groupA4.addShape( new Button(options.renderModes, font, "stack-4", 0.50f, 0.50f/2f).setCorner(0f).setDragAndResizeable(false) );
+ groupA4.addShape( new Label(options.renderModes, font, 0.70f/4f, "A4 pajq").setDragAndResizeable(false).setColor(0, 0, 1, 1) );
+ }
+ groupA4.scale(sxy, sxy, 1);
+ groupA4.moveTo(sceneBox.getLow()).move(nextPos, 0, 0);
+ groupA4.validate(reqGLP);
+ System.err.println("Group-A4 "+groupA4);
+ System.err.println("Group-A4 Layout "+groupA4.getLayout());
+ groupA4.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ scene.addShape(groupA4);
+ // scene.addShape( new Rectangle(options.renderModes, 1f, 1f, 0.01f).scale(sxy, sxy, 1).moveTo(sceneBox.getLow()).move(nextPos, 0, 0).setInteractive(false).setColor(0, 0, 0, 1) );
+ nextPos += groupA4.getScaledWidth() * 1.5f;
+
+ if( reLayout ) {
+ try { Thread.sleep(1000); } catch (final InterruptedException e1) { }
+ groupA4.markShapeDirty();
+ groupA4.validate(reqGLP);
+ System.err.println("Group-A4.2 "+groupA4);
+ System.err.println("Group-A4 Layout.2 "+groupA4.getLayout());
+ }
+
//
//
//
nextPos = 0;
- final Group groupB0 = new Group(new GridLayout(2, 1f, 1/2f, new Padding(0.05f, 0.05f)));
- {
- groupB0.addShape( new Button(options.renderModes, font, "r1 c1", 1f, 1f/2f).setCorner(0f).setDragAndResizeable(false) );
- groupB0.addShape( new Button(options.renderModes, font, "r1 c2", 1f, 1f/2f).setCorner(0f).setDragAndResizeable(false) );
- groupB0.addShape( new Button(options.renderModes, font, "r2 c1", 1f, 1f/2f).setCorner(0f).setDragAndResizeable(false) );
- groupB0.addShape( new Button(options.renderModes, font, "r2 c2", 1f, 1f/2f).setCorner(0f).setDragAndResizeable(false) );
- }
- groupB0.setInteractive(true);
- groupB0.scale(sxy, sxy, 1);
- groupB0.moveTo(sceneBox.getLow()).move(nextPos, sceneBox.getHeight()/2f, 0);
- groupB0.validate(reqGLP);
- System.err.println("Group-B0 "+groupB0);
- System.err.println("Group-B0 Layout "+groupB0.getLayout());
- groupB0.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
- scene.addShape(groupB0);
- nextPos = groupB0.getScaledWidth() * 1.5f;
-
try { Thread.sleep(1000); } catch (final InterruptedException e1) { }
if( !options.stayOpen ) {
window.destroy();
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutGrid01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutGrid01.java
new file mode 100644
index 000000000..a62a5a65a
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutGrid01.java
@@ -0,0 +1,503 @@
+/**
+ * Copyright 2010-2023 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.demos.graph.ui;
+
+import java.io.IOException;
+
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.font.Font;
+import com.jogamp.graph.font.FontFactory;
+import com.jogamp.graph.font.FontSet;
+import com.jogamp.graph.ui.Group;
+import com.jogamp.graph.ui.Scene;
+import com.jogamp.graph.ui.Shape;
+import com.jogamp.graph.ui.Scene.PMVMatrixSetup;
+import com.jogamp.graph.ui.layout.Alignment;
+import com.jogamp.graph.ui.layout.Gap;
+import com.jogamp.graph.ui.layout.GridLayout;
+import com.jogamp.graph.ui.layout.Padding;
+import com.jogamp.graph.ui.shapes.Button;
+import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GLCapabilities;
+import com.jogamp.opengl.GLProfile;
+import com.jogamp.opengl.demos.graph.ui.util.GraphUIDemoArgs;
+import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.Recti;
+import com.jogamp.opengl.math.Vec3f;
+import com.jogamp.opengl.math.Vec4f;
+import com.jogamp.opengl.math.geom.AABBox;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.PMVMatrix;
+
+/**
+ * Res independent {@link Shape}s in a {@link Group} using a {@link GridLayout}, contained within a Scene attached to GLWindow.
+ * <p>
+ * Pass '-keep' to main-function to keep running after animation,
+ * then user can test Shape drag-move and drag-resize w/ 1-pointer.
+ * </p>
+ */
+public class UILayoutGrid01 {
+ static GraphUIDemoArgs options = new GraphUIDemoArgs(1280, 720, Region.VBAA_RENDERING_BIT);
+
+ /**
+ * Our PMVMatrixSetup:
+ * - gluPerspective like Scene's default
+ * - no normal scale to 1, keep a longer distance to near plane for rotation effects. We scale Shapes
+ */
+ public static class MyPMVMatrixSetup implements PMVMatrixSetup {
+ static float Z_DIST = -1f;
+ @Override
+ public void set(final PMVMatrix pmv, final Recti viewport) {
+ final float ratio = (float)viewport.width()/(float)viewport.height();
+ pmv.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmv.glLoadIdentity();
+ pmv.gluPerspective(Scene.DEFAULT_ANGLE, ratio, Scene.DEFAULT_ZNEAR, Scene.DEFAULT_ZFAR);
+ pmv.glTranslatef(0f, 0f, Z_DIST); // Scene.DEFAULT_SCENE_DIST);
+
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmv.glLoadIdentity();
+ }
+
+ @Override
+ public void setPlaneBox(final AABBox planeBox, final PMVMatrix pmv, final Recti viewport) {
+ final float orthoDist = -Z_DIST; // Scene.DEFAULT_SCENE_DIST;
+ final Vec3f obj00Coord = new Vec3f();
+ final Vec3f obj11Coord = new Vec3f();
+
+ Scene.winToPlaneCoord(pmv, viewport, Scene.DEFAULT_ZNEAR, Scene.DEFAULT_ZFAR, viewport.x(), viewport.y(), orthoDist, obj00Coord);
+ Scene.winToPlaneCoord(pmv, viewport, Scene.DEFAULT_ZNEAR, Scene.DEFAULT_ZFAR, viewport.width(), viewport.height(), orthoDist, obj11Coord);
+
+ planeBox.setSize( obj00Coord, obj11Coord );
+ }
+ };
+
+ static final boolean reLayout = false;
+ static final int reLayoutSleep = 500;
+
+ public static void main(final String[] args) throws IOException {
+ if( 0 != args.length ) {
+ final int[] idx = { 0 };
+ for (idx[0] = 0; idx[0] < args.length; ++idx[0]) {
+ if( options.parse(args, idx) ) {
+ continue;
+ }
+ }
+ }
+ options.renderModes |= Region.COLORCHANNEL_RENDERING_BIT;
+ System.err.println(options);
+
+ final GLProfile reqGLP = GLProfile.get(options.glProfileName);
+ System.err.println("GLProfile: "+reqGLP);
+
+ final Animator animator = new Animator();
+
+ final GLCapabilities caps = new GLCapabilities(reqGLP);
+ caps.setAlphaBits(4);
+ if( options.sceneMSAASamples > 0 ) {
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(options.sceneMSAASamples);
+ }
+ System.out.println("Requested: " + caps);
+
+ final GLWindow window = GLWindow.create(caps);
+ window.setSize(options.surface_width, options.surface_height);
+ window.setTitle(UILayoutGrid01.class.getSimpleName()+": "+window.getSurfaceWidth()+" x "+window.getSurfaceHeight());
+ window.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowResized(final WindowEvent e) {
+ window.setTitle(UILayoutGrid01.class.getSimpleName()+": "+window.getSurfaceWidth()+" x "+window.getSurfaceHeight());
+ }
+ @Override
+ public void windowDestroyNotify(final WindowEvent e) {
+ animator.stop();
+ }
+ });
+
+
+ final Scene scene = new Scene();
+ scene.setPMVMatrixSetup(new MyPMVMatrixSetup());
+ scene.setClearParams(new float[] { 1f, 1f, 1f, 1f}, GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ scene.setFrustumCullingEnabled(true);
+ scene.attachInputListenerTo(window);
+ window.addGLEventListener(scene);
+ window.setVisible(true);
+ scene.waitUntilDisplayed();
+
+ animator.setUpdateFPSFrames(1*60, null); // System.err);
+ animator.add(window);
+ animator.start();
+
+ /**
+ * We can share this instance w/ all UI elements,
+ * since only mouse action / gesture is complete for a single one (press, drag, released and click).
+ */
+ final Shape.MouseGestureAdapter dragZoomRotateListener = new Shape.MouseGestureAdapter() {
+ @Override
+ public void mouseWheelMoved(final MouseEvent e) {
+ final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment();
+ final Shape shape = shapeEvent.shape;
+ final Vec3f rot = new Vec3f(e.getRotation()).scale( FloatUtil.PI / 180.0f );
+ // swap axis for onscreen rotation matching natural feel
+ final float tmp = rot.x(); rot.setX( rot.y() ); rot.setY( tmp );
+ shape.getRotation().rotateByEuler( rot.scale( 2f ) );
+ }
+ };
+
+ //
+ // Resolution independent, no screen size
+ //
+ final Font font = FontFactory.get(FontFactory.UBUNTU).get(FontSet.FAMILY_LIGHT, FontSet.STYLE_SERIF);
+ System.err.println("Font: "+font.getFullFamilyName());
+
+ final AABBox sceneBox = scene.getBounds();
+ System.err.println("SceneBox "+sceneBox);
+
+ final Vec4f borderColor = new Vec4f(0, 0, 1f, 0.6f);
+ final float borderThickness = 0.01f;
+ final float sxy = 1/10f * sceneBox.getWidth();
+ float nextXPos = 0, nextYTop = sceneBox.getHeight();
+
+ final Group groupA0 = new Group(new GridLayout(1, 1f, 1/2f, Alignment.Fill, new Gap(0.10f)));
+ groupA0.addShape( new Button(options.renderModes, font, "ro co", 1f, 1f/2f).setCorner(0f).setBorder(borderThickness).addMouseListener(dragZoomRotateListener) );
+ groupA0.setBorder(borderThickness).setBorderColor(borderColor);
+ groupA0.scale(sxy, sxy, 1);
+ groupA0.setInteractive(true);
+ groupA0.validate(reqGLP);
+ groupA0.moveTo(sceneBox.getLow()).move(nextXPos, nextYTop-groupA0.getScaledHeight(), 0);
+ System.err.println("Group-A0 "+groupA0);
+ System.err.println("Group-A0 Layout "+groupA0.getLayout());
+ groupA0.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ scene.addShape(groupA0);
+ nextXPos += groupA0.getScaledWidth() * 1.1f;
+ if( reLayout ) {
+ try { Thread.sleep(reLayoutSleep); } catch (final InterruptedException e1) { }
+ groupA0.markShapeDirty();
+ groupA0.validate(reqGLP);
+ System.err.println("Group-A0.2 "+groupA0);
+ System.err.println("Group-A0 Layout.2 "+groupA0.getLayout());
+ groupA0.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ }
+
+ final Group groupA1 = new Group(new GridLayout(1, 1, 1/2f, Alignment.Fill, new Gap(0.10f)));
+ groupA1.addShape( new Button(options.renderModes, font, "ro co", 1f, 1/2f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ groupA1.addShape( new Button(options.renderModes, font, "r1 r1", 1f, 1/2f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ groupA1.setBorder(sxy*borderThickness).setBorderColor(borderColor);
+ groupA1.scale(sxy, sxy, 1);
+ groupA1.setInteractive(true);
+ groupA1.validate(reqGLP);
+ groupA1.moveTo(sceneBox.getLow()).move(nextXPos, nextYTop-groupA1.getScaledHeight(), 0);
+ System.err.println("Group-A1 "+groupA1);
+ System.err.println("Group-A1 Layout "+groupA1.getLayout());
+ groupA1.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ scene.addShape(groupA1);
+ nextXPos += groupA1.getScaledWidth() * 1.1f;
+ if( reLayout ) {
+ try { Thread.sleep(reLayoutSleep); } catch (final InterruptedException e1) { }
+ groupA1.markShapeDirty();
+ groupA1.validate(reqGLP);
+ System.err.println("Group-A1.2 "+groupA1);
+ System.err.println("Group-A1 Layout.2 "+groupA1.getLayout());
+ groupA1.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ }
+
+ final Group groupA2 = new Group(new GridLayout(1, 1/2f, Alignment.Fill, new Gap(0.10f), 1));
+ groupA2.addShape( new Button(options.renderModes, font, "ro co", 1f, 1/2f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ groupA2.addShape( new Button(options.renderModes, font, "r1 c1", 1f, 1/2f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ groupA2.setBorder(sxy*borderThickness).setBorderColor(borderColor);
+ groupA2.scale(sxy, sxy, 1);
+ groupA2.setInteractive(true);
+ groupA2.validate(reqGLP);
+ groupA2.moveTo(sceneBox.getLow()).move(nextXPos, nextYTop-groupA2.getScaledHeight(), 0);
+ System.err.println("Group-A2 "+groupA2);
+ System.err.println("Group-A2 Layout "+groupA2.getLayout());
+ groupA2.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ scene.addShape(groupA2);
+ nextXPos += groupA2.getScaledWidth() * 1.1f;
+ if( reLayout ) {
+ try { Thread.sleep(reLayoutSleep); } catch (final InterruptedException e1) { }
+ groupA2.markShapeDirty();
+ groupA2.validate(reqGLP);
+ System.err.println("Group-A2.2 "+groupA2);
+ System.err.println("Group-A2 Layout.2 "+groupA2.getLayout());
+ groupA2.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ }
+
+ final Group groupA3 = new Group(new GridLayout(2, 1f, 1/2f, Alignment.Fill, new Gap(0.10f)));
+ {
+ groupA3.addShape( new Button(options.renderModes, font, "ro co", 1f, 1f/2f).setCorner(0f).setBorder(borderThickness).addMouseListener(dragZoomRotateListener) );
+ groupA3.addShape( new Button(options.renderModes, font, "r1 c2", 1f, 1f/2f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ groupA3.addShape( new Button(options.renderModes, font, "r2 c1", 1f, 1f/2f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ groupA3.addShape( new Button(options.renderModes, font, "r2 c2", 1f, 1f/2f).setCorner(0f).setBorder(borderThickness).addMouseListener(dragZoomRotateListener) );
+ }
+ groupA3.setBorder(borderThickness).setBorderColor(borderColor);
+ groupA3.scale(sxy, sxy, 1);
+ groupA3.setInteractive(true);
+ groupA3.validate(reqGLP);
+ groupA3.moveTo(sceneBox.getLow()).move(nextXPos, nextYTop-groupA3.getScaledHeight(), 0);
+ System.err.println("Group-A3 "+groupA3);
+ System.err.println("Group-A3 Layout "+groupA3.getLayout());
+ groupA3.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ scene.addShape(groupA3);
+ nextXPos += groupA3.getScaledWidth() * 1.1f;
+ if( reLayout ) {
+ try { Thread.sleep(reLayoutSleep); } catch (final InterruptedException e1) { }
+ groupA3.markShapeDirty();
+ groupA3.validate(reqGLP);
+ System.err.println("Group-A3.2 "+groupA3);
+ System.err.println("Group-A3 Layout.2 "+groupA3.getLayout());
+ groupA3.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ }
+
+ final Group groupA4 = new Group(new GridLayout(2, 1f, 1/2f, Alignment.Fill, new Gap(0.10f)));
+ {
+ groupA4.addShape( new Button(options.renderModes, font, "ro co", 1f, 1f/2f).setCorner(0f).setBorder(borderThickness).addMouseListener(dragZoomRotateListener) );
+ groupA4.addShape( new Button(options.renderModes, font, "r1 c2", 1f, 1f/2f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ groupA4.addShape( new Button(options.renderModes, font, "r2 c1", 1f, 1f/2f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ groupA4.addShape( new Button(options.renderModes, font, "r2 c2", 1f, 1f/2f).setCorner(0f).setBorder(borderThickness).addMouseListener(dragZoomRotateListener) );
+ groupA4.addShape( new Button(options.renderModes, font, "r3 c1", 1f, 1f/2f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ }
+ groupA4.setBorder(borderThickness).setBorderColor(borderColor);
+ groupA4.scale(sxy, sxy, 1);
+ groupA4.setInteractive(true);
+ groupA4.validate(reqGLP);
+ groupA4.moveTo(sceneBox.getLow()).move(nextXPos, nextYTop-groupA4.getScaledHeight(), 0);
+ System.err.println("Group-A4 "+groupA4);
+ System.err.println("Group-A4 Layout "+groupA4.getLayout());
+ groupA4.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ scene.addShape(groupA4);
+ nextXPos += groupA4.getScaledWidth() * 1.1f;
+ if( reLayout ) {
+ try { Thread.sleep(reLayoutSleep); } catch (final InterruptedException e1) { }
+ groupA4.markShapeDirty();
+ groupA4.validate(reqGLP);
+ System.err.println("Group-A4.2 "+groupA4);
+ System.err.println("Group-A4 Layout.2 "+groupA4.getLayout());
+ groupA4.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ }
+
+ // next line
+ nextXPos = 0;
+ nextYTop = 2f*sceneBox.getHeight()/3f;
+
+ final Group groupB0 = new Group(new GridLayout(2, sxy, sxy/2f, Alignment.Fill, new Gap(sxy*0.10f)));
+ {
+ groupB0.addShape( new Button(options.renderModes, font, "ro co", 1f, 1f/2f).setCorner(0f).setBorder(borderThickness).addMouseListener(dragZoomRotateListener) );
+ groupB0.addShape( new Button(options.renderModes, font, "r1 c2", 1f, 1f/2f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ groupB0.addShape( new Button(options.renderModes, font, "r2 c1", 1f, 1f/2f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ groupB0.addShape( new Button(options.renderModes, font, "r2 c2", 1f, 1f/2f).setCorner(0f).setBorder(borderThickness).addMouseListener(dragZoomRotateListener) );
+ groupB0.addShape( new Button(options.renderModes, font, "r3 c1", 1f, 1f/2f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ }
+ groupB0.setBorder(sxy*borderThickness).setBorderColor(borderColor);
+ // groupB0.scale(2*sxy, 2*sxy, 1);
+ groupB0.setInteractive(true);
+ groupB0.validate(reqGLP);
+ groupB0.moveTo(sceneBox.getLow()).move(nextXPos, nextYTop-groupB0.getScaledHeight(), 0);
+ System.err.println("Group-B0 "+groupB0);
+ System.err.println("Group-B0 Layout "+groupB0.getLayout());
+ groupB0.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ scene.addShape(groupB0);
+ nextXPos += groupB0.getScaledWidth() * 1.1f;
+ if( reLayout ) {
+ try { Thread.sleep(reLayoutSleep); } catch (final InterruptedException e1) { }
+ groupB0.markShapeDirty();
+ groupB0.validate(reqGLP);
+ System.err.println("Group-B0.2 "+groupB0);
+ System.err.println("Group-B0 Layout.2 "+groupB0.getLayout());
+ groupB0.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ }
+
+ final Group groupB1 = new Group(new GridLayout(2, sxy, sxy/2f, Alignment.FillCenter, new Gap(sxy*0.10f)));
+ {
+ final Padding p = new Padding(0.05f);
+ groupB1.addShape( new Button(options.renderModes, font, "ro co", 1, 1/2f).setCorner(0f).setPaddding(p).setBorder(borderThickness).addMouseListener(dragZoomRotateListener) );
+ groupB1.addShape( new Button(options.renderModes, font, "r1 c2", 1, 1/2f).setCorner(0f).setPaddding(p).setBorder(borderThickness).setDragAndResizeable(false) );
+ groupB1.addShape( new Button(options.renderModes, font, "r2 c1", 1, 1/2f).setCorner(0f).setPaddding(p).setBorder(borderThickness).setDragAndResizeable(false) );
+ groupB1.addShape( new Button(options.renderModes, font, "r2 c2", 1, 1/2f).setCorner(0f).setPaddding(p).setBorder(borderThickness).addMouseListener(dragZoomRotateListener) );
+ groupB1.addShape( new Button(options.renderModes, font, "r3 c1", 1, 1/2f).setCorner(0f).setPaddding(p).setBorder(borderThickness).addMouseListener(dragZoomRotateListener) );
+ }
+ groupB1.setBorder(sxy*borderThickness).setBorderColor(borderColor);
+ // groupB1.scale(2*sxy, 2*sxy, 1);
+ groupB1.setInteractive(true);
+ groupB1.validate(reqGLP);
+ groupB1.moveTo(sceneBox.getLow()).move(nextXPos, nextYTop-groupB1.getScaledHeight(), 0);
+ System.err.println("Group-B1 "+groupB1);
+ System.err.println("Group-B1 Layout "+groupB1.getLayout());
+ groupB1.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ scene.addShape(groupB1);
+ nextXPos += groupB1.getScaledWidth() * 1.1f;
+ if( reLayout ) {
+ try { Thread.sleep(reLayoutSleep); } catch (final InterruptedException e1) { }
+ groupB1.markShapeDirty();
+ groupB1.validate(reqGLP);
+ System.err.println("Group-B1.2 "+groupB1);
+ System.err.println("Group-B1 Layout.2 "+groupB1.getLayout());
+ groupB1.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ }
+
+ final Group groupB2 = new Group(new GridLayout(2, sxy, sxy/2f, Alignment.FillCenter, new Gap(sxy*0.10f)));
+ {
+ final Padding p = new Padding(sxy/2f*0.05f);
+ groupB2.addShape( new Button(options.renderModes, font, "ro co", sxy/2f, sxy/4f).setCorner(0f).setPaddding(p).setBorder(sxy/2f*borderThickness).addMouseListener(dragZoomRotateListener) );
+ groupB2.addShape( new Button(options.renderModes, font, "r1 c2", sxy/2f, sxy/4f).setCorner(0f).setPaddding(p).setBorder(sxy/2f*borderThickness).setDragAndResizeable(false) );
+ groupB2.addShape( new Button(options.renderModes, font, "r2 c1", sxy/2f, sxy/4f).setCorner(0f).setPaddding(p).setBorder(sxy/2f*borderThickness).setDragAndResizeable(false) );
+ groupB2.addShape( new Button(options.renderModes, font, "r2 c2", sxy/2f, sxy/4f).setCorner(0f).setPaddding(p).setBorder(sxy/2f*borderThickness).addMouseListener(dragZoomRotateListener) );
+ groupB2.addShape( new Button(options.renderModes, font, "r3 c1", sxy/2f, sxy/4f).setCorner(0f).setPaddding(p).setBorder(sxy/2f*borderThickness).addMouseListener(dragZoomRotateListener) );
+ }
+ groupB2.setBorder(sxy*borderThickness).setBorderColor(borderColor);
+ // groupB2.scale(2*sxy, 2*sxy, 1);
+ groupB2.setInteractive(true);
+ groupB2.validate(reqGLP);
+ groupB2.moveTo(sceneBox.getLow()).move(nextXPos, nextYTop-groupB2.getScaledHeight(), 0);
+ System.err.println("Group-B2 "+groupB2);
+ System.err.println("Group-B2 Layout "+groupB2.getLayout());
+ groupB2.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ scene.addShape(groupB2);
+ nextXPos += groupB2.getScaledWidth() * 1.1f;
+ if( reLayout ) {
+ try { Thread.sleep(reLayoutSleep); } catch (final InterruptedException e1) { }
+ groupB2.markShapeDirty();
+ groupB2.validate(reqGLP);
+ System.err.println("Group-B2.2 "+groupB2);
+ System.err.println("Group-B2 Layout.2 "+groupB2.getLayout());
+ groupB2.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ }
+
+ final Group groupB3 = new Group(new GridLayout(2, sxy, sxy/2f, Alignment.Fill, new Gap(sxy*0.10f)));
+ {
+ final Padding p = new Padding(sxy/2f*0.05f);
+ groupB3.addShape( new Button(options.renderModes, font, "ro co", sxy/2f, sxy/4f).setCorner(0f).setPaddding(p).setBorder(sxy/2f*borderThickness).addMouseListener(dragZoomRotateListener) );
+ groupB3.addShape( new Button(options.renderModes, font, "r1 c2", sxy/2f, sxy/4f).setCorner(0f).setPaddding(p).setBorder(sxy/2f*borderThickness).setDragAndResizeable(false) );
+ groupB3.addShape( new Button(options.renderModes, font, "r2 c1", sxy/2f, sxy/4f).setCorner(0f).setPaddding(p).setBorder(sxy/2f*borderThickness).setDragAndResizeable(false) );
+ groupB3.addShape( new Button(options.renderModes, font, "r2 c2", sxy/2f, sxy/4f).setCorner(0f).setPaddding(p).setBorder(sxy/2f*borderThickness).addMouseListener(dragZoomRotateListener) );
+ groupB3.addShape( new Button(options.renderModes, font, "r3 c1", sxy/2f, sxy/4f).setCorner(0f).setPaddding(p).setBorder(sxy/2f*borderThickness).addMouseListener(dragZoomRotateListener) );
+ }
+ groupB3.setBorder(sxy*borderThickness).setBorderColor(borderColor);
+ // groupB3.scale(2*sxy, 2*sxy, 1);
+ groupB3.setInteractive(true);
+ groupB3.validate(reqGLP);
+ groupB3.moveTo(sceneBox.getLow()).move(nextXPos, nextYTop-groupB3.getScaledHeight(), 0);
+ System.err.println("Group-B3 "+groupB3);
+ System.err.println("Group-B3 Layout "+groupB3.getLayout());
+ groupB3.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ scene.addShape(groupB3);
+ nextXPos += groupB3.getScaledWidth() * 1.1f;
+ if( reLayout ) {
+ try { Thread.sleep(reLayoutSleep); } catch (final InterruptedException e1) { }
+ groupB3.markShapeDirty();
+ groupB3.validate(reqGLP);
+ System.err.println("Group-B3.2 "+groupB3);
+ System.err.println("Group-B3 Layout.2 "+groupB3.getLayout());
+ groupB3.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ }
+
+ // next line
+ nextXPos = 0;
+ nextYTop = sceneBox.getHeight()/3f;
+
+ final Group groupC0 = new Group(new GridLayout(2, 0, 0, Alignment.Fill, new Gap(0.03f)));
+ {
+ final Group glyphGrid = new Group(new GridLayout(2, 0.3f, 0.3f, Alignment.Fill, new Gap(0.3f * 0.10f)));
+ glyphGrid.addShape( new Button(options.renderModes, font, "0.0", 1f, 1f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ glyphGrid.addShape( new Button(options.renderModes, font, "0.1", 1f, 1f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ glyphGrid.addShape( new Button(options.renderModes, font, "1.0", 1f, 1f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ glyphGrid.addShape( new Button(options.renderModes, font, "1.1", 1f, 1f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ groupC0.addShape(glyphGrid.setBorder(borderThickness));
+
+ final Group infoGrid = new Group(new GridLayout(1, 1/4f, 1/2f, Alignment.Fill, new Gap(0.02f)));
+ // final Group glyphView = new Group();
+ // glyphView.addShape(new Rectangle(options.renderModes, 1f, 1f, 0.005f).setInteractive(false));
+ // glyphView.addShape(new Button(options.renderModes, font, "S", 1f, 1f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ // infoGrid.addShape(glyphView.setBorder(borderThickness));
+ infoGrid.addShape(new Button(options.renderModes, font, " S ", 1/2f, 1f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+
+ // final Group infoView = new Group();
+ // infoView.addShape(new Button(options.renderModes, font, "Info", 1f, 1f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ // infoGrid.addShape(infoView.setBorder(borderThickness));
+ infoGrid.addShape(new Button(options.renderModes, font, " Info ", 1/2f, 1f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ groupC0.addShape(infoGrid.setBorder(borderThickness));
+ // groupC0.addShape(new Button(options.renderModes, font, "S", 1/4f, 0.5f).setCorner(0f).setBorder(borderThickness).setDragAndResizeable(false) );
+ }
+ groupC0.setBorder(sxy*borderThickness).setBorderColor(borderColor);
+ groupC0.scale(2*sxy, 2*sxy, 1);
+ groupC0.setInteractive(true);
+ groupC0.validate(reqGLP);
+ groupC0.moveTo(sceneBox.getLow()).move(nextXPos, nextYTop-groupC0.getScaledHeight(), 0);
+ System.err.println("Group-C0 "+groupC0);
+ System.err.println("Group-C0 Layout "+groupC0.getLayout());
+ groupC0.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ scene.addShape(groupC0);
+ nextXPos += groupC0.getScaledWidth() * 1.1f;
+ if( reLayout ) {
+ try { Thread.sleep(reLayoutSleep); } catch (final InterruptedException e1) { }
+ groupC0.markShapeDirty();
+ groupC0.validate(reqGLP);
+ System.err.println("Group-C0.2 "+groupC0);
+ System.err.println("Group-C0 Layout.2 "+groupC0.getLayout());
+ groupC0.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ }
+
+ final Group groupC3 = new Group(new GridLayout(2, sxy, sxy/2f, Alignment.Center, new Gap(sxy*0.10f)));
+ {
+ final Padding p = new Padding(sxy*0.05f);
+ groupC3.addShape( new Button(options.renderModes, font, "ro co", sxy/2f, sxy/4f).setCorner(0f).setPaddding(p).setBorder(sxy*borderThickness).addMouseListener(dragZoomRotateListener) );
+ groupC3.addShape( new Button(options.renderModes, font, "r1 c2", sxy/2f, sxy/4f).setCorner(0f).setPaddding(p).setBorder(sxy*borderThickness).setDragAndResizeable(false) );
+ groupC3.addShape( new Button(options.renderModes, font, "r2 c1", sxy/2f, sxy/4f).setCorner(0f).setPaddding(p).setBorder(sxy*borderThickness).setDragAndResizeable(false) );
+ groupC3.addShape( new Button(options.renderModes, font, "r2 c2", sxy/2f, sxy/4f).setCorner(0f).setPaddding(p).setBorder(sxy*borderThickness).addMouseListener(dragZoomRotateListener) );
+ groupC3.addShape( new Button(options.renderModes, font, "r3 c1", sxy/2f, sxy/4f).setCorner(0f).setPaddding(p).setBorder(sxy*borderThickness).addMouseListener(dragZoomRotateListener) );
+ }
+ groupC3.setBorder(sxy*borderThickness).setBorderColor(borderColor);
+ // groupC3.scale(2*sxy, 2*sxy, 1);
+ groupC3.setInteractive(true);
+ groupC3.validate(reqGLP);
+ groupC3.moveTo(sceneBox.getLow()).move(nextXPos, nextYTop-groupC3.getScaledHeight(), 0);
+ System.err.println("Group-C3 "+groupC3);
+ System.err.println("Group-C3 Layout "+groupC3.getLayout());
+ groupC3.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ scene.addShape(groupC3);
+ nextXPos += groupC3.getScaledWidth() * 1.1f;
+ if( reLayout ) {
+ try { Thread.sleep(reLayoutSleep); } catch (final InterruptedException e1) { }
+ groupC3.markShapeDirty();
+ groupC3.validate(reqGLP);
+ System.err.println("Group-C3.2 "+groupC3);
+ System.err.println("Group-C3 Layout.2 "+groupC3.getLayout());
+ groupC3.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ }
+
+ try { Thread.sleep(1000); } catch (final InterruptedException e1) { }
+ scene.screenshot(true, scene.nextScreenshotFile(null, UILayoutGrid01.class.getSimpleName(), options.renderModes, caps, null));
+ if( !options.stayOpen ) {
+ window.destroy();
+ }
+ }
+}
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03.java
index c5aa32d55..0c00508d8 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03.java
@@ -128,7 +128,7 @@ public class UISceneDemo03 {
final Scene scene = new Scene();
scene.setClearParams(new float[] { 1f, 1f, 1f, 1f }, GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
scene.setPMVMatrixSetup(new MyPMVMatrixSetup());
- scene.setDebugBox(options.debugBoxThickness);
+ scene.setDebugBorderBox(options.debugBoxThickness);
final Group glyphGroup = new Group();
scene.addShape(glyphGroup);
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03b.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03b.java
index 1668ec883..805d9dafc 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03b.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03b.java
@@ -100,7 +100,9 @@ public class UISceneDemo03b {
}
public static void main(final String[] args) throws IOException {
- int autoSpeed = 0;
+ int autoSpeed = -1;
+ setVelocity(80/1000f);
+ options.keepRunning = true;
if (0 != args.length) {
final int[] idx = { 0 };
@@ -110,6 +112,7 @@ public class UISceneDemo03b {
} else if (args[idx[0]].equals("-v")) {
++idx[0];
setVelocity(MiscUtils.atoi(args[idx[0]], (int) velocity * 1000) / 1000f);
+ autoSpeed = 0;
} else if(args[idx[0]].equals("-aspeed")) {
autoSpeed = -1;
setVelocity(80/1000f);
@@ -134,12 +137,12 @@ public class UISceneDemo03b {
final Scene scene = new Scene();
scene.setClearParams(new float[] { 1f, 1f, 1f, 1f }, GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
scene.setPMVMatrixSetup(new MyPMVMatrixSetup());
- scene.setDebugBox(options.debugBoxThickness);
+ scene.setDebugBorderBox(options.debugBoxThickness);
final Group glyphGroup = new Group();
scene.addShape(glyphGroup);
- // scene.setFrustumCullingEnabled(true);
+ scene.setFrustumCullingEnabled(true);
glyphGroup.setFrustumCullingEnabled(true);
final Animator animator = new Animator();
@@ -212,6 +215,13 @@ public class UISceneDemo03b {
final GLProfile hasGLP = window.getChosenGLCapabilities().getGLProfile();
final AABBox sceneBox = scene.getBounds();
+ glyphGroup.addShape( new Rectangle(options.renderModes, sceneBox, sceneBox.getWidth()*0.01f) );
+ // glyphGroup.addShape( new Rectangle(options.renderModes, sceneBox.getMinX(), sceneBox.getMinY(), sceneBox.getWidth(), sceneBox.getHeight(), sceneBox.getWidth()*0.01f) );
+ // glyphGroup.addShape( new Rectangle(options.renderModes, sceneBox.getMinX()*0.5f, sceneBox.getMinY()*0.5f, sceneBox.getWidth()*0.5f, sceneBox.getHeight()*0.5f, sceneBox.getWidth()*0.5f*0.01f, sceneBox.getMinZ()) );
+ glyphGroup.scale(0.8f, 0.8f, 1f);
+ // glyphGroup.scale(0.5f, 0.5f, 1f);
+ glyphGroup.setRotationPivot(0, 0, 0);
+ glyphGroup.validate(hasGLP);
System.err.println("SceneBox " + sceneBox);
System.err.println("Frustum " + scene.getMatrix().getFrustum());
System.err.println("GlyphGroup.0: "+glyphGroup);
@@ -259,7 +269,8 @@ public class UISceneDemo03b {
// Setup the moving glyphs
//
- final List<GlyphShape> glyphShapes = new ArrayList<GlyphShape>();
+ final List<GlyphShape> glyphShapesAnim = new ArrayList<GlyphShape>();
+ final List<GlyphShape> glyphShapesAll = new ArrayList<GlyphShape>();
final float pixPerMM, dpiV;
{
@@ -271,12 +282,14 @@ public class UISceneDemo03b {
boolean z_only = true;
int txt_idx = 0;
- final AABBox glyphBox = glyphGroup.getBounds().resize(sceneBox);
+ final AABBox glyphBox = glyphGroup.getBounds();
final float g_w = glyphBox.getWidth();
final float g_h = glyphBox.getHeight();
- glyphGroup.scale(0.8f, 0.8f, 1f);
- glyphGroup.validate(hasGLP);
+
+ // glyphGroup.scale(0.8f, 0.8f, 1f);
+ // glyphGroup.validate(hasGLP);
System.err.println("GlyphBox " + glyphBox);
+ System.err.println("GlyphGroup " + glyphGroup);
glyphGroup.addMouseListener( new Shape.MouseGestureAdapter() {
@Override
@@ -361,11 +374,11 @@ public class UISceneDemo03b {
}
z_only = !z_only;
window.invoke(true, (drawable) -> {
- glyphGroup.removeAllShapes(drawable.getGL().getGL2ES2(), scene.getRenderer());
+ glyphGroup.removeShapes(drawable.getGL().getGL2ES2(), scene.getRenderer(), glyphShapesAll);
return true;
});
- glyphGroup.addShape( new Rectangle(options.renderModes, g_w, g_h, g_w*0.01f) );
- glyphGroup.getShapes().get(0).setInteractive(false);
+ glyphShapesAll.clear();
+ glyphShapesAnim.clear();
final float[] movingGlyphPixPerShapeUnit;
{
@@ -378,9 +391,9 @@ public class UISceneDemo03b {
final int[] movingGlyphSizePx = testGlyph.getSurfaceSize(scene, pmv, new int[2]); // [px]
movingGlyphPixPerShapeUnit = testGlyph.getPixelPerShapeUnit(movingGlyphSizePx, new float[2]); // [px]/[shapeUnit]
- final AABBox box = GlyphShape.processString(glyphShapes, options.renderModes, font, originalTexts[txt_idx]);
+ final AABBox box = GlyphShape.processString(glyphShapesAll, options.renderModes, font, originalTexts[txt_idx]);
System.err.println("Shapes: "+box);
- for(final GlyphShape gs : glyphShapes) {
+ for(final GlyphShape gs : glyphShapesAll) {
gs.setScale(fontScale, fontScale, 1f);
gs.setColor(0.1f, 0.1f, 0.1f, 1);
final Vec3f target = gs.getOrigPos(fontScale).add(glyphBox.getMinX(), 0f, 0f);
@@ -396,14 +409,15 @@ public class UISceneDemo03b {
testGlyph.setEnabled(false);
glyphGroup.addShape(testGlyph);
}
- glyphGroup.addShapes(glyphShapes);
+ glyphGroup.addShapes(glyphShapesAll);
+ glyphShapesAnim.addAll(glyphShapesAll);
final float pos_eps = FloatUtil.EPSILON * 5000; // ~= 0.0005960
final float rot_eps = FloatUtil.adegToRad(0.5f); // 1 adeg ~= 0.01745 rad
final long t0_us = Clock.currentNanos() / 1000; // [us]
final long[] t2_us = { t0_us };
- while (!glyphShapes.isEmpty()) {
+ while (!glyphShapesAnim.isEmpty()) {
window.invoke(true, (drawable) -> {
final long t3_us = Clock.currentNanos() / 1000;
final float dt_s = (t3_us - t2_us[0]) / 1e6f;
@@ -413,8 +427,8 @@ public class UISceneDemo03b {
final float velocity_obj = velocity_px / movingGlyphPixPerShapeUnit[0]; // [shapeUnit]/[s]
final float dxy = velocity_obj * dt_s; // [shapeUnit]
- for (int idx = glyphShapes.size() - 1; 0 <= idx; --idx) {
- final GlyphShape glyph = glyphShapes.get(idx);
+ for (int idx = glyphShapesAnim.size() - 1; 0 <= idx; --idx) {
+ final GlyphShape glyph = glyphShapesAnim.get(idx);
final Vec3f pos = new Vec3f(glyph.getPosition());
final Vec3f target = glyph.getOrigPos(fontScale).add(glyphBox.getMinX(), 0f, 0f);
final Vec3f p_t = target.minus(pos);
@@ -435,7 +449,7 @@ public class UISceneDemo03b {
}
glyph.moveTo(target.x(), target.y(), target.z());
q.setIdentity();
- glyphShapes.remove(idx);
+ glyphShapesAnim.remove(idx);
continue;
}
if( !pos_ok ) {
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo11.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo11.java
index 001f585fd..6c20247c2 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo11.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo11.java
@@ -37,8 +37,9 @@ import com.jogamp.graph.font.FontSet;
import com.jogamp.graph.ui.Group;
import com.jogamp.graph.ui.Scene;
import com.jogamp.graph.ui.Shape;
+import com.jogamp.graph.ui.layout.Alignment;
+import com.jogamp.graph.ui.layout.Gap;
import com.jogamp.graph.ui.layout.GridLayout;
-import com.jogamp.graph.ui.layout.Padding;
import com.jogamp.graph.ui.shapes.Button;
import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.event.WindowEvent;
@@ -81,7 +82,7 @@ public class UISceneDemo11 {
final Font font = FontFactory.get(FontFactory.UBUNTU).get(FontSet.FAMILY_LIGHT, FontSet.STYLE_SERIF);
System.err.println("Font: "+font.getFullFamilyName());
- final Group groupA0 = new Group(new GridLayout(2, 1f, 1/2f, new Padding(0.05f, 0.05f)));
+ final Group groupA0 = new Group(new GridLayout(2, 1f, 1/2f, Alignment.Fill, new Gap(0.10f)));
{
groupA0.addShape( new Button(options.renderModes, font, "r1 c1", 1f, 1f/2f).setCorner(0f).setDragAndResizeable(false) );
groupA0.addShape( new Button(options.renderModes, font, "r1 c2", 1f, 1f/2f).setCorner(0f).setDragAndResizeable(false) );
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java
index d732795ca..eeb52082f 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java
@@ -49,8 +49,9 @@ import com.jogamp.graph.ui.Group;
import com.jogamp.graph.ui.Scene;
import com.jogamp.graph.ui.Shape;
import com.jogamp.graph.ui.Scene.PMVMatrixSetup;
+import com.jogamp.graph.ui.layout.Alignment;
+import com.jogamp.graph.ui.layout.Gap;
import com.jogamp.graph.ui.layout.GridLayout;
-import com.jogamp.graph.ui.layout.Padding;
import com.jogamp.graph.ui.shapes.Button;
import com.jogamp.graph.ui.shapes.GLButton;
import com.jogamp.graph.ui.shapes.ImageButton;
@@ -307,7 +308,7 @@ public class UISceneDemo20 implements GLEventListener {
scene.setPMVMatrixSetup(new MyPMVMatrixSetup());
scene.getRenderState().setHintMask(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED);
// scene.setSampleCount(3); // easy on embedded devices w/ just 3 samples (default is 4)?
- scene.setDebugBox(options.debugBoxThickness);
+ scene.setDebugBorderBox(options.debugBoxThickness);
scene.addShape(buttonsLeft);
scene.addShape(buttonsRight);
}
@@ -384,12 +385,12 @@ public class UISceneDemo20 implements GLEventListener {
final float buttonLWidth = buttonXSizeNorm;
final float buttonLHeight = buttonLWidth / 2.5f;
- buttonsLeft.setLayout(new GridLayout(buttonLWidth, buttonLHeight, new Padding(buttonLHeight*0.25f, buttonLWidth*0.05f), 7));
+ buttonsLeft.setLayout(new GridLayout(buttonLWidth, buttonLHeight, Alignment.Fill, new Gap(buttonLHeight*0.50f, buttonLWidth*0.10f), 7));
final float buttonRWidth = 2f*buttonLWidth;
final float buttonRHeight = 2f*buttonLHeight;
- buttonsRight.setLayout(new GridLayout(1, buttonRWidth, buttonRHeight, new Padding(buttonLHeight*0.25f, buttonLWidth*0.05f)));
+ buttonsRight.setLayout(new GridLayout(1, buttonRWidth, buttonRHeight, Alignment.Fill, new Gap(buttonLHeight*0.50f, buttonLWidth*0.10f)));
System.err.println("Button Size: "+buttonLWidth+" x "+buttonLHeight);
@@ -861,20 +862,22 @@ public class UISceneDemo20 implements GLEventListener {
buttonsRight.setScale(button_sxy, button_sxy, 1f);
final float dz = 0f;
- final float dyTop = sceneHeight * relTop;
+ final float dxLeft = sceneBox.getMinX();
+ final float dyBottom = sceneBox.getMinY();
+ final float dyTop = dyBottom + sceneHeight * relTop;
System.err.println("XXX: dw "+sceneWidth+", dh "+sceneHeight+", dyTop "+dyTop);
System.err.println("BL "+buttonsLeft);
System.err.println("BL "+buttonsLeft.getLayout());
System.err.println("BR "+buttonsRight);
System.err.println("BR "+buttonsRight.getLayout());
- buttonsLeft.moveTo(0f, dyTop - buttonsLeft.getScaledHeight(), dz);
- buttonsRight.moveTo(sceneWidth - buttonsRight.getScaledWidth(), dyTop - buttonsRight.getScaledHeight(), dz);
+ buttonsLeft.moveTo(dxLeft, dyTop - buttonsLeft.getScaledHeight(), dz);
+ buttonsRight.moveTo(dxLeft + sceneWidth - buttonsRight.getScaledWidth(), dyTop - buttonsRight.getScaledHeight(), dz);
jogampLabel.setScale(sceneHeight, sceneHeight, 1f);
- final float dxMiddleAbs = sceneWidth * relMiddle;
- final float dyTopLabelAbs = sceneHeight - jogampLabel.getScaledLineHeight();
+ final float dxMiddleAbs = dxLeft + sceneWidth * relMiddle;
+ final float dyTopLabelAbs = dyBottom + sceneHeight - jogampLabel.getScaledLineHeight();
jogampLabel.moveTo(dxMiddleAbs, dyTopLabelAbs - jogampLabel.getScaledLineHeight(), dz);
{
final float pixelSize10Pt = FontScale.toPixels(fontSizePt, dpiV);
@@ -920,8 +923,8 @@ public class UISceneDemo20 implements GLEventListener {
if(null == labels[currentText]) {
final AABBox sbox = scene.getBounds();
final float sceneHeight = sbox.getHeight();
- final float dyTop = sbox.getHeight() - jogampLabel.getScaledLineHeight();
- final float dxMiddle = sbox.getWidth() * relMiddle;
+ final float dyTop = sbox.getMinY() + sbox.getHeight() - jogampLabel.getScaledLineHeight();
+ final float dxMiddle = sbox.getMinX() + sbox.getWidth() * relMiddle;
labels[currentText] = new Label(renderModes, font, fontSizeFixedNorm, strings[currentText]);
labels[currentText].setScale(sceneHeight, sceneHeight, 1f);
labels[currentText].setColor(0.1f, 0.1f, 0.1f, 1.0f);
@@ -984,32 +987,33 @@ public class UISceneDemo20 implements GLEventListener {
/**
* Our PMVMatrixSetup:
* - gluPerspective like Scene's default
- * - no normal scale to 1, keep distance to near plane for rotation effects. We scale Shapes
- * - translate origin to bottom-left
+ * - no normal scale to 1, keep a longer distance to near plane for rotation effects. We scale Shapes
*/
public static class MyPMVMatrixSetup implements PMVMatrixSetup {
+ static float Z_DIST = -1f;
@Override
public void set(final PMVMatrix pmv, final Recti viewport) {
final float ratio = (float)viewport.width()/(float)viewport.height();
pmv.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
pmv.glLoadIdentity();
pmv.gluPerspective(Scene.DEFAULT_ANGLE, ratio, Scene.DEFAULT_ZNEAR, Scene.DEFAULT_ZFAR);
- pmv.glTranslatef(0f, 0f, Scene.DEFAULT_SCENE_DIST);
+ pmv.glTranslatef(0f, 0f, Z_DIST);
pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmv.glLoadIdentity();
-
- // Translate origin to bottom-left
- final AABBox planeBox0 = new AABBox();
- setPlaneBox(planeBox0, pmv, viewport);
- pmv.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
- pmv.glTranslatef(planeBox0.getMinX(), planeBox0.getMinY(), 0f);
- pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
}
@Override
public void setPlaneBox(final AABBox planeBox, final PMVMatrix pmv, final Recti viewport) {
- Scene.getDefaultPMVMatrixSetup().setPlaneBox(planeBox, pmv, viewport);
+ // Scene.getDefaultPMVMatrixSetup().setPlaneBox(planeBox, pmv, viewport);
+ final float orthoDist = -Z_DIST; // Scene.DEFAULT_SCENE_DIST;
+ final Vec3f obj00Coord = new Vec3f();
+ final Vec3f obj11Coord = new Vec3f();
+
+ Scene.winToPlaneCoord(pmv, viewport, Scene.DEFAULT_ZNEAR, Scene.DEFAULT_ZFAR, viewport.x(), viewport.y(), orthoDist, obj00Coord);
+ Scene.winToPlaneCoord(pmv, viewport, Scene.DEFAULT_ZNEAR, Scene.DEFAULT_ZFAR, viewport.width(), viewport.height(), orthoDist, obj11Coord);
+
+ planeBox.setSize( obj00Coord, obj11Coord );
}
};
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+"]";
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/FontViewListener01.java b/src/test/com/jogamp/opengl/test/junit/graph/FontViewListener01.java
index 538c07967..01f6e456d 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/FontViewListener01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/FontViewListener01.java
@@ -32,8 +32,9 @@ import com.jogamp.graph.font.FontScale;
import com.jogamp.graph.ui.Group;
import com.jogamp.graph.ui.Scene;
import com.jogamp.graph.ui.Shape;
+import com.jogamp.graph.ui.layout.Alignment;
+import com.jogamp.graph.ui.layout.Gap;
import com.jogamp.graph.ui.layout.GridLayout;
-import com.jogamp.graph.ui.layout.Padding;
import com.jogamp.graph.ui.shapes.GlyphShape;
import com.jogamp.graph.ui.shapes.Rectangle;
import com.jogamp.newt.opengl.GLWindow;
@@ -122,7 +123,7 @@ public class FontViewListener01 implements GLEventListener {
final float gridSize = gridCols > gridRows ? 1f/gridCols : 1f/gridRows;
System.err.println("Reshape Grid "+gridCols+" x "+gridRows+", "+cellCount+" cells, gridSize "+gridSize);
- grid = new Group(new GridLayout(gridCols, gridSize, gridSize, new Padding(gridSize*0.05f, gridSize*0.05f)));
+ grid = new Group(new GridLayout(gridCols, gridSize, gridSize, Alignment.Fill, new Gap(gridSize*0.10f)));
scene.addShape(grid);
for(int i=0; i<cellCount; ++i) {