Leveraging tooltips

@sgold said: On a hunch, I commented out my code which invokes screen.releaseForcedToolTip() and the issue went away, at least partially. So I think my issue has to do with releasing the forced tool tip when there isn't one set.

[java]
public void releaseForcedToolTip() {
if (useToolTips) {
forcedToolTip = false;
forcedToolTipText = “”;
toolTip.setText(“”);
toolTip.hide();
}
}
[/java]

I don’t like that unconditional toolTip.hide()

Suggestions? I’m always open to them! ToolTips was a semi-after thought… actually, I think it was a feature request at one point. I haven’t made use of them myself (aside from test projects)… so likely, there is room for major improvement.

The stuff I do use on a consistent basis is put through countless scenarios and will likely be closer to a final solution then features I don’t use regularly.

EDIT: I think I see why this could be an issue when not using the gui scene picking/event handling. I’ll provide an overloaded method with a boolean for hiding/not hiding.

Done & commited…

[java]
Screen.releaseForcedToolTips();
Screen.releaseForcedToolTips(boolean hide);
[/java]

I don’t think that’s the best solution. Lets pause and think about this a bit, rather than expanding the API piecemeal.

My mental model of the situation is that there should be two tool tip texts, a user (“forced”) text and a GUI text. Changing one should not affect the other. Turning tool tips on or off should not affect the stored text, only whether it is displayed. There’s a model-view distinction here, I think. The decision of which text to display should be made dynamically, with the GUI text overriding the user text in the case where they’re both non-empty. Does this make sense to you?

@sgold said: I don't think that's the best solution. Lets pause and think about this a bit, rather than expanding the API piecemeal.

My mental model of the situation is that there should be two tool tip texts, a user (“forced”) text and a GUI text. Changing one should not affect the other. Turning tool tips on or off should not affect the stored text, only whether it is displayed. There’s a model-view distinction here, I think. The decision of which text to display should be made dynamically, with the GUI text overriding the user text in the case where they’re both non-empty. Does this make sense to you?

The outcome of the above is the way it currently works if the events happen in the following order:

  • Gui element check
  • If null >
  • Scene spatial check

Changing the number of elements used to display this won’t make a difference… aside from leading to the potential of both tooltip windows showing up if the user fails to handle them properly. The dynamic check mentioned above is still dependent on the checks happening in the proper order.

I’m not apposed to changing it… not even apposed to the scenario mentioned above. I just want to make sure that it is understood that the underlining issue will not be resolved with the solution above.

The only way to ensure that the tooptips display correctly would be to allow the user to inject a hook into the proper place in the raycasting process. Otherwise, automatic hide/show of tooltips will always hit a snag in one (or more) of many potential scenarios.

I don’t see any risk of two tooltips appearing at the same time with my proposed
implementation. Maybe I’m confused, or perhaps I haven’t explained my idea
clearly to you yet.

If I implement my idea and send you the diffs, will you take a look at them and
consider integrating them into your repo?

@sgold said: I don't see any risk of two tooltips appearing at the same time with my proposed implementation. Maybe I'm confused, or perhaps I haven't explained my idea clearly to you yet.

If I implement my idea and send you the diffs, will you take a look at them and
consider integrating them into your repo?

Always!

Here’s my Screen.java diff:

# This patch file was generated by NetBeans IDE
# It uses platform neutral UTF-8 encoding and \n newlines.
--- Base (BASE)
+++ Locally Modified (Based On LOCAL)
@@ -594,7 +594,7 @@
 			if (app.getInputManager().isCursorVisible())
 				cursorEffects.updatePosition(mouseXY);
 		}
-		if (useToolTips) updateToolTipLocation();
+            updateToolTipLocation();
 		if (!mousePressed) {
 			mouseFocusElement = getEventElement(evt.getX(), evt.getY());
 			if (mouseFocusElement != null) {
@@ -2123,29 +2123,8 @@
 	 */
 	@Override
 	public void setUseToolTips(boolean useToolTips) {
-		this.useToolTips = useToolTips;
-		if (useToolTips) {
-			if (toolTip == null) {
-				toolTip = new ToolTip(
-					this,
-					"GlobalToolTip",
-					new Vector2f(0,0),
-					new Vector2f(200,50)
-				);
-				toolTip.setIgnoreGlobalAlpha(true);
-				toolTip.setIsGlobalModal(true);
-				toolTip.setTextPadding(2);
-				toolTip.setTextPosition(0, 0);
-				toolTip.hide();
-				addElement(toolTip);
-				toolTip.move(0,0,20);
-			} else {
-				t0neg0dGUI.attachChild(toolTip);
-			}
-		} else {
-			if (toolTip != null)
-				toolTip.removeFromParent();
-		}
+            this.useToolTips = useToolTips;
+            updateToolTipLocation();
 	}
 	
 	/**
@@ -2157,46 +2136,66 @@
 		return useToolTips;
 	}
 	
-	/**
-	 * For internal use only - DO NOT CALL THIS METHOD
-	 */
-	@Override
-	public void updateToolTipLocation() {
-		if (useToolTips) {
-			if (this.mouseFocusElement != null && getApplication().getInputManager().isCursorVisible()) {
-				String toolTipText = this.mouseFocusElement.getToolTipText();
-				if (toolTipText != null) {
-					if (!toolTip.getText().equals(this.mouseFocusElement.getToolTipText())) {
-						toolTip.setText("");
-						toolTip.setHeight(25);
-						float finalWidth = BitmapTextUtil.getTextWidth(toolTip, toolTipText, toolTipMaxWidth);
-						toolTip.setText(toolTipText);
-						toolTip.setWidth(finalWidth+(toolTip.getTextPadding()*12));
-						toolTip.setHeight(toolTip.getTextElement().getHeight()+(toolTip.getTextPadding()*12));
-						toolTip.getTextElement().setBox(new Rectangle(0,0,toolTip.getWidth()-(toolTip.getTextPadding()*2),toolTip.getHeight()-(toolTip.getTextPadding()*2)));
-					}
-					setToolTipLocation();
-					if (!toolTip.getIsVisible())
-						toolTip.show();
-				} else {
-					if (!forcedToolTip) {
-						toolTip.setText("");
-						toolTip.hide();
-					} else {
-						setToolTipLocation();
-					}
-				}
-			} else {
-				if (!forcedToolTip) {
-					toolTip.setText("");
-					toolTip.hide();
-				} else {
-					setToolTipLocation();
-				}
-			}
-		}
-	}
-	
+    /**
+     * For internal use only - DO NOT CALL THIS METHOD
+     */
+    @Override
+    public void updateToolTipLocation() {
+        if (toolTip == null) {
+            /*
+             * Initialize the global tool tip on first invocation.
+             */
+            toolTip = new ToolTip(this, "GlobalToolTip", new Vector2f(0, 0), new Vector2f(200, 50));
+            toolTip.setIgnoreGlobalAlpha(true);
+            toolTip.setIsGlobalModal(true);
+            toolTip.setText("");
+            toolTip.setTextPadding(2);
+            toolTip.setTextPosition(0, 0);
+            toolTip.hide();
+            addElement(toolTip);
+            toolTip.move(0, 0, 20);
+        }
+        /*
+         * Determine what text (if any) the tool tip should display.
+         */
+        String newText = null;
+        if (useToolTips && getApplication().getInputManager().isCursorVisible()) {
+            if (mouseFocusElement != null) {
+                newText = mouseFocusElement.getToolTipText();
+            } else {
+                newText = forcedToolTipText;
+            }
+        }
+
+        if (newText == null || newText.isEmpty()) {
+            /*
+             * Clear and hide the old tool tip.
+             */
+            toolTip.setText("");
+            toolTip.hide();
+            return;
+        }
+
+        String oldText = toolTip.getText();
+        if (!oldText.equals(newText)) {
+            /*
+             * Change the tool tip text and resize the tool tip.
+             */
+            toolTip.setText("");
+            toolTip.setHeight(25);
+            float finalWidth = BitmapTextUtil.getTextWidth(toolTip, newText, toolTipMaxWidth);
+            toolTip.setText(newText);
+            toolTip.setWidth(finalWidth + (toolTip.getTextPadding() * 12));
+            toolTip.setHeight(toolTip.getTextElement().getHeight() + (toolTip.getTextPadding() * 12));
+            toolTip.getTextElement().setBox(new Rectangle(0, 0, toolTip.getWidth() - (toolTip.getTextPadding() * 2), toolTip.getHeight() - (toolTip.getTextPadding() * 2)));
+        }
+
+        setToolTipLocation();
+        if (!toolTip.getIsVisible()) {
+            toolTip.show();
+        }
+    }
+
 	private void setToolTipLocation() {
 		float nextX = mouseXY.x-(toolTip.getWidth()/2);
 		if (nextX < 0) nextX = 0;
@@ -2207,44 +2206,15 @@
 	}
 	
 //	@Override
-	public void setForcedToolTip(String toolTipText) {
-		if (useToolTips) {
-			if (getApplication().getInputManager().isCursorVisible()) {
-				forcedToolTip = true;
-				if (!forcedToolTipText.equals(toolTipText)) {
-					forcedToolTipText = toolTipText;
-					toolTip.setText("");
-					toolTip.setHeight(25);
-					float finalWidth = BitmapTextUtil.getTextWidth(toolTip, toolTipText, toolTipMaxWidth);
-					toolTip.setText(toolTipText);
-					toolTip.setWidth(finalWidth+(toolTip.getTextPadding()*12));
-					toolTip.setHeight(toolTip.getTextElement().getHeight()+(toolTip.getTextPadding()*12));
-					toolTip.getTextElement().setBox(new Rectangle(0,0,toolTip.getWidth()-(toolTip.getTextPadding()*2),toolTip.getHeight()-(toolTip.getTextPadding()*2)));
-				}
-				setToolTipLocation();
-				if (!toolTip.getIsVisible())
-					toolTip.show();
-			}
-		}
-	}
+    public void setForcedToolTip(String toolTipText) {
+        forcedToolTipText = toolTipText;
+        updateToolTipLocation();
+    }
 	
 //	@Override
-	public void releaseForcedToolTip() {
-		releaseForcedToolTip(true);
-	}
-	
-	public void releaseForcedToolTip(boolean hide) {
-		if (useToolTips) {
-			forcedToolTip = false;
-			forcedToolTipText = "";
-			toolTip.setText("");
-			if (hide) toolTip.hide();
-		}
-	}
-	
-	public void hideToolTip() {
-		releaseForcedToolTip();
-	}
+    public void releaseForcedToolTip() {
+        setForcedToolTip(null);
+    }
 	//</editor-fold>
 	
 	//<editor-fold desc="Audio Support">
1 Like

@sgold
I have had ZERO time to do anything today (aside from answer a question or two). I just wanted you to know that I have this, from first glance it all looks good to me. I should be able to test it either this evening, or tomorrow at the latest. If there are any issues, I’ll grab you to discuss how to handle them and make sure that it sits well with you, though, I don’t think there will be an issue from what I read through.

EDIT: Forgot to ask… does this resolve the issue you had? I’m assuming that it does. If everything works in my current tests, I’ll commit the changes and push out an update.

@t0neg0d: I tested it and it seems to do what I want.

1 Like
@sgold said: @t0neg0d: I tested it and it seems to do what I want.

Hey you… soooooo sorry for the delay on this. I have been beyond ill and bed ridden for a few days. I applied the patch and all works well. Thanks so much for cleaning this up for me. The update has been committed, however the plugin won’t update until this evening.

2 Likes

Thanks for applying the patch. I’m glad you’re back.

1 Like

The plugin updated last night. Looks good from here. Thanks again.

1 Like