Lesson: General Tooltip Support

Although class EditMode provides support for tooltip presentation, it surely cannot be used in a viewer type diagramming application. Since NavigationMode, which we have used in our simple graph viewer in the Creating a Simple Graph Viewer trail, lacks tooltip support, let's create a specialized view mode that we can use to add tooltip presentation to any application.

The screenshot of SimpleGraphViewer5Tooltips in Figure 1.3, “Data presentation using tooltip in SimpleGraphViewer” shows where we want to go.

Figure 1.3. Data presentation using tooltip in SimpleGraphViewer

Data presentation using tooltip in SimpleGraphViewer

In Example 1.2, “ViewMode implementation class TooltipMode” you can take a look at the complete source code for our tooltip presentation view mode. It closely resembles the tooltip-related API of class y.view.EditMode.

Example 1.2. ViewMode implementation class TooltipMode

public class TooltipMode extends ViewMode {
  public static final Object NODE_TOOLTIP_DPKEY =
      "TooltipMode.NODE_TOOLTIP_DPKEY";
  public static final Object EDGE_TOOLTIP_DPKEY =
      "TooltipMode.EDGE_TOOLTIP_DPKEY";

  boolean showNodeTips;
  boolean showEdgeTips;

  /**
   * Instantiates a new TooltipMode.
   * By default, node tooltips are enabled.
   */
  public TooltipMode() {
    this(true, false);
  }

  /** Instantiates a new TooltipMode. */
  public TooltipMode(boolean showNodeTips, boolean showEdgeTips) {
    this.showNodeTips = showNodeTips;
    this.showEdgeTips = showEdgeTips;
  }

  /**
   * If set to <code>true</code> this view mode will show a tooltip displaying
   * whatever is returned by {@link #getNodeTip(Node node)}.
   */
  public void showNodeTips(boolean showToolTip) {
    showNodeTips = showToolTip;
    if (!showNodeTips && view != null) {
      view.setToolTipText(null);
    }
  }

  /**
   * Returns <code>true</code> if this view mode should display tooltip text for
   * nodes.
   */
  public boolean doShowNodeTips() {
    return showNodeTips;
  }

  /**
   * If set to <code>true</code> this view mode will show a tooltip displaying
   * whatever is returned by {@link #getEdgeTip(Edge edge)}.
   */
  public void showEdgeTips(boolean showToolTip) {
    showEdgeTips = showToolTip;
    if (!showEdgeTips && view != null) {
      view.setToolTipText(null);
    }
  }

  /**
   * Returns <code>true</code> if this view mode should display tooltip text for
   * edges.
   */
  public boolean doShowEdgeTips() {
    return showEdgeTips;
  }

  public void mouseMoved(double x, double y) {
    HitInfo hitInfo = getHitInfo(x, y);

    if (doShowNodeTips() || doShowEdgeTips()) {
      String tooltipText = null;
      if (hitInfo.getHitNode() != null) {
        if (doShowNodeTips()) {
          tooltipText = getNodeTip(hitInfo.getHitNode());
        }
      }
      else if (hitInfo.getHitEdge() != null) {
        if (doShowEdgeTips()) {
          tooltipText = getEdgeTip(hitInfo.getHitEdge());
        }
      }
      if (tooltipText != null && tooltipText.length() < 1) {
        tooltipText = null;
      }
      view.setToolTipText(tooltipText);
    }
  }

  /**
   * Returns the tooltip text to be displayed for the given node.
   * <p>
   * This method will be called to get the tooltip text associated with the
   * given node. The tooltip text will only be displayed if
   * <code>doShowNodeTips</code> returns <code>true</code>.
   * </p>
   * <p>
   * By default the label text of the node will be returned. If a data provider
   * is registered with the node's graph using the {@link #NODE_TOOLTIP_DPKEY}
   * key, then the tooltip text that is returned by the data provider for the
   * given node is used instead.
   * <br/>
   * Subclasses may want to override this behavior.
   * </p>
   */
  protected String getNodeTip(Node node) {
    String result;
    DataProvider dp = getGraph2D().getDataProvider(NODE_TOOLTIP_DPKEY);

    if (dp != null && (result = (String)dp.get(node)) != null) {
      return result;
    }
    return getGraph2D().getLabelText(node);
  }

  /**
   * Returns the tooltip text to be displayed for the given edge.
   * <p>
   * This method will be called to get the tooltip text associated with the
   * given edge. The tooltip text will only be displayed if
   * <code>doShowEdgeTips</code> returns <code>true</code>.
   * </p>
   * <p>
   * By default the label text of the edge's first label will be returned. If a
   * data provider is registered with the node's graph using the
   * {@link #EDGE_TOOLTIP_DPKEY} key, then the tooltip text that is returned by
   * the data provider for the given edge is used instead.
   * <br/>
   * Subclasses may want to override this behavior.
   * </p>
   */
  protected String getEdgeTip(Edge edge) {
    String result;
    DataProvider dp = getGraph2D().getDataProvider(EDGE_TOOLTIP_DPKEY);

    if (dp != null && (result = (String)dp.get(edge)) != null) {
      return result;
    }

    EdgeRealizer er = getGraph2D().getRealizer(edge);
    return (er.labelCount() > 0) ? er.getLabel(0).getText() : null;
  }
}

Using Class TooltipMode

Using the TooltipMode class we can easily customize tooltips without the need for subclassing. We can do so by means of data providers that we register with a graph using the data provider keys defined in TooltipMode, namely NODE_TOOLTIP_DPKEY and EDGE_TOOLTIP_DPKEY.

For example, let's add a data provider to our graph that generates the tooltip text for a node on-the-fly, using the following logic which simply prints the width and height of a node, nicely arranged using some HTML styling. In the SimpleGraphViewer5 application from the Creating a Simple Graph Viewer trail, we can do this in the main method as follows.

Example 1.3. Registering a data provider for node tooltips

sgv.getGraph().addDataProvider(TooltipMode.NODE_TOOLTIP_DPKEY, 
                               new DataProviderAdapter() {
    public Object get(Object actuallyNode) {
      Node node = (Node)actuallyNode;
      Graph2D graph = (Graph2D)node.getGraph();
      return "<html>width x height: <b>" + 
             graph.getWidth(node) + "</b> x <b>" + graph.getHeight(node) + 
             "</b></html>";
    }
});

Of course, we also need to add TooltipMode itself to the view modes that process mouse events occurring in our view. We will do so in the same way that NavigationMode is added in the createGraph2DView method of SimpleGraphViewer5, using the addViewMode method of Graph2DView.

Example 1.4. Adding TooltipMode to the view modes of a given view

// 'view' is of type y.view.Graph2DView.

view.addViewMode(new TooltipMode());

Now, our modified simple graph viewer application, SimpleGraphViewer5Tooltips, will present tooltips for nodes that show the width and height.

Related Resources

You will find related information in the yFiles for Java Developer's Guide:

In the yFiles for Java source code demos:

  • ViewMode-related source code demo applications