More CLICKABLE link on a tooltip - how to?

One of previous message shows a way of doing clickable link on tooltip. see:

http://forum.java.sun.com/thread.jspa?threadID=592163&messageID=3093997

I modified the code a little bit to put tooltip on a button instead of panel.

import java.awt.BorderLayout;

import java.awt.Point;

import java.awt.event.MouseEvent;

import javax.swing.*;

import javax.swing.event.*;

import javax.swing.plaf.ToolTipUI;

public class HyperLinkToolTip extends JToolTip {

private JEditorPane theEditorPane;

public HyperLinkToolTip() {

setLayout(new BorderLayout());

LookAndFeel.installBorder(this, "ToolTip.border");

LookAndFeel.installColors(this, "ToolTip.background", "ToolTip.foreground");

theEditorPane = new JEditorPane();

theEditorPane.setContentType("text/html");

theEditorPane.setEditable(false);

theEditorPane.addHyperlinkListener(new HyperlinkListener() {

public void hyperlinkUpdate(HyperlinkEvent e) {

if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {

// do whatever you want with the url

System.out.println("clicked on link : " + e.getDescription());

}

}

});

add(theEditorPane);

}

public void setTipText(String tipText) {

theEditorPane.setText(tipText);

}

public void updateUI() {

setUI(new ToolTipUI() {});

}

public static void main(String[] args) {

final JFrame frame = new JFrame(HyperLinkToolTip.class.getName());

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JPanel panel = new JPanel();

JButton btn = new JButton() {

public JToolTip createToolTip() {

JToolTip tip = new HyperLinkToolTip();

tip.setComponent(this);

return tip;

}

// Set tooltip location

public Point getToolTipLocation(MouseEvent event) {

return new Point(getWidth()/2, getHeight()/2);

}

};

btn.setText("Tooltip Test");

btn.setToolTipText("<html><body><a href=\"http://www.sun.com\">Goto www.sun.com for details.</a></body></html>");

panel.add(btn);

frame.setContentPane(panel);

SwingUtilities.invokeLater(new Runnable() {

public void run() {

frame.setSize(400, 400);

frame.setVisible(true);

}

});

}

}

The code works fine in Java application. But, when I use it in an applet, it is almost impossible to click on the tooltip. The tooltip is flashing or disappears when trying to move mouse on the tooltip. I did set the location of tooltip to make sure there is no gap between button and tooltip. Here is the code for applet:

import java.awt.*;

import javax.swing.*;

import java.awt.event.MouseEvent;

public class ToolTipApplet extends JApplet {

private JPanel jContentPane = null;

private JButton btnTest = null;

public ToolTipApplet() {

super();

}

public void init() {

this.setSize(300, 200);

this.setContentPane(getJContentPane());

}

private JPanel getJContentPane() {

if (jContentPane == null) {

jContentPane = new JPanel();

jContentPane.setLayout(new FlowLayout());

jContentPane.add(getBtnTest(), null);

}

return jContentPane;

}

private JButton getBtnTest() {

if (btnTest == null) {

btnTest = new JButton() {

public JToolTip createToolTip() {

JToolTip tip = new HyperLinkToolTip();

tip.setComponent(this);

return tip;

}

// Set tooltip location

public Point getToolTipLocation(MouseEvent event) {

return new Point(getWidth()/2, getHeight()/2);

}

};

btnTest.setText("Tooltip Test");

btnTest.setToolTipText("<html><body><a href=\"http://www.sun.com\">Goto www.sun.com for details.</a></body></html>");

}

return btnTest;

}

}

No idea why application and applet behave differently here. (I am using JRE1.6u1 for the test.)

Thanks a lot!

[4117 byte] By [hedgefunda] at [2007-11-27 7:33:35]
# 1

I figured it out myself. I believe it is a bug in the implementation of ToolTipManager, which doesn't handle the mouseExited correctly. I basically change its implementation using the following code. Since you cannot subclass ToolTipManager, I copied over the code of original ToolTipManager and modified the mouseExited function. Then, let widget use my new ToolTipManager by overrid setToolTipText() function.

public void mouseExited(MouseEvent event) {

boolean shouldHide = true;

if (insideComponent == null)

{

// Drag exit

}

if (window != null && event.getSource() == window)

{

// if we get an exit and have a heavy window

// we need to check if it if overlapping the inside component

Container insideComponentWindow = insideComponent.getTopLevelAncestor();

Point location = event.getPoint();

SwingUtilities.convertPointToScreen(location, window);

location.x -= insideComponentWindow.getX();

location.y -= insideComponentWindow.getY();

location = SwingUtilities.convertPoint(null,location,insideComponent);

if (location.x >= 0 && location.x < insideComponent.getWidth() &&

location.y >= 0 && location.y < insideComponent.getHeight())

{

shouldHide = false;

}

else

{

shouldHide = true;

}

}

else if(event.getSource() == insideComponent && tipWindow != null) {

Window win = SwingUtilities.getWindowAncestor(insideComponent);

if (win != null)

{// insideComponent may have been hidden (e.g. in a menu)

Point location = event.getPoint();

SwingUtilities.convertPointToScreen(location, insideComponent);

Rectangle bounds = insideComponent.getTopLevelAncestor().getBounds();

Point loc = new Point(0, 0);

SwingUtilities.convertPointToScreen(loc, tip);

bounds.x = loc.x;

bounds.y = loc.y;

bounds.width = tip.getWidth();

bounds.height = tip.getHeight();

if (location.x >= bounds.x && location.x < (bounds.x + bounds.width) &&

location.y >= bounds.y && location.y < (bounds.y + bounds.height))

{

shouldHide = false;

}

else

{

shouldHide = true;

}

}

}

if (shouldHide)

{

enterTimer.stop();

if (insideComponent != null)

{

insideComponent.removeMouseMotionListener(this);

}

insideComponent = null;

toolTipText = null;

mouseEvent = null;

hideTipWindow();

exitTimer.restart();

}

}

hedgefunda at 2007-7-12 19:14:00 > top of Java-index,Desktop,Core GUI APIs...