diff options
author | Sven Göthel <[email protected]> | 2024-02-07 03:25:27 +0100 |
---|---|---|
committer | Sven Göthel <[email protected]> | 2024-02-07 03:25:27 +0100 |
commit | 29697eaac78bdc0c1a6cfb8547516c614dc1db8e (patch) | |
tree | c3fc6ca20df251aa150022c7b519d6a12f0053dc | |
parent | 5bacb8e6887b55ab2053dc5ed76bebcc0743a45e (diff) |
GraphUI Shape: Add MouseEvent to MoveListener; RangeSlider: Add rel obj position + NEWT MouseEvent to listener, renamed {Slider->Change}Listener and add PeekListener for mouse-over events
8 files changed, 132 insertions, 75 deletions
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java index 4839f6a83..dd10bc822 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java @@ -291,7 +291,7 @@ public class FontView01 { new SliderParam( new Vec2f(glyphGridCellSize/4f, glyphGridSize.y()), glyphGridCellSize/10f, true ) ); glyphView.getVertSlider().setColor(0.3f, 0.3f, 0.3f, 0.7f).setName("GlyphView"); if( VERBOSE_UI ) { - glyphView.getVertSlider().addSliderListener((final RangeSlider w, final float old_val, final float val, final float old_val_pct, final float val_pct) -> { + glyphView.getVertSlider().addChangeListener((final RangeSlider w, final float old_val, final float val, final float old_val_pct, final float val_pct, Vec3f pos, MouseEvent e) -> { final Vec2f minmax = w.getMinMax(); final float row_f = val / glyphGridCellSize; System.err.println("VertSlider: row["+row_f+".."+(row_f+gridDim.rowsPerPage-1)+"]/"+gridDim.rows+ diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UIMediaGrid01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UIMediaGrid01.java index f9949e70c..ad9e6c93c 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/ui/UIMediaGrid01.java +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UIMediaGrid01.java @@ -287,7 +287,7 @@ public class UIMediaGrid01 { mediaView.getVertSlider().setColor(0.3f, 0.3f, 0.3f, 0.7f).setName("MediaView"); // mediaView.setRelayoutOnDirtyShapes(false); // avoid group re-validate to ease load in Group.isShapeDirty() w/ thousands of glyphs if( VERBOSE_UI ) { - mediaView.getVertSlider().addSliderListener((final RangeSlider w, final float old_val, final float val, final float old_val_pct, final float val_pct) -> { + mediaView.getVertSlider().addChangeListener((final RangeSlider w, final float old_val, final float val, final float old_val_pct, final float val_pct, Vec3f pos, MouseEvent e) -> { final Vec2f minmax = w.getMinMax(); final float row_f = val / mediaCellHeight; System.err.println("VertSlider: row "+row_f+", val["+old_val+" -> "+val+"], pct["+(100*old_val_pct)+"% -> "+(100*val_pct)+"%], minmax "+minmax); diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo10.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo10.java index ce81d360f..8fe4a04dd 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo10.java +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo10.java @@ -118,7 +118,7 @@ public class UISceneDemo10 { scene.setPMVMatrixSetup(new MyPMVMatrixSetup()); scene.setClearParams(new float[] { 1f, 1f, 1f, 1f}, GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - shape.onMove((final Shape s, final Vec3f origin, final Vec3f dest) -> { + shape.onMove((final Shape s, final Vec3f origin, final Vec3f dest, MouseEvent e) -> { final Vec3f p = shape.getPosition(); System.err.println("Shape moved: "+origin+" -> "+p); } ); 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 8e466dbe5..27dca8358 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java @@ -727,7 +727,7 @@ public class UISceneDemo20 implements GLEventListener { } }); - button.onMove((final Shape shape, final Vec3f origin, final Vec3f dest) -> { + button.onMove((final Shape shape, final Vec3f origin, final Vec3f dest, final MouseEvent e) -> { final ALAudioSink aSink = alAudioSink[0]; if( null != aSink && aSink.getContext().isValid() ) { setSoundPosition(shape, aSink.getContext(), aSink.getSource()); @@ -804,26 +804,18 @@ public class UISceneDemo20 implements GLEventListener { System.err.println("Sine "+sineSound); } } ); - final Shape.MoveListener setAudioPosition = new Shape.MoveListener() { - @Override - public void run(final Shape shape, final Vec3f origin, final Vec3f dest) { - setSoundPosition(shape, aSink.getContext(), aSource); - } - }; - final Shape.ListenerBool initAudio = new Shape.ListenerBool() { - @Override - public boolean run(final Shape shape) { - if( null != aSink && aSink.getContext().isValid() ) { - initSound(shape, aSink.getContext(), aSource); - System.err.println("Sine Audio: "+aSink); - return true; - } else { - return false; - } + button.onInit( (final Shape shape) -> { + if( null != aSink && aSink.getContext().isValid() ) { + initSound(shape, aSink.getContext(), aSource); + System.err.println("Sine Audio: "+aSink); + return true; + } else { + return false; } - }; - button.onInit( initAudio ); - button.onMove( setAudioPosition ); + } ); + button.onMove( (final Shape shape, final Vec3f origin, final Vec3f dest, final MouseEvent e) -> { + setSoundPosition(shape, aSink.getContext(), aSource); + } ); buttonsRight.addShape(button); } if( true ) { diff --git a/src/graphui/classes/com/jogamp/graph/ui/Shape.java b/src/graphui/classes/com/jogamp/graph/ui/Shape.java index 6e5a904ee..bd0983e5d 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/Shape.java +++ b/src/graphui/classes/com/jogamp/graph/ui/Shape.java @@ -117,10 +117,11 @@ public abstract class Shape { /** * Move callback * @param s the moved shape - * @param origin original position - * @param dest new position + * @param origin original position, relative object coordinates to the associated {@link Shape} + * @param dest new position, relative object coordinates to the associated {@link Shape} + * @param e original Newt {@link MouseEvent} */ - void run(Shape s, Vec3f origin, Vec3f dest); + void run(Shape s, Vec3f origin, Vec3f dest, MouseEvent e); } /** @@ -514,7 +515,7 @@ public abstract class Shape { * Dispatch activation event event to this shape * @return true to signal operation complete and to stop traversal, otherwise false */ - private final void dispatchActivationEvent(final Shape s) { + protected final void dispatchActivationEvent(final Shape s) { final int sz = activationListeners.size(); for(int i = 0; i < sz; i++ ) { activationListeners.get(i).run(s); @@ -549,16 +550,16 @@ public abstract class Shape { return this; } - private final Shape moveNotify(final float dtx, final float dty, final float dtz) { - forwardMove(position.copy(), position.add(dtx, dty, dtz)); + private final Shape moveNotify(final float dtx, final float dty, final float dtz, final MouseEvent e) { + forwardMove(position.copy(), position.add(dtx, dty, dtz), e); return this; } - private final void forwardMove(final Vec3f origin, final Vec3f dest) { + private final void forwardMove(final Vec3f origin, final Vec3f dest, final MouseEvent e) { if( !origin.isEqual(dest) ) { iMatDirty = true; if( null != onMoveListener ) { - onMoveListener.run(this, origin, dest); + onMoveListener.run(this, origin, dest, e); } } } @@ -2047,9 +2048,9 @@ public abstract class Shape { scale, sx, sy); } if( isIO(IO_IN_RESIZE_BR) ) { - moveNotify( 0, sdy2, 0f); // bottom-right, sticky left- and top-edge + moveNotify( 0, sdy2, 0f, e); // bottom-right, sticky left- and top-edge } else { - moveNotify( sdx, sdy2, 0f); // bottom-left, sticky right- and top-edge + moveNotify( sdx, sdy2, 0f, e); // bottom-left, sticky right- and top-edge } setScale(sx, sy, scale.z()); } @@ -2060,7 +2061,7 @@ public abstract class Shape { glWinX, glWinY, shapeEvent.winDrag[0], shapeEvent.winDrag[1], x_flip, y_flip, objPos, shapeEvent.objDrag, euler); } - moveNotify( sdx, sdy, 0f); + moveNotify( sdx, sdy, 0f, e); return true; // end signal traversal with completed move } } diff --git a/src/graphui/classes/com/jogamp/graph/ui/widgets/MediaPlayer.java b/src/graphui/classes/com/jogamp/graph/ui/widgets/MediaPlayer.java index 4495570e2..7a0fed0fb 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/widgets/MediaPlayer.java +++ b/src/graphui/classes/com/jogamp/graph/ui/widgets/MediaPlayer.java @@ -304,7 +304,7 @@ public class MediaPlayer extends Widget { } } } ); - ctrlSlider.addSliderListener((final RangeSlider w, final float old_val, final float val, final float old_val_pct, final float val_pct) -> { + ctrlSlider.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) -> { if( DEBUG ) { System.err.println("Dragged "+w.getName()+": "+PTS.toTimeStr(Math.round(val), true)+"ms, "+(val_pct*100f)+"%"); System.err.println("Slider.D "+ctrlSlider.getDescription()); diff --git a/src/graphui/classes/com/jogamp/graph/ui/widgets/RangeSlider.java b/src/graphui/classes/com/jogamp/graph/ui/widgets/RangeSlider.java index 3bd11c432..2a2242f9e 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/widgets/RangeSlider.java +++ b/src/graphui/classes/com/jogamp/graph/ui/widgets/RangeSlider.java @@ -59,9 +59,9 @@ import com.jogamp.opengl.util.texture.TextureSequence; */ public final class RangeSlider extends Widget { /** - * {@link RangeSlider} slider listener + * {@link RangeSlider} slider value changed listener */ - public static interface SliderListener { + public static interface ChangeListener { /** * Slide dragged by user (including clicked position) * @param w the {@link RangeSlider} widget owning the slider @@ -69,11 +69,30 @@ public final class RangeSlider extends Widget { * @param val the absolute value position of the slider * @param old_val_pct previous percentage value position of the slider * @param val_pct the percentage value position of the slider + * @param pos object position relative to the slider's bar + * @param e NEWT original event or {@code null} if sourced from non-mouse, e.g. key-event */ - void dragged(RangeSlider w, float old_val, float val, float old_val_pct, float val_pct); + void dragged(RangeSlider w, float old_val, float val, float old_val_pct, float val_pct, Vec3f pos, MouseEvent e); } - private static interface SliderAction { - public void run(SliderListener l); + private static interface ChangedAction { + public void run(ChangeListener l); + } + /** + * {@link RangeSlider} slider value peek listener + */ + public static interface PeekListener { + /** + * Slide position/value peeked by user (mouse over/hover) + * @param w the {@link RangeSlider} widget owning the slider + * @param val the absolute value peeked at the slider + * @param val_pct the percentage value position peeked at the slider + * @param pos object position relative to the slider's bar + * @param e NEWT original event + */ + void peeked(RangeSlider w, float val, float val_pct, Vec3f pos, MouseEvent e); + } + private static interface PeekAction { + public void run(PeekListener l); } private static final boolean DEBUG = false; @@ -89,7 +108,8 @@ public final class RangeSlider extends Widget { private final Group barAndKnob, marks; private final Rectangle bar; private final GraphShape knob; - private ArrayList<SliderListener> sliderListeners = new ArrayList<SliderListener>(); + private ArrayList<ChangeListener> changeListeners = new ArrayList<ChangeListener>(); + private ArrayList<PeekListener> peekListeners = new ArrayList<PeekListener>(); private final Vec2f minMax = new Vec2f(0, 100); private final float knobScale; private float pageSize; @@ -183,27 +203,37 @@ public final class RangeSlider extends Widget { reconfig(minMax, true, value, false, 0); - knob.onMove((final Shape s, final Vec3f origin, final Vec3f dest) -> { + knob.onMove((final Shape s, final Vec3f origin, final Vec3f dest, final MouseEvent e) -> { final float old_val = val; final float old_val_pct = val_pct; if( Float.isFinite(pageSize) ) { final float dy = inverted ? +knobLength: 0; // offset to knob start - setValuePct( getKnobValuePct( dest.x(), dest.y(), dy ) ); + setValue(dest.x(), dest.y(), dy); } else { - setValuePct( getKnobValuePct( dest.x(), dest.y(), knobLength/2f ) ); // centered + setValue(dest.x(), dest.y(), knobLength/2f); // centered } - dispatchToListener( (final SliderListener l) -> { - l.dragged(RangeSlider.this, old_val, val, old_val_pct, val_pct); + dispatchToListener( (final ChangeListener l) -> { + l.dragged(RangeSlider.this, old_val, val, old_val_pct, val_pct, dest, e); }); }); bar.onClicked((final Shape s, final Vec3f pos, final MouseEvent e) -> { final float old_val = val; final float old_val_pct = val_pct; - setValuePct( getKnobValuePct( pos.x(), pos.y(), 0 ) ); - dispatchToListener( (final SliderListener l) -> { - l.dragged(RangeSlider.this, old_val, val, old_val_pct, val_pct); + setValue(pos.x(), pos.y(), 0); + dispatchToListener( (final ChangeListener l) -> { + l.dragged(RangeSlider.this, old_val, val, old_val_pct, val_pct, pos, e); + }); + }); + bar.onHover((final Shape s, final Vec3f pos, final MouseEvent e) -> { + final float pval_pct = getKnobValuePct( pos.x(), pos.y(), 0 ); + final float pval = valuePctToValue( pval_pct ); + dispatchToListener( (final PeekListener l) -> { + l.peeked(this, pval, pval_pct, pos, e); }); }); + bar.addActivationListener((final Shape s) -> { + dispatchActivationEvent(s); + }); final Shape.MouseGestureListener mouseListener = new Shape.MouseGestureAdapter() { @Override public void mouseWheelMoved(final MouseEvent e) { @@ -240,8 +270,8 @@ public final class RangeSlider extends Widget { } } setValue( v ); - dispatchToListener( (final SliderListener l) -> { - l.dragged(RangeSlider.this, old_val, val, old_val_pct, val_pct); + dispatchToListener( (final ChangeListener l) -> { + l.dragged(RangeSlider.this, old_val, val, old_val_pct, val_pct, knob.getPosition().minus(bar.getPosition()), e); }); } }; @@ -305,8 +335,8 @@ public final class RangeSlider extends Widget { } if( action ) { setValue( v ); - dispatchToListener( (final SliderListener l) -> { - l.dragged(RangeSlider.this, old_val, val, old_val_pct, val_pct); + dispatchToListener( (final ChangeListener l) -> { + l.dragged(RangeSlider.this, old_val, val, old_val_pct, val_pct, knob.getPosition().minus(bar.getPosition()), null); }); } } @@ -354,38 +384,67 @@ public final class RangeSlider extends Widget { @Override protected void clearImpl0(final GL2ES2 gl, final RegionRenderer renderer) { super.clearImpl0(gl, renderer); - sliderListeners.clear(); + changeListeners.clear(); + peekListeners.clear(); } @Override protected void destroyImpl0(final GL2ES2 gl, final RegionRenderer renderer) { super.destroyImpl0(gl, renderer); - sliderListeners.clear(); + changeListeners.clear(); + peekListeners.clear(); } - public final RangeSlider addSliderListener(final SliderListener l) { + public final RangeSlider addChangeListener(final ChangeListener l) { if(l == null) { return this; } @SuppressWarnings("unchecked") - final ArrayList<SliderListener> clonedListeners = (ArrayList<SliderListener>) sliderListeners.clone(); + final ArrayList<ChangeListener> clonedListeners = (ArrayList<ChangeListener>) changeListeners.clone(); clonedListeners.add(l); - sliderListeners = clonedListeners; + changeListeners = clonedListeners; return this; } - public final RangeSlider removeSliderListener(final SliderListener l) { + public final RangeSlider removeChangeListener(final ChangeListener l) { if (l == null) { return this; } @SuppressWarnings("unchecked") - final ArrayList<SliderListener> clonedListeners = (ArrayList<SliderListener>) sliderListeners.clone(); + final ArrayList<ChangeListener> clonedListeners = (ArrayList<ChangeListener>) changeListeners.clone(); clonedListeners.remove(l); - sliderListeners = clonedListeners; + changeListeners = clonedListeners; return this; } - private final void dispatchToListener(final SliderAction action) { - final int sz = sliderListeners.size(); + private final void dispatchToListener(final ChangedAction action) { + final int sz = changeListeners.size(); for(int i = 0; i < sz; i++ ) { - action.run( sliderListeners.get(i) ); + action.run( changeListeners.get(i) ); + } + } + + public final RangeSlider addPeekListener(final PeekListener l) { + if(l == null) { + return this; + } + @SuppressWarnings("unchecked") + final ArrayList<PeekListener> clonedListeners = (ArrayList<PeekListener>) peekListeners.clone(); + clonedListeners.add(l); + peekListeners = clonedListeners; + return this; + } + public final RangeSlider removePeekListener(final PeekListener l) { + if (l == null) { + return this; + } + @SuppressWarnings("unchecked") + final ArrayList<PeekListener> clonedListeners = (ArrayList<PeekListener>) peekListeners.clone(); + clonedListeners.remove(l); + peekListeners = clonedListeners; + return this; + } + private final void dispatchToListener(final PeekAction action) { + final int sz = peekListeners.size(); + for(int i = 0; i < sz; i++ ) { + action.run( peekListeners.get(i) ); } } @@ -596,17 +655,11 @@ public final class RangeSlider extends Widget { return reconfig(minMax, false, 0, true, pageSz); } - public RangeSlider setValuePct(final float v) { - final float range = getRange(); - if( Float.isFinite(v) && Float.isFinite(range) && !FloatUtil.isZero(range) ) { - final float pgsz_pct = Float.isFinite(pageSize) ? pageSize / range : 0f; - final float pct = Math.max(0f, Math.min(1f - pgsz_pct, v)); - return setValue( minMax.x() + ( pct * range ) ); - } else { - return setValue( 0f ); - } + private RangeSlider setValue(final float pos_x, final float pos_y, final float adjustment) { + return setValue( valuePctToValue( getKnobValuePct(pos_x, pos_y, adjustment) ) ); } + // private float getKnobValuePct(final float pos_x, final float pos_y, final float adjustment) { /** * Sets slider value * @param v new value of slider, clipped against {@link #getMinMax()} @@ -673,6 +726,16 @@ public final class RangeSlider extends Widget { } return Math.max(0.0f, Math.min(1.0f, inverted ? 1f - v : v)); } + private float valuePctToValue(final float v) { + final float range = getRange(); + if( Float.isFinite(v) && Float.isFinite(range) && !FloatUtil.isZero(range) ) { + final float pgsz_pct = Float.isFinite(pageSize) ? pageSize / range : 0f; + final float pct = Math.max(0f, Math.min(1f - pgsz_pct, v)); + return minMax.x() + ( pct * range ); + } else { + return 0f; + } + } private void setKnob() { final Vec2f pos = getItemPctPos(new Vec2f(), val_pct, knobLength, knobThickn); diff --git a/src/graphui/classes/com/jogamp/graph/ui/widgets/RangedGroup.java b/src/graphui/classes/com/jogamp/graph/ui/widgets/RangedGroup.java index e22b67c7f..0ebe3a258 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/widgets/RangedGroup.java +++ b/src/graphui/classes/com/jogamp/graph/ui/widgets/RangedGroup.java @@ -41,6 +41,7 @@ import com.jogamp.math.geom.AABBox; import com.jogamp.math.geom.Cube; import com.jogamp.math.geom.Frustum; import com.jogamp.math.util.PMVMatrix4f; +import com.jogamp.newt.event.MouseEvent; import com.jogamp.opengl.GL2ES2; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.util.texture.TextureSequence; @@ -103,7 +104,7 @@ public class RangedGroup extends Widget { horizSlider = new RangeSlider(renderModes, horizSliderParam.size, new Vec2f(0, content.getBounds().getWidth()), horizSliderParam.unitSize, contentSize.x(), 0).setInverted(horizSliderParam.inverted); addShape(horizSlider); - horizSlider.addSliderListener((final RangeSlider w, final float old_val, final float val, final float old_val_pct, final float val_pct) -> { + horizSlider.addChangeListener((final RangeSlider w, final float old_val, final float val, final float old_val_pct, final float val_pct, Vec3f pos, MouseEvent e) -> { final Vec3f oldPos = content.getPosition(); if( horizSlider.isInverted() ) { content.moveTo(contentPosZero.x()-val, oldPos.y(), oldPos.z()); @@ -118,7 +119,7 @@ public class RangedGroup extends Widget { vertSlider = new RangeSlider(renderModes, vertSliderParam.size, new Vec2f(0, content.getBounds().getHeight()), vertSliderParam.unitSize, contentSize.y(), 0).setInverted(vertSliderParam.inverted); addShape(vertSlider); - vertSlider.addSliderListener((final RangeSlider w, final float old_val, final float val, final float old_val_pct, final float val_pct) -> { + vertSlider.addChangeListener((final RangeSlider w, final float old_val, final float val, final float old_val_pct, final float val_pct, Vec3f pos, MouseEvent e) -> { final Vec3f oldPos = content.getPosition(); if( vertSlider.isInverted() ) { content.moveTo(oldPos.x(), contentPosZero.y()+val, oldPos.z()); |