org.eclipse.epp.internal.mpc.ui.wizards.OverviewToolTip.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.epp.internal.mpc.ui.wizards.OverviewToolTip.java

Source

/*******************************************************************************
 * Copyright (c) 2009, 2010 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
 *******************************************************************************/

package org.eclipse.epp.internal.mpc.ui.wizards;

import java.net.URL;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.Platform;
import org.eclipse.epp.internal.mpc.core.util.TextUtil;
import org.eclipse.epp.internal.mpc.ui.MarketplaceClientUi;
import org.eclipse.epp.internal.mpc.ui.util.Util;
import org.eclipse.equinox.internal.p2.discovery.AbstractCatalogSource;
import org.eclipse.equinox.internal.p2.discovery.model.Overview;
import org.eclipse.equinox.internal.p2.ui.discovery.util.WorkbenchUtil;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.window.ToolTip;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.browser.LocationListener;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
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
 */
class OverviewToolTip extends ToolTip {

    final int SCREENSHOT_HEIGHT = 240;

    final int SCREENSHOT_WIDTH = 320;

    private final Overview overview;

    private final AbstractCatalogSource source;

    private final Control parent;

    private final Image leftImage;

    private final IMarketplaceWebBrowser browser;

    public OverviewToolTip(Control control, IMarketplaceWebBrowser browser, AbstractCatalogSource 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;
        this.browser = browser;
        setHideOnMouseDown(false); // required for links to work
    }

    @Override
    protected Composite createToolTipContentArea(Event event, final Composite parent) {
        GridLayoutFactory.fillDefaults().applyTo(parent);

        Color backgroundColor = parent.getDisplay().getSystemColor(SWT.COLOR_WHITE);
        final Composite container = new Composite(parent, SWT.NULL);
        container.setBackground(backgroundColor);

        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 heightHint = SCREENSHOT_HEIGHT + (borderWidth * 2);
        final int widthHint = SCREENSHOT_WIDTH;

        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);
            imageLabel.setBackground(backgroundColor);
            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(backgroundColor);
        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);

        Browser summaryLabel = new Browser(summaryContainer, SWT.NULL);

        Font dialogFont = JFaceResources.getDialogFont();
        FontData[] fontData = dialogFont.getFontData();
        String attr = ""; //$NON-NLS-1$
        String fontSizeUnitOfMeasure = "pt"; //$NON-NLS-1$
        if (Platform.OS_MACOSX.equals(Platform.getOS())) {
            fontSizeUnitOfMeasure = "px"; //$NON-NLS-1$
        } else if (Platform.OS_WIN32.equals(Platform.getOS())) {
            attr = "overflow: auto; "; //$NON-NLS-1$
        }
        String cssStyle = "body, p, div, *  {" + attr + "font-family:\"" + fontData[0].getName() //$NON-NLS-1$ //$NON-NLS-2$
                + "\",Arial,sans-serif !important;font-size:" + fontData[0].getHeight() + fontSizeUnitOfMeasure //$NON-NLS-1$
                + " !important;" //$NON-NLS-1$
                + "} body { margin: 0px; background-color: white;}"; //$NON-NLS-1$
        summaryLabel.setFont(dialogFont);
        String html = "<html><style>" + cssStyle + "</style><body>" + TextUtil.cleanInformalHtmlMarkup(summary) //$NON-NLS-1$//$NON-NLS-2$
                + "</body></html>"; //$NON-NLS-1$
        summaryLabel.setText(html);
        summaryLabel.setBackground(backgroundColor);
        // instead of opening links in the tooltip, open a new browser window
        summaryLabel.addLocationListener(new LocationListener() {
            public void changing(LocationEvent event) {
                if (event.location.equals("about:blank")) { //$NON-NLS-1$
                    return;
                }
                event.doit = false;
                OverviewToolTip.this.hide();
                WorkbenchUtil.openUrl(event.location, IWorkbenchBrowserSupport.AS_EXTERNAL);
            }

            public void changed(LocationEvent event) {
            }
        });

        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true)
                .hint(SWT.DEFAULT, image == null ? SCREENSHOT_HEIGHT : SWT.DEFAULT).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, SCREENSHOT_HEIGHT).indent(borderWidth, borderWidth)
                    .applyTo(imageLabel);
            imageLabel.setImage(image);
            imageLabel.setBackground(backgroundColor);
            imageLabel.setSize(widthHint, SCREENSHOT_HEIGHT);

            final Cursor handCursor = new Cursor(image.getDevice(), SWT.CURSOR_HAND);
            imageLabel.setCursor(handCursor);
            imageLabel.addDisposeListener(new DisposeListener() {
                public void widgetDisposed(DisposeEvent e) {
                    handCursor.dispose();
                }
            });
            imageLabel.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseDown(MouseEvent e) {
                    OverviewToolTip.this.hide();
                    WorkbenchUtil.openUrl(overview.getScreenshot(), IWorkbenchBrowserSupport.AS_EXTERNAL);
                }
            });

            // creates a border
            imageContainer.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
        }
        if (hasLearnMoreLink) {
            Link link = new Link(summaryContainer, SWT.NULL);
            GridDataFactory.fillDefaults().grab(false, false).align(SWT.BEGINNING, SWT.CENTER).applyTo(link);
            link.setText(Messages.OverviewToolTip_learnMoreLink);
            link.setBackground(backgroundColor);
            link.setToolTipText(NLS.bind(Messages.OverviewToolTip_openUrlInBrowser, overview.getUrl()));
            link.addSelectionListener(new SelectionListener() {
                public void widgetSelected(SelectionEvent e) {
                    OverviewToolTip.this.hide();
                    browser.openUrl(overview.getUrl());
                }

                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(AbstractCatalogSource discoverySource, String imagePath) {
        URL resource = discoverySource.getResource(imagePath);
        if (resource != null) {
            try {
                ImageDescriptor descriptor = ImageDescriptor.createFromURL(resource);
                Image image = descriptor.createImage();
                Rectangle imageBounds = image.getBounds();
                if (imageBounds.width > SCREENSHOT_WIDTH || imageBounds.height > SCREENSHOT_HEIGHT) {
                    final Image scaledImage = Util.scaleImage(image, SCREENSHOT_WIDTH, SCREENSHOT_HEIGHT);
                    Image originalImage = image;
                    image = scaledImage;
                    originalImage.dispose();
                }
                return image;
            } catch (SWTException e) {
                // ignore, probably a bad image format
                MarketplaceClientUi.error(
                        NLS.bind(Messages.OverviewToolTip_cannotRenderImage_reason, imagePath, e.getMessage()), e);
            }
        }
        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));
    }

}