JOGL v2.6.0-rc-20250706
JOGL, High-Performance Graphics Binding for Java™ (public API).
RangedGroup.java
Go to the documentation of this file.
1/**
2 * Copyright 2010-2024 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28package com.jogamp.graph.ui.widgets;
29
30import com.jogamp.graph.curve.Region;
31import com.jogamp.graph.curve.opengl.GLRegion;
32import com.jogamp.graph.curve.opengl.RegionRenderer;
33import com.jogamp.graph.ui.Group;
34import com.jogamp.graph.ui.Shape;
35import com.jogamp.graph.ui.layout.Alignment;
36import com.jogamp.graph.ui.layout.GridLayout;
37import com.jogamp.math.Vec2f;
38import com.jogamp.math.Vec3f;
39import com.jogamp.math.Vec4f;
40import com.jogamp.math.geom.AABBox;
41import com.jogamp.math.geom.Cube;
42import com.jogamp.math.geom.Frustum;
43import com.jogamp.math.util.PMVMatrix4f;
44import com.jogamp.newt.event.MouseEvent;
45import com.jogamp.opengl.GL2ES2;
46import com.jogamp.opengl.GLProfile;
47import com.jogamp.opengl.util.texture.TextureSequence;
48
49/**
50 * Ranged {@link Group} {@link Widget}, displaying a clipped content {@link Group}
51 * with optional horizontal and/or vertical {@link RangeSlider}.
52 */
53public class RangedGroup extends Widget {
54 private final Group content;
55 private final Group clippedContent;
56 private final RangeSlider horizSlider, vertSlider;
57 private final Vec2f contentPosZero = new Vec2f();
58
59 /** {@link RangeSlider} configuration parameter for {@link RangedGroup}. */
60 public static final class SliderParam {
61 /** spatial dimension of the slider box. A horizontal slider has width >= height. */
62 public final Vec2f size;
63 /** size of one unit (element) in sliding direction */
64 public final float unitSize;
65 /**
66 * Toggle whether the slider uses an inverted value range,
67 * e.g. top 0% and bottom 100% for an vertical inverted slider
68 * instead of bottom 0% and top 100% for a vertical non-inverted slider.
69 */
70 public final boolean inverted;
71
72 /**
73 *
74 * @param size spatial dimension of this slider box. A horizontal slider has width >= height.
75 * @param unitSize size of one unit (element) in sliding direction
76 * @param inverted toggle to invert value range, see {@link #inverted}
77 */
78 public SliderParam(final Vec2f size, final float unitSize, final boolean inverted) {
79 this.size = size;
80 this.unitSize = unitSize;
81 this.inverted = inverted;
82 }
83 }
84
85 /**
86 * Construct a {@link RangedGroup}
87 * @param renderModes Graph's {@link Region} render modes, see {@link GLRegion#create(GLProfile, int, TextureSequence) create(..)}.
88 * @param content the {@link Group} with content to view
89 * @param contentSize the fixed spatial size of the clipped content to view, i.e. page-size
90 * @param horizSliderParam optional initial horizontal slider parameters, null for none
91 * @param vertSliderParam optional initial vertical slider parameters, null for none
92 */
93 public RangedGroup(final int renderModes, final Group content, final Vec2f contentSize,
94 final SliderParam horizSliderParam, final SliderParam vertSliderParam)
95 {
96 super( new GridLayout(1 + (null != vertSliderParam ? 1 : 0), 0f, 0f, Alignment.None)); // vertical slider adds to the right column
97 this.content = content;
98 this.clippedContent = new Group( new GridLayout(1, 0f, 0f, Alignment.None));
99 this.clippedContent.setFixedSize(contentSize);
100 this.clippedContent.addShape(content);
101 addShape(clippedContent);
102
103 if( null != horizSliderParam ) {
104 horizSlider = new RangeSlider(renderModes, horizSliderParam.size,
105 new Vec2f(0, content.getBounds().getWidth()), horizSliderParam.unitSize, contentSize.x(), 0).setInverted(horizSliderParam.inverted);
106 addShape(horizSlider);
107 horizSlider.addChangeListener((final RangeSlider w, final float old_val, final float val, final float old_val_pct, final float val_pct, final Vec3f pos, final MouseEvent e) -> {
108 final Vec3f oldPos = content.getPosition();
109 if( horizSlider.isInverted() ) {
110 content.moveTo(contentPosZero.x()-val, oldPos.y(), oldPos.z());
111 } else {
112 content.moveTo(contentPosZero.x()+val, oldPos.y(), oldPos.z());
113 }
114 } );
115 } else {
116 horizSlider = null;
117 }
118 if( null != vertSliderParam ) {
119 vertSlider = new RangeSlider(renderModes, vertSliderParam.size,
120 new Vec2f(0, content.getBounds().getHeight()), vertSliderParam.unitSize, contentSize.y(), 0).setInverted(vertSliderParam.inverted);
121 addShape(vertSlider);
122 vertSlider.addChangeListener((final RangeSlider w, final float old_val, final float val, final float old_val_pct, final float val_pct, final Vec3f pos, final MouseEvent e) -> {
123 final Vec3f oldPos = content.getPosition();
124 if( vertSlider.isInverted() ) {
125 content.moveTo(oldPos.x(), contentPosZero.y()+val, oldPos.z());
126 } else {
127 content.moveTo(oldPos.x(), contentPosZero.y()-val, oldPos.z());
128 }
129 } );
130 } else {
131 vertSlider = null;
132 }
133 this.onDraw( (final Shape shape, final GL2ES2 gl_, final RegionRenderer renderer_) -> {
134 content.moveTo(contentPosZero.x(), contentPosZero.y(), 0);
135 return true;
136 });
137 }
138
139 public Group getContent() { return content; }
140 public Vec2f getContentSize(final Vec2f out) { return clippedContent.getFixedSize(out); }
141 public Group getClippedContent() { return clippedContent; }
142 /** Returns the used horizontal {@link RangeSlider} or {@code null}. */
143 public RangeSlider getHorizSlider() { return horizSlider; }
144 /** Returns the used vertical {@link RangeSlider} or {@code null}. */
145 public RangeSlider getVertSlider() { return vertSlider; }
146
147 @Override
148 protected void validateImpl(final GL2ES2 gl, final GLProfile glp) {
149 if( isShapeDirty() ) {
150 final Vec3f pos = content.getPosition().copy(); // preserve content position
151 super.validateImpl(gl, glp);
152
153 final AABBox cb = content.getBounds();
154 final Vec3f contentSize = clippedContent.getFixedSize();
155 contentPosZero.set(0, 0);
156 if( null != horizSlider ) {
157 horizSlider.setMinMax(new Vec2f(0, content.getBounds().getWidth()));
158 if( horizSlider.isInverted() ) {
159 contentPosZero.setX( cb.getWidth() - contentSize.x() );
160 }
161 }
162 if( null != vertSlider ) {
163 vertSlider.setMinMax(new Vec2f(0, content.getBounds().getHeight()));
164 if( vertSlider.isInverted() ) {
165 contentPosZero.setY( contentSize.y() - cb.getHeight() );
166 }
167 }
168 content.moveTo( pos );
169 }
170 }
171 @Override
172 protected void drawImpl0(final GL2ES2 gl, final RegionRenderer renderer, final Vec4f rgba) {
173 if( content.isVisible() ) {
174 final PMVMatrix4f pmv = renderer.getMatrix();
175
176 // Mv pre-multiplied Frustum, clippedContent is on same PMV
177 final Frustum clipFrustum = tempC00.set( clippedContent.getBounds() ).transform( pmv.getMv() ).updateFrustumPlanes(tempF00);
178 content.setClipMvFrustum(clipFrustum);
179 super.drawImpl0(gl, renderer, rgba);
180 content.setClipMvFrustum(null);
181 }
182 }
183 private final Frustum tempF00 = new Frustum(); // OK, synchronized
184 private final Cube tempC00 = new Cube(); // OK, synchronized
185}
final PMVMatrix4f getMatrix()
Borrow the current PMVMatrix4f.
Group of Shapes, optionally utilizing a Group.Layout.
Definition: Group.java:61
Group()
Create a group of Shapes w/o Group.Layout.
Definition: Group.java:106
void addShape(final Shape s)
Adds a Shape.
Definition: Group.java:225
AABBox getBounds(final PMVMatrix4f pmv, final Shape shape)
Returns AABBox dimension of given Shape from this container's perspective, i.e.
Definition: Group.java:686
Group setFixedSize(final Vec3f v)
Enforce size of this group for all given 3 dimensions getBounds() without adjusting 3D z-axis like se...
Definition: Group.java:156
Group setClipMvFrustum(final Frustum v)
Enable Modelview (Mv) Frustum clipping on explicit given pre-multiplied w/ Mv-matrix clip-box for thi...
Definition: Group.java:211
Vec3f getFixedSize()
Returns borrowed fixed size instance, see setFixedSize(Vec3f) and setFixedSize(Vec2f).
Definition: Group.java:164
void drawImpl0(final GL2ES2 gl, final RegionRenderer renderer, final Vec4f rgba)
Actual draw implementation, called by draw(GL2ES2, RegionRenderer).
Definition: Group.java:403
boolean isShapeDirty()
Returns the shape's dirty state, see markShapeDirty().
Definition: Group.java:561
Generic Shape, potentially using a Graph via GraphShape or other means of representing content.
Definition: Shape.java:87
final void onDraw(final DrawListener l)
Set a user one-shot initializer callback or custom draw(GL2ES2, RegionRenderer) hook.
Definition: Shape.java:477
final Shape moveTo(final float tx, final float ty, final float tz)
Move to scaled position.
Definition: Shape.java:543
final Vec3f getPosition()
Returns position Vec3f reference, i.e.
Definition: Shape.java:587
final boolean isVisible()
Returns true if this shape is set visible by the user, otherwise false.
Definition: Shape.java:353
Immutable layout alignment options, including Bit#Fill.
Definition: Alignment.java:35
static final Alignment None
No alignment constant.
Definition: Alignment.java:37
GraphUI Grid Group.Layout.
Definition: GridLayout.java:56
RangeSlider Widget either utilizing a simple positional round knob or a rectangular page-sized knob.
final RangeSlider addChangeListener(final ChangeListener l)
RangeSlider setMinMax(final Vec2f minMax, final float value)
Sets slider value range and current value, also updates related pageSize parameter if used.
RangeSlider setInverted(final boolean v)
Sets whether this slider uses an inverted value range, e.g.
boolean isInverted()
See setInverted(boolean).
RangeSlider configuration parameter for RangedGroup.
final Vec2f size
spatial dimension of the slider box.
SliderParam(final Vec2f size, final float unitSize, final boolean inverted)
final boolean inverted
Toggle whether the slider uses an inverted value range, e.g.
final float unitSize
size of one unit (element) in sliding direction
Ranged Group Widget, displaying a clipped content Group with optional horizontal and/or vertical Rang...
void validateImpl(final GL2ES2 gl, final GLProfile glp)
void drawImpl0(final GL2ES2 gl, final RegionRenderer renderer, final Vec4f rgba)
Actual draw implementation, called by draw(GL2ES2, RegionRenderer).
RangeSlider getHorizSlider()
Returns the used horizontal RangeSlider or null.
RangeSlider getVertSlider()
Returns the used vertical RangeSlider or null.
RangedGroup(final int renderModes, final Group content, final Vec2f contentSize, final SliderParam horizSliderParam, final SliderParam vertSliderParam)
Construct a RangedGroup.
A widget specifies specific UI semantics including individual controls.
Definition: Widget.java:44
2D Vector based upon two float components.
Definition: Vec2f.java:37
void set(final Vec2f o)
this = o, returns this.
Definition: Vec2f.java:73
void setY(final float y)
Definition: Vec2f.java:139
void setX(final float x)
Definition: Vec2f.java:138
3D Vector based upon three float components.
Definition: Vec3f.java:37
4D Vector based upon four float components.
Definition: Vec4f.java:37
Axis Aligned Bounding Box.
Definition: AABBox.java:54
final float getWidth()
Definition: AABBox.java:879
final float getHeight()
Definition: AABBox.java:883
Simple 8-point Vec3f cube compound having z-far <= z-near @endiliteral.
Definition: Cube.java:48
Frustum updateFrustumPlanes(final Frustum frustum)
Calculate the frustum planes using this Cube.
Definition: Cube.java:194
Cube transform(final Matrix4f mat)
Affine 3f-vector transformation of all 8-points with given matrix, Matrix4f#mulVec3f(Vec3f).
Definition: Cube.java:163
Cube set(final AABBox box)
Setting this cube to given AABBox minimum and maximum.
Definition: Cube.java:126
Providing frustum planes derived by different inputs (P*MV, ..) used to classify objects.
Definition: Frustum.java:81
PMVMatrix4f implements the basic computer graphics Matrix4f pack using projection (P),...
final Matrix4f getMv()
Returns the modelview matrix (Mv).
Pointer event of type PointerType.
Definition: MouseEvent.java:74
Specifies the the OpenGL profile.
Definition: GLProfile.java:77