/*******************************************************************************
* 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;
}
}