001: /*******************************************************************************
002: * Copyright (c) 2004, 2006 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 java.util.Enumeration;
013: import java.util.Hashtable;
014: import java.util.Properties;
015:
016: import org.eclipse.core.runtime.FileLocator;
017: import org.eclipse.core.runtime.Path;
018: import org.eclipse.jface.resource.JFaceResources;
019: import org.eclipse.swt.graphics.Color;
020: import org.eclipse.swt.graphics.Font;
021: import org.eclipse.swt.graphics.Image;
022: import org.eclipse.ui.forms.widgets.FormToolkit;
023: import org.eclipse.ui.internal.intro.impl.model.AbstractBaseIntroElement;
024: import org.eclipse.ui.internal.intro.impl.model.AbstractIntroContainer;
025: import org.eclipse.ui.internal.intro.impl.model.AbstractIntroElement;
026: import org.eclipse.ui.internal.intro.impl.model.AbstractIntroIdElement;
027: import org.eclipse.ui.internal.intro.impl.model.AbstractIntroPage;
028: import org.eclipse.ui.internal.intro.impl.model.IntroGroup;
029: import org.eclipse.ui.internal.intro.impl.model.IntroImage;
030: import org.eclipse.ui.internal.intro.impl.model.IntroLink;
031: import org.eclipse.ui.internal.intro.impl.model.IntroModelRoot;
032: import org.eclipse.ui.internal.intro.impl.model.IntroText;
033: import org.eclipse.ui.internal.intro.impl.model.loader.ModelLoaderUtil;
034: import org.eclipse.ui.internal.intro.impl.util.ImageUtil;
035: import org.eclipse.ui.internal.intro.impl.util.Log;
036: import org.osgi.framework.Bundle;
037:
038: public class PageStyleManager extends SharedStyleManager {
039:
040: private AbstractIntroPage page;
041: private Hashtable altStyleContexts = new Hashtable();
042: private IntroModelRoot root;
043:
044: /**
045: * Constructor used when page styles need to be loaded. The plugin's bundle
046: * is retrieved from the page model class. The default properties are
047: * assumed to be the presentation shared properties. The inherrited
048: * properties are properties that we got from included and extension styles.
049: *
050: * @param modelRoot
051: */
052: public PageStyleManager(AbstractIntroPage page,
053: Properties sharedProperties) {
054: this .page = page;
055: context = new StyleContext();
056: context.bundle = page.getBundle();
057:
058: // honor shared-style.
059: if (page.injectSharedStyle())
060: properties = new Properties(sharedProperties);
061: else
062: properties = new Properties();
063: String altStyle = page.getAltStyle();
064: if (altStyle != null) {
065: load(properties, altStyle, context);
066: }
067:
068: // AltStyles Hashtable has alt-styles as keys, the bundles as
069: // values.
070: Hashtable altStyles = page.getAltStyles();
071: if (altStyles != null) {
072: Enumeration styles = altStyles.keys();
073: while (styles.hasMoreElements()) {
074: String style = (String) styles.nextElement();
075: Properties inheritedProperties = new Properties();
076: Bundle bundle = (Bundle) altStyles.get(style);
077: StyleContext sc = new StyleContext();
078: sc.bundle = bundle;
079: load(inheritedProperties, style, sc);
080: altStyleContexts.put(inheritedProperties, sc);
081: }
082: }
083:
084: // cache root
085: root = (IntroModelRoot) page.getParentPage().getParent();
086: }
087:
088: // Override parent method to include alt-styles. Use implicit keys as well.
089: public String getProperty(String key) {
090: return getProperty(key, true);
091: }
092:
093: // Override parent method to include alt-styles. If useImplicit is true, we
094: // try to resolve a key without its pageId.
095: private String getProperty(String key, boolean useImplicitKey) {
096: Properties aProperties = findPropertyOwner(key);
097: String value = super .doGetProperty(aProperties, key);
098: if (useImplicitKey) {
099: if (value == null && page.getId() != null
100: && key.startsWith(page.getId())) {
101: // did not find the key as-is. Trim pageId and try again.
102: String relativeKey = key.substring(page.getId()
103: .length());
104: return getProperty(relativeKey);
105: }
106: }
107: return value;
108: }
109:
110: /**
111: * Finds a Properties that represents an inherited shared style, or this
112: * current pages style. If the given key is not found, the pageId is trimmed
113: * from the begining of the key, and the key is looked up again. If key does
114: * not start with a pageId, lookup only the key as is.
115: *
116: * @param key
117: * @return
118: */
119: private Properties findPropertyOwner(String key) {
120: // search for the key in this page's properties first.
121: if (properties.containsKey(key))
122: return properties;
123:
124: // search inherited properties second.
125: Enumeration inheritedPageProperties = altStyleContexts.keys();
126: while (inheritedPageProperties.hasMoreElements()) {
127: Properties aProperties = (Properties) inheritedPageProperties
128: .nextElement();
129: if (aProperties.containsKey(key))
130: return aProperties;
131: }
132: // we did not find the key. Return the local properties anyway.
133: return properties;
134: }
135:
136: /**
137: * Finds the context from which this key was loaded. If the key is not from
138: * an inherited alt style, then use the context corresponding to this page.
139: *
140: * @param key
141: * @return
142: */
143:
144: protected StyleContext getAssociatedContext(String key) {
145: Properties aProperties = findPropertyOwner(key);
146: StyleContext context = (StyleContext) altStyleContexts
147: .get(aProperties);
148: if (context != null)
149: return context;
150: return super .getAssociatedContext(key);
151: }
152:
153: /*
154: * For number of columns, do not return 1 as the default, to allow for
155: * further processing. At the root page level, getting a 0 as ncolumns means
156: * that the number of columns is the number of children. At the page level,
157: * default is 1.
158: */
159: public int getPageNumberOfColumns() {
160: return getIntProperty(page, ".layout.ncolumns", 0); //$NON-NLS-1$
161: }
162:
163: public int getNumberOfColumns(IntroGroup group) {
164: return getIntProperty(group, ".layout.ncolumns", 0); //$NON-NLS-1$
165: }
166:
167: public boolean getEqualWidth(IntroGroup group) {
168: return getBooleanProperty(group, ".layout.equalWidth", false); //$NON-NLS-1$
169: }
170:
171: public int getPageVerticalSpacing() {
172: return getIntProperty(page, ".layout.vspacing", 5); //$NON-NLS-1$
173: }
174:
175: public int getVerticalSpacing(IntroGroup group) {
176: return getIntProperty(group, ".layout.vspacing", 5); //$NON-NLS-1$
177: }
178:
179: public int getPageHorizantalSpacing() {
180: return getIntProperty(page, ".layout.hspacing", 5); //$NON-NLS-1$
181: }
182:
183: public int getHorizantalSpacing(IntroGroup group) {
184: return getIntProperty(group, ".layout.hspacing", 5); //$NON-NLS-1$
185: }
186:
187: public int getColSpan(AbstractBaseIntroElement element) {
188: return getIntProperty(element, ".layout.colspan", 1); //$NON-NLS-1$
189: }
190:
191: public int getRowSpan(AbstractBaseIntroElement element) {
192: return getIntProperty(element, ".layout.rowspan", 1); //$NON-NLS-1$
193: }
194:
195: private int getIntProperty(AbstractBaseIntroElement element,
196: String qualifier, int defaultValue) {
197: StringBuffer buff = ModelLoaderUtil.createPathToElementKey(
198: element, true);
199: if (buff == null)
200: return defaultValue;
201: String key = buff.append(qualifier).toString();
202: return getIntProperty(key, defaultValue);
203: }
204:
205: private boolean getBooleanProperty(
206: AbstractBaseIntroElement element, String qualifier,
207: boolean defaultValue) {
208: StringBuffer buff = ModelLoaderUtil.createPathToElementKey(
209: element, true);
210: if (buff == null)
211: return defaultValue;
212: String key = buff.append(qualifier).toString();
213: return getBooleanProperty(key, defaultValue);
214: }
215:
216: private int getIntProperty(String key, int defaulValue) {
217: int intValue = defaulValue;
218: String value = getProperty(key);
219: if (value == null)
220: return intValue;
221:
222: try {
223: intValue = Integer.parseInt(value);
224: } catch (NumberFormatException e) {
225: Log
226: .error(
227: "Failed to parse key: " + key + " as an integer.", e); //$NON-NLS-1$ //$NON-NLS-2$
228: }
229: return intValue;
230: }
231:
232: private boolean getBooleanProperty(String key, boolean defaultValue) {
233: boolean booleanValue = defaultValue;
234: String value = getProperty(key);
235: if (value != null)
236: booleanValue = value.equalsIgnoreCase("true"); //$NON-NLS-1$
237: return booleanValue;
238: }
239:
240: /**
241: * Finds the description text of the given group. Looks for the Text child
242: * element whos id is specified as follows:
243: * <p>
244: * <pageId>. <path_to_group>.description-id= <id of child description Text
245: * element>
246: * </p>
247: * If not found, use the default description style.
248: *
249: * Returns null if no default style found, or any id in path is null.
250: *
251: * @param group
252: * @return
253: */
254: public String getDescription(IntroGroup group) {
255: StringBuffer buff = ModelLoaderUtil.createPathToElementKey(
256: group, true);
257: if (buff == null)
258: return null;
259: String key = buff.append(".description-id").toString(); //$NON-NLS-1$
260: return doGetDescription(group, key);
261: }
262:
263: /**
264: * Finds the description text of the associated page. Looks for the Text
265: * child element whos id is specified as follows:
266: * <p>
267: * <pageId>.description-id= <id of child description Text element>
268: * </p>
269: * If not found, use the default description style.
270: *
271: * Returns null if no default style found, or any id in path is null.
272: *
273: * @param group
274: * @return
275: */
276: public String getPageDescription() {
277: if (page.getId() == null)
278: return null;
279: String key = page.getId() + ".description-id"; //$NON-NLS-1$
280: return doGetDescription(page, key);
281: }
282:
283: private String doGetDescription(AbstractIntroContainer parent,
284: String key) {
285: String path = getProperty(key);
286: String description = null;
287: if (path != null)
288: description = findTextFromPath(parent, path);
289: if (description != null)
290: return description;
291: return findTextFromStyleId(parent, getDescriptionStyleId());
292: }
293:
294: private String getDescriptionStyleId() {
295: String key = "description-style-id"; //$NON-NLS-1$
296: return getProperty(key);
297: }
298:
299: /**
300: * Finds the subtitle of the associated page. Looks for the Text child
301: * element whose id is specified as follows:
302: * <p>
303: * <pageId>.description-id= <id of child description Text element>
304: * </p>
305: * If not found, use the default description style.
306: *
307: * @param group
308: * @return
309: */
310: public String getPageSubTitle() {
311: String key = page.getId() + ".subtitle-id"; //$NON-NLS-1$
312: String path = getProperty(key);
313: String description = null;
314: if (path != null)
315: description = findTextFromPath(page, path);
316: if (description != null)
317: return description;
318: return findTextFromStyleId(page, getPageSubTitleStyleId());
319: }
320:
321: private String getPageSubTitleStyleId() {
322: String key = "subtitle-style-id"; //$NON-NLS-1$
323: return getProperty(key);
324: }
325:
326: private String findTextFromPath(AbstractIntroContainer parent,
327: String path) {
328: AbstractIntroElement child = parent.findTarget(root, path);
329: if (child != null && child.isOfType(AbstractIntroElement.TEXT)) {
330: makeFiltered(child);
331: return ((IntroText) child).getText();
332: }
333: return null;
334: }
335:
336: /**
337: * Returns the first direct child text element with the given style-id.
338: *
339: * @return
340: */
341: private String findTextFromStyleId(AbstractIntroContainer parent,
342: String styleId) {
343: IntroText[] allText = (IntroText[]) parent
344: .getChildrenOfType(AbstractIntroElement.TEXT);
345: for (int i = 0; i < allText.length; i++) {
346: if (allText[i].getStyleId() == null)
347: // not all elements have style id.
348: continue;
349: if (allText[i].getStyleId().equals(styleId)) {
350: makeFiltered(allText[i]);
351: return allText[i].getText();
352: }
353: }
354: return null;
355: }
356:
357: /**
358: * Util method to check model type, and filter model element out if it is of
359: * the correct type.
360: *
361: * @param element
362: */
363: private AbstractIntroElement makeFiltered(
364: AbstractIntroElement element) {
365: if (element.isOfType(AbstractIntroElement.BASE_ELEMENT))
366: ((AbstractBaseIntroElement) element).setFilterState(true);
367: return element;
368: }
369:
370: public boolean getShowLinkDescription() {
371: String key = page.getId() + ".show-link-description"; //$NON-NLS-1$
372: String value = getProperty(key);
373: if (value == null) {
374: key = ".show-link-description"; //$NON-NLS-1$
375: value = getProperty(key);
376: }
377: if (value == null)
378: value = "true"; //$NON-NLS-1$
379: return value.toLowerCase().equals("true"); //$NON-NLS-1$
380: }
381:
382: public boolean showHomePageNavigation() {
383: String key = page.getId() + ".show-home-page-navigation"; //$NON-NLS-1$
384: String value = getProperty(key);
385: if (value == null) {
386: key = ".show-home-page-navigation"; //$NON-NLS-1$
387: value = getProperty(key);
388: }
389: if (value == null)
390: value = "true"; //$NON-NLS-1$
391: return value.equalsIgnoreCase("true"); //$NON-NLS-1$
392: }
393:
394: public Color getColor(FormToolkit toolkit,
395: AbstractBaseIntroElement element) {
396: StringBuffer buff = ModelLoaderUtil.createPathToElementKey(
397: element, true);
398: if (buff == null)
399: return null;
400: String key = buff.append(".font.fg").toString(); //$NON-NLS-1$
401: return getColor(toolkit, key);
402: }
403:
404: public Color getBackgrond(FormToolkit toolkit,
405: AbstractBaseIntroElement element) {
406: StringBuffer buff = ModelLoaderUtil.createPathToElementKey(
407: element, true);
408: if (buff == null)
409: return null;
410: String key = buff.append(".bg").toString(); //$NON-NLS-1$
411: return getColor(toolkit, key);
412: }
413:
414: public boolean isBold(IntroText text) {
415: String value = null;
416: /*
417: StringBuffer buff = ModelLoaderUtil.createPathToElementKey(text, true);
418: if (buff != null) {
419: String key = buff.append(".font.bold").toString(); //$NON-NLS-1$
420: value = getProperty(key);
421: if (value != null)
422: return value.toLowerCase().equals("true"); //$NON-NLS-1$
423: else {
424: buff = ModelLoaderUtil.createPathToElementKey(text, true);
425: }
426: }
427: */
428: value = getPropertyValue(text, ".font.bold"); //$NON-NLS-1$
429: if (value == null) {
430: // bold is not specified by ID. Check to see if there is a style-id
431: // specified for bold.
432: value = getProperty("bold-style-id"); //$NON-NLS-1$
433: if (value != null && text.getStyleId() != null)
434: return text.getStyleId().equals(value);
435: }
436: return false;
437: }
438:
439: private String getPropertyValue(AbstractIntroIdElement element,
440: String suffix) {
441: StringBuffer buff = ModelLoaderUtil.createPathToElementKey(
442: element, true);
443: if (buff != null) {
444: String key = buff.append(suffix).toString();
445: String value = getProperty(key);
446: if (value != null)
447: return value;
448: // try the page.id key
449: buff = ModelLoaderUtil.createPathToElementKey(element,
450: false);
451: if (buff != null) {
452: key = buff.append(suffix).toString();
453: value = getProperty(key);
454: return value;
455: }
456: }
457: return null;
458: }
459:
460: public static Font getBannerFont() {
461: return JFaceResources.getBannerFont();
462: }
463:
464: public static Font getHeaderFont() {
465: return JFaceResources.getHeaderFont();
466: }
467:
468: /**
469: * Retrieves an image for a link in a page. If not found, uses the page's
470: * default link image. If still not found, uses the passed default.
471: *
472: * @param link
473: * @param qualifier
474: * @return
475: */
476: public Image getImage(IntroLink link, String qualifier,
477: String defaultKey) {
478: // try the Id first
479: String key = createImageByIdKey(page, link, qualifier);
480: String value = getProperty(key, false);
481: if (value == null) {
482: key = createImageKey(page, link, qualifier);
483: // special case where we have to handle this because extended code does
484: // not go through getProperty() in this method.
485: value = getProperty(key, false);
486: }
487: if (value == null && page.getId() != null
488: && key.startsWith(page.getId()))
489: // did not use the key as-is. Trim pageId and try again.
490: key = key.substring(page.getId().length());
491:
492: // pageKey can not become an implicit key.
493: String pageKey = createImageKey(page, null, qualifier);
494:
495: return getImage(key, pageKey, defaultKey);
496: }
497:
498: private String createImageKey(AbstractIntroPage page,
499: IntroLink link, String qualifier) {
500: StringBuffer buff = null;
501: if (link != null) {
502: buff = ModelLoaderUtil.createPathToElementKey(link, true);
503: if (buff == null)
504: return ""; //$NON-NLS-1$
505: } else {
506: buff = new StringBuffer();
507: buff.append(page.getId());
508: }
509: buff.append("."); //$NON-NLS-1$
510: buff.append(qualifier);
511: return buff.toString();
512: }
513:
514: private String createImageByIdKey(AbstractIntroPage page,
515: IntroLink link, String qualifier) {
516: if (link == null || link.getId() == null)
517: return ""; //$NON-NLS-1$
518: StringBuffer buff = new StringBuffer();
519: buff.append(page.getId());
520: buff.append("."); //$NON-NLS-1$
521: buff.append(link.getId());
522: buff.append("."); //$NON-NLS-1$
523: buff.append(qualifier);
524: return buff.toString();
525: }
526:
527: public Image getImage(IntroImage introImage) {
528: String imageLocation = introImage.getSrcAsIs();
529: StringBuffer buff = ModelLoaderUtil.createPathToElementKey(
530: introImage, true);
531: String key;
532: if (buff == null) {
533: key = "//" + imageLocation; //$NON-NLS-1$
534: } else {
535: key = buff != null ? buff.toString() : null;
536: }
537: if (ImageUtil.hasImage(key))
538: return ImageUtil.getImage(key);
539: // key not already registered.
540: if (buff != null) {
541: StyleContext acontext = getAssociatedContext(key);
542: if (acontext.inTheme) {
543: ImageUtil.registerImage(key, acontext.path,
544: imageLocation);
545: return ImageUtil.getImage(key);
546: }
547: }
548: Bundle bundle = introImage.getBundle();
549: if (FileLocator.find(bundle, new Path(imageLocation), null) == null) {
550: return null;
551: }
552: ImageUtil.registerImage(key, bundle, imageLocation);
553: return ImageUtil.getImage(key);
554:
555: }
556:
557: }
|