aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-04-12 19:20:24 +0200
committerSven Gothel <[email protected]>2023-04-12 19:20:24 +0200
commit6a0ac90182efba40b0e6dab8f6390898aced70e8 (patch)
treec263bb343b66755d30fb81564df5232a96992bd1 /src
parent92ec47e74eef3ba47627b04ddf78996fa3a2296f (diff)
GraphUI GridLayout: Functional Grid Layout w/ Padding, demo'ed in UISceneDemo20 with button Groups
All layout magic is simply performed in Group.Layout.layout(..) @ validate, incl. updating the bounding box to have the padding included. This demonstrates GraphUI's capability to be used with correct layout, i.e. its pure matrix based position, scale and rotation.
Diffstat (limited to 'src')
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo11.java18
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java281
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/Group.java47
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/layout/GridLayout.java144
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/layout/Padding.java49
5 files changed, 348 insertions, 191 deletions
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 3e9c3f4bf..0479349b7 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo11.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo11.java
@@ -38,6 +38,7 @@ import com.jogamp.graph.ui.Group;
import com.jogamp.graph.ui.Scene;
import com.jogamp.graph.ui.Shape;
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.newt.event.MouseEvent;
@@ -82,17 +83,18 @@ public class UISceneDemo11 {
final Font font = FontFactory.get(FontFactory.UBUNTU).get(FontSet.FAMILY_LIGHT, FontSet.STYLE_SERIF);
System.err.println("Font: "+font.getFullFamilyName());
- final float shapeWidth = 1/8f;
- final float shapeHeight = shapeWidth/2.5f;
- final Group groupA0 = new Group(new GridLayout(2, shapeWidth*1.1f, shapeHeight*1.1f));
+ final Group groupA0 = new Group(new GridLayout(2, 1f, 1/2f, new Padding(0.1f, 0.1f)));
{
- groupA0.addShape( new Button(renderModes, font, "1", shapeWidth, shapeHeight) );
- groupA0.addShape( new Button(renderModes, font, "2", shapeWidth, shapeHeight) );
- groupA0.addShape( new Button(renderModes, font, "3", shapeWidth, shapeHeight) );
- groupA0.addShape( new Button(renderModes, font, "4", shapeWidth, shapeHeight) );
+ 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) );
+ groupA0.addShape( new Button(options.renderModes, font, "r2 c1", 1f, 1f/2f).setCorner(0f).setDragAndResizeable(false) );
+ groupA0.addShape( new Button(options.renderModes, font, "r2 c2", 1f, 1f/2f).setCorner(0f).setDragAndResizeable(false) );
}
- groupA0.validate(glp);
+ groupA0.setInteractive(true);
+ groupA0.scale(1/8f, 1/8f, 1);
+ groupA0.validate(reqGLP);
System.err.println("Group-A0 "+groupA0);
+ System.err.println("Group-A0 Layout "+groupA0.getLayout());
groupA0.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
final Scene scene = new Scene();
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 f181e51b9..4d132814c 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java
@@ -45,9 +45,12 @@ import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;
import com.jogamp.graph.font.FontScale;
import com.jogamp.graph.ui.GraphShape;
+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.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;
@@ -194,12 +197,11 @@ public class UISceneDemo20 implements GLEventListener {
private final Font fontFPS;
private final Uri filmURL;
- private final float relTop = 80f/100f;
+ private final float relTop = 90f/100f;
private final float relMiddle = 22f/100f;
- private final float relLeft = 11f/100f;
/** Relative Button Size to Window Height, normalized to 1. */
- private static final float buttonXSizeNorm = 0.084f;
+ private static final float buttonXSizeNorm = 0.09f; // 0.084f;
private static final float fontSizePt = 10f;
/** Relative Font Size to Window Height for Main Text, normalized to 1. */
private static final float fontSizeFixedNorm = 0.04f;
@@ -217,8 +219,8 @@ public class UISceneDemo20 implements GLEventListener {
private String actionText = null;
private Label[] labels = null;
private String[] strings = null;
- private final List<RoundButton> buttons = new ArrayList<RoundButton>();
- private int buttonsLeftCount = 0;
+ final Group buttonsLeft = new Group();
+ final Group buttonsRight = new Group();
private Label truePtSizeLabel = null;
private Label jogampLabel = null;
private Label fpsLabel = null;
@@ -305,20 +307,27 @@ public class UISceneDemo20 implements GLEventListener {
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.addShape(buttonsLeft);
+ scene.addShape(buttonsRight);
}
private void rotateButtons(final Vec3f angdeg) {
angdeg.scale(FloatUtil.PI / 180.0f); // -> radians
- for(int i=0; i<buttons.size(); i++) {
- buttons.get(i).getRotation().rotateByEuler( angdeg );
+ final List<Shape> sl = new ArrayList<Shape>();
+ sl.addAll(buttonsLeft.getShapes());
+ sl.addAll(buttonsRight.getShapes());
+ for(final Shape s : sl) {
+ s.getRotation().rotateByEuler( angdeg );
}
}
private void setButtonsSpacing(final float dx, final float dy) {
- for(int i=0; i<buttons.size(); i++) {
- final RoundButton b = buttons.get(i);
- if( b instanceof Button ) {
- final Button lb = (Button) b;
+ final List<Shape> sl = new ArrayList<Shape>();
+ sl.addAll(buttonsLeft.getShapes());
+ sl.addAll(buttonsRight.getShapes());
+ for(final Shape s : sl) {
+ if( s instanceof Button ) {
+ final Button lb = (Button) s;
final float sx = lb.getSpacingX()+dx, sy = lb.getSpacingY()+dy;
System.err.println("Spacing: X "+sx+", Y "+sy);
lb.setSpacing(sx, sy);
@@ -327,20 +336,31 @@ public class UISceneDemo20 implements GLEventListener {
}
private void setButtonsCorner(final float dc) {
- for(int i=0; i<buttons.size(); i++) {
- final float c = buttons.get(i).getCorner()+dc;
- System.err.println("Corner: "+c);
- buttons.get(i).setCorner(c);
+ final List<Shape> sl = new ArrayList<Shape>();
+ sl.addAll(buttonsLeft.getShapes());
+ sl.addAll(buttonsRight.getShapes());
+ for(final Shape s : sl) {
+ if( s instanceof RoundButton ) {
+ final RoundButton rb = (RoundButton)s;
+ final float c = rb.getCorner()+dc;
+ System.err.println("Corner: "+c);
+ rb.setCorner(c);
+ }
}
}
private void resetButtons() {
- for(int i=0; i<buttons.size(); i++) {
- final RoundButton b = buttons.get(i);
- b.getRotation().setIdentity();
- b.setCorner(RoundButton.DEFAULT_CORNER);
- if( b instanceof Button ) {
- ((Button)b).setSpacing(Button.DEFAULT_SPACING_X, Button.DEFAULT_SPACING_Y);
+ final List<Shape> sl = new ArrayList<Shape>();
+ sl.addAll(buttonsLeft.getShapes());
+ sl.addAll(buttonsRight.getShapes());
+ for(final Shape s : sl) {
+ if( s instanceof RoundButton ) {
+ final RoundButton b = (RoundButton)s;
+ b.getRotation().setIdentity();
+ b.setCorner(RoundButton.DEFAULT_CORNER);
+ if( b instanceof Button ) {
+ ((Button)b).setSpacing(Button.DEFAULT_SPACING_X, Button.DEFAULT_SPACING_Y);
+ }
}
}
}
@@ -356,24 +376,25 @@ public class UISceneDemo20 implements GLEventListener {
return scene.getShapeByName(name);
}
- private void initButtons(final GL2ES2 gl, final float scale) {
+ private void initButtons(final GL2ES2 gl) {
final boolean pass2Mode = Region.isTwoPass( renderModes ) ;
- buttons.clear();
-
- final float buttonXSize = buttonXSizeNorm * scale;
- final float buttonYSize = buttonXSize / 2.5f;
- final float button2XSize = 2f*buttonXSize;
- final float button2YSize = 2f*buttonYSize;
- System.err.println("Button Size: "+buttonXSize+" x "+buttonYSize+", scale "+scale);
- final float xStartLeft = 0f; // aligned to left edge w/ space via reshape
- final float xStartRight = -button2XSize - button2XSize/8f; // aligned to right edge via reshape
- final float yStartTop = 0f; // aligned to top edge w/ space via reshape
- final float diffX = 1.2f * buttonXSize;
- final float diffY = 1.5f * buttonYSize;
-
- Button button = new Button(renderModes, fontButtons, " Next Text ", buttonXSize, buttonYSize);
+ buttonsLeft.removeAllShapes(gl, scene.getRenderer());
+ buttonsRight.removeAllShapes(gl, scene.getRenderer());
+
+ final float buttonLWidth = buttonXSizeNorm;
+ final float buttonLHeight = buttonLWidth / 2.5f;
+ buttonsLeft.setLayout(new GridLayout(buttonLWidth, buttonLHeight, new Padding(buttonLWidth*0.1f, buttonLHeight*0.5f), 7));
+
+ final float buttonRWidth = 2f*buttonLWidth;
+ final float buttonRHeight = 2f*buttonLHeight;
+
+ buttonsRight.setLayout(new GridLayout(1, buttonRWidth, buttonRHeight, new Padding(buttonLWidth*0.1f, buttonLHeight*0.5f)));
+
+ System.err.println("Button Size: "+buttonLWidth+" x "+buttonLHeight);
+
+ RoundButton button;
+ button = new Button(renderModes, fontButtons, " Next Text ", buttonLWidth, buttonLHeight);
button.setName(BUTTON_NEXTTEXT);
- button.move(xStartLeft, yStartTop-diffY*buttons.size(), 0f);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
@@ -386,11 +407,10 @@ public class UISceneDemo20 implements GLEventListener {
}
} } );
button.addMouseListener(dragZoomRotateListener);
- buttons.add(button);
+ buttonsLeft.addShape(button);
- button = new Button(renderModes, fontButtons, "Show fps", buttonXSize, buttonYSize);
+ button = new Button(renderModes, fontButtons, "Show fps", buttonLWidth, buttonLHeight);
button.setName(BUTTON_FPS);
- button.move(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
button.setToggleable(true);
button.setToggle(fpsLabel.isEnabled());
button.addMouseListener(new Shape.MouseGestureAdapter() {
@@ -403,11 +423,10 @@ public class UISceneDemo20 implements GLEventListener {
fpsLabel.setEnabled(!fpsLabel.isEnabled());
} } );
button.addMouseListener(dragZoomRotateListener);
- buttons.add(button);
+ buttonsLeft.addShape(button);
- button = new Button(renderModes, fontButtons, " V-Sync ", buttonXSize, buttonYSize);
+ button = new Button(renderModes, fontButtons, " V-Sync ", buttonLWidth, buttonLHeight);
button.setName(BUTTON_VSYNC);
- button.move(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
button.setToggleable(true);
button.setToggle(gl.getSwapInterval()>0);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@@ -427,10 +446,9 @@ public class UISceneDemo20 implements GLEventListener {
});
} } );
button.addMouseListener(dragZoomRotateListener);
- buttons.add(button);
+ buttonsLeft.addShape(button);
- button = new Button(renderModes, fontButtons, "< Tilt >", buttonXSize, buttonYSize);
- button.move(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
+ button = new Button(renderModes, fontButtons, "< Tilt >", buttonLWidth, buttonLHeight);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
@@ -445,11 +463,10 @@ public class UISceneDemo20 implements GLEventListener {
public void mouseWheelMoved(final MouseEvent e) {
rotateButtons(new Vec3f( 0f, e.getRotation()[1], 0f ) );
} } );
- buttons.add(button);
+ buttonsLeft.addShape(button);
- if( pass2Mode ) { // second column to the left
- button = new Button(renderModes, fontButtons, "< Samples >", buttonXSize, buttonYSize);
- button.move(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
+ if( pass2Mode ) {
+ button = new Button(renderModes, fontButtons, "< Samples >", buttonLWidth, buttonLHeight);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
@@ -465,10 +482,9 @@ public class UISceneDemo20 implements GLEventListener {
sampleCount = scene.setSampleCount(sampleCount); // validated / clipped
} } );
button.addMouseListener(dragZoomRotateListener);
- buttons.add(button);
+ buttonsLeft.addShape(button);
- button = new Button(renderModes, fontButtons, "< Quality >", buttonXSize, buttonYSize);
- button.move(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
+ button = new Button(renderModes, fontButtons, "< Quality >", buttonLWidth, buttonLHeight);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
@@ -491,14 +507,13 @@ public class UISceneDemo20 implements GLEventListener {
}
} } );
button.addMouseListener(dragZoomRotateListener);
- buttons.add(button);
+ buttonsLeft.addShape(button);
}
- button = new Button(renderModes, fontButtons, "Quit", buttonXSize, buttonYSize);
+ button = new Button(renderModes, fontButtons, "Quit", buttonLWidth, buttonLHeight);
button.setName(BUTTON_QUIT);
- button.move(xStartLeft,yStartTop - diffY*buttons.size(), 0f);
button.setColor(0.7f, 0.0f, 0.0f, 1.0f);
- button.setLabelColor(1.2f, 1.2f, 1.2f);
+ ((Button)button).setLabelColor(1.2f, 1.2f, 1.2f);
button.setPressedColorMod(1.1f, 0.0f, 0.0f, 1.0f);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
@@ -516,36 +531,29 @@ public class UISceneDemo20 implements GLEventListener {
} }.start();
} } );
button.addMouseListener(dragZoomRotateListener);
- buttons.add(button);
+ buttonsLeft.addShape(button);
// second column to the left
{
- final int j = 1; // column
- int k = 0; // row
- button = new Button(renderModes, fontButtons, "Y Flip", buttonXSize, buttonYSize);
- button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
+ button = new Button(renderModes, fontButtons, "Y Flip", buttonLWidth, buttonLHeight);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
rotateButtons(new Vec3f ( 0f, 180f, 0f ));
} } );
button.addMouseListener(dragZoomRotateListener);
- buttons.add(button);
+ buttonsLeft.addShape(button);
- k++;
- button = new Button(renderModes, fontButtons, "X Flip", buttonXSize, buttonYSize);
- button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
+ button = new Button(renderModes, fontButtons, "X Flip", buttonLWidth, buttonLHeight);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
rotateButtons(new Vec3f ( 180f, 0f, 0f ));
} } );
button.addMouseListener(dragZoomRotateListener);
- buttons.add(button);
- k++;
+ buttonsLeft.addShape(button);
- button = new Button(renderModes, fontButtons, "< Space >", buttonXSize, buttonYSize);
- button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
+ button = new Button(renderModes, fontButtons, "< Space >", buttonLWidth, buttonLHeight);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
@@ -562,11 +570,9 @@ public class UISceneDemo20 implements GLEventListener {
public void mouseWheelMoved(final MouseEvent e) {
setButtonsSpacing(e.getRotation()[0]/100f, e.getRotation()[1]/200f);
} } );
- buttons.add(button);
- k++;
+ buttonsLeft.addShape(button);
- button = new Button(renderModes, fontButtons, "< Corner >", buttonXSize, buttonYSize);
- button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
+ button = new Button(renderModes, fontButtons, "< Corner >", buttonLWidth, buttonLHeight);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
@@ -583,22 +589,18 @@ public class UISceneDemo20 implements GLEventListener {
public void mouseWheelMoved(final MouseEvent e) {
setButtonsCorner(e.getRotation()[1]/20f);
} } );
- buttons.add(button);
- k++;
+ buttonsLeft.addShape(button);
- button = new Button(renderModes, fontButtons, " Reset ", buttonXSize, buttonYSize);
- button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
+ button = new Button(renderModes, fontButtons, " Reset ", buttonLWidth, buttonLHeight);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
resetButtons();
} } );
button.addMouseListener(dragZoomRotateListener);
- buttons.add(button);
- k++;
+ buttonsLeft.addShape(button);
- button = new Button(renderModes, fontButtons, " Snapshot ", buttonXSize, buttonYSize);
- button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f);
+ button = new Button(renderModes, fontButtons, " Snapshot ", buttonLWidth, buttonLHeight);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
@@ -608,12 +610,12 @@ public class UISceneDemo20 implements GLEventListener {
});
} } );
button.addMouseListener(dragZoomRotateListener);
- buttons.add(button);
- k++;
+ buttonsLeft.addShape(button);
}
- buttonsLeftCount = buttons.size();
-
+ //
+ // buttonRight
+ //
final int texUnitMediaPlayer, texUnitImageButton, texUnitGLELButton;
{
// works - but not required ..
@@ -625,27 +627,27 @@ public class UISceneDemo20 implements GLEventListener {
if( true ) {
final GLMediaPlayer mPlayer = GLMediaPlayerFactory.createDefault();
mPlayer.setTextureUnit(texUnitMediaPlayer);
- final MediaButton mPlayerButton = new MediaButton(renderModes, button2XSize,
- button2YSize, mPlayer);
- mPlayerButton.setName(BUTTON_MOVIE);
- mPlayerButton.setVerbose(false);
- mPlayerButton.addDefaultEventListener();
- mPlayerButton.move(xStartRight, yStartTop - diffY*1, 0f);
- mPlayerButton.setToggleable(true);
- mPlayerButton.setToggle(true); // toggle == false -> mute audio
- mPlayerButton.setToggleOffColorMod(0f, 1f, 0f, 1.0f);
- mPlayerButton.addMouseListener(dragZoomRotateListener);
- mPlayerButton.addMouseListener(new Shape.MouseGestureAdapter() {
+ button = new MediaButton(renderModes, buttonRWidth, buttonRHeight, mPlayer);
+ button.setName(BUTTON_MOVIE);
+ ((MediaButton)button).setVerbose(false);
+ ((MediaButton)button).addDefaultEventListener();
+ button.setToggleable(true);
+ button.setToggle(true); // toggle == false -> mute audio
+ button.setToggleOffColorMod(0f, 1f, 0f, 1.0f);
+ button.addMouseListener(dragZoomRotateListener);
+ button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
- mPlayer.setAudioVolume( mPlayerButton.isToggleOn() ? 1f : 0f );
+ final Shape.EventInfo info = (Shape.EventInfo)e.getAttachment();
+ final MediaButton s = (MediaButton)info.shape;
+ mPlayer.setAudioVolume( s.isToggleOn() ? 1f : 0f );
} } );
- buttons.add(mPlayerButton);
+ buttonsRight.addShape(button);
mPlayer.playStream(filmURL, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT);
}
if( true ) {
final ImageSequence imgSeq = new ImageSequence(texUnitImageButton, true);
- final ImageButton imgButton = new ImageButton(renderModes, button2XSize, button2YSize, imgSeq);
+ button = new ImageButton(renderModes, buttonRWidth, buttonRHeight, imgSeq);
try {
imgSeq.addFrame(gl, UISceneDemo20.class, "button-released-145x53.png", TextureIO.PNG);
imgSeq.addFrame(gl, UISceneDemo20.class, "button-pressed-145x53.png", TextureIO.PNG);
@@ -653,19 +655,22 @@ public class UISceneDemo20 implements GLEventListener {
e2.printStackTrace();
}
imgSeq.setManualStepping(true);
- imgButton.move(xStartRight, yStartTop - diffY*2.5f, 0f);
- imgButton.addMouseListener(dragZoomRotateListener);
- imgButton.addMouseListener(new Shape.MouseGestureAdapter() {
+ button.addMouseListener(dragZoomRotateListener);
+ button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mousePressed(final MouseEvent e) {
- imgButton.setCurrentIdx(1);
- System.err.println("XXX: "+imgButton);
+ final Shape.EventInfo info = (Shape.EventInfo)e.getAttachment();
+ final ImageButton s = (ImageButton)info.shape;
+ s.setCurrentIdx(1);
+ System.err.println("XXX: "+s);
}
@Override
public void mouseReleased(final MouseEvent e) {
- imgButton.setCurrentIdx(0);
+ final Shape.EventInfo info = (Shape.EventInfo)e.getAttachment();
+ final ImageButton s = (ImageButton)info.shape;
+ s.setCurrentIdx(0);
} } );
- buttons.add(imgButton);
+ buttonsRight.addShape(button);
}
if( true ) {
// Issues w/ OSX and NewtCanvasAWT when rendering / animating
@@ -694,21 +699,22 @@ public class UISceneDemo20 implements GLEventListener {
System.err.println("Gears Anim: End");
}
}).start();
- final GLButton b = new GLButton(renderModes, button2XSize, button2YSize,
- texUnitGLELButton, gears, false /* useAlpha */);
- b.setName(BUTTON_GLEL);
- b.setToggleable(true);
- b.setToggle(false); // toggle == true -> animation
- b.setAnimate(false);
- b.move(xStartRight, yStartTop - diffY*4f, 0f);
- b.addMouseListener(dragZoomRotateListener);
- b.addMouseListener(new Shape.MouseGestureAdapter() {
+ button = new GLButton(renderModes, buttonRWidth, buttonRHeight,
+ texUnitGLELButton, gears, false /* useAlpha */);
+ button.setName(BUTTON_GLEL);
+ button.setToggleable(true);
+ button.setToggle(false); // toggle == true -> animation
+ ((GLButton)button).setAnimate(false);
+ button.addMouseListener(dragZoomRotateListener);
+ button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
- b.setAnimate( b.isToggleOn() );
- animate[0] = b.getAnimate();
+ final Shape.EventInfo info = (Shape.EventInfo)e.getAttachment();
+ final GLButton s = (GLButton)info.shape;
+ s.setAnimate( s.isToggleOn() );
+ animate[0] = s.getAnimate();
} } );
- buttons.add(b);
+ buttonsRight.addShape(button);
}
}
@@ -820,6 +826,7 @@ public class UISceneDemo20 implements GLEventListener {
initTexts();
initLabels(gl);
+ initButtons(gl);
scene.init(drawable);
@@ -848,31 +855,23 @@ public class UISceneDemo20 implements GLEventListener {
final float sceneWidth = sceneBox.getWidth();
final float sceneHeight = sceneBox.getHeight();
final float button_sxy = sceneWidth > sceneHeight ? sceneWidth : sceneHeight;
- if( buttons.isEmpty() ) {
- initButtons(drawable.getGL().getGL2ES2(), button_sxy);
- scene.addShapes(buttons);
- }
- final float dw = sceneWidth - lastSceneWidth;
- final float dh = sceneHeight - lastSceneHeight;
+ buttonsLeft.validate(drawable.getGL().getGL2ES2());
+ buttonsRight.validate(drawable.getGL().getGL2ES2());
- final float dz = 0f;
- final float dyTop = dh * relTop;
- final float dxLeft = dw * relLeft;
- final float dxRight = dw;
-
- System.err.println("XXX: dw "+dw+", dh "+dh+", dxLeft "+dxLeft+", dxRight "+dxRight+", dyTop "+dyTop);
+ buttonsLeft.setScale(button_sxy, button_sxy, 1f);
+ buttonsRight.setScale(button_sxy, button_sxy, 1f);
- for(int i=0; i<buttons.size() && i<buttonsLeftCount; i++) {
- // System.err.println("Button["+i+"].L0: "+buttons.get(i));
- buttons.get(i).move(dxLeft, dyTop, dz);
- // System.err.println("Button["+i+"].LM: "+buttons.get(i));
- }
- for(int i=buttonsLeftCount; i<buttons.size(); i++) {
- // System.err.println("Button["+i+"].R0: "+buttons.get(i));
- buttons.get(i).move(dxRight, dyTop, dz);
- // System.err.println("Button["+i+"].RM: "+buttons.get(i));
- }
+ final float dz = 0f;
+ final float dyTop = 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);
jogampLabel.setScale(sceneHeight, sceneHeight, 1f);
diff --git a/src/graphui/classes/com/jogamp/graph/ui/Group.java b/src/graphui/classes/com/jogamp/graph/ui/Group.java
index b3ae5b41d..e349b1302 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/Group.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/Group.java
@@ -48,10 +48,22 @@ import jogamp.graph.ui.TreeTool;
* @see Group.Layout
*/
public class Group extends Shape implements Container {
- /** Layout for the group, called @ {@link Group#validate(GL2ES2)} or {@link Group#validate(GLProfile)}. */
+ /** Layout for the GraphUI {@link Group}, called @ {@link Shape#validate(GL2ES2)} or {@link Shape#validate(GLProfile)}. */
public static interface Layout {
- /** Performing the layout, called @ {@link Group#validate(GL2ES2)} or {@link Group#validate(GLProfile)}. */
- void layout(Group g);
+ /**
+ * Performing the layout of {@link Group#getShapes()}, called @ {@link Shape#validate(GL2ES2)} or {@link Shape#validate(GLProfile)}.
+ * <p>
+ * According to the implemented layout, method
+ * - may scale the {@Link Shape}s
+ * - may move the {@Link Shape}s
+ * - may reuse the given {@link PMVMatrix} `pmv`
+ * - must update the given {@link AABBox} `box`
+ * </p>
+ * @param g the {@link Group} to layout
+ * @param box the bounding box of {@link Group} to be updated by this method.
+ * @param pmv a {@link PMVMatrix} which can be reused.
+ */
+ void layout(final Group g, final AABBox box, final PMVMatrix pmv);
}
private final List<Shape> shapes = new ArrayList<Shape>();
@@ -161,12 +173,6 @@ public class Group extends Shape implements Container {
}
}
- private void layout() {
- if( null != layouter ) {
- layouter.layout(this);
- }
- }
-
private boolean doFrustumCulling = false;
@Override
@@ -200,21 +206,25 @@ public class Group extends Shape implements Container {
@Override
protected void validateImpl(final GLProfile glp, final GL2ES2 gl) {
if( isShapeDirty() ) {
- layout();
final PMVMatrix pmv = new PMVMatrix();
final AABBox tmpBox = new AABBox();
for(final Shape s : shapes) {
- // s.validateImpl(glp, gl);
if( null != gl ) {
s.validate(gl);
} else {
s.validate(glp);
}
- pmv.glPushMatrix();
- s.setTransform(pmv);
- s.getBounds().transformMv(pmv, tmpBox);
- pmv.glPopMatrix();
- box.resize(tmpBox);
+ }
+ if( null != layouter ) {
+ layouter.layout(this, box, pmv);
+ } else {
+ for(final Shape s : shapes) {
+ pmv.glPushMatrix();
+ s.setTransform(pmv);
+ s.getBounds().transformMv(pmv, tmpBox);
+ pmv.glPopMatrix();
+ box.resize(tmpBox);
+ }
}
}
}
@@ -249,6 +259,11 @@ public class Group extends Shape implements Container {
}
@Override
+ public String getSubString() {
+ return super.getSubString()+", shapes "+shapes.size();
+ }
+
+ @Override
public boolean forOne(final PMVMatrix pmv, final Shape shape, final Runnable action) {
return TreeTool.forOne(shapes, pmv, shape, action);
}
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 bd2fd2d76..7d1739dd6 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/layout/GridLayout.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/layout/GridLayout.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2010-2023 JogAmp Community. All rights reserved.
+ * Copyright 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:
@@ -27,43 +27,135 @@
*/
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.graph.ui.Group.Layout;
+import com.jogamp.opengl.math.geom.AABBox;
+import com.jogamp.opengl.util.PMVMatrix;
+/**
+ * GraphUI Grid {@link Group.Layout}.
+ */
public class GridLayout implements Group.Layout {
- private final int columns;
- private final float padX, padY;
+ /** Layout order for {@link Group#getShapes()}} after population. */
+ public static enum Order {
+ /** COLUMN layout order of {@link Group#getShapes()}} is left to right and top to bottom. */
+ COLUMN,
+ /** ROW layout order of {@link Group#getShapes()}} is top to bottom and left to right. */
+ ROW
+ }
+ private final Order order;
+ private final int col_limit;
+ private final int row_limit;
+ private final float cellWidth, cellHeight;
+ private final Padding padding;
+ private int row_count, col_count;
+
+
+ /**
+ * Default layout order of {@link Group#getShapes()}} is {@link Order#COLUMN}.
+ * @param column_limit [1..inf)
+ * @param cellWidth
+ * @param cellHeight
+ */
+ public GridLayout(final int column_limit, final float cellWidth, final float cellHeight) {
+ this(Math.max(1, column_limit), -1, cellWidth, cellHeight, new Padding());
+ }
+
+ /**
+ * Default layout order of {@link Group#getShapes()}} is {@link Order#COLUMN}.
+ * @param column_limit [1..inf)
+ * @param cellWidth
+ * @param cellHeight
+ * @param padding
+ */
+ 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);
+ }
/**
- *
- * @param columns [1..inf)
- * @param padX
- * @param padY
+ * Default layout order of {@link Group#getShapes()}} is {@link Order#ROW}.
+ * @param cellWidth
+ * @param cellHeight
+ * @param padding
+ * @param row_limit [1..inf)
*/
- public GridLayout(final int columns, final float padX, final float padY) {
- this.columns = Math.max(1, columns);
- this.padX = padX;
- this.padY = padY;
+ 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);
+ }
+
+ private GridLayout(final int column_limit, final int row_limit, final float cellWidth, final float cellHeight, final Padding padding) {
+ this.order = 0 < column_limit ? Order.COLUMN : Order.ROW;
+ this.col_limit = column_limit;
+ this.row_limit = row_limit;
+ this.cellWidth = cellWidth;
+ this.cellHeight = cellHeight;
+ this.padding = padding;;
+ row_count = 0;
+ col_count = 0;
}
+ public Order getOrder() { return order; }
+ public int getColumnCount() { return col_count; }
+ public int getRowCount() { return row_count; }
+
@Override
- public void layout(final Group g) {
- int col = 0;
- float x=0;
- float y=0;
- for(final Shape s : g.getShapes()) {
- s.moveTo(x, y, 0);
- if( col + 1 == columns ) {
- col = 0;
- // row++;
- x = 0;
- y -= padY;
- } else {
- col++;
- x += padX;
+ public void layout(final Group g, final AABBox box, final PMVMatrix pmv) {
+ 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 );
+ }
+ int col_i = 0, row_i = 0;
+ final AABBox sbox = new AABBox();
+ for(final Shape s : shapes) {
+ // measure size
+ pmv.glPushMatrix();
+ s.setTransform(pmv);
+ s.getBounds().transformMv(pmv, sbox);
+ pmv.glPopMatrix();
+
+ // 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 );
+ 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);
+
+ // position for next cell
+ if( Order.COLUMN == order ) {
+ if( col_i + 1 == col_limit ) {
+ col_i = 0;
+ row_i++;
+ } else {
+ col_i++;
+ }
+ } else { // Order.ROW_MAJOR == order
+ if( row_i + 1 == row_limit ) {
+ row_i = 0;
+ col_i++;
+ } else {
+ row_i++;
+ }
}
}
}
+
+ @Override
+ public String toString() {
+ return "Grid["+row_count+"x"+col_count+", "+order+", cell["+cellWidth+" x "+cellHeight+"], "+padding+"]";
+ }
}
diff --git a/src/graphui/classes/com/jogamp/graph/ui/layout/Padding.java b/src/graphui/classes/com/jogamp/graph/ui/layout/Padding.java
new file mode 100644
index 000000000..f4b35e723
--- /dev/null
+++ b/src/graphui/classes/com/jogamp/graph/ui/layout/Padding.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright 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.graph.ui.layout;
+
+/**
+ * GraphUI Padding of cells, e.g. {@link GridLayout}.
+ */
+public class Padding {
+ public final float left, right, bottom, top;
+
+ public Padding() {
+ left = 0f; right = 0f; bottom = 0f; top = 0f;
+ }
+ public Padding(final float width, final float height) {
+ left = width/2f; right = width/2f; bottom = height/2f; top = height/2f;
+ }
+ public Padding(final float left, final float right, final float bottom, final float top) {
+ this.left = left; this.right = right; this.bottom = bottom; this.top = top;
+ }
+ public float width() { return left + right; }
+ public float height() { return bottom + top; }
+ @Override
+ public String toString() { return "Padding[l "+left+", r "+right+", b "+bottom+", t "+top+"]"; }
+}