summaryrefslogtreecommitdiffstats
path: root/src/graphui/classes/com/jogamp/graph
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-04-28 12:40:23 +0200
committerSven Gothel <[email protected]>2023-04-28 12:40:23 +0200
commit87814f1c86b132a16ddf6822d05b83c3ed091fe2 (patch)
tree885134dd7398a748a0837b536a26771c933dafd2 /src/graphui/classes/com/jogamp/graph
parentbd10664189e944699492008776819a28a2d95ecf (diff)
GraphUI Revise Padding and Border: Padding + Border belong to Shape's bounds. Account for both (seperately) and add border rendering to Group as well.
Diffstat (limited to 'src/graphui/classes/com/jogamp/graph')
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/GraphShape.java27
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/Group.java38
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/Scene.java12
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/Shape.java74
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/layout/Margin.java2
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/layout/Padding.java2
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/shapes/Rectangle.java46
7 files changed, 159 insertions, 42 deletions
diff --git a/src/graphui/classes/com/jogamp/graph/ui/GraphShape.java b/src/graphui/classes/com/jogamp/graph/ui/GraphShape.java
index 040b0a32c..7dccd41a0 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/GraphShape.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/GraphShape.java
@@ -34,8 +34,10 @@ import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.GLRegion;
import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.ui.layout.Padding;
import com.jogamp.opengl.GL2ES2;
import com.jogamp.opengl.GLProfile;
+import com.jogamp.opengl.math.Vec3f;
import com.jogamp.opengl.math.Vec4f;
import com.jogamp.opengl.util.texture.TextureSequence;
@@ -206,9 +208,18 @@ public abstract class GraphShape extends Shape {
clearDirtyRegions(gl);
}
if( isShapeDirty() ) {
+ // box has been reset
addShapeToRegion(glp, gl); // calls updateGLRegion(..)
if( hasBorder() ) {
+ // Also takes padding into account
addBorderOutline();
+ } else if( hasPadding() ) {
+ final Padding p = getPadding();
+ final Vec3f l = box.getLow();
+ final Vec3f h = box.getHigh();
+ box.resize(l.x() - p.left, l.y() - p.bottom, l.z());
+ box.resize(h.x() + p.right, h.y() + p.top, l.z());
+ setRotationPivot( box.getCenter() );
}
region.setQuality(regionQuality);
} else if( isStateDirty() ) {
@@ -218,10 +229,11 @@ public abstract class GraphShape extends Shape {
protected void addBorderOutline() {
final OutlineShape shape = new OutlineShape();
- final float x1 = box.getMinX();
- final float x2 = box.getMaxX();
- final float y1 = box.getMinY();
- final float y2 = box.getMaxY();
+ final Padding dist = null != getPadding() ? getPadding() : new Padding();
+ final float x1 = box.getMinX() - dist.left;
+ final float x2 = box.getMaxX() + dist.right;
+ final float y1 = box.getMinY() - dist.bottom;
+ final float y2 = box.getMaxY() + dist.top;
final float z = box.getCenter().z(); // 0; // box.getMinZ() + 0.025f;
{
// Outer OutlineShape as Winding.CCW.
@@ -235,8 +247,7 @@ public abstract class GraphShape extends Shape {
}
{
// Inner OutlineShape as Winding.CW.
- final float dxy0 = box.getWidth() < box.getHeight() ? box.getWidth() : box.getHeight();
- final float dxy = dxy0 * getBorderThickness();
+ final float dxy = getBorderThickness();
shape.moveTo(x1+dxy, y1+dxy, z);
shape.lineTo(x1+dxy, y2-dxy, z);
shape.lineTo(x2-dxy, y2-dxy, z);
@@ -246,7 +257,9 @@ public abstract class GraphShape extends Shape {
}
shape.setIsQuadraticNurbs();
shape.setSharpness(oshapeSharpness);
- region.addOutlineShape(shape, null, borderColor);
+ region.addOutlineShape(shape, null, getBorderColor());
+ box.resize(shape.getBounds()); // border <-> shape = padding, and part of shape size
+ setRotationPivot( box.getCenter() );
}
protected void clearImpl(final GL2ES2 gl, final RegionRenderer renderer) { }
diff --git a/src/graphui/classes/com/jogamp/graph/ui/Group.java b/src/graphui/classes/com/jogamp/graph/ui/Group.java
index 1de20240d..d82df3a52 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/Group.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/Group.java
@@ -33,10 +33,14 @@ import java.util.Collection;
import java.util.Comparator;
import java.util.List;
+import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.GLRegion;
import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.ui.layout.Padding;
+import com.jogamp.graph.ui.shapes.Rectangle;
import com.jogamp.opengl.GL2ES2;
import com.jogamp.opengl.GLProfile;
+import com.jogamp.opengl.math.Vec3f;
import com.jogamp.opengl.math.Vec4f;
import com.jogamp.opengl.math.geom.AABBox;
import com.jogamp.opengl.util.PMVMatrix;
@@ -70,6 +74,7 @@ public class Group extends Shape implements Container {
private final List<Shape> shapes = new ArrayList<Shape>();
private Layout layouter;
+ private Rectangle border = null;
/**
* Create a Graph based {@link GLRegion} UI {@link Shape}.
@@ -126,7 +131,6 @@ public class Group extends Shape implements Container {
/** Removes given shape and destroy it. */
public void removeShape(final GL2ES2 gl, final RegionRenderer renderer, final Shape s) {
- s.setBorder(0f);
shapes.remove(s);
s.destroy(gl, renderer);
}
@@ -183,6 +187,10 @@ public class Group extends Shape implements Container {
// s.destroyImpl0(gl, renderer);
s.destroy(gl, renderer);;
}
+ if( null != border ) {
+ border.destroy(gl, renderer);
+ border = null;
+ }
}
private boolean doFrustumCulling = false;
@@ -208,7 +216,6 @@ public class Group extends Shape implements Container {
shape.setTransform(pmv);
if( !doFrustumCulling || !pmv.getFrustum().isAABBoxOutside( shape.getBounds() ) ) {
- // FIXME: Optimize to reuse modulated rgba
if( null == rgba ) {
shape.drawToSelect(gl, renderer, sampleCount);
} else {
@@ -218,11 +225,19 @@ public class Group extends Shape implements Container {
pmv.glPopMatrix();
}
}
+ if( null != border ) {
+ if( null == rgba ) {
+ border.drawToSelect(gl, renderer, sampleCount);
+ } else {
+ border.draw(gl, renderer, sampleCount);
+ }
+ }
}
@Override
protected void validateImpl(final GLProfile glp, final GL2ES2 gl) {
if( isShapeDirty() ) {
+ // box has been reset
final PMVMatrix pmv = new PMVMatrix();
if( null != layouter ) {
for(final Shape s : shapes) {
@@ -248,6 +263,25 @@ public class Group extends Shape implements Container {
box.resize(tsbox);
}
}
+ if( hasPadding() ) {
+ final Padding p = getPadding();
+ final Vec3f l = box.getLow();
+ final Vec3f h = box.getHigh();
+ box.resize(l.x() - p.left, l.y() - p.bottom, l.z());
+ box.resize(h.x() + p.right, h.y() + p.top, l.z());
+ setRotationPivot( box.getCenter() );
+ }
+ if( hasBorder() ) {
+ if( null == border ) {
+ border = new Rectangle(Region.VBAA_RENDERING_BIT, box, getBorderThickness());
+ } else {
+ border.setEnabled(true);
+ border.setBounds(box, getBorderThickness());
+ }
+ border.setColor(getBorderColor());
+ } else if( null != border ) {
+ border.setEnabled(false);
+ }
}
}
diff --git a/src/graphui/classes/com/jogamp/graph/ui/Scene.java b/src/graphui/classes/com/jogamp/graph/ui/Scene.java
index 4955e683a..4ddcc719c 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/Scene.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/Scene.java
@@ -110,7 +110,7 @@ public final class Scene implements Container, GLEventListener {
private static final boolean DEBUG = false;
private final List<Shape> shapes = new ArrayList<Shape>();
- private float dbgbox_thickness = 0f;
+ private float dbgBorderThickness = 0f;
private boolean doFrustumCulling = false;
private float[] clearColor = null;
@@ -217,7 +217,7 @@ public final class Scene implements Container, GLEventListener {
}
@Override
public void addShape(final Shape s) {
- s.setBorder(dbgbox_thickness);
+ s.setBorder(dbgBorderThickness);
shapes.add(s);
}
@Override
@@ -315,11 +315,11 @@ public final class Scene implements Container, GLEventListener {
}
/**
- * Sets the {@link #getBounds()} fractional thickness of the debug box ranging [0..1] for all shapes, zero for no debug box (default).
- * @param v fractional thickness of {@link #getBounds()} ranging [0..1], zero for no debug box
+ * Sets the debug {@link Shape#setBorder(float) border} thickness for all existing or added shapes, zero for no debug border (default).
+ * @param v thickness debug border, zero for no border
*/
- public final void setDebugBox(final float v) {
- dbgbox_thickness = v;
+ public final void setDebugBorderBox(final float v) {
+ dbgBorderThickness = v;
for(int i=0; i<shapes.size(); i++) {
shapes.get(i).setBorder(v);
}
diff --git a/src/graphui/classes/com/jogamp/graph/ui/Shape.java b/src/graphui/classes/com/jogamp/graph/ui/Shape.java
index 5ef40a57f..5f88550dd 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/Shape.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/Shape.java
@@ -35,6 +35,7 @@ import com.jogamp.opengl.GL2ES2;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.ui.layout.Padding;
import com.jogamp.newt.event.GestureHandler.GestureEvent;
import com.jogamp.newt.event.GestureHandler.GestureListener;
import com.jogamp.newt.event.MouseAdapter;
@@ -63,6 +64,9 @@ import com.jogamp.opengl.util.PMVMatrix;
* A shape is expected to have its 0/0 origin in its bottom-left corner, otherwise the drag-zoom sticky-edge will not work as expected.
* </p>
* <p>
+ * A shape's {@link #getBounds()} includes its optional {@link #getPadding()} and optional {@link #getBorderThickness()}.
+ * </p>
+ * <p>
* GraphUI is GPU based and resolution independent.
* </p>
* <p>
@@ -136,8 +140,9 @@ public abstract class Shape {
private boolean resizable = true;
private boolean interactive = true;
private boolean enabled = true;
- private float border_thickness = 0f;
- protected final Vec4f borderColor = new Vec4f(0.75f, 0.75f, 0.75f, 1.0f);
+ private float borderThickness = 0f;
+ private Padding padding = null;
+ private final Vec4f borderColor = new Vec4f(0.0f, 0.0f, 0.0f, 1.0f);
private ArrayList<MouseGestureListener> mouseListeners = new ArrayList<MouseGestureListener>();
private Listener onMoveListener = null;
@@ -159,18 +164,49 @@ public abstract class Shape {
public final Shape setEnabled(final boolean v) { enabled = v; return this; }
/**
- * Sets the thickness of the debug box, zero for no border (default).
- * @param v border thickness, zero for no debug box
+ * Sets the padding for this shape, which is included in {@link #getBounds()B} and also includes the border. Default is zero.
+ *
+ * Method issues {@link #markShapeDirty()}.
+ *
+ * @param padding distance of shape to the border, i.e. padding
+ * @return this shape for chaining
+ * @see #getPadding()
+ * @see #hasPadding()
+ */
+ public final Shape setPaddding(final Padding padding) {
+ this.padding = padding;
+ markShapeDirty();
+ return this;
+ }
+
+ /**
+ * Returns {@link Padding} of this shape, which is included in {@link #getBounds()B} and also includes the border. Default is zero.
+ * @see #setPaddding(Padding)
+ * @see #hasPadding()
*/
- public final Shape setBorder(final float v) {
- border_thickness = Math.max(0f, v);
+ public Padding getPadding() { return padding; }
+
+ /** Returns true if {@link #setPaddding(Padding)} added a non {@link Padding#zeroSumSize()} spacing to this shape. */
+ public boolean hasPadding() { null != padding && !padding.zeroSumSize(); }
+
+ /**
+ * Sets the thickness of the border, which is included in {@link #getBounds()} and is outside of {@link #getPadding()}. Default is zero for no border.
+ *
+ * Method issues {@link #markShapeDirty()}.
+ *
+ * @param thickness border thickness, zero for no border
+ * @return this shape for chaining
+ */
+ public final Shape setBorder(final float thickness) {
+ borderThickness = Math.max(0f, thickness);
+ markShapeDirty();
return this;
}
- /** Returns true if a border has been enabled via {@link #setBorder(float)}. */
- public final boolean hasBorder() { return !FloatUtil.isZero(border_thickness); }
+ /** Returns true if a border has been enabled via {@link #setBorder(float, Padding)}. */
+ public final boolean hasBorder() { return !FloatUtil.isZero(borderThickness); }
- /** Returns the border thickness, see {@link #setBorder(float)}. */
- public final float getBorderThickness() { return border_thickness; }
+ /** Returns the border thickness, see {@link #setBorder(float, Padding)}. */
+ public final float getBorderThickness() { return borderThickness; }
/**
* Clears all data and reset all states as if this instance was newly created
@@ -319,8 +355,10 @@ public abstract class Shape {
/**
* Returns the unscaled bounding {@link AABBox} for this shape, borrowing internal instance.
*
- * The returned {@link AABBox} will only cover this unscaled shape
- * after an initial call to {@link #draw(GL2ES2, RegionRenderer, int[]) draw(..)}
+ * The returned {@link AABBox} will cover the unscaled shape
+ * as well as its optional {@link #getPadding()} and optional {@link #getBorderThickness()}.
+ *
+ * The returned {@link AABBox} is only valid after an initial call to {@link #draw(GL2ES2, RegionRenderer, int[]) draw(..)}
* or {@link #validate(GL2ES2)}.
*
* @see #getBounds(GLProfile)
@@ -330,8 +368,10 @@ public abstract class Shape {
/**
* Returns the scaled width of the bounding {@link AABBox} for this shape.
*
- * The returned width will only cover the scaled shape
- * after an initial call to {@link #draw(GL2ES2, RegionRenderer, int[]) draw(..)}
+ * The returned width will cover the scaled shape
+ * as well as its optional scaled {@link #getPadding()} and optional scaled {@link #getBorderThickness()}.
+ *
+ * The returned width is only valid after an initial call to {@link #draw(GL2ES2, RegionRenderer, int[]) draw(..)}
* or {@link #validate(GL2ES2)}.
*
* @see #getBounds()
@@ -343,8 +383,10 @@ public abstract class Shape {
/**
* Returns the scaled height of the bounding {@link AABBox} for this shape.
*
- * The returned height will only cover the scaled shape
- * after an initial call to {@link #draw(GL2ES2, RegionRenderer, int[]) draw(..)}
+ * The returned height will cover the scaled shape
+ * as well as its optional scaled {@link #getPadding()} and optional scaled {@link #getBorderThickness()}.
+ *
+ * The returned height is only valid after an initial call to {@link #draw(GL2ES2, RegionRenderer, int[]) draw(..)}
* or {@link #validate(GL2ES2)}.
*
* @see #getBounds()
diff --git a/src/graphui/classes/com/jogamp/graph/ui/layout/Margin.java b/src/graphui/classes/com/jogamp/graph/ui/layout/Margin.java
index f78c9dea9..fde7217b6 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/layout/Margin.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/layout/Margin.java
@@ -30,7 +30,7 @@ package com.jogamp.graph.ui.layout;
import com.jogamp.opengl.math.FloatUtil;
/**
- * GraphUI CSS property Margin, space between or around elements.
+ * GraphUI CSS property Margin, space between or around elements and not included in the element's size.
*
* The CSS margin properties are used to create space around elements, outside of any defined borders.
*
diff --git a/src/graphui/classes/com/jogamp/graph/ui/layout/Padding.java b/src/graphui/classes/com/jogamp/graph/ui/layout/Padding.java
index 52c46bc3a..1d5eca002 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/layout/Padding.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/layout/Padding.java
@@ -30,7 +30,7 @@ package com.jogamp.graph.ui.layout;
import com.jogamp.opengl.math.FloatUtil;
/**
- * GraphUI CSS property Padding, space belonging to the element.
+ * GraphUI CSS property Padding, space belonging to the element and included in the element's size.
*
* The CSS padding properties are used to generate space around an element's content, inside of any defined borders.
*/
diff --git a/src/graphui/classes/com/jogamp/graph/ui/shapes/Rectangle.java b/src/graphui/classes/com/jogamp/graph/ui/shapes/Rectangle.java
index 90433a45e..2b9698e3a 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/shapes/Rectangle.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/shapes/Rectangle.java
@@ -31,42 +31,70 @@ import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.ui.GraphShape;
import com.jogamp.opengl.GL2ES2;
import com.jogamp.opengl.GLProfile;
+import com.jogamp.opengl.math.geom.AABBox;
/**
- * A GraphUI Rectangle {@link GraphShape}
+ * A GraphUI rectangle {@link GraphShape}
* <p>
* GraphUI is GPU based and resolution independent.
* </p>
*/
public class Rectangle extends GraphShape {
- private float width, height, lineWidth;
+ private float minX, minY, zPos;
+ private float width;
+ private float height;
+ private float lineWidth;
- public Rectangle(final int renderModes, final float width, final float height, final float linewidth) {
+ public Rectangle(final int renderModes, final float minX, final float minY, final float width, final float height, final float lineWidth, final float zPos) {
super(renderModes);
+ this.minX = minX;
+ this.minY = minY;
+ this.zPos = zPos;
this.width = width;
this.height = height;
- this.lineWidth = linewidth;
+ this.lineWidth = lineWidth;
+ }
+
+ public Rectangle(final int renderModes, final AABBox abox, final float lineWidth) {
+ this( renderModes, abox.getMinX(), abox.getMinY(), abox.getWidth(), abox.getHeight(), lineWidth, abox.getCenter().z());
+ }
+
+ public Rectangle(final int renderModes, final float minX, final float minY, final float width, final float height, final float lineWidth) {
+ this( renderModes, minX, minY, width, height, lineWidth, 0);
+ }
+ public Rectangle(final int renderModes, final float width, final float height, final float lineWidth) {
+ this( renderModes, 0, 0, width, height, lineWidth, 0);
}
public final float getWidth() { return width; }
public final float getHeight() { return height; }
public final float getLineWidth() { return lineWidth; }
+ public void setPosition(final float minX, final float minY, final float zPos) {
+ this.minX = minX;
+ this.minY = minY;
+ this.zPos = zPos;
+ markShapeDirty();
+ }
public void setDimension(final float width, final float height, final float lineWidth) {
this.width = width;
this.height = height;
this.lineWidth = lineWidth;
markShapeDirty();
}
+ public void setBounds(final AABBox abox, final float lineWidth) {
+ setPosition(abox.getMinX(), abox.getMinY(), abox.getCenter().z());
+ setDimension(abox.getWidth(), abox.getHeight(), lineWidth);
+ }
@Override
protected void addShapeToRegion(final GLProfile glp, final GL2ES2 gl) {
final OutlineShape shape = new OutlineShape();
- final float x1 = 0f;
- final float y1 = 0f;
- final float x2 = getWidth();
- final float y2 = getHeight();
- final float z = 0f;
+ final float x1 = minX;
+ final float y1 = minY;
+ final float x2 = minX + getWidth();
+ final float y2 = minY + getHeight();
+ final float z = zPos;
{
// Outer OutlineShape as Winding.CCW.
shape.moveTo(x1, y1, z);