Eclipse: Rich Hovers Redux

In Using the new Rich Text Hovers in Eclipse 3.4, I, uh, suggested that perhaps, um, maybe, an implementation of ITextHoverExtension2#getHoverInfo2 (from the package org.eclipse.jface.text) could return either a String or “An implementation of IInformationControlExtension2“.

That was a m- mi- mis- mistake. What I meant to say was:

[It] is the responsibility of the implementer of IInformationControl and IInformationControlExtension2 to specify the concrete nature of the information control’s input…

In plain(er) English: If you write the hover control, you get to specify the hover information. The implementation of getHoverInfo2 must be aware of the hover control’s implementation, and must conform to its specification.

So as a plug-in author, how can you create hovers with rich display formats? I’ve found two options. The first of these doesn’t even require any of the extensions that I’ve already touched upon.

Using the DefaultHoverControl

Straight out of the box (as it were), the JavaEditor example plug-in is configured to use the default version of the org.eclipse.jface.text.DefaultHoverControl class. In this configuration, the DefaultHoverControl treats its text input as raw text (without markup), as shown in the screen shot below.

(Note: The example Java editor plug-in simply copies the current text selection into the hover. In these screen shots, the selection is a Java comment that contains HTML markup.)

Screen shot of Java editor plug-in example, showing HTML markup passed through as text.

Some of the constructors for DefaultHoverControl enable the control to process a subset of HTML. To use one of these, we need to add the following method to JavaSourceViewerConfiguration in the sample editor; this overrides the base class implementation in org.eclipse.jface.text.source.SourceViewerConfiguration :

/**
 * Returns the information control creator. The creator is a 
 * factory creating information controls for the given source
 * viewer. This implementation always returns a creator for
 * <code>JavaInformationControl</code> instances.
 *
 * @param sourceViewer the source viewer to be configured
 *        by this configuration
 * @return the information control creator, or <code>null</code> 
 *         if no information support should be installed
 * @since 2.0
 */
public IInformationControlCreator 
getInformationControlCreator(ISourceViewer sourceViewer) {
   return new IInformationControlCreator() {
      public IInformationControl createInformationControl(Shell parent) {
          return new JavaHoverInformationControl(parent);
      }
   };
}

Unlike the base class implementation, this version calls the two-argument constructor DefaultInformationControl(parent, false). Internally, this constructor will create an HTMLTextPresenter object, which supports some simple HTML markup.

The emphasis here is on simple HTML. Unfortunately, while HTMLTextPresenter happily reads the HTML markup, it doesn’t implement very much of it. As this screenshot illustrates, both <code> and <em> markup are ignored. (There’s no example hyperlink here, but I can confirm that they’re ignored as well.)

Another Java editor plug-in example, showing partially supported HTML markup.

Creating a new hover control

HoveringIf you need to support richer content than DefaultInformationControl can handle, then it’s likely that you’ll need to create your own hover control. This may require some experimentation, as the definitive guide to writing hover controls hasn’t been written yet (or if it has been, its visibility flag is set to false.)

I’ve put together a demo of a hover control that uses the SWT Browser widget. The JavaHoverInformationControl class implementation requires only about 150 lines of code, plus a few changes in two other files in the JavaEditor demo. It’s still rough around the edges; you may not be replacing your desktop browser with it anytime soon, but it should help to illustrate how a plug-in author can take control over hover controls.

In this screenshot, you can see that the example comment is now displayed in all of its HTML glory in the hover:

The JavaHoverInformationControl, showing HTML displayed in a small Browser widget.

For additional demo value—and to show how this all ties in with ITextHoverExtension2#getHoverInfo2—the JavaHoverInformationControl also displays something useful when no text is currently selected:

It isn't all that useful, really.
(Well, it’s useful to me, anyway!)

A few aspects of the demo are worth describing here. The tie-in to ITextHoverExtension2#getHoverInfo2 is through an interface nested within the new JavaHoverInformationControl class:

public interface IHTMLHoverInfo {
    /**
     * @return true if the String returned by getHTMLString()
     *  represents a URL;  false if the String contains marked-up text.
     */
    public boolean isURL();

    /**
     * @return The input string to be displayed in the Browser widget
     *  (either as marked-up text, or as a URL.)
     */
    public String getHTMLString();
}

This is reflected in the JavaTextHover class, which I’ve modified to implementITextHoverExtension2#getHoverInfo2. This implementation returns an Object that conforms to the IHTMLHoverInfo interface:

public class JavaTextHover 
                implements ITextHover, ITextHoverExtension2 {
//... other methods are not shown here...
public Object getHoverInfo2(ITextViewer textViewer, 
                                      IRegion hoverRegion) {

    // Start with the string returned by the older getHoverInfo()
    final String selection = getHoverInfo(textViewer, hoverRegion);

   // If text is selected in the editor window, it's returned as the
   // hover string. If no text is selected, then the returned hover is
   // a URL pointing to www.outofwhatbox.com/blog.
    return new JavaHoverInformationControl.IHTMLHoverInfo() {
        public boolean isURL() {return selection.length() == 0;}
        public String getHTMLString() {
            if (isURL()){
                return "http://www.outofwhatbox.com/blog";
            }
            return selection;
        }
    };
}

Similarly, the JavaHoverInformationControl#setObject method will invoke this object’s isURL method, indicating whether to handle the input as marked-up text or as a URL:

    public void setInput(Object input) {
        // Assume that the input is marked-up text, not a URL
        fIsURL = false;
        final String inputString;

        if (input instanceof IHTMLHoverInfo) {
            // Get the input string, then see whether it's a URL
            IHTMLHoverInfo inputInfo = (IHTMLHoverInfo) input;
            inputString = inputInfo.getHTMLString();
            fIsURL= inputInfo.isURL();

//... rest of the code not shown here...

I’ve packaged the JavaHoverInformationControl implementation with the modified source from the sample org.eclipse.ui.examples.javaeditor package. It’s available for download as a ZIP file file and as a gzip’d tar file.

, , ,

7 Comments

  • TK says:

    Actually i am searching for a rich hovertext. But your download link doesnt work or i dont have the permission to download it. If it is the first case, can you fix it please?

  • thiago alencar says:

    it doesn’t work at all

  • Henno Vermeulen says:

    This seems to be a hover for eclipse editors.

    How easy/hard would it be to get such a rich html tooltip with color support as in your example (which ignored <code> and <em>) working on an arbitrary SWT control?

    I.e. I would like to call something like
    new HtmlToolTip(control, "Hello world")
    and have it working.

    (See also my forum post http://www.eclipse.org/forums/index.php?t=msg&goto=551389&S=15e3e271d91f521d26beb7b2ba809148#msg_551389 )

    [edited to fix formatting — dbreslau]

    • Dan Breslau says:

      Hi, Henno —

      I’m not sure why org.eclipse.jface.window.ToolTip and
      org.eclipse.jface.text.ITextHover are separate protocols, but they are. Worse still, org.eclipse.jface.window.ToolTip is an abstract class with no associated interfaces.

      The best suggestion that I can offer right now is to try to create a subclass of org.eclipse.jface.window.ToolTip that proxies a org.eclipse.jface.text.ITextHover implementation. I can’t promise that it would work, or work well, because I haven’t examined the ToolTip API in much detail.

  • […] this, we can provide a more complex IInformationControl, which holds a Browser control. Please read Dan Breslau’s post for […]

Leave a Reply to Dan Breslau

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>