blob: 18f01b636294b09e4a10d76655e13989d4e6b62b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2016 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.ui.internal.intro.impl.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.ui.forms.IFormColors;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.widgets.Form;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ImageHyperlink;
import org.eclipse.ui.forms.widgets.ScrolledPageBook;
import org.eclipse.ui.internal.intro.impl.IIntroConstants;
import org.eclipse.ui.internal.intro.impl.Messages;
import org.eclipse.ui.internal.intro.impl.model.AbstractBaseIntroElement;
import org.eclipse.ui.internal.intro.impl.model.AbstractIntroElement;
import org.eclipse.ui.internal.intro.impl.model.IntroContentProvider;
import org.eclipse.ui.internal.intro.impl.model.IntroGroup;
import org.eclipse.ui.internal.intro.impl.model.IntroHomePage;
import org.eclipse.ui.internal.intro.impl.model.IntroLink;
import org.eclipse.ui.internal.intro.impl.model.IntroModelRoot;
import org.eclipse.ui.internal.intro.impl.model.url.IntroURLParser;
import org.eclipse.ui.internal.intro.impl.util.DialogUtil;
import org.eclipse.ui.internal.intro.impl.util.ImageUtil;
import org.eclipse.ui.internal.intro.impl.util.StringUtil;
import org.eclipse.ui.internal.intro.impl.util.Util;
import org.eclipse.ui.intro.config.IIntroContentProviderSite;
/**
* A Composite that represents the Root Page. It is swapped in the main page
* book in the FormIntroPartImplementation class.
*/
public class RootPageForm implements IIntroConstants {
private FormToolkit toolkit;
private IntroHomePage rootPage;
private Form parentForm;
protected Label descriptionLabel;
private PageStyleManager rootPageStyleManager;
private IIntroContentProviderSite site;
private PageWidgetFactory factory;
class PageComposite extends Composite {
public PageComposite(Composite parent, int style) {
super(parent, style);
}
// Do not allow composite to take wHint as-is - layout manager
// can reject the hint and compute larger width.
@Override
public Point computeSize(int wHint, int hHint, boolean changed) {
return ((RootPageLayout) getLayout()).computeSize(this, wHint,
hHint, changed);
}
}
class RootPageLayout extends Layout {
// gap between link composite and description label.
private int VERTICAL_SPACING = 20;
private int LABEL_MARGIN_WIDTH = 5;
/*
* Custom layout for Root Page Composite.
*/
@Override
protected Point computeSize(Composite composite, int wHint, int hHint,
boolean flushCache) {
int innerWHint = wHint;
if (wHint != SWT.DEFAULT)
innerWHint -= LABEL_MARGIN_WIDTH + LABEL_MARGIN_WIDTH;
Control[] children = composite.getChildren();
Point s1 = children[0].computeSize(SWT.DEFAULT, SWT.DEFAULT);
Point s2 = children[1].computeSize(innerWHint, SWT.DEFAULT);
s2.x += LABEL_MARGIN_WIDTH;
int height = 2 * (s2.y + VERTICAL_SPACING + s1.y / 2);
Point size = new Point(Math.max(s1.x, s2.x), height + 5);
return size;
}
@Override
protected void layout(Composite composite, boolean flushCache) {
Control[] children = composite.getChildren();
Rectangle carea = composite.getClientArea();
Control content = children[0];
Control label = children[1];
Point contentSize = content.computeSize(SWT.DEFAULT, SWT.DEFAULT);
Point labelSize = label.computeSize(carea.width - 2
- LABEL_MARGIN_WIDTH * 2, SWT.DEFAULT);
content.setBounds(carea.width / 2 - contentSize.x / 2, carea.height
/ 2 - contentSize.y / 2, contentSize.x, contentSize.y);
label.setBounds(LABEL_MARGIN_WIDTH, content.getLocation().y
+ contentSize.y + VERTICAL_SPACING, carea.width
- LABEL_MARGIN_WIDTH * 2, labelSize.y);
}
}
private HyperlinkAdapter hyperlinkAdapter = new HyperlinkAdapter() {
@Override
public void linkActivated(HyperlinkEvent e) {
ImageHyperlink imageLink = (ImageHyperlink) e.getSource();
IntroLink introLink = (IntroLink) imageLink.getData(INTRO_LINK);
IntroURLParser parser = new IntroURLParser(introLink.getUrl());
if (parser.hasIntroUrl()) {
// execute the action embedded in the IntroURL
parser.getIntroURL().execute();
return;
} else if (parser.hasProtocol()) {
Util.openBrowser(introLink.getUrl());
return;
}
DialogUtil.displayInfoMessage(imageLink.getShell(),
Messages.HyperlinkAdapter_urlIs + introLink.getUrl());
}
@Override
public void linkEntered(HyperlinkEvent e) {
ImageHyperlink imageLink = (ImageHyperlink) e.getSource();
IntroLink introLink = (IntroLink) imageLink.getData(INTRO_LINK);
updateDescription(introLink.getText());
}
@Override
public void linkExited(HyperlinkEvent e) {
// empty text on exit.
updateDescription(""); //$NON-NLS-1$
}
private void updateDescription(String text) {
if (text == null)
text = ""; //$NON-NLS-1$
descriptionLabel.setText(text);
descriptionLabel.getParent().layout();
}
};
/**
*
*/
public RootPageForm(FormToolkit toolkit, IntroModelRoot modelRoot,
Form parentForm) {
this.toolkit = toolkit;
this.rootPage = modelRoot.getRootPage();
this.parentForm = parentForm;
}
/**
* Create the form for the root page. Number of columns there is equal to
* the number of links.
*
* @param pageBook
*/
public void createPartControl(ScrolledPageBook mainPageBook,
SharedStyleManager shardStyleManager) {
// first, create the root page style manager from shared style manager.
rootPageStyleManager = new PageStyleManager(rootPage, shardStyleManager
.getProperties());
// Set title of Main form from root page title.
parentForm.setText(rootPage.getTitle());
// Composite for full root page. It has custom layout, and two
// children: the content composite and the description label.
Composite rootPageComposite = new PageComposite(mainPageBook
.getContainer(), SWT.NULL);
toolkit.adapt(rootPageComposite);
mainPageBook.registerPage(rootPage.getId(), rootPageComposite);
rootPageComposite.setLayout(new RootPageLayout());
// Util.highlight(pageComposite, SWT.COLOR_DARK_CYAN);
// create the contents composite in the center of the root page.
createRootPageContent(rootPageComposite);
// create description label for links description.
descriptionLabel = createHoverLabel(rootPageComposite);
// Clear memory. No need for style manager any more.
rootPageStyleManager = null;
}
/**
* Creates content of the root page.
*/
private void createRootPageContent(Composite rootPageComposite) {
// setup page composite/layout
Composite contentComposite = toolkit.createComposite(rootPageComposite);
GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
contentComposite.setLayoutData(gd);
AbstractIntroElement[] children = (AbstractIntroElement[]) rootPage
.getChildrenOfType(AbstractIntroElement.GROUP
| AbstractIntroElement.LINK | AbstractIntroElement.CONTENT_PROVIDER);
int numChildren = children.length;
GridLayout layout = new GridLayout();
// separate links a bit more.
layout.horizontalSpacing = rootPageStyleManager
.getPageHorizantalSpacing();
layout.verticalSpacing = rootPageStyleManager.getPageVerticalSpacing();
// set number of columns.
int numColumns = rootPageStyleManager.getPageNumberOfColumns();
numColumns = numColumns == 0 ? numChildren : numColumns;
layout.numColumns = numColumns;
layout.horizontalSpacing = rootPageStyleManager
.getPageHorizantalSpacing();
layout.verticalSpacing = rootPageStyleManager.getPageVerticalSpacing();
contentComposite.setLayout(layout);
for (int i = 0; i < children.length; i++) {
if (((AbstractBaseIntroElement) children[i]).isFiltered())
continue;
if (children[i].getType() == AbstractIntroElement.GROUP)
createGroupContent(contentComposite, (IntroGroup) children[i]);
else if (children[i].getType() == AbstractIntroElement.LINK)
createImageHyperlink(contentComposite, (IntroLink) children[i]);
else if (children[i].getType() == AbstractIntroElement.CONTENT_PROVIDER)
createContentProvider(contentComposite, (IntroContentProvider)children[i]);
}
}
/**
* Creates content of the root page.
*/
private void createGroupContent(Composite parent, IntroGroup group) {
AbstractIntroElement[] children = (AbstractIntroElement[]) group
.getChildrenOfType(AbstractIntroElement.GROUP
| AbstractIntroElement.LINK |
AbstractIntroElement.CONTENT_PROVIDER);
int numChildren = children.length;
// setup page composite/layout
Composite contentComposite = toolkit.createComposite(parent);
GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
gd.horizontalSpan = rootPageStyleManager.getColSpan(group);
gd.verticalSpan = rootPageStyleManager.getRowSpan(group);
contentComposite.setLayoutData(gd);
GridLayout layout = new GridLayout();
// separate links a bit more.
layout.horizontalSpacing = 20;
// set number of columns.
int numColumns = rootPageStyleManager.getNumberOfColumns(group);
numColumns = numColumns < 1 ? numChildren : numColumns;
layout.numColumns = numColumns;
layout.verticalSpacing = rootPageStyleManager.getVerticalSpacing(group);
layout.horizontalSpacing = rootPageStyleManager
.getHorizantalSpacing(group);
contentComposite.setLayout(layout);
for (int i = 0; i < children.length; i++) {
if (((AbstractBaseIntroElement) children[i]).isFiltered())
continue;
if (children[i].getType() == AbstractIntroElement.GROUP)
createGroupContent(contentComposite, (IntroGroup) children[i]);
else if (children[i].getType() == AbstractIntroElement.LINK)
createImageHyperlink(contentComposite, (IntroLink) children[i]);
else if (children[i].getType() == AbstractIntroElement.CONTENT_PROVIDER)
createContentProvider(contentComposite, (IntroContentProvider)children[i]);
}
}
/**
* Creates an Image Hyperlink from an IntroLink. Model object is cached in
* link.
*
* @param body
* @param link
*/
private void createImageHyperlink(Composite parent, IntroLink link) {
// create the container composite that will hold the imageHyperLink and
// the label for the description.
Composite container = toolkit.createComposite(parent);
// Util.highlight(container, SWT.COLOR_CYAN);
GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
gd.horizontalSpan = rootPageStyleManager.getColSpan(link);
gd.verticalSpan = rootPageStyleManager.getRowSpan(link);
container.setLayoutData(gd);
GridLayout layout = new GridLayout();
layout.marginWidth = 0;
layout.marginHeight = 0;
container.setLayout(layout);
ImageHyperlink imageLink = toolkit.createImageHyperlink(container,
SWT.NULL);
imageLink.setImage(rootPageStyleManager.getImage(link, "link-icon", //$NON-NLS-1$
ImageUtil.DEFAULT_ROOT_LINK));
imageLink.setHoverImage(rootPageStyleManager.getImage(link,
"hover-icon", null)); //$NON-NLS-1$
// each link is centered in cell.
gd = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
imageLink.setLayoutData(gd);
// cache the intro link model object for description and URL.
imageLink.setData(INTRO_LINK, link);
imageLink.addHyperlinkListener(hyperlinkAdapter);
// description label.
Label linkLabel = toolkit.createLabel(container, link.getLabel());
gd = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
linkLabel.setFont(PageStyleManager.getBannerFont());
linkLabel.setLayoutData(gd);
}
/**
* Creates a label to display the link description when you hover over a
* hyperlink.
*
* @param body
*/
private Label createHoverLabel(Composite body) {
Label label = toolkit.createLabel(body, "", SWT.WRAP); //$NON-NLS-1$
String key = StringUtil.concat(rootPage.getId(), ".", "hover-text.fg") //$NON-NLS-1$ //$NON-NLS-2$
.toString();
Color fg = rootPageStyleManager.getColor(toolkit, key);
if (fg == null)
fg = toolkit.getColors().getColor(IFormColors.TITLE);
label.setForeground(fg);
label.setAlignment(SWT.CENTER);
label.setFont(PageStyleManager.getBannerFont());
return label;
}
private void createContentProvider(Composite parent, IntroContentProvider providerElement) {
if (factory==null) {
factory = new PageWidgetFactory(toolkit, rootPageStyleManager);
factory.setContentProviderSite(site);
}
factory.createContentProvider(parent, providerElement);
}
public void setContentProviderSite(IIntroContentProviderSite site) {
this.site = site;
}
}