/***************************************************************************** * Copyright (c) 2009 CEA LIST & LIFL * * * 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: * Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation * *****************************************************************************/ package org.eclipse.papyrus.infra.core.sasheditor.internal; import java.util.logging.Logger; import org.eclipse.papyrus.infra.core.sasheditor.editor.IPageImageUtils; import org.eclipse.papyrus.infra.core.sasheditor.internal.preferences.ITabTooltipPreferences; import org.eclipse.papyrus.infra.core.sasheditor.internal.preferences.TabTooltipPreferences; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.graphics.Transform; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; /** * A class managing tooltips as Part. * * @author dumoulin */ public class ImageToolTipManager { /** Log object */ Logger log = Logger.getLogger(getClass().getName()); protected ITabTooltipPreferences settings = new TabTooltipPreferences(); /** */ private Control toolTipedControl; /** * Size of the image to show. */ private Rectangle toolTipExpectedSize = new Rectangle(0, 0, 100, 80); private int offsetX = 20; private int offsetY = 20; /** * Position of the tooltip relative to the tooltiped swt.Control. */ private int toolTipAlignement = SWT.TOP; /** * */ private Shell tip = null; /** * Cached value of the image. Use to do dispose when closing. */ private Image image = null; /** * Constructor. */ public ImageToolTipManager() { // TODO Auto-generated constructor stub } private void resetTimer() { if( settings.getTooltipAutoCloseDelay() == -1) return; // do reset timer } /** * Close the tooltip and dispose it. */ public void closeToolTip() { if(tip != null) { tip.dispose(); tip = null; } if(image != null) { image.dispose(); image = null; } toolTipedControl = null; } /** * Disable the tooltip. * If the tooltip is shown, hide it. * In the disable state, calls to showTooltip() with the same Control will not * show the tooltip again untill another control is proposed. * A call to closeToolTip() is required to show the same Control again. */ public void disableToolTip() { // Close the tooltip. if(tip != null) { tip.dispose(); tip = null; } if(image != null) { image.dispose(); image = null; } // Keep the control for future checking. } /** * dispose the tooltip and its resources. * */ public void dispose() { if(tip != null) { tip.dispose(); tip = null; } if(image != null) { image.dispose(); image = null; } toolTipedControl = null; } /** * Ask to show the tooltip. * First check if preferences allows to show tooltip. * * @param pagePart The PagePart for which a ToolTip should be opened. * @param flyedControl The control that trigger the tooltip opening * @param mousePos */ public void showToolTip(PagePart pagePart, Rectangle flyedControlBounds, Point mousePos) { // If tooltip is already showing for this control, skip. if(toolTipedControl == pagePart.getControl()) { resetTimer(); return; } if( ! settings.isTooltipEnable() ) return; // Check if we are showing the tooltip for current tab. if( ! settings.isTooltipForCurrentTabShown() && pagePart.getParent().getVisiblePagePart() == pagePart ) { // close current tooltip if any closeToolTip(); return; } doShowToolTip(pagePart, flyedControlBounds, mousePos); } /** * Do show th tooltip, unless we can't get an image for the part. * @param pagePart * @param flyedControlBounds * @param mousePos */ private void doShowToolTip(PagePart pagePart, Rectangle flyedControlBounds, Point mousePos) { Image image = getPageImage(pagePart); if(image == null) return; toolTipedControl = pagePart.getControl(); // Change image scale float scaleFactor = settings.getScaledFactor(); //.5f; Image scaledImage = scaledImage(pagePart.getControl().getDisplay(), image, scaleFactor); image.dispose(); // Remember the image to be able to dispose it. this.image = scaledImage; Point pos = computeToolTipPosition(flyedControlBounds, mousePos, scaledImage.getBounds()); openToolTip(pagePart.getControl(), scaledImage, pos); } /** * Compute the tooltip position. * * @param relatedControlBounds * Bounds of the item to which the tooltip apply * @param mousePos * Position of the mouse inside the relatedControlBounds. * @param toolTipSize * Size of the ToolTip. * * @return Position of the tooltip */ private Point computeToolTipPosition(Rectangle relatedControlBounds, Point mousePos, Rectangle toolTipSize) { int x, y; if(toolTipAlignement == SWT.TOP) { // Position.x = mousePoint.x // Position.y = itemBounds - (toolTipSize.y + offsetY) x = mousePos.x; y = relatedControlBounds.y - (toolTipSize.height + offsetY); } else if(toolTipAlignement == SWT.BOTTOM) { x = mousePos.x; y = relatedControlBounds.y + (relatedControlBounds.height + offsetY); } else { throw new UnsupportedOperationException("Not yet implemented for this alignement."); } return new Point(x, y); } /** * Open a tooltip like window containing the image. * * @param device * The control from which atPoint is specified. * @param scaledImage * @param atPoint */ private void openToolTip(Control device, Image scaledImage, Point atPoint) { if(tip != null && !tip.isDisposed()) tip.dispose(); tip = new Shell(device.getShell(), SWT.ON_TOP | SWT.NO_FOCUS | SWT.TOOL); FillLayout layout = new FillLayout(); layout.marginWidth = 2; tip.setLayout(layout); Label label = new Label(tip, SWT.NONE); label.setImage(scaledImage); Point size = tip.computeSize(SWT.DEFAULT, SWT.DEFAULT); Point pt = device.toDisplay(atPoint.x + 20, atPoint.y); tip.setBounds(pt.x, pt.y, size.x, size.y); tip.setVisible(true); } /** * Create an image corresponding to the control. * * @param control * The control for which an image is to be built. * @return */ private Image createControlImage(Control control) { // Create an image of the part. Rectangle size; size = control.getBounds(); if(size.width == 0 && size.height == 0) { Point pt = control.computeSize(SWT.DEFAULT, SWT.DEFAULT); size = new Rectangle(0, 0, pt.x, pt.y); } Image image = new Image(control.getDisplay(), size); GC gc = new GC(image); boolean success = control.print(gc); gc.dispose(); if(!success) { image.dispose(); // log.warning("Can't create Snapshot for the control of '" + part + "'."); return null; } return image; } /** * Create an image corresponding to the control. * * @param control * The control for which an image is to be built. * @return */ private Image scaledImage2(Device device, Image image, float factor) { Rectangle imageBounds = image.getBounds(); Rectangle size = computeToolTipSize(image, factor); Image scaledImage = new Image(device, size); GC gc = new GC(scaledImage); gc.drawImage(image, 0, 0, imageBounds.width, imageBounds.height, 0, 0, size.width, size.height); return scaledImage; } /** * Compute the expected size of the tooltip. * For now, simply return the expected size. * * @param image * @param factor * @return */ private Rectangle computeToolTipSize(Image image, float factor) { // Rectangle imageBounds = image.getBounds(); // Rectangle size; return toolTipExpectedSize; } /** * Create a new image which is the input image scaled. * * @param image * @param factor * @return */ private Image scaledImage(Device device, Image image, float factor) { Rectangle bounds = image.getBounds(); // Float factor = 0.5f; Rectangle newBounds = new Rectangle(0, 0, Math.round(bounds.width * factor), Math.round(bounds.height * factor)); Image scaledImage = new Image(device, newBounds); GC gc = new GC(scaledImage); gc.setAdvanced(true); gc.setAntialias(SWT.ON); Transform tr = new Transform(device); tr.scale(factor, factor); gc.setTransform(tr); gc.drawImage(image, 0, 0); gc.dispose(); tr.dispose(); return scaledImage; } /** * get the Image for the page. * @param pagePart * @return */ private Image getPageImage( PagePart pagePart ) { return IPageImageUtils.getPageImage(pagePart); } }