aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-09-23 04:02:23 +0200
committerSven Gothel <[email protected]>2023-09-23 04:02:23 +0200
commit3ecb8e9d1bfd1149f32b05c13c5ec1be6c0cab54 (patch)
tree3d87c109d06875d38a2ae07130c37863c9b104f3
parent6c97c5fa201d221a37773db54994d27e34ba86c3 (diff)
GraphUI Layout: Add UILayoutBoxGridOffset01, showing behavior w/ shapes not starting at 0/0 but at an offset
OK for centered or non-zoomed .. as used w/ FontView01 to show the underline space. Sure, Fill (zoom) w/o center on offset shapes is tricky and a matter of definition and taste, but in general useless.
-rw-r--r--make/scripts/tests.sh6
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBoxGridOffset01.java373
2 files changed, 376 insertions, 3 deletions
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index ce5401339..309a0604e 100644
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -1008,10 +1008,10 @@ function testawtswt() {
#testawt com.jogamp.opengl.demos.es2.GearsES2 $*
#testnoawt com.jogamp.opengl.demos.graph.ui.UIGraphDemoU01a $*
#testnoawt com.jogamp.opengl.demos.graph.ui.UILayoutGrid01 $*
-#testnoawt com.jogamp.opengl.demos.graph.ui.UILayoutGrid02 $*
-#testnoawt com.jogamp.opengl.demos.av.MovieCube $*
-testnoawt com.jogamp.opengl.demos.av.MovieSimple $*
#testnoawt com.jogamp.opengl.demos.graph.ui.UILayoutBox01 $*
+testnoawt com.jogamp.opengl.demos.graph.ui.UILayoutBoxGridOffset01 $*
+#testnoawt com.jogamp.opengl.demos.av.MovieCube $*
+#testnoawt com.jogamp.opengl.demos.av.MovieSimple $*
#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/UILayoutBoxGridOffset01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBoxGridOffset01.java
new file mode 100644
index 000000000..dc865045a
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBoxGridOffset01.java
@@ -0,0 +1,373 @@
+/**
+ * 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.layout.Alignment;
+import com.jogamp.graph.ui.layout.BoxLayout;
+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.Label;
+import com.jogamp.graph.ui.shapes.Rectangle;
+import com.jogamp.math.FloatUtil;
+import com.jogamp.math.Vec3f;
+import com.jogamp.math.Vec4f;
+import com.jogamp.math.geom.AABBox;
+import com.jogamp.math.geom.plane.AffineTransform;
+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.Tooltips;
+import com.jogamp.opengl.demos.util.CommandlineOptions;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Res independent {@link Shape}s with offset (not starting at origin)
+ * in a {@link Group} using {@link BoxLayout} and {@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 UILayoutBoxGridOffset01 {
+ static CommandlineOptions options = new CommandlineOptions(1920, 1080, Region.VBAA_RENDERING_BIT);
+
+ static boolean reLayout = true;
+ static final int reLayoutSleep = 500;
+
+ private static final Vec4f groupBorderColor = new Vec4f(0, 0, 1f, 0.6f);
+ private static final float borderThickness = 0.01f;
+
+ 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;
+ } else if (args[idx[0]].equals("-no_relayout")) {
+ reLayout = false;
+ }
+ }
+ }
+ System.err.println(options);
+
+ final GLProfile reqGLP = GLProfile.get(options.glProfileName);
+ System.err.println("GLProfile: "+reqGLP);
+
+ final Animator animator = new Animator(0 /* w/o AWT */);
+
+ 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(UILayoutBoxGridOffset01.class.getSimpleName()+": "+window.getSurfaceWidth()+" x "+window.getSurfaceHeight());
+ window.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowResized(final WindowEvent e) {
+ window.setTitle(UILayoutBoxGridOffset01.class.getSimpleName()+": "+window.getSurfaceWidth()+" x "+window.getSurfaceHeight());
+ }
+ @Override
+ public void windowDestroyNotify(final WindowEvent e) {
+ animator.stop();
+ }
+ });
+
+
+ final int zBits = 16;
+ final Scene scene = new Scene(options.graphAASamples);
+ scene.setPMVMatrixSetup(new Scene.DefaultPMVMatrixSetup(-1f));
+ System.err.println("Z16-Precision: default "+Scene.DEFAULT_Z16_EPSILON);
+ System.err.println("Z16-Precision: zDist -1f, zNear 0.1f "+FloatUtil.getZBufferEpsilon(zBits, -1f, 0.1f));
+ System.err.println("Z16-Precision: current "+scene.getZEpsilon(zBits));
+ 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();
+
+ //
+ // 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();
+ final float zEps = scene.getZEpsilon(zBits); // Z Epsilon, i.e. minimum recognized delta (resolution)
+ System.err.println("SceneBox "+sceneBox+", zEps "+zEps);
+
+ final float cellGapX = sceneBox.getWidth() / 6f;
+ final float cellGapY = sceneBox.getHeight() * 0.40f;
+ // final float sxy = 1/10f * sceneBox.getWidth();
+ final float sxy = 1/12f * sceneBox.getWidth();
+ // final float sxy = 1/4f * sceneBox.getHeight();
+ final Vec3f nextPos = new Vec3f();
+
+ {
+ final float minX = 0.00f, minY = 0.00f, width = 0.5f, height = 0.5f, lineWidth = 0.05f;
+ if( true ) {
+ final Group g = setupGroup(new Group(new BoxLayout(1f, 1f, Alignment.None)),
+ reqGLP, scene, zEps,
+ sxy, nextPos, cellGapX,
+ font, 11,
+ (final Group gp) -> {
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ }, minX, minY );
+ nextPos.setX( nextPos.x() + cellGapX );
+ }
+ }
+ {
+ final float minX = 0.125f, minY = 0.125f, width = 0.5f, height = 0.5f, lineWidth = 0.05f;
+ if( true ) {
+ final Group g = setupGroup(new Group(new BoxLayout(1f, 1f, Alignment.None)),
+ reqGLP, scene, zEps,
+ sxy, nextPos, cellGapX,
+ font, 12,
+ (final Group gp) -> {
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ }, minX, minY );
+ nextPos.setX( nextPos.x() + cellGapX );
+ }
+ if( true ) {
+ final Group g = setupGroup(new Group(new BoxLayout(1f, 1f, Alignment.Fill)),
+ reqGLP, scene, zEps,
+ sxy, nextPos, cellGapX,
+ font, 13,
+ (final Group gp) -> {
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ }, minX, minY );
+ nextPos.setX( nextPos.x() + cellGapX );
+ }
+ if( true ) {
+ final Group g = setupGroup(new Group(new BoxLayout(1f, 1f, Alignment.Center)),
+ reqGLP, scene, zEps,
+ sxy, nextPos, cellGapX,
+ font, 14,
+ (final Group gp) -> {
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ }, minX, minY );
+ nextPos.setX( nextPos.x() + cellGapX );
+ }
+ if( true ) {
+ final Group g = setupGroup(new Group(new BoxLayout(1f, 1f, Alignment.FillCenter)),
+ reqGLP, scene, zEps,
+ sxy, nextPos, cellGapX,
+ font, 15,
+ (final Group gp) -> {
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ }, minX, minY );
+ nextPos.setX( nextPos.x() + cellGapX );
+ }
+ }
+
+
+ //
+ //
+ // next line
+ nextPos.set(0, nextPos.y() + cellGapY / 2f, 0 );
+
+ {
+ final float minX = 0.000f, minY = 0.000f, width = 0.5f, height = 0.5f, lineWidth = 0.05f;
+ if( true ) {
+ final Group g = setupGroup(new Group(new GridLayout(2, 1f, 1f, Alignment.None)),
+ reqGLP, scene, zEps,
+ sxy, nextPos, cellGapX,
+ font, 21,
+ (final Group gp) -> {
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ }, minX, minY );
+ nextPos.setX( nextPos.x() + cellGapX );
+ }
+ }
+ {
+ final float minX = 0.125f, minY = 0.125f, width = 0.5f, height = 0.5f, lineWidth = 0.05f;
+ if( true ) {
+ final Group g = setupGroup(new Group(new GridLayout(2, 1f, 1f, Alignment.None)),
+ reqGLP, scene, zEps,
+ sxy, nextPos, cellGapX,
+ font, 22,
+ (final Group gp) -> {
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ }, minX, minY );
+ nextPos.setX( nextPos.x() + cellGapX );
+ }
+ if( true ) {
+ final Group g = setupGroup(new Group(new GridLayout(2, 1f, 1f, Alignment.Fill)),
+ reqGLP, scene, zEps,
+ sxy, nextPos, cellGapX,
+ font, 23,
+ (final Group gp) -> {
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ }, minX, minY );
+ nextPos.setX( nextPos.x() + cellGapX );
+ }
+ if( true ) {
+ final Group g = setupGroup(new Group(new GridLayout(2, 1f, 1f, Alignment.Center)),
+ reqGLP, scene, zEps,
+ sxy, nextPos, cellGapX,
+ font, 24,
+ (final Group gp) -> {
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ }, minX, minY );
+ nextPos.setX( nextPos.x() + cellGapX );
+ }
+ if( true ) {
+ final Group g = setupGroup(new Group(new GridLayout(2, 1f, 1f, Alignment.FillCenter)),
+ reqGLP, scene, zEps,
+ sxy, nextPos, cellGapX,
+ font, 25,
+ (final Group gp) -> {
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ gp.addShape( new Rectangle(options.renderModes, minX, minY, width, height, lineWidth, 0).setDragAndResizeable(false) );
+ }, minX, minY );
+ nextPos.setX( nextPos.x() + cellGapX );
+ }
+ }
+
+ // next line
+ nextPos.set(0, nextPos.y() + cellGapY, 0 );
+
+ // ...
+
+ {
+ final AABBox sceneDim = scene.getBounds();
+ final String text = " Press group description to magnify! ";
+ final AABBox textDim = font.getGlyphBounds(text, new AffineTransform(), new AffineTransform());
+ final float l_sxy = 1/4f * sceneDim.getWidth() / textDim.getWidth();
+
+ final Shape label = new Label(options.renderModes, font, text).setColor(0, 0, 0, 1).setInteractive(false)
+ .scale(l_sxy, l_sxy, 1).moveTo(sceneDim.getLow())
+ .move(sceneDim.getWidth() - textDim.getWidth()*l_sxy, sceneDim.getHeight() - textDim.getHeight()*l_sxy, 0);
+ scene.addShape(label);
+ }
+
+ try { Thread.sleep(1000); } catch (final InterruptedException e1) { }
+ scene.screenshot(true, scene.nextScreenshotFile(null, UILayoutBoxGridOffset01.class.getSimpleName(), options.renderModes, caps, null));
+ if( !options.stayOpen ) {
+ window.destroy();
+ }
+ }
+
+ static interface GroupMod {
+ void mod(Group group);
+ }
+ static Group setupGroup(final Group g, final GLProfile reqGLP, final Scene scene, final float zEps,
+ final float sxy, final Vec3f nextPos, final float cellGap,
+ final Font font, final int id,
+ final GroupMod modImpl, final float offX, final float offY) {
+ final String suffix = String.format("%2d", id);
+ g.setName(id);
+ final AABBox sceneBox = scene.getBounds();
+ modImpl.mod(g);
+ g.setBorder(borderThickness).setBorderColor(groupBorderColor);
+ g.scale(sxy, sxy, 1);
+ g.setInteractive(true);
+ g.validate(reqGLP);
+ g.moveTo(sceneBox.getLow()).move(nextPos);
+ System.err.println("Group-"+suffix+" "+g);
+ System.err.println("Group-"+suffix+" Layout "+g.getLayout());
+ g.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ scene.addShape(g);
+ {
+ final float X_width = font.getGlyph(font.getGlyphID(' ')).getAdvance();
+ /**
+ * ID 23: G 23, size[total 2.1 x 1.7, cell 1.0 x 0.5]
+ * Padding[t 0.05, r 0.05, b 0.05, l 0.05]
+ * Gap[r 0.1, c 0.1], Align [CenterHoriz, CenterVert, Fill]
+ */
+ final String fixed_text = "Gap[r 0.1, c 0.1], Align [CenterHoriz, CenterVert, Fi";
+ final float l_sxy = g.getScaledWidth() / font.getGlyphBounds(fixed_text, new AffineTransform(), new AffineTransform()).getWidth();
+
+ final String text;
+ final Group.Layout l = g.getLayout();
+ if( l instanceof GridLayout ) {
+ final GridLayout gl = (GridLayout)l;
+ text = String.format("Grid %2d, off %.3f/%.3f, size[total %.1f x %.1f, cell %.1f x %.1f]%n%s%n%s, Align %s",
+ id, offX, offY, g.getBounds().getWidth(), g.getBounds().getHeight(), gl.getCellSize().x(), gl.getCellSize().y(),
+ ( null == gl.getPadding() || gl.getPadding().zeroSumSize() ) ? "Padding none" : gl.getPadding().toString(),
+ gl.getGap().zeroSumSize() ? "Gap none" : gl.getGap().toString(),
+ gl.getAlignment() );
+ } else if( l instanceof BoxLayout ){
+ final BoxLayout bl = (BoxLayout)l;
+ text = String.format("Box %2d, off %.3f/%.3f, size[total %.1f x %.1f, cell %.1f x %.1f]%n%s%n%s, Align %s",
+ id, offX, offY, g.getBounds().getWidth(), g.getBounds().getHeight(), bl.getCellSize().x(), bl.getCellSize().y(),
+ ( null == bl.getPadding() || bl.getPadding().zeroSumSize() ) ? "Padding none" : bl.getPadding().toString(),
+ bl.getMargin().zeroSumSize() ? "Margin none" : bl.getMargin().toString(),
+ bl.getAlignment() );
+ } else {
+ text = String.format("Layout %2d, off %.3f/%.3f, size[total %.1f x %.1f", id, offX, offY, g.getBounds().getWidth(), g.getBounds().getHeight());
+ }
+ final Shape label = new Label(options.renderModes, font, text).setColor(0, 0, 0, 1).validate(reqGLP);
+ label.scale(l_sxy, l_sxy, 1).moveTo(sceneBox.getLow()).move(nextPos).move(l_sxy*X_width, g.getScaledHeight(), 0)
+ .addMouseListener(new Tooltips.ZoomLabelOnClickListener(scene, options.renderModes, 1/6f)).setDragAndResizeable(false);
+ scene.addShape(label);
+ }
+ if( reLayout ) {
+ try { Thread.sleep(reLayoutSleep); } catch (final InterruptedException e1) { }
+ g.markShapeDirty();
+ g.validate(reqGLP);
+ System.err.println("Group-"+suffix+".2 "+g);
+ System.err.println("Group-"+suffix+" Layout.2 "+g.getLayout());
+ g.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
+ }
+ return g;
+ }
+
+}