/******************************************************************************* * Copyright (c) 2000, 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.draw2d; import java.util.Timer; import java.util.TimerTask; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseTrackAdapter; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Display; import org.eclipse.draw2d.geometry.Dimension; /** * This class is used by SWTEventDispatcher as support to display Figure tooltips on a * mouse hover event. Tooltips are drawn directly below the cursor unless the display * does not allow, in which case the tooltip will be drawn directly above the cursor. * Tooltips will be displayed with a LineBorder. The background of the tooltips will be * the standard SWT tooltipBackground color unless the Figure's tooltip has set its own * background. */ public class ToolTipHelper extends PopUpHelper { private Timer timer; private IFigure currentTipSource; /** * Constructs a ToolTipHelper to be associated with Control <i>c</i>. * * @param c the control * @since 2.0 */ public ToolTipHelper(org.eclipse.swt.widgets.Control c) { super(c, SWT.TOOL | SWT.ON_TOP); getShell().setBackground(ColorConstants.tooltipBackground); getShell().setForeground(ColorConstants.tooltipForeground); } /* * Calculates the location where the tooltip will be painted. Returns this as a Point. * Tooltip will be painted directly below the cursor if possible, otherwise it will be * painted directly above cursor. */ private Point computeWindowLocation(IFigure tip, int eventX, int eventY) { org.eclipse.swt.graphics.Rectangle clientArea = control.getDisplay().getClientArea(); Point preferredLocation = new Point(eventX, eventY + 26); Dimension tipSize = getLightweightSystem() .getRootFigure() .getPreferredSize() .getExpanded(getShellTrimSize()); // Adjust location if tip is going to fall outside display if (preferredLocation.y + tipSize.height > clientArea.height) preferredLocation.y = eventY - tipSize.height; if (preferredLocation.x + tipSize.width > clientArea.width) preferredLocation.x -= (preferredLocation.x + tipSize.width) - clientArea.width; return preferredLocation; } /** * Sets the LightWeightSystem's contents to the passed tooltip, and displays the tip. The * tip will be displayed only if the tip source is different than the previously viewed * tip source. (i.e. The cursor has moved off of the previous tooltip source figure.) * <p> * The tooltip will be painted directly below the cursor if possible, otherwise it will be * painted directly above cursor. * * @param hoverSource the figure over which the hover event was fired * @param tip the tooltip to be displayed * @param eventX the x coordinate of the hover event * @param eventY the y coordinate of the hover event * @since 2.0 */ public void displayToolTipNear(IFigure hoverSource, IFigure tip, int eventX, int eventY) { if (tip != null && hoverSource != currentTipSource) { getLightweightSystem().setContents(tip); Point displayPoint = computeWindowLocation(tip, eventX, eventY); Dimension shellSize = getLightweightSystem().getRootFigure() .getPreferredSize().getExpanded(getShellTrimSize()); setShellBounds(displayPoint.x, displayPoint.y, shellSize.width, shellSize.height); show(); currentTipSource = hoverSource; timer = new Timer(true); timer.schedule(new TimerTask() { public void run() { Display.getDefault().syncExec(new Runnable() { public void run() { hide(); timer.cancel(); } }); } }, 5000); } } /** * Disposes of the tooltip's shell and kills the timer. * * @see PopUpHelper#dispose() */ public void dispose() { if (isShowing()) { timer.cancel(); hide(); } getShell().dispose(); } /** * @see PopUpHelper#hookShellListeners() */ protected void hookShellListeners() { // Close the tooltip window if the mouse enters the tooltip getShell().addMouseTrackListener(new MouseTrackAdapter() { public void mouseEnter(org.eclipse.swt.events.MouseEvent e) { hide(); currentTipSource = null; timer.cancel(); } }); } /** * Displays the hover source's tooltip if a tooltip of another source is currently being * displayed. * * @param figureUnderMouse the figure over which the cursor was when called * @param tip the tooltip to be displayed * @param eventX the x coordinate of the cursor * @param eventY the y coordinate of the cursor * @since 2.0 */ public void updateToolTip(IFigure figureUnderMouse, IFigure tip, int eventX, int eventY) { /* If the cursor is not on any Figures, it has been moved off of the control. Hide the tool tip. */ if (figureUnderMouse == null) { if (isShowing()) { hide(); timer.cancel(); } } // Makes tooltip appear without a hover event if a tip is currently being displayed if (isShowing() && figureUnderMouse != currentTipSource) { hide(); timer.cancel(); displayToolTipNear(figureUnderMouse, tip, eventX, eventY); } else if (!isShowing() && figureUnderMouse != currentTipSource) currentTipSource = null; } }