blob: c0bfde650389c664753d76ac64fb569e39703261 [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.SWTError;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
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.FormText;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Hyperlink;
import org.eclipse.ui.forms.widgets.ImageHyperlink;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.forms.widgets.TableWrapData;
import org.eclipse.ui.forms.widgets.TableWrapLayout;
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.IntroHTML;
import org.eclipse.ui.internal.intro.impl.model.IntroImage;
import org.eclipse.ui.internal.intro.impl.model.IntroLink;
import org.eclipse.ui.internal.intro.impl.model.IntroSeparator;
import org.eclipse.ui.internal.intro.impl.model.IntroText;
import org.eclipse.ui.internal.intro.impl.model.loader.ContentProviderManager;
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.Log;
import org.eclipse.ui.internal.intro.impl.util.StringUtil;
import org.eclipse.ui.internal.intro.impl.util.Util;
import org.eclipse.ui.intro.config.IIntroContentProvider;
import org.eclipse.ui.intro.config.IIntroContentProviderSite;
/**
* Factory to create all UI forms widgets for the Forms intro presentation.
*/
public class PageWidgetFactory {
protected HyperlinkAdapter hyperlinkAdapter = new HyperlinkAdapter() {
@Override
public void linkActivated(HyperlinkEvent e) {
String url = (String) e.getHref();
IntroURLParser parser = new IntroURLParser(url);
if (parser.hasIntroUrl()) {
// execute the action embedded in the IntroURL
parser.getIntroURL().execute();
return;
} else if (parser.hasProtocol()) {
Util.openBrowser(url);
return;
}
DialogUtil.displayInfoMessage(((Control) e.getSource()).getShell(),
Messages.HyperlinkAdapter_urlIs + " " + url); //$NON-NLS-1$
}
@Override
public void linkEntered(HyperlinkEvent e) {
}
@Override
public void linkExited(HyperlinkEvent e) {
}
};
protected FormToolkit toolkit;
protected PageStyleManager styleManager;
protected IIntroContentProviderSite site;
/*
* protect bad creation.
*/
protected PageWidgetFactory(FormToolkit toolkit,
PageStyleManager styleManager) {
this.toolkit = toolkit;
this.styleManager = styleManager;
}
public void setContentProviderSite(IIntroContentProviderSite site) {
this.site = site;
}
public void createIntroElement(Composite parent,
AbstractIntroElement element) {
// check if this element is filtered, and if yes, do not create it.
boolean isFiltered = getFilterState(element);
if (isFiltered)
return;
Control c = null;
switch (element.getType()) {
case AbstractIntroElement.GROUP:
IntroGroup group = (IntroGroup) element;
c = createGroup(parent, group);
updateLayoutData(c, element);
// c must be a composite.
Composite newParent = (Composite) c;
if (c instanceof Section)
// client is a composite also.
newParent = (Composite) ((Section) newParent).getClient();
AbstractIntroElement[] children = group.getChildren();
for (int i = 0; i < children.length; i++)
createIntroElement(newParent, children[i]);
break;
case AbstractIntroElement.LINK:
IntroLink link = (IntroLink) element;
c = createImageHyperlink(parent, link);
updateLayoutData(c, element);
break;
case AbstractIntroElement.TEXT:
IntroText text = (IntroText) element;
c = createText(parent, text);
updateLayoutData(c, element);
break;
case AbstractIntroElement.IMAGE:
IntroImage image = (IntroImage) element;
c = createImage(parent, image);
if (c!=null)
updateLayoutData(c, element);
break;
case AbstractIntroElement.HTML:
IntroHTML html = (IntroHTML) element;
if (html.isInlined()) {
IntroText htmlText = html.getIntroText();
if (htmlText != null)
c = createText(parent, htmlText);
else {
IntroImage htmlImage = html.getIntroImage();
if (htmlImage != null)
c = createImage(parent, htmlImage);
}
} else {
// embedded HTML, so we can show it from a link.
String embddedLink = html.getSrc();
if (embddedLink == null)
break;
String linkText = StringUtil
.concat(
"<p><a href=\"http://org.eclipse.ui.intro/openBrowser?url=", //$NON-NLS-1$
embddedLink, "\">", //$NON-NLS-1$
Messages.HTML_embeddedLink, "</a></p>").toString(); //$NON-NLS-1$
linkText = generateFormText(linkText);
c = createFormText(parent, linkText, null);
}
if (c != null)
updateLayoutData(c, element);
break;
case AbstractIntroElement.CONTENT_PROVIDER:
IntroContentProvider provider = (IntroContentProvider) element;
c = createContentProvider(parent, provider);
updateLayoutData(c, element);
break;
case AbstractIntroElement.HR:
IntroSeparator sep = (IntroSeparator)element;
c = createSeparator(parent, sep);
updateLayoutData(c, element);
break;
default:
break;
}
}
private void updateLayoutData(Control c, AbstractIntroElement element) {
TableWrapData currentTd = (TableWrapData) c.getLayoutData();
if (currentTd == null) {
currentTd = new TableWrapData(TableWrapData.FILL,
TableWrapData.FILL);
currentTd.grabHorizontal = true;
c.setLayoutData(currentTd);
}
currentTd.colspan = styleManager
.getColSpan((AbstractBaseIntroElement) element);
currentTd.rowspan = styleManager
.getRowSpan((AbstractBaseIntroElement) element);
}
private Composite createGroup(Composite parent, IntroGroup group) {
String label = group.getLabel();
String description = styleManager.getDescription(group);
boolean expandable = group.isExpandable();
boolean expanded = group.isExpanded();
Composite client = null;
Composite control = null;
if (description != null || label != null || expandable) {
int style = description != null ? Section.DESCRIPTION : SWT.NULL;
if (expandable)
style |= Section.TWISTIE | Section.FOCUS_TITLE | Section.CLIENT_INDENT;
if (expanded)
style |= Section.EXPANDED;
Section section = toolkit.createSection(parent, style);
if (label != null)
section.setText(label);
if (description != null)
section.setDescription(description);
colorControl(section, group);
client = toolkit.createComposite(section, SWT.WRAP);
section.setClient(client);
control = section;
} else {
client = toolkit.createComposite(parent, SWT.WRAP);
control = client;
}
TableWrapLayout layout = new TableWrapLayout();
int numColumns = styleManager.getNumberOfColumns(group);
numColumns = numColumns < 1 ? 1 : numColumns;
layout.numColumns = numColumns;
layout.makeColumnsEqualWidth = styleManager.getEqualWidth(group);
layout.verticalSpacing = styleManager.getVerticalSpacing(group);
layout.horizontalSpacing = styleManager.getHorizantalSpacing(group);
client.setLayout(layout);
// Util.highlight(client, SWT.COLOR_YELLOW);
return control;
}
/**
* Creates an Image Hyperlink from an IntroLink. Model object is NOT cached.
*
* @param body
* @param link
*/
private Control createImageHyperlink(Composite parent, IntroLink link) {
Control control;
Hyperlink linkControl;
boolean showLinkDescription = styleManager.getShowLinkDescription();
Image linkImage = styleManager.getImage(link, "link-icon", //$NON-NLS-1$
ImageUtil.DEFAULT_LINK);
if (showLinkDescription && link.getText() != null) {
Composite container = toolkit.createComposite(parent);
TableWrapLayout layout = new TableWrapLayout();
layout.leftMargin = layout.rightMargin = 0;
layout.topMargin = layout.bottomMargin = 0;
layout.verticalSpacing = 0;
layout.numColumns = 2;
container.setLayout(layout);
//Label ilabel = toolkit.createLabel(container, null);
ImageHyperlink ilabel = toolkit.createImageHyperlink(container, SWT.NULL);
ilabel.setImage(linkImage);
ilabel.setHoverImage(styleManager.getImage(link, "hover-icon", //$NON-NLS-1$
null));
ilabel.setHref(link.getUrl());
ilabel.addHyperlinkListener(hyperlinkAdapter);
TableWrapData td = new TableWrapData();
td.valign = TableWrapData.TOP;
td.rowspan = 2;
ilabel.setLayoutData(td);
linkControl = toolkit.createHyperlink(container, null, SWT.WRAP);
td = new TableWrapData(TableWrapData.LEFT, TableWrapData.BOTTOM);
td.grabVertical = true;
linkControl.setLayoutData(td);
// Util.highlight(linkControl, SWT.COLOR_RED);
// Util.highlight(container, SWT.COLOR_DARK_YELLOW);
Control desc = createText(container, link.getIntroText());
td = new TableWrapData(TableWrapData.FILL, TableWrapData.TOP);
td.grabHorizontal = true;
td.grabVertical = true;
desc.setLayoutData(td);
control = container;
} else {
ImageHyperlink imageLink = toolkit.createImageHyperlink(parent,
SWT.WRAP | SWT.CENTER);
imageLink.setImage(linkImage);
imageLink.setHoverImage(styleManager.getImage(link, "hover-icon", //$NON-NLS-1$
null));
TableWrapData td = new TableWrapData();
td.grabHorizontal = true;
imageLink.setLayoutData(td);
linkControl = imageLink;
control = linkControl;
}
linkControl.setText(link.getLabel());
linkControl.setFont(PageStyleManager.getBannerFont());
colorControl(linkControl, link);
linkControl.setHref(link.getUrl());
linkControl.addHyperlinkListener(hyperlinkAdapter);
// Util.highlight(linkControl, SWT.COLOR_DARK_YELLOW);
return control;
}
/**
* Creates a forms Text or FormattedText.
*
* @param body
* @param link
*/
protected Control createText(Composite parent, IntroText text) {
Color fg = styleManager.getColor(toolkit, text);
boolean isBold = styleManager.isBold(text);
// formatted case. If text is alredy formatted, the bold property is
// ignored.
if (text.isFormatted())
return createFormText(parent, generateFormText(text.getText()), fg);
// non formatted case.
if (isBold)
return createFormText(parent, generateBoldFormText(text.getText()),
fg);
return createText(parent, StringUtil.normalizeWhiteSpace(text.getText()), fg);
}
private Control createFormText(Composite parent, String text, Color fg) {
FormText formText = toolkit.createFormText(parent, false);
formText.addHyperlinkListener(hyperlinkAdapter);
try {
formText.setText(text, true, true);
} catch (SWTError e) {
Log.error(e.getMessage(), e);
return createText(parent, text, fg);
}
if (fg != null)
formText.setForeground(fg);
return formText;
}
private Control createText(Composite parent, String text, Color fg) {
Label label = toolkit.createLabel(parent, text, SWT.WRAP);
if (fg != null)
label.setForeground(fg);
return label;
}
protected Control createImage(Composite parent, IntroImage image) {
Label ilabel = null;
Image imageFile = styleManager.getImage(image);
if (imageFile != null) {
ilabel = toolkit.createLabel(parent, null, SWT.LEFT);
ilabel.setImage(imageFile);
if (image.getAlt() != null)
ilabel.setToolTipText(image.getAlt());
}
// for images, do not use default layout. Grab horizontal is not what we
// want.
if (ilabel!=null) {
TableWrapData td = new TableWrapData();
ilabel.setLayoutData(td);
}
return ilabel;
}
public Control createContentProvider(Composite parent,
IntroContentProvider provider) {
// If we've already loaded the content provider for this element,
// retrieve it, otherwise load the class.
// Create parent composite to hold dynamic content, and set layout
// accordingly.
Composite container = toolkit.createComposite(parent);
TableWrapLayout layout = new TableWrapLayout();
layout.topMargin = 0;
layout.bottomMargin = 0;
layout.leftMargin = 0;
layout.rightMargin = 0;
container.setLayout(layout);
container.setData(provider);
IIntroContentProvider providerClass = ContentProviderManager.getInst()
.getContentProvider(provider);
if (providerClass == null)
// content provider never created before, create it.
providerClass = ContentProviderManager.getInst()
.createContentProvider(provider, site);
if (providerClass != null) {
try {
providerClass.createContent(provider.getId(), container,
toolkit);
} catch (Exception e) {
Log.error(
"Failed to create the content of Intro model content provider: " //$NON-NLS-1$
+ provider.getClassName(), e);
// null provider.
providerClass = null;
}
}
if (providerClass == null) {
// we failed to create a provider class, create the embedded text.
IntroText text = provider.getIntroText();
if (text != null)
createText(container, text);
}
return container;
}
protected Control createSeparator(Composite parent, IntroSeparator sep) {
String key = sep.getParentPage().getId()+".separator.fg"; //$NON-NLS-1$
Color fg = styleManager.getColor(toolkit, key);
//Composite l = toolkit.createCompositeSeparator(parent);
Composite l = new Composite(parent, SWT.NULL);
if (fg!=null)
l.setBackground(fg);
else
l.setBackground(toolkit.getColors().getColor(IFormColors.SEPARATOR));
TableWrapData td = new TableWrapData(TableWrapData.FILL,
TableWrapData.FILL);
td.grabHorizontal = true;
td.maxHeight = 1;
l.setLayoutData(td);
return l;
}
private void colorControl(Control elementControl,
AbstractBaseIntroElement element) {
Color fg = styleManager.getColor(toolkit, element);
if (fg != null)
elementControl.setForeground(fg);
Color bg = styleManager.getBackgrond(toolkit, element);
if (bg != null)
elementControl.setBackground(bg);
}
/*
* creates form text on a formatted string. A formatted string is any string
* that has a " <" in it. If it starts with a <p> then it is assumed that
* the text if a proper UI forms formatted text. If not, the <p> tag is
* added.
*/
private String generateFormText(String text) {
StringBuffer sbuf = new StringBuffer();
sbuf.append("<form>"); //$NON-NLS-1$
if (text.startsWith("<p>")) //$NON-NLS-1$
sbuf.append(text);
else {
sbuf.append("<p>"); //$NON-NLS-1$
sbuf.append(text);
sbuf.append("</p>"); //$NON-NLS-1$
}
sbuf.append("</form>"); //$NON-NLS-1$
return sbuf.toString();
}
/**
* Will be only called for non formatted text.
*
* @param text
* @return
*/
private String generateBoldFormText(String text) {
StringBuffer sbuf = new StringBuffer();
sbuf.append("<form>"); //$NON-NLS-1$
sbuf.append("<p>"); //$NON-NLS-1$
sbuf.append("<b>"); //$NON-NLS-1$
sbuf.append(text);
sbuf.append("</b>"); //$NON-NLS-1$
sbuf.append("</p>"); //$NON-NLS-1$
sbuf.append("</form>"); //$NON-NLS-1$
return sbuf.toString();
}
/**
* Check the filter state of the element. Only base elements have the filter
* attribute.
*
* @param element
* @return
*/
private boolean getFilterState(AbstractIntroElement element) {
if (element.isOfType(AbstractIntroElement.BASE_ELEMENT))
return ((AbstractBaseIntroElement) element).isFiltered();
return false;
}
}