diff options
author | Sven Göthel <[email protected]> | 2024-01-07 21:27:18 +0100 |
---|---|---|
committer | Sven Göthel <[email protected]> | 2024-01-07 21:27:18 +0100 |
commit | 6dbd73108ec0b2f829674c07771c232395034157 (patch) | |
tree | f6d8083e5384f4b80785a03f6d30d9e061a2af76 /src/graphui/classes/com/jogamp/graph | |
parent | c2452b211dc3f347dbffaac4e6c35b3c3e8c6d65 (diff) |
GraphUI Tooltip: Simplify integration w/ Scene + Shape; Use Shape.setToolTip(Tooltip) for generic usage; Add TooltipText colors.
Shape also takes care of setting Tooltip's tool-Shape (itself),
simplifying Tooltip ctor and having it more independent from Scene/Shape.
Tooltip also drop Scene reference, as it shall be passed from Scene caller
at Tooltip.createTip(..)
Diffstat (limited to 'src/graphui/classes/com/jogamp/graph')
5 files changed, 101 insertions, 66 deletions
diff --git a/src/graphui/classes/com/jogamp/graph/ui/Scene.java b/src/graphui/classes/com/jogamp/graph/ui/Scene.java index e2dc96b8d..15ced642b 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/Scene.java +++ b/src/graphui/classes/com/jogamp/graph/ui/Scene.java @@ -133,8 +133,8 @@ public final class Scene implements Container, GLEventListener { private static final boolean DEBUG = false; private final List<Shape> shapes = new CopyOnWriteArrayList<Shape>(); - private final AtomicReference<Tooltip> startedToolTip = new AtomicReference<Tooltip>(); - private final AtomicReference<GraphShape> toolTipHUD = new AtomicReference<GraphShape>(); + private final AtomicReference<Tooltip> toolTipStarted = new AtomicReference<Tooltip>(); + private final AtomicReference<Shape> toolTipHUD = new AtomicReference<Shape>(); private boolean doFrustumCulling = false; @@ -503,12 +503,11 @@ public final class Scene implements Container, GLEventListener { displayedOnce = true; syncDisplayedOnce.notifyAll(); } - final Tooltip tt = startedToolTip.get(); + final Tooltip tt = toolTipStarted.get(); if( null != tt && null == toolTipHUD.get() ) { - final GraphShape[] t = { null }; - if( tt.tick() && forOne(pmv, tt.tool, () -> { t[0] = tt.createTip(pmv); }) ) { - toolTipHUD.set( t[0] ); - startedToolTip.set(null); + final Shape[] hud = { null }; + if( tt.tick() && forOne(pmv, tt.getTool(), () -> { hud[0] = tt.createTip(Scene.this, pmv); }) ) { + setToolTip( hud[0] ); } } } @@ -1053,7 +1052,7 @@ public final class Scene implements Container, GLEventListener { private final class SBCGestureListener implements GestureHandler.GestureListener { @Override public void gestureDetected(final GestureEvent gh) { - clearToolTips(); + clearToolTip(); if( null != activeShape ) { // gesture .. delegate to active shape! final InputEvent orig = gh.getTrigger(); @@ -1121,7 +1120,7 @@ public final class Scene implements Container, GLEventListener { @Override public void mousePressed(final MouseEvent e) { - clearToolTips(); + clearToolTip(); if( -1 == lId || e.getPointerId(0) == lId ) { lx = e.getX(); ly = e.getY(); @@ -1135,7 +1134,7 @@ public final class Scene implements Container, GLEventListener { @Override public void mouseReleased(final MouseEvent e) { - clearToolTips(); + clearToolTip(); // flip to GL window coordinates, origin bottom-left final int glWinX = e.getX(); final int glWinY = getHeight() - e.getY() - 1; @@ -1151,7 +1150,7 @@ public final class Scene implements Container, GLEventListener { @Override public void mouseClicked(final MouseEvent e) { - clearToolTips(); + clearToolTip(); // flip to GL window coordinates final int glWinX = e.getX(); final int glWinY = getHeight() - e.getY() - 1; @@ -1168,7 +1167,7 @@ public final class Scene implements Container, GLEventListener { @Override public void mouseDragged(final MouseEvent e) { - clearToolTips(); + clearToolTip(); // drag activeShape, if no gesture-activity, only on 1st pointer if( null != activeShape && activeShape.isInteractive() && !pinchToZoomGesture.isWithinGesture() && e.getPointerId(0) == lId ) { lx = e.getX(); @@ -1184,7 +1183,7 @@ public final class Scene implements Container, GLEventListener { @Override public void mouseWheelMoved(final MouseEvent e) { - clearToolTips(); + clearToolTip(); // flip to GL window coordinates final int glWinX = lx; final int glWinY = getHeight() - ly - 1; @@ -1193,7 +1192,7 @@ public final class Scene implements Container, GLEventListener { @Override public void mouseMoved(final MouseEvent e) { - clearToolTips(); + clearToolTip(); if( -1 == lId || e.getPointerId(0) == lId ) { lx = e.getX(); ly = e.getY(); @@ -1204,7 +1203,7 @@ public final class Scene implements Container, GLEventListener { final Shape s = dispatchMouseEventPickShape(e, glWinX, glWinY); if( null != s ) { mouseOver = true; - startedToolTip.set( s.startToolTip() ); + toolTipStarted.set( s.startToolTip() ); } else { mouseOver = false; } @@ -1213,7 +1212,7 @@ public final class Scene implements Container, GLEventListener { public void mouseEntered(final MouseEvent e) { } @Override public void mouseExited(final MouseEvent e) { - clearToolTips(); + clearToolTip(); releaseActiveShape(); clear(); } @@ -1234,7 +1233,17 @@ public final class Scene implements Container, GLEventListener { } } - private void clearToolTips() { + private void setToolTip(final Shape hud) { + toolTipStarted.set( null ); + addShape( hud ); + toolTipHUD.set( hud ); + } + + private void clearToolTip() { + final Tooltip tt = toolTipStarted.getAndSet(null); + if( null != tt ) { + tt.stop(); + } final Shape s = toolTipHUD.getAndSet(null); if( null != s ) { invoke(false, (final GLAutoDrawable drawable) -> { @@ -1242,10 +1251,6 @@ public final class Scene implements Container, GLEventListener { return true; }); } - final Tooltip tt = startedToolTip.getAndSet(null); - if( null != tt ) { - tt.stop(); - } } /** diff --git a/src/graphui/classes/com/jogamp/graph/ui/Shape.java b/src/graphui/classes/com/jogamp/graph/ui/Shape.java index cb5a5e896..6d1a80a06 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/Shape.java +++ b/src/graphui/classes/com/jogamp/graph/ui/Shape.java @@ -205,7 +205,6 @@ public abstract class Shape { private static final float resize_sxy_min = 1f/200f; // 1/2% - TODO: Maybe customizable? private static final float resize_section = 1f/5f; // resize action in a corner - private static final long toolTipdelayMS = 1000; private volatile Tooltip tooltip = null; /** @@ -1333,22 +1332,23 @@ public abstract class Shape { return position.z() * getScale().z() + zOffset; } - /** Set's a {@link TooltipText} for this shape using default 1s delay */ - public Tooltip setToolTip(final CharSequence text, final Font font, final float scaleY, final Scene scene) { - final Tooltip oldTT = tooltip; - tooltip = null; - final Tooltip newTT = new TooltipText(text, font, scaleY, this, toolTipdelayMS, scene, Region.VBAA_RENDERING_BIT); + /** Set's a new {@link Tooltip} for this shape. */ + public Tooltip setToolTip(final Tooltip newTooltip) { + final Tooltip oldTT = this.tooltip; + this.tooltip = null; if( null != oldTT ) { oldTT.stop(); } - tooltip = newTT; - return newTT; + newTooltip.setToolOwner(this); + this.tooltip = newTooltip; + return newTooltip; } public void removeToolTip() { final Tooltip tt = tooltip; tooltip = null; if( null != tt ) { tt.stop(); + tt.setToolOwner(null); } } private void stopToolTip() { diff --git a/src/graphui/classes/com/jogamp/graph/ui/Tooltip.java b/src/graphui/classes/com/jogamp/graph/ui/Tooltip.java index 88cfeac99..b8e2467fe 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/Tooltip.java +++ b/src/graphui/classes/com/jogamp/graph/ui/Tooltip.java @@ -30,30 +30,37 @@ package com.jogamp.graph.ui; import com.jogamp.common.os.Clock; import com.jogamp.math.util.PMVMatrix4f; -/** A HUD tooltip for {@link Shape}, see {@link Shape#setToolTip(CharSequence, com.jogamp.graph.font.Font, float, Scene)}. */ +/** A HUD tooltip for {@link Shape}, see {@link Shape#setToolTip(Tooltip)}. */ public abstract class Tooltip { - /** Shape belonging to this tooltip's tool. */ - protected final Shape tool; - protected final long delayMS; - protected final Scene scene; + /** Default tooltip delay is {@value}ms */ + public static final long DEFAULT_DELAY = 1000; + + private final long delayMS; /** Delay t1, time to show tooltip, i.e. t0 + delayMS */ - protected volatile long delayT1; + private volatile long delayT1; + /** Shape 'tool' owning this tooltip. */ + private Shape tool; - protected Tooltip(final Shape tool, final long delayMS, final Scene scene) { - this.tool = tool; + protected Tooltip(final long delayMS) { this.delayMS = delayMS; - this.scene = scene; this.delayT1 = 0; + this.tool = null; + } + /* pp */ final void setToolOwner(final Shape owner) { tool = owner; } + + /** Returns {@link Shape} 'tool' owning this tooltip, set after {@link Shape#setToolTip(Tooltip)}. */ + public final Shape getTool() { + return tool; } /** Stops the timer. */ - public void stop() { + public final void stop() { this.delayT1 = 0; } /** Starts the timer. */ - public void start() { + public final void start() { this.delayT1 = Clock.currentMillis() + delayMS; } @@ -61,7 +68,7 @@ public abstract class Tooltip { * Send tick to this tooltip * @return true if timer has been reached to {@link #createTip(PMVMatrix4f)}, otherwise false */ - public boolean tick() { + public final boolean tick() { if( 0 == delayT1 ) { return false; } @@ -73,10 +80,11 @@ public abstract class Tooltip { } /** - * Create a new HUD tip shape + * Create a new HUD tip shape, usually called by {@link Scene} + * @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)} * @return newly created HUD tip shape */ - public abstract GraphShape createTip(final PMVMatrix4f pmv); + public abstract Shape createTip(final Scene scene, final PMVMatrix4f pmv); }
\ No newline at end of file diff --git a/src/graphui/classes/com/jogamp/graph/ui/TooltipText.java b/src/graphui/classes/com/jogamp/graph/ui/TooltipText.java index 6c2912bf4..b421604c9 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/TooltipText.java +++ b/src/graphui/classes/com/jogamp/graph/ui/TooltipText.java @@ -31,35 +31,58 @@ import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.GLRegion; import com.jogamp.graph.font.Font; import com.jogamp.graph.ui.shapes.Button; +import com.jogamp.math.Vec4f; import com.jogamp.math.geom.AABBox; import com.jogamp.math.geom.plane.AffineTransform; import com.jogamp.math.util.PMVMatrix4f; import com.jogamp.opengl.GLProfile; -/** A HUD text {@link Tooltip} for {@link Shape}, see {@link Shape#setToolTip(CharSequence, com.jogamp.graph.font.Font, float, Scene)}. */ +/** A HUD text {@link Tooltip} for {@link Shape}, see {@link Shape#setToolTip(Tooltip)}. */ public class TooltipText extends Tooltip { /** Text of this tooltip */ - final private CharSequence tipText; + private final CharSequence tipText; /** Font of this tooltip */ - final private Font tipFont; - final private float scaleY; - final private int renderModes; + private final Font tipFont; + private final float scaleY; + private final int renderModes; + private final Vec4f backColor = new Vec4f(); + private final Vec4f labelColor = new Vec4f(); + /** * Ctor of {@link TooltipText}. - * @param scene the {@link Scene} to be attached to while pressed + * @param tipText HUD tip text + * @param tipFont HUD tip font + * @param backColor HUD tip background color + * @param labelColor HUD tip label color + * @param scaleY HUD tip vertical scale against tool height + * @param delayMS delay until HUD tip is visible after timer start (mouse moved) * @param renderModes Graph's {@link Region} render modes, see {@link GLRegion#create(GLProfile, int, TextureSequence) create(..)}. */ - /* pp */ TooltipText(final CharSequence tipText, final Font tipFont, final float scaleY, final Shape tool, final long delayMS, final Scene scene, final int renderModes) { - super(tool, delayMS, scene); + public TooltipText(final CharSequence tipText, final Font tipFont, final Vec4f backColor, final Vec4f labelColor, + final float scaleY, final long delayMS, final int renderModes) + { + super(delayMS); this.tipText = tipText; this.tipFont = tipFont; this.scaleY = scaleY; this.renderModes = renderModes; + this.backColor.set(backColor); + this.labelColor.set(labelColor); + } + /** + * Ctor of {@link TooltipText} using {@link Tooltip#DEFAULT_DELAY}, {@link Region#VBAA_RENDERING_BIT} + * and a slightly transparent yellow background with an almost black opaque text color. + * @param tipText HUD tip text + * @param tipFont HUD tip font + * @param scaleY HUD tip vertical scale against tool height + * @param tool the tool shape for this tip + */ + public TooltipText(final CharSequence tipText, final Font tipFont, final float scaleY) { + this(tipText, tipFont, new Vec4f(1, 1, 0, 0.80f), new Vec4f(0.1f, 0.1f, 0.1f, 1), scaleY, Tooltip.DEFAULT_DELAY, Region.VBAA_RENDERING_BIT); } @Override - public GraphShape createTip(final PMVMatrix4f pmv) { - this.delayT1 = 0; + public Shape createTip(final Scene scene, final PMVMatrix4f pmv) { final float zEps = scene.getZEpsilon(16); // Precompute text-box size .. guessing pixelSize @@ -68,7 +91,7 @@ public class TooltipText extends Tooltip { final AABBox tipBox_em = tipFont.getGlyphBounds(tipText, tempT1, tempT2); // final AABBox toolAABox = scene.getBounds(new PMVMatrix4f(), tool); - final AABBox toolAABox = tool.getBounds().transform(pmv.getMv(), new AABBox()); + final AABBox toolAABox = getTool().getBounds().transform(pmv.getMv(), new AABBox()); final float h = toolAABox.getHeight() * scaleY; final float w = tipBox_em.getWidth() / tipBox_em.getHeight() * h; @@ -88,12 +111,11 @@ public class TooltipText extends Tooltip { final Button ntip = (Button) new Button(renderModes, tipFont, tipText, w, h, zEps) .setPerp() .moveTo(xpos, ypos, 100*zEps) - .setColor(1, 1, 0, 0.80f) + .setColor(backColor) // .setBorder(0.05f).setBorderColor(0, 0, 0, 1) .setInteractive(false); - ntip.setLabelColor(0, 0, 0); + ntip.setLabelColor(labelColor); ntip.setSpacing(0.10f, 0.10f); - scene.addShape(ntip); return ntip; } } 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 2cde62668..57a9b3909 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/widgets/MediaPlayer.java +++ b/src/graphui/classes/com/jogamp/graph/ui/widgets/MediaPlayer.java @@ -162,7 +162,7 @@ public class MediaPlayer extends Widget { for(final GLMediaPlayer.Chapter c : mp.getChapters()) { System.err.println(c); final Shape mark = ctrlSlider.addMark(c.start, new Vec4f(0.9f, 0.9f, 0.9f, 0.5f)); - mark.setToolTip(c.title+"\n"+PTS.millisToTimeStr(c.start, false), fontInfo, 5, scene); + mark.setToolTip(new TooltipText(c.title+"\n"+PTS.millisToTimeStr(c.start, false), fontInfo, 5)); } } else if( eventMask.isSet(GLMediaPlayer.EventMask.Bit.Play) ) { playButton.setToggle(true); @@ -306,7 +306,7 @@ public class MediaPlayer extends Widget { }); playButton.setToggle(true); // on == play ctrlGroup.addShape(playButton); - playButton.setToolTip("Play", fontInfo, toolTipScaleY, scene); + playButton.setToolTip(new TooltipText("Play", fontInfo, toolTipScaleY)); } { // 2 final Button button = new Button(renderModes, fontSymbols, @@ -317,7 +317,7 @@ public class MediaPlayer extends Widget { mPlayer.seek(0); }); ctrlGroup.addShape(button); - button.setToolTip("Back", fontInfo, toolTipScaleY, scene); + button.setToolTip(new TooltipText("Back", fontInfo, toolTipScaleY)); } { // 3 final Button button = new Button(renderModes, fontSymbols, @@ -328,7 +328,7 @@ public class MediaPlayer extends Widget { mPlayer.setPlaySpeed(mPlayer.getPlaySpeed() - 0.5f); }); ctrlGroup.addShape(button); - button.setToolTip("Fast-Rewind", fontInfo, toolTipScaleY, scene); + button.setToolTip(new TooltipText("Fast-Rewind", fontInfo, toolTipScaleY)); } { // 4 final Button button = new Button(renderModes, fontSymbols, @@ -339,7 +339,7 @@ public class MediaPlayer extends Widget { mPlayer.setPlaySpeed(mPlayer.getPlaySpeed() + 0.5f); }); ctrlGroup.addShape(button); - button.setToolTip("Fast-Forward", fontInfo, toolTipScaleY, scene); + button.setToolTip(new TooltipText("Fast-Forward", fontInfo, toolTipScaleY)); } { // 5 final Button button = new Button(renderModes, fontSymbols, @@ -358,7 +358,7 @@ public class MediaPlayer extends Widget { mPlayer.seek(pts1); } } ); ctrlGroup.addShape(button); - button.setToolTip("Replay 5", fontInfo, toolTipScaleY, scene); + button.setToolTip(new TooltipText("Replay-5", fontInfo, toolTipScaleY)); } { // 6 final Button button = new Button(renderModes, fontSymbols, @@ -377,7 +377,7 @@ public class MediaPlayer extends Widget { mPlayer.seek(pts1); } } ); ctrlGroup.addShape(button); - button.setToolTip("Forward 5", fontInfo, toolTipScaleY, scene); + button.setToolTip(new TooltipText("Forward-5", fontInfo, toolTipScaleY)); } { // 7 final Button button = new Button(renderModes, fontSymbols, @@ -401,7 +401,7 @@ public class MediaPlayer extends Widget { } } ); button.setToggle( !mPlayer.isAudioMuted() ); // on == volume ctrlGroup.addShape(button); - button.setToolTip("Volume", fontInfo, toolTipScaleY, scene); + button.setToolTip(new TooltipText("Volume", fontInfo, toolTipScaleY)); } { // 8 ctrlGroup.addShape(timeLabel); @@ -467,7 +467,7 @@ public class MediaPlayer extends Widget { }); button.setToggle( false ); // on == zoom ctrlGroup.addShape(button); - button.setToolTip("Zoom", fontInfo, toolTipScaleY, scene); + button.setToolTip(new TooltipText("Zoom", fontInfo, toolTipScaleY)); } for(final Shape cs : customCtrls ) { ctrlGroup.addShape(cs); |