diff options
author | Sven Göthel <[email protected]> | 2024-01-20 05:11:28 +0100 |
---|---|---|
committer | Sven Göthel <[email protected]> | 2024-01-20 05:11:28 +0100 |
commit | 018f2633ba8f7106439ec70829d2444abf0c389b (patch) | |
tree | 1be2e6b9090cfd25600d147ae819982b8053f926 /src/graphui/classes/com/jogamp/graph | |
parent | 5a24e0bbaaa0cdb61292e264b4919295fff40a2a (diff) |
GraphUI Tooltip*: Allow user to trigger display via now(); Ensure TooltipShape.DestroyCallback gets passed the user provided Shape only
Diffstat (limited to 'src/graphui/classes/com/jogamp/graph')
4 files changed, 108 insertions, 45 deletions
diff --git a/src/graphui/classes/com/jogamp/graph/ui/Scene.java b/src/graphui/classes/com/jogamp/graph/ui/Scene.java index fa11f2675..5c9c6859e 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/Scene.java +++ b/src/graphui/classes/com/jogamp/graph/ui/Scene.java @@ -485,15 +485,8 @@ public final class Scene implements Container, GLEventListener { syncDisplayedOnce.notifyAll(); } final Tooltip tt = toolTipActive.get(); - if( null != tt && null == toolTipHUD.get() ) { - final Shape[] hud = { null }; - if( tt.tick() && forOne(pmv, tt.getTool(), () -> { - final AABBox toolMvBounds = tt.getToolMvBounds(pmv); - hud[0] = tt.createTip(drawable, Scene.this, pmv, toolMvBounds); - }) ) - { - setToolTip( hud[0] ); - } + if( null != tt ) { + activateTooltipImpl(drawable, pmv, tt); } } @@ -1103,7 +1096,7 @@ public final class Scene implements Container, GLEventListener { @Override public void mousePressed(final MouseEvent e) { - clearToolTip(); + // clearToolTip(); if( -1 == lId || e.getPointerId(0) == lId ) { lx = e.getX(); ly = e.getY(); @@ -1117,7 +1110,7 @@ public final class Scene implements Container, GLEventListener { @Override public void mouseReleased(final MouseEvent e) { - clearToolTip(); + // clearToolTip(); // flip to GL window coordinates, origin bottom-left final int glWinX = e.getX(); final int glWinY = getHeight() - e.getY() - 1; @@ -1133,7 +1126,6 @@ public final class Scene implements Container, GLEventListener { @Override public void mouseClicked(final MouseEvent e) { - clearToolTip(); // flip to GL window coordinates final int glWinX = e.getX(); final int glWinY = getHeight() - e.getY() - 1; @@ -1146,6 +1138,7 @@ public final class Scene implements Container, GLEventListener { releaseActiveShape(); clear(); } + clearToolTip(); } @Override @@ -1158,8 +1151,8 @@ public final class Scene implements Container, GLEventListener { // dragged .. delegate to active shape! // flip to GL window coordinates, origin bottom-left - final int glWinX = lx; - final int glWinY = getHeight() - ly - 1; + final int glWinX = e.getX(); + final int glWinY = getHeight() - e.getY() - 1; dispatchMouseEventForShape(activeShape, e, glWinX, glWinY); } } @@ -1175,7 +1168,6 @@ public final class Scene implements Container, GLEventListener { @Override public void mouseMoved(final MouseEvent e) { - clearToolTip(); if( -1 == lId || e.getPointerId(0) == lId ) { lx = e.getX(); ly = e.getY(); @@ -1184,9 +1176,12 @@ public final class Scene implements Container, GLEventListener { final int glWinX = lx; final int glWinY = getHeight() - ly - 1; final Shape s = dispatchMouseEventPickShape(e, glWinX, glWinY); + clearToolTip(); if( null != s ) { mouseOver = true; - toolTipActive.set( s.startToolTip() ); + synchronized( toolTipActive ) { + toolTipActive.set( s.startToolTip(true /* lookupParents */) ); + } } else { mouseOver = false; } @@ -1222,20 +1217,39 @@ public final class Scene implements Container, GLEventListener { } private void clearToolTip() { - final Tooltip tt = toolTipActive.getAndSet(null); - if( null != tt ) { - tt.stop(); + final Tooltip tt; + synchronized( toolTipActive ) { + tt = toolTipActive.get(); + if( null != tt && tt.stop(false) ) { + toolTipActive.set(null); + } } final Shape s = toolTipHUD.getAndSet(null); if( null != s ) { invoke(false, (final GLAutoDrawable drawable) -> { - if( s == removeShape(s) ) { - tt.destroyTip(drawable.getGL().getGL2ES2(), renderer, s); + if( null != tt ) { + if( s == removeShape(s) ) { + tt.destroyTip(drawable.getGL().getGL2ES2(), renderer, s); + } + } else { + removeShape(drawable.getGL().getGL2ES2(), renderer, s); } return true; }); } } + private void activateTooltipImpl(final GLAutoDrawable drawable, final PMVMatrix4f pmv, final Tooltip tt) { + if( null == toolTipHUD.get() ) { + final Shape[] hud = { null }; + if( tt.tick() && forOne(pmv, tt.getTool(), () -> { + final AABBox toolMvBounds = tt.getToolMvBounds(pmv); + hud[0] = tt.createTip(drawable, Scene.this, pmv, toolMvBounds); + }) ) + { + setToolTip( hud[0] ); + } + } + } /** * Return a formatted status string containing avg fps and avg frame duration. diff --git a/src/graphui/classes/com/jogamp/graph/ui/Shape.java b/src/graphui/classes/com/jogamp/graph/ui/Shape.java index 672aab9a7..36b15d739 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/Shape.java +++ b/src/graphui/classes/com/jogamp/graph/ui/Shape.java @@ -214,7 +214,7 @@ public abstract class Shape { private static final int DIRTY_SHAPE = 1 << 0 ; private static final int DIRTY_STATE = 1 << 1 ; - private Group parent; + private volatile Group parent = null; protected final AABBox box; private final Vec3f position = new Vec3f(); @@ -286,6 +286,7 @@ public abstract class Shape { } protected void setParent(final Group c) { parent = c; } + /** * Returns the last parent container {@link Group} this shape has been added to or {@code null}. * <p> @@ -500,17 +501,17 @@ 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)); - return this; - } - /** Move about scaled distance. Position ends up in PMVMatrix4f unmodified. No {@link MoveListener} notification will occur. */ public final Shape move(final Vec3f dt) { position.add(dt); return this; } + private final Shape moveNotify(final float dtx, final float dty, final float dtz) { + forwardMove(position.copy(), position.add(dtx, dty, dtz)); + return this; + } + private final void forwardMove(final Vec3f origin, final Vec3f dest) { if( !origin.isEqual(dest) ) { if( null != onMoveListener ) { @@ -1389,7 +1390,7 @@ public abstract class Shape { releaseInteraction(); final Tooltip tt = tooltip; if( null != tt ) { - tt.stop(); + tt.stop(false); } } if( DEBUG ) { @@ -1429,7 +1430,7 @@ public abstract class Shape { final Tooltip oldTT = this.tooltip; this.tooltip = null; if( null != oldTT ) { - oldTT.stop(); + oldTT.stop(true); } newTooltip.setTool(this); this.tooltip = newTooltip; @@ -1439,21 +1440,31 @@ public abstract class Shape { final Tooltip tt = tooltip; tooltip = null; if( null != tt ) { - tt.stop(); + tt.stop(true); tt.setTool(null); } } private void stopToolTip() { final Tooltip tt = tooltip; if( null != tt ) { - tt.stop(); + tt.stop(true); } } - /* pp */ Tooltip startToolTip() { - final Tooltip tt = tooltip; + /* pp */ Tooltip startToolTip(final boolean lookupParents) { + Tooltip tt = tooltip; if( null != tt ) { tt.start(); return tt; + } else if( lookupParents ) { + Shape p = getParent(); + while( null != p ) { + tt = p.startToolTip(false); + if( null != tt ) { + return tt; + } else { + p = p.getParent(); + } + } } return null; } diff --git a/src/graphui/classes/com/jogamp/graph/ui/Tooltip.java b/src/graphui/classes/com/jogamp/graph/ui/Tooltip.java index 7bed984f5..b7a79b4ca 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/Tooltip.java +++ b/src/graphui/classes/com/jogamp/graph/ui/Tooltip.java @@ -47,12 +47,18 @@ public abstract class Tooltip { private final long delayMS; /** Delay t1, time to show tooltip, i.e. t0 + delayMS */ private volatile long delayT1; + /** Toggle for forced tooltip display */ + private volatile boolean forced; /** Shape 'tool' owning this tooltip. */ private Shape tool; protected final int renderModes; protected final Vec4f backColor = new Vec4f(1, 1, 0, 1); protected final Vec4f frontColor = new Vec4f(0.1f, 0.1f, 0.1f, 1); + @Override + public String toString() { + return "Tooltip[d "+delayMS+", next "+delayT1+", forced "+forced+"]"; + } /** * * @param backColor optional HUD tip background color @@ -63,6 +69,7 @@ public abstract class Tooltip { protected Tooltip(final Vec4f backColor, final Vec4f frontColor, final long delayMS, final int renderModes) { this.delayMS = delayMS; this.delayT1 = 0; + this.forced = false; this.tool = null; this.renderModes = renderModes; if( null != backColor ) { @@ -79,19 +86,45 @@ public abstract class Tooltip { return tool; } - /** Stops the timer. */ - public final void stop() { - this.delayT1 = 0; + /** + * Stops the timer if not enforced via {@link #now()} or {@code clearForced} is true. + * @param clearForced if true, also clears enforced flag set by {@link #now()} + * @return true if timer has been stopped, otherwise false + */ + public final boolean stop(final boolean clearForced) { + if( clearForced ) { + this.delayT1 = 0; + this.forced = false; + return true; + } else if( !this.forced ) { + this.delayT1 = 0; + return true; + } else { + return false; + } } /** Starts the timer. */ public final void start() { - this.delayT1 = Clock.currentMillis() + delayMS; + if( !this.forced ) { + this.delayT1 = Clock.currentMillis() + delayMS; + } + } + + /** Enforce tooltip display with next {@link #tick()}. */ + public final void now() { + this.forced = true; + this.delayT1 = Clock.currentMillis() - 1; + } + + /** Returns true if display is enforced via {@link #now()}. */ + public final boolean forced() { + return forced; } /** * Send tick to this tooltip - * @return true if timer has been reached to {@link #createTip(PMVMatrix4f)}, otherwise false + * @return true if {@link #start() started} timer has been reached or is enforced via {@link #now()} to {@link #createTip(PMVMatrix4f)}, otherwise false */ public final boolean tick() { if( 0 == delayT1 ) { @@ -101,6 +134,7 @@ public abstract class Tooltip { return false; } this.delayT1 = 0; + this.forced = false; return true; } @@ -136,7 +170,7 @@ public abstract class Tooltip { * @param drawable current {@link GLAutoDrawable} * @param scene the {@link Scene} caller for which this HUD tip shape is created * @param pmv {@link PMVMatrix4f}, which shall be properly initialized, e.g. via {@link Scene#setupMatrix(PMVMatrix4f)} - * @param toolMvBounds TODO + * @param toolMvBounds {@link AABBox} of the {@link #getTool()} in model-view (Mv) space of the given {@link Scene} * @return newly created HUD tip shape * @see #destroyTip(GL2ES2, RegionRenderer, Shape) */ diff --git a/src/graphui/classes/com/jogamp/graph/ui/TooltipShape.java b/src/graphui/classes/com/jogamp/graph/ui/TooltipShape.java index ec3dbf45f..40cc8c66d 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/TooltipShape.java +++ b/src/graphui/classes/com/jogamp/graph/ui/TooltipShape.java @@ -30,7 +30,6 @@ package com.jogamp.graph.ui; import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.ui.layout.Alignment; import com.jogamp.graph.ui.layout.BoxLayout; -import com.jogamp.graph.ui.layout.GridLayout; import com.jogamp.graph.ui.shapes.Rectangle; import com.jogamp.math.Vec2f; import com.jogamp.math.Vec4f; @@ -50,7 +49,7 @@ public class TooltipShape extends Tooltip { * </p> * @param gl * @param renderer - * @param tip + * @param tip the user provided {@link Shape} as passed via {@link TooltipShape#TooltipShape(Vec4f, Vec4f, float, Vec2f, long, int, Shape, DestroyCallback)}. * @see TooltipShape#TooltipShape(Vec2f, long, Shape, DestroyCallback) * @see TooltipShape#createTip(GLAutoDrawable, Scene, PMVMatrix4f, AABBox) */ @@ -106,8 +105,9 @@ public class TooltipShape extends Tooltip { final float h = toolMvBounds.getHeight()*scale.y(); final Group g = new Group(new BoxLayout(w, h, Alignment.FillCenter)); - g.addShape(new Rectangle(renderModes, 1*w/h, 1, 0).setColor(backColor).setBorder(borderThickness).setBorderColor(frontColor)); - g.addShape(tip.move(0, 0, zEps)); // above back + g.addShape(new Rectangle(renderModes, 1*w/h, 1, 0).setColor(backColor).setBorder(borderThickness).setBorderColor(frontColor).move(0, 0, -zEps)); + g.setName("TooltipShapeGroup"); + g.addShape(tip); g.setInteractive(false); final Vec2f pos = getTipMvPosition(scene, toolMvBounds, w, h); @@ -115,11 +115,15 @@ public class TooltipShape extends Tooltip { return g; } @Override - public void destroyTip(final GL2ES2 gl, final RegionRenderer renderer, final Shape tip) { + public void destroyTip(final GL2ES2 gl, final RegionRenderer renderer, final Shape tipGroup) { if( null != dtorCallback ) { + // Remove user tip from our layout group first and dtor our group + // This allows the user to receive its own passed tip + ((Group)tipGroup).removeShape(tip); + tipGroup.destroy(gl, renderer); dtorCallback.destroyTip(gl, renderer, tip); } else { - super.destroyTip(gl, renderer, tip); + super.destroyTip(gl, renderer, tipGroup); } } } |