001: /*******************************************************************************
002: * Copyright (c) 2004, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal.intro.impl.swt;
011:
012: import org.eclipse.swt.SWT;
013: import org.eclipse.swt.SWTError;
014: import org.eclipse.swt.graphics.Color;
015: import org.eclipse.swt.graphics.Image;
016: import org.eclipse.swt.widgets.Composite;
017: import org.eclipse.swt.widgets.Control;
018: import org.eclipse.swt.widgets.Label;
019: import org.eclipse.ui.forms.IFormColors;
020: import org.eclipse.ui.forms.events.HyperlinkAdapter;
021: import org.eclipse.ui.forms.events.HyperlinkEvent;
022: import org.eclipse.ui.forms.widgets.FormText;
023: import org.eclipse.ui.forms.widgets.FormToolkit;
024: import org.eclipse.ui.forms.widgets.Hyperlink;
025: import org.eclipse.ui.forms.widgets.ImageHyperlink;
026: import org.eclipse.ui.forms.widgets.Section;
027: import org.eclipse.ui.forms.widgets.TableWrapData;
028: import org.eclipse.ui.forms.widgets.TableWrapLayout;
029: import org.eclipse.ui.internal.intro.impl.Messages;
030: import org.eclipse.ui.internal.intro.impl.model.AbstractBaseIntroElement;
031: import org.eclipse.ui.internal.intro.impl.model.AbstractIntroElement;
032: import org.eclipse.ui.internal.intro.impl.model.IntroContentProvider;
033: import org.eclipse.ui.internal.intro.impl.model.IntroGroup;
034: import org.eclipse.ui.internal.intro.impl.model.IntroHTML;
035: import org.eclipse.ui.internal.intro.impl.model.IntroImage;
036: import org.eclipse.ui.internal.intro.impl.model.IntroLink;
037: import org.eclipse.ui.internal.intro.impl.model.IntroSeparator;
038: import org.eclipse.ui.internal.intro.impl.model.IntroText;
039: import org.eclipse.ui.internal.intro.impl.model.loader.ContentProviderManager;
040: import org.eclipse.ui.internal.intro.impl.model.url.IntroURLParser;
041: import org.eclipse.ui.internal.intro.impl.util.DialogUtil;
042: import org.eclipse.ui.internal.intro.impl.util.ImageUtil;
043: import org.eclipse.ui.internal.intro.impl.util.Log;
044: import org.eclipse.ui.internal.intro.impl.util.StringUtil;
045: import org.eclipse.ui.internal.intro.impl.util.Util;
046: import org.eclipse.ui.intro.config.IIntroContentProvider;
047: import org.eclipse.ui.intro.config.IIntroContentProviderSite;
048:
049: /**
050: * Factory to create all UI forms widgets for the Forms intro presentation.
051: */
052: public class PageWidgetFactory {
053:
054: protected HyperlinkAdapter hyperlinkAdapter = new HyperlinkAdapter() {
055:
056: public void linkActivated(HyperlinkEvent e) {
057: String url = (String) e.getHref();
058: IntroURLParser parser = new IntroURLParser(url);
059: if (parser.hasIntroUrl()) {
060: // execute the action embedded in the IntroURL
061: parser.getIntroURL().execute();
062: return;
063: } else if (parser.hasProtocol()) {
064: Util.openBrowser(url);
065: return;
066: }
067: DialogUtil.displayInfoMessage(((Control) e.getSource())
068: .getShell(), Messages.HyperlinkAdapter_urlIs
069: + " " + url); //$NON-NLS-1$
070: }
071:
072: public void linkEntered(HyperlinkEvent e) {
073: }
074:
075: public void linkExited(HyperlinkEvent e) {
076: }
077: };
078:
079: protected FormToolkit toolkit;
080: protected PageStyleManager styleManager;
081: protected IIntroContentProviderSite site;
082:
083: /*
084: * protect bad creation.
085: */
086: protected PageWidgetFactory(FormToolkit toolkit,
087: PageStyleManager styleManager) {
088: this .toolkit = toolkit;
089: this .styleManager = styleManager;
090: }
091:
092: public void setContentProviderSite(IIntroContentProviderSite site) {
093: this .site = site;
094: }
095:
096: public void createIntroElement(Composite parent,
097: AbstractIntroElement element) {
098: // check if this element is filtered, and if yes, do not create it.
099: boolean isFiltered = getFilterState(element);
100: if (isFiltered)
101: return;
102:
103: Control c = null;
104: switch (element.getType()) {
105: case AbstractIntroElement.GROUP:
106: IntroGroup group = (IntroGroup) element;
107: c = createGroup(parent, group);
108: updateLayoutData(c, element);
109: // c must be a composite.
110: Composite newParent = (Composite) c;
111: if (c instanceof Section)
112: // client is a composite also.
113: newParent = (Composite) ((Section) newParent)
114: .getClient();
115: AbstractIntroElement[] children = group.getChildren();
116: for (int i = 0; i < children.length; i++)
117: createIntroElement(newParent, children[i]);
118: break;
119: case AbstractIntroElement.LINK:
120: IntroLink link = (IntroLink) element;
121: c = createImageHyperlink(parent, link);
122: updateLayoutData(c, element);
123: break;
124: case AbstractIntroElement.TEXT:
125: IntroText text = (IntroText) element;
126: c = createText(parent, text);
127: updateLayoutData(c, element);
128: break;
129: case AbstractIntroElement.IMAGE:
130: IntroImage image = (IntroImage) element;
131: c = createImage(parent, image);
132: if (c != null)
133: updateLayoutData(c, element);
134: break;
135: case AbstractIntroElement.HTML:
136: IntroHTML html = (IntroHTML) element;
137: if (html.isInlined()) {
138: IntroText htmlText = html.getIntroText();
139: if (htmlText != null)
140: c = createText(parent, htmlText);
141: else {
142: IntroImage htmlImage = html.getIntroImage();
143: if (htmlImage != null)
144: c = createImage(parent, htmlImage);
145: }
146: } else {
147: // embedded HTML, so we can show it from a link.
148: String embddedLink = html.getSrc();
149: if (embddedLink == null)
150: break;
151: String linkText = StringUtil
152: .concat(
153: "<p><a href=\"http://org.eclipse.ui.intro/openBrowser?url=", //$NON-NLS-1$
154: embddedLink, "\">", //$NON-NLS-1$
155: Messages.HTML_embeddedLink, "</a></p>").toString(); //$NON-NLS-1$
156: linkText = generateFormText(linkText);
157: c = createFormText(parent, linkText, null);
158: }
159: if (c != null)
160: updateLayoutData(c, element);
161: break;
162: case AbstractIntroElement.CONTENT_PROVIDER:
163: IntroContentProvider provider = (IntroContentProvider) element;
164: c = createContentProvider(parent, provider);
165: updateLayoutData(c, element);
166: break;
167: case AbstractIntroElement.HR:
168: IntroSeparator sep = (IntroSeparator) element;
169: c = createSeparator(parent, sep);
170: updateLayoutData(c, element);
171: break;
172:
173: default:
174: break;
175: }
176: }
177:
178: private void updateLayoutData(Control c,
179: AbstractIntroElement element) {
180: TableWrapData currentTd = (TableWrapData) c.getLayoutData();
181: if (currentTd == null) {
182: currentTd = new TableWrapData(TableWrapData.FILL,
183: TableWrapData.FILL);
184: currentTd.grabHorizontal = true;
185: c.setLayoutData(currentTd);
186: }
187:
188: currentTd.colspan = styleManager
189: .getColSpan((AbstractBaseIntroElement) element);
190: currentTd.rowspan = styleManager
191: .getRowSpan((AbstractBaseIntroElement) element);
192:
193: }
194:
195: private Composite createGroup(Composite parent, IntroGroup group) {
196: String label = group.getLabel();
197: String description = styleManager.getDescription(group);
198: boolean expandable = group.isExpandable();
199: boolean expanded = group.isExpanded();
200: Composite client = null;
201: Composite control = null;
202: if (description != null || label != null || expandable) {
203: int style = description != null ? Section.DESCRIPTION
204: : SWT.NULL;
205: if (expandable)
206: style |= Section.TWISTIE | Section.FOCUS_TITLE
207: | Section.CLIENT_INDENT;
208: if (expanded)
209: style |= Section.EXPANDED;
210: Section section = toolkit.createSection(parent, style);
211: if (label != null)
212: section.setText(label);
213: if (description != null)
214: section.setDescription(description);
215: colorControl(section, group);
216: client = toolkit.createComposite(section, SWT.WRAP);
217: section.setClient(client);
218: control = section;
219: } else {
220: client = toolkit.createComposite(parent, SWT.WRAP);
221: control = client;
222: }
223:
224: TableWrapLayout layout = new TableWrapLayout();
225: int numColumns = styleManager.getNumberOfColumns(group);
226: numColumns = numColumns < 1 ? 1 : numColumns;
227: layout.numColumns = numColumns;
228: layout.makeColumnsEqualWidth = styleManager
229: .getEqualWidth(group);
230: layout.verticalSpacing = styleManager.getVerticalSpacing(group);
231: layout.horizontalSpacing = styleManager
232: .getHorizantalSpacing(group);
233: client.setLayout(layout);
234: // Util.highlight(client, SWT.COLOR_YELLOW);
235: return control;
236: }
237:
238: /**
239: * Creates an Image Hyperlink from an IntroLink. Model object is NOT cached.
240: *
241: * @param body
242: * @param link
243: */
244: private Control createImageHyperlink(Composite parent,
245: IntroLink link) {
246: Control control;
247: Hyperlink linkControl;
248: boolean showLinkDescription = styleManager
249: .getShowLinkDescription();
250: Image linkImage = styleManager.getImage(link, "link-icon", //$NON-NLS-1$
251: ImageUtil.DEFAULT_LINK);
252:
253: if (showLinkDescription && link.getText() != null) {
254: Composite container = toolkit.createComposite(parent);
255: TableWrapLayout layout = new TableWrapLayout();
256: layout.leftMargin = layout.rightMargin = 0;
257: layout.topMargin = layout.bottomMargin = 0;
258: layout.verticalSpacing = 0;
259: layout.numColumns = 2;
260: container.setLayout(layout);
261:
262: //Label ilabel = toolkit.createLabel(container, null);
263: ImageHyperlink ilabel = toolkit.createImageHyperlink(
264: container, SWT.NULL);
265: ilabel.setImage(linkImage);
266: ilabel.setHoverImage(styleManager.getImage(link,
267: "hover-icon", //$NON-NLS-1$
268: null));
269: ilabel.setHref(link.getUrl());
270: ilabel.addHyperlinkListener(hyperlinkAdapter);
271: TableWrapData td = new TableWrapData();
272: td.valign = TableWrapData.TOP;
273: td.rowspan = 2;
274: ilabel.setLayoutData(td);
275:
276: linkControl = toolkit.createHyperlink(container, null,
277: SWT.WRAP);
278: td = new TableWrapData(TableWrapData.LEFT,
279: TableWrapData.BOTTOM);
280: td.grabVertical = true;
281: linkControl.setLayoutData(td);
282: // Util.highlight(linkControl, SWT.COLOR_RED);
283: // Util.highlight(container, SWT.COLOR_DARK_YELLOW);
284:
285: Control desc = createText(container, link.getIntroText());
286: td = new TableWrapData(TableWrapData.FILL,
287: TableWrapData.TOP);
288: td.grabHorizontal = true;
289: td.grabVertical = true;
290: desc.setLayoutData(td);
291: control = container;
292: } else {
293: ImageHyperlink imageLink = toolkit.createImageHyperlink(
294: parent, SWT.WRAP | SWT.CENTER);
295: imageLink.setImage(linkImage);
296: imageLink.setHoverImage(styleManager.getImage(link,
297: "hover-icon", //$NON-NLS-1$
298: null));
299: TableWrapData td = new TableWrapData();
300: td.grabHorizontal = true;
301: imageLink.setLayoutData(td);
302: linkControl = imageLink;
303: control = linkControl;
304: }
305: linkControl.setText(link.getLabel());
306: linkControl.setFont(PageStyleManager.getBannerFont());
307: colorControl(linkControl, link);
308: linkControl.setHref(link.getUrl());
309: linkControl.addHyperlinkListener(hyperlinkAdapter);
310: // Util.highlight(linkControl, SWT.COLOR_DARK_YELLOW);
311: return control;
312: }
313:
314: /**
315: * Creates a forms Text or FormattedText.
316: *
317: * @param body
318: * @param link
319: */
320: protected Control createText(Composite parent, IntroText text) {
321: Color fg = styleManager.getColor(toolkit, text);
322: boolean isBold = styleManager.isBold(text);
323: // formatted case. If text is alredy formatted, the bold property is
324: // ignored.
325: if (text.isFormatted())
326: return createFormText(parent, generateFormText(text
327: .getText()), fg);
328:
329: // non formatted case.
330: if (isBold)
331: return createFormText(parent, generateBoldFormText(text
332: .getText()), fg);
333: return createText(parent, text.getText(), fg);
334: }
335:
336: private Control createFormText(Composite parent, String text,
337: Color fg) {
338: FormText formText = toolkit.createFormText(parent, false);
339: formText.addHyperlinkListener(hyperlinkAdapter);
340: try {
341: formText.setText(text, true, true);
342: } catch (SWTError e) {
343: Log.error(e.getMessage(), e);
344: return createText(parent, text, fg);
345: }
346: if (fg != null)
347: formText.setForeground(fg);
348: return formText;
349: }
350:
351: private Control createText(Composite parent, String text, Color fg) {
352: Label label = toolkit.createLabel(parent, text, SWT.WRAP);
353: if (fg != null)
354: label.setForeground(fg);
355: return label;
356: }
357:
358: protected Control createImage(Composite parent, IntroImage image) {
359: Label ilabel = null;
360: Image imageFile = styleManager.getImage(image);
361: if (imageFile != null) {
362: ilabel = toolkit.createLabel(parent, null, SWT.LEFT);
363: ilabel.setImage(imageFile);
364: if (image.getAlt() != null)
365: ilabel.setToolTipText(image.getAlt());
366: }
367: // for images, do not use default layout. Grab horizontal is not what we
368: // want.
369: if (ilabel != null) {
370: TableWrapData td = new TableWrapData();
371: ilabel.setLayoutData(td);
372: }
373: return ilabel;
374: }
375:
376: public Control createContentProvider(Composite parent,
377: IntroContentProvider provider) {
378: // If we've already loaded the content provider for this element,
379: // retrieve it, otherwise load the class.
380: // Create parent composite to hold dynamic content, and set layout
381: // accordingly.
382: Composite container = toolkit.createComposite(parent);
383: TableWrapLayout layout = new TableWrapLayout();
384: layout.topMargin = 0;
385: layout.bottomMargin = 0;
386: layout.leftMargin = 0;
387: layout.rightMargin = 0;
388: container.setLayout(layout);
389: container.setData(provider);
390:
391: IIntroContentProvider providerClass = ContentProviderManager
392: .getInst().getContentProvider(provider);
393: if (providerClass == null)
394: // content provider never created before, create it.
395: providerClass = ContentProviderManager.getInst()
396: .createContentProvider(provider, site);
397:
398: if (providerClass != null) {
399: try {
400: providerClass.createContent(provider.getId(),
401: container, toolkit);
402: } catch (Exception e) {
403: Log.error(
404: "Failed to create the content of Intro model content provider: " //$NON-NLS-1$
405: + provider.getClassName(), e);
406: // null provider.
407: providerClass = null;
408: }
409: }
410:
411: if (providerClass == null) {
412: // we failed to create a provider class, create the embedded text.
413: IntroText text = provider.getIntroText();
414: if (text != null)
415: createText(container, text);
416: }
417: return container;
418: }
419:
420: protected Control createSeparator(Composite parent,
421: IntroSeparator sep) {
422: String key = sep.getParentPage().getId() + ".separator.fg"; //$NON-NLS-1$
423: Color fg = styleManager.getColor(toolkit, key);
424: //Composite l = toolkit.createCompositeSeparator(parent);
425: Composite l = new Composite(parent, SWT.NULL);
426: if (fg != null)
427: l.setBackground(fg);
428: else
429: l.setBackground(toolkit.getColors().getColor(
430: IFormColors.SEPARATOR));
431: TableWrapData td = new TableWrapData(TableWrapData.FILL,
432: TableWrapData.FILL);
433: td.grabHorizontal = true;
434: td.maxHeight = 1;
435: l.setLayoutData(td);
436: return l;
437: }
438:
439: private void colorControl(Control elementControl,
440: AbstractBaseIntroElement element) {
441: Color fg = styleManager.getColor(toolkit, element);
442: if (fg != null)
443: elementControl.setForeground(fg);
444: Color bg = styleManager.getBackgrond(toolkit, element);
445: if (bg != null)
446: elementControl.setBackground(bg);
447: }
448:
449: /*
450: * creates form text on a formatted string. A formatted string is any string
451: * that has a " <" in it. If it starts with a <p> then it is assumed that
452: * the text if a proper UI forms formatted text. If not, the <p> tag is
453: * added.
454: */
455: private String generateFormText(String text) {
456: StringBuffer sbuf = new StringBuffer();
457: sbuf.append("<form>"); //$NON-NLS-1$
458: if (text.startsWith("<p>")) //$NON-NLS-1$
459: sbuf.append(text);
460: else {
461: sbuf.append("<p>"); //$NON-NLS-1$
462: sbuf.append(text);
463: sbuf.append("</p>"); //$NON-NLS-1$
464: }
465: sbuf.append("</form>"); //$NON-NLS-1$
466: return sbuf.toString();
467: }
468:
469: /**
470: * Will be only called for non formatted text.
471: *
472: * @param text
473: * @return
474: */
475: private String generateBoldFormText(String text) {
476: StringBuffer sbuf = new StringBuffer();
477: sbuf.append("<form>"); //$NON-NLS-1$
478: sbuf.append("<p>"); //$NON-NLS-1$
479: sbuf.append("<b>"); //$NON-NLS-1$
480: sbuf.append(text);
481: sbuf.append("</b>"); //$NON-NLS-1$
482: sbuf.append("</p>"); //$NON-NLS-1$
483: sbuf.append("</form>"); //$NON-NLS-1$
484: return sbuf.toString();
485: }
486:
487: /**
488: * Check the filter state of the element. Only base elements have the filter
489: * attribute.
490: *
491: * @param element
492: * @return
493: */
494: private boolean getFilterState(AbstractIntroElement element) {
495: if (element.isOfType(AbstractIntroElement.BASE_ELEMENT))
496: return ((AbstractBaseIntroElement) element).isFiltered();
497: return false;
498: }
499:
500: }
|