package esmska.gui; import esmska.data.event.ValuedEventSupport; import esmska.data.event.ValuedListener; import java.awt.Cursor; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import javax.swing.JLabel; import javax.swing.text.AttributeSet; import javax.swing.text.html.HTML; import org.apache.commons.lang.StringUtils; /** * Shows HTML text in a JLabel. This only adds the feature of executing links * in the label, normal JLabel's do the rest of the work. * * Sets hand cursor when mouse is over a hyperlink. After clicking on a hyperlink * sends a ValuedEvent. * * @author Jeffrey Bush * @see <a href="http://forums.sun.com/thread.jspa?forumID=57&threadID=574895">Original source code</a> */ public class JHtmlLabel extends JLabel implements MouseListener, MouseMotionListener { public static enum Events { /** Hyperlink clicked. Event value: String with URL of the hyperlink. */ LINK_CLICKED } private boolean autoHyperlinkHandling = true; private AccessibleJLabel acc = null; // <editor-fold defaultstate="collapsed" desc="ValuedEvent support"> private ValuedEventSupport<Events, String> valuedSupport = new ValuedEventSupport<Events, String>(this); public void addValuedListener(ValuedListener<Events, String> valuedListener) { valuedSupport.addValuedListener(valuedListener); } public void removeValuedListener(ValuedListener<Events, String> valuedListener) { valuedSupport.removeValuedListener(valuedListener); } // </editor-fold> public JHtmlLabel() { this(null); } public JHtmlLabel(String text) { super(text); acc = (AccessibleJLabel) getAccessibleContext(); addMouseListener(this); addMouseMotionListener(this); } /** Set whether this JLabel should automatically open browser on hyperlink * click (an event will still be sent). By default true. */ public void setAutoHyperlinkHandling(boolean autoHyperlinkHandling) { this.autoHyperlinkHandling = autoHyperlinkHandling; } /** Get whether this JLabel should automatically open browser on hyperlink * click (an event will still be sent). By default true. */ public boolean isAutoHyperlinkHandling() { return this.autoHyperlinkHandling; } @Override public void mouseClicked(MouseEvent e) { AttributeSet charAttr = acc.getCharacterAttribute(acc.getIndexAtPoint(e.getPoint())); if (charAttr == null) { return; } AttributeSet attr = (AttributeSet) charAttr.getAttribute(HTML.Tag.A); if (attr == null) { return; } String url = (String) attr.getAttribute(HTML.Attribute.HREF); if (url != null) { valuedSupport.fireEventOccured(Events.LINK_CLICKED, url); if (autoHyperlinkHandling) { Actions.getBrowseAction(url).actionPerformed(null); } } } @Override public void mouseMoved(MouseEvent e) { AttributeSet charAttr = acc.getCharacterAttribute(acc.getIndexAtPoint(e.getPoint())); AttributeSet attr = null; if (charAttr != null) { attr = (AttributeSet) charAttr.getAttribute(HTML.Tag.A); } if (attr == null) { setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); setToolTipText(null); } else { setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); String tooltip = (String) attr.getAttribute(HTML.Attribute.HREF); setToolTipText(StringUtils.startsWith(tooltip, "esmska://") ? null : tooltip); } } @Override public void mousePressed(MouseEvent e) { } @Override public void mouseReleased(MouseEvent e) { } @Override public void mouseEntered(MouseEvent e) { } @Override public void mouseExited(MouseEvent e) { } @Override public void mouseDragged(MouseEvent e) { mouseMoved(e); } }