diff options
Diffstat (limited to 'src')
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+"]"; } +} |