/*******************************************************************************
* Copyright (c) 2009 Tasktop Technologies 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:
* Tasktop Technologies - initial API and implementation
* Obeo - adaptation for Amalgamation, EMF based and no Mylyn dependency
* CEA LIST - adaptation to Papyrus
*******************************************************************************/
package org.eclipse.papyrus.infra.discovery.ui.internal.common;
import java.net.MalformedURLException;
import java.net.URL;
import org.eclipse.core.runtime.Assert;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.window.ToolTip;
import org.eclipse.osgi.util.NLS;
import org.eclipse.papyrus.infra.discovery.Overview;
import org.eclipse.papyrus.infra.discovery.ui.internal.wizards.Messages;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
/**
* @author David Green
*/
public class OverviewToolTip extends GradientToolTip {
private final Overview overview;
private final Resource source;
private final Control parent;
private final Image leftImage;
public OverviewToolTip(Control control, Resource source, Overview overview, Image leftImage) {
super(control, ToolTip.RECREATE, true);
Assert.isNotNull(source);
Assert.isNotNull(overview);
this.parent = control;
this.source = source;
this.overview = overview;
this.leftImage = leftImage;
setHideOnMouseDown(false); // required for links to work
}
@Override
protected Composite createToolTipArea(Event event, final Composite parent) {
GridLayoutFactory.fillDefaults().applyTo(parent);
Composite container = new Composite(parent, SWT.NULL);
container.setBackground(null);
Image image = null;
if (overview.getScreenshot() != null) {
image = computeImage(source, overview.getScreenshot());
if (image != null) {
final Image fimage = image;
container.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
fimage.dispose();
}
});
}
}
final boolean hasLearnMoreLink = overview.getUrl() != null && overview.getUrl().length() > 0;
final int borderWidth = 1;
final int fixedImageHeight = 240;
final int fixedImageWidth = 320;
final int heightHint = fixedImageHeight + (borderWidth * 2);
final int widthHint = fixedImageWidth;
final int containerWidthHintWithImage = 650;
final int containerWidthHintWithoutImage = 500;
GridDataFactory.fillDefaults().grab(true, true).hint(image == null ? containerWidthHintWithoutImage : containerWidthHintWithImage, SWT.DEFAULT).applyTo(container);
GridLayoutFactory.fillDefaults().numColumns((leftImage != null) ? 3 : 2).margins(5, 5).spacing(3, 0).applyTo(container);
if (leftImage != null) {
Label imageLabel = new Label(container, SWT.NONE);
imageLabel.setImage(leftImage);
int imageWidthHint = leftImage.getBounds().width + 5;
GridDataFactory.fillDefaults().align(SWT.BEGINNING, SWT.BEGINNING).hint(imageWidthHint, SWT.DEFAULT).applyTo(imageLabel);
}
String summary = overview.getSummary();
Composite summaryContainer = new Composite(container, SWT.NULL);
summaryContainer.setBackground(null);
GridLayoutFactory.fillDefaults().applyTo(summaryContainer);
GridDataFactory gridDataFactory = GridDataFactory.fillDefaults().grab(true, true).span(image == null ? 2 : 1, 1);
if (image != null) {
gridDataFactory.hint(widthHint, heightHint);
}
gridDataFactory.applyTo(summaryContainer);
StyledText summaryLabel = new StyledText(summaryContainer, SWT.WRAP | SWT.READ_ONLY | SWT.NO_FOCUS);
summaryLabel.setText(summary);
Point size = summaryLabel.computeSize(widthHint, SWT.DEFAULT);
if (size.y > heightHint - 20) {
summaryLabel.dispose();
summaryLabel = new StyledText(summaryContainer, SWT.WRAP | SWT.READ_ONLY | SWT.NO_FOCUS | SWT.V_SCROLL);
summaryLabel.setText(summary);
}
summaryLabel.setBackground(null);
GridDataFactory.fillDefaults().grab(true, true).align(SWT.BEGINNING, SWT.BEGINNING).applyTo(summaryLabel);
if (image != null) {
final Composite imageContainer = new Composite(container, SWT.BORDER);
GridLayoutFactory.fillDefaults().applyTo(imageContainer);
GridDataFactory.fillDefaults().grab(false, false).align(SWT.CENTER, SWT.BEGINNING).hint(widthHint + (borderWidth * 2), heightHint).applyTo(imageContainer);
Label imageLabel = new Label(imageContainer, SWT.NULL);
GridDataFactory.fillDefaults().hint(widthHint, fixedImageHeight).indent(borderWidth, borderWidth).applyTo(imageLabel);
imageLabel.setImage(image);
imageLabel.setBackground(null);
imageLabel.setSize(widthHint, fixedImageHeight);
// creates a border
imageContainer.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_BLACK));
}
if (hasLearnMoreLink) {
Link link = new Link(summaryContainer, SWT.NULL);
GridDataFactory.fillDefaults().grab(false, false).align(SWT.BEGINNING, SWT.CENTER).applyTo(link);
link.setText(Messages.ConnectorDescriptorToolTip_detailsLink);
link.setBackground(null);
link.setToolTipText(NLS.bind(Messages.ConnectorDescriptorToolTip_detailsLink_tooltip, overview.getUrl()));
link.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
WorkbenchUtil.openUrl(overview.getUrl(), IWorkbenchBrowserSupport.AS_EXTERNAL);
}
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
});
}
if (image == null) {
// prevent overviews with no image from providing unlimited text.
Point optimalSize = summaryContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
if (optimalSize.y > (heightHint + 10)) {
((GridData) summaryContainer.getLayoutData()).heightHint = heightHint;
container.layout(true);
}
}
// hack: cause the tooltip to gain focus so that we can capture the
// escape key
// this must be done async since the tooltip is not yet visible.
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
if (!parent.isDisposed()) {
parent.setFocus();
}
}
});
return container;
}
private Image computeImage(Resource discoverySource, String imagePath) {
URI uri = discoverySource.getURI();
URI trimed = uri.trimSegments(1);
String urlPath = trimed.toString() + "/" + imagePath;
URL resource = null;
try {
resource = new URL(urlPath);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
}
if (resource != null) {
ImageDescriptor descriptor = ImageDescriptor.createFromURL(resource);
Image image = descriptor.createImage();
return image;
}
return null;
}
public void show(Control titleControl) {
Point titleAbsLocation = titleControl.getParent().toDisplay(titleControl.getLocation());
Point containerAbsLocation = parent.getParent().toDisplay(parent.getLocation());
Rectangle bounds = titleControl.getBounds();
int relativeX = titleAbsLocation.x - containerAbsLocation.x;
int relativeY = titleAbsLocation.y - containerAbsLocation.y;
relativeY += bounds.height + 3;
show(new Point(relativeX, relativeY));
}
}