001: /*******************************************************************************
002: * Copyright (c) 2000, 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.jface.viewers;
011:
012: import org.eclipse.core.runtime.Assert;
013: import org.eclipse.core.runtime.ListenerList;
014: import org.eclipse.swt.graphics.Color;
015: import org.eclipse.swt.graphics.Font;
016: import org.eclipse.swt.graphics.Image;
017:
018: /**
019: * A decorating label provider is a label provider which combines
020: * a nested label provider and an optional decorator.
021: * The decorator decorates the label text, image, font and colors provided by
022: * the nested label provider.
023: */
024: public class DecoratingLabelProvider extends LabelProvider implements
025: ILabelProvider, IViewerLabelProvider, IColorProvider,
026: IFontProvider, ITreePathLabelProvider {
027:
028: private ILabelProvider provider;
029:
030: private ILabelDecorator decorator;
031:
032: // Need to keep our own list of listeners
033: private ListenerList listeners = new ListenerList();
034:
035: private IDecorationContext decorationContext = DecorationContext.DEFAULT_CONTEXT;
036:
037: /**
038: * Creates a decorating label provider which uses the given label decorator
039: * to decorate labels provided by the given label provider.
040: *
041: * @param provider the nested label provider
042: * @param decorator the label decorator, or <code>null</code> if no decorator is to be used initially
043: */
044: public DecoratingLabelProvider(ILabelProvider provider,
045: ILabelDecorator decorator) {
046: Assert.isNotNull(provider);
047: this .provider = provider;
048: this .decorator = decorator;
049: }
050:
051: /**
052: * The <code>DecoratingLabelProvider</code> implementation of this <code>IBaseLabelProvider</code> method
053: * adds the listener to both the nested label provider and the label decorator.
054: *
055: * @param listener a label provider listener
056: */
057: public void addListener(ILabelProviderListener listener) {
058: super .addListener(listener);
059: provider.addListener(listener);
060: if (decorator != null) {
061: decorator.addListener(listener);
062: }
063: listeners.add(listener);
064: }
065:
066: /**
067: * The <code>DecoratingLabelProvider</code> implementation of this <code>IBaseLabelProvider</code> method
068: * disposes both the nested label provider and the label decorator.
069: */
070: public void dispose() {
071: provider.dispose();
072: if (decorator != null) {
073: decorator.dispose();
074: }
075: }
076:
077: /**
078: * The <code>DecoratingLabelProvider</code> implementation of this
079: * <code>ILabelProvider</code> method returns the image provided
080: * by the nested label provider's <code>getImage</code> method,
081: * decorated with the decoration provided by the label decorator's
082: * <code>decorateImage</code> method.
083: */
084: public Image getImage(Object element) {
085: Image image = provider.getImage(element);
086: if (decorator != null) {
087: if (decorator instanceof LabelDecorator) {
088: LabelDecorator ld2 = (LabelDecorator) decorator;
089: Image decorated = ld2.decorateImage(image, element,
090: getDecorationContext());
091: if (decorated != null) {
092: return decorated;
093: }
094: } else {
095: Image decorated = decorator.decorateImage(image,
096: element);
097: if (decorated != null) {
098: return decorated;
099: }
100: }
101: }
102: return image;
103: }
104:
105: /**
106: * Returns the label decorator, or <code>null</code> if none has been set.
107: *
108: * @return the label decorator, or <code>null</code> if none has been set.
109: */
110: public ILabelDecorator getLabelDecorator() {
111: return decorator;
112: }
113:
114: /**
115: * Returns the nested label provider.
116: *
117: * @return the nested label provider
118: */
119: public ILabelProvider getLabelProvider() {
120: return provider;
121: }
122:
123: /**
124: * The <code>DecoratingLabelProvider</code> implementation of this
125: * <code>ILabelProvider</code> method returns the text label provided
126: * by the nested label provider's <code>getText</code> method,
127: * decorated with the decoration provided by the label decorator's
128: * <code>decorateText</code> method.
129: */
130: public String getText(Object element) {
131: String text = provider.getText(element);
132: if (decorator != null) {
133: if (decorator instanceof LabelDecorator) {
134: LabelDecorator ld2 = (LabelDecorator) decorator;
135: String decorated = ld2.decorateText(text, element,
136: getDecorationContext());
137: if (decorated != null) {
138: return decorated;
139: }
140: } else {
141: String decorated = decorator
142: .decorateText(text, element);
143: if (decorated != null) {
144: return decorated;
145: }
146: }
147: }
148: return text;
149: }
150:
151: /**
152: * The <code>DecoratingLabelProvider</code> implementation of this
153: * <code>IBaseLabelProvider</code> method returns <code>true</code> if the corresponding method
154: * on the nested label provider returns <code>true</code> or if the corresponding method on the
155: * decorator returns <code>true</code>.
156: */
157: public boolean isLabelProperty(Object element, String property) {
158: if (provider.isLabelProperty(element, property)) {
159: return true;
160: }
161: if (decorator != null
162: && decorator.isLabelProperty(element, property)) {
163: return true;
164: }
165: return false;
166: }
167:
168: /**
169: * The <code>DecoratingLabelProvider</code> implementation of this <code>IBaseLabelProvider</code> method
170: * removes the listener from both the nested label provider and the label decorator.
171: *
172: * @param listener a label provider listener
173: */
174: public void removeListener(ILabelProviderListener listener) {
175: super .removeListener(listener);
176: provider.removeListener(listener);
177: if (decorator != null) {
178: decorator.removeListener(listener);
179: }
180: listeners.remove(listener);
181: }
182:
183: /**
184: * Sets the label decorator.
185: * Removes all known listeners from the old decorator, and adds all known listeners to the new decorator.
186: * The old decorator is not disposed.
187: * Fires a label provider changed event indicating that all labels should be updated.
188: * Has no effect if the given decorator is identical to the current one.
189: *
190: * @param decorator the label decorator, or <code>null</code> if no decorations are to be applied
191: */
192: public void setLabelDecorator(ILabelDecorator decorator) {
193: ILabelDecorator oldDecorator = this .decorator;
194: if (oldDecorator != decorator) {
195: Object[] listenerList = this .listeners.getListeners();
196: if (oldDecorator != null) {
197: for (int i = 0; i < listenerList.length; ++i) {
198: oldDecorator
199: .removeListener((ILabelProviderListener) listenerList[i]);
200: }
201: }
202: this .decorator = decorator;
203: if (decorator != null) {
204: for (int i = 0; i < listenerList.length; ++i) {
205: decorator
206: .addListener((ILabelProviderListener) listenerList[i]);
207: }
208: }
209: fireLabelProviderChanged(new LabelProviderChangedEvent(this ));
210: }
211: }
212:
213: /*
214: * (non-Javadoc)
215: * @see org.eclipse.jface.viewers.IViewerLabelProvider#updateLabel(org.eclipse.jface.viewers.ViewerLabel, java.lang.Object)
216: */
217: public void updateLabel(ViewerLabel settings, Object element) {
218:
219: ILabelDecorator currentDecorator = getLabelDecorator();
220: String oldText = settings.getText();
221: boolean decorationReady = true;
222: if (currentDecorator instanceof IDelayedLabelDecorator) {
223: IDelayedLabelDecorator delayedDecorator = (IDelayedLabelDecorator) currentDecorator;
224: if (!delayedDecorator.prepareDecoration(element, oldText)) {
225: // The decoration is not ready but has been queued for processing
226: decorationReady = false;
227: }
228: }
229: // update icon and label
230:
231: if (decorationReady || oldText == null
232: || settings.getText().length() == 0) {
233: settings.setText(getText(element));
234: }
235:
236: Image oldImage = settings.getImage();
237: if (decorationReady || oldImage == null) {
238: settings.setImage(getImage(element));
239: }
240:
241: if (decorationReady) {
242: updateForDecorationReady(settings, element);
243: }
244:
245: }
246:
247: /**
248: * Decoration is ready. Update anything else for the settings.
249: * @param settings The object collecting the settings.
250: * @param element The Object being decorated.
251: * @since 3.1
252: */
253: protected void updateForDecorationReady(ViewerLabel settings,
254: Object element) {
255:
256: if (decorator instanceof IColorDecorator) {
257: IColorDecorator colorDecorator = (IColorDecorator) decorator;
258: settings.setBackground(colorDecorator
259: .decorateBackground(element));
260: settings.setForeground(colorDecorator
261: .decorateForeground(element));
262: }
263:
264: if (decorator instanceof IFontDecorator) {
265: settings.setFont(((IFontDecorator) decorator)
266: .decorateFont(element));
267: }
268:
269: }
270:
271: /* (non-Javadoc)
272: * @see org.eclipse.jface.viewers.IColorProvider#getBackground(java.lang.Object)
273: */
274: public Color getBackground(Object element) {
275: if (provider instanceof IColorProvider) {
276: return ((IColorProvider) provider).getBackground(element);
277: }
278: return null;
279: }
280:
281: /* (non-Javadoc)
282: * @see org.eclipse.jface.viewers.IFontProvider#getFont(java.lang.Object)
283: */
284: public Font getFont(Object element) {
285: if (provider instanceof IFontProvider) {
286: return ((IFontProvider) provider).getFont(element);
287: }
288: return null;
289: }
290:
291: /* (non-Javadoc)
292: * @see org.eclipse.jface.viewers.IColorProvider#getForeground(java.lang.Object)
293: */
294: public Color getForeground(Object element) {
295: if (provider instanceof IColorProvider) {
296: return ((IColorProvider) provider).getForeground(element);
297: }
298: return null;
299: }
300:
301: /**
302: * Return the decoration context associated with this label provider.
303: * It will be passed to the decorator if the decorator is an
304: * instance of {@link LabelDecorator}.
305: * @return the decoration context associated with this label provider
306: *
307: * @since 3.2
308: */
309: public IDecorationContext getDecorationContext() {
310: return decorationContext;
311: }
312:
313: /**
314: * Set the decoration context that will be based to the decorator
315: * for this label provider if that decorator implements {@link LabelDecorator}.
316: * @param decorationContext the decoration context.
317: *
318: * @since 3.2
319: */
320: public void setDecorationContext(
321: IDecorationContext decorationContext) {
322: Assert.isNotNull(decorationContext);
323: this .decorationContext = decorationContext;
324: }
325:
326: /* (non-Javadoc)
327: * @see org.eclipse.jface.viewers.ITreePathLabelProvider#updateLabel(org.eclipse.jface.viewers.ViewerLabel, org.eclipse.jface.viewers.TreePath)
328: */
329: public void updateLabel(ViewerLabel settings, TreePath elementPath) {
330: ILabelDecorator currentDecorator = getLabelDecorator();
331: String oldText = settings.getText();
332: Object element = elementPath.getLastSegment();
333: boolean decorationReady = true;
334: if (currentDecorator instanceof LabelDecorator) {
335: LabelDecorator labelDecorator = (LabelDecorator) currentDecorator;
336: if (!labelDecorator.prepareDecoration(element, oldText,
337: getDecorationContext())) {
338: // The decoration is not ready but has been queued for processing
339: decorationReady = false;
340: }
341: } else if (currentDecorator instanceof IDelayedLabelDecorator) {
342: IDelayedLabelDecorator delayedDecorator = (IDelayedLabelDecorator) currentDecorator;
343: if (!delayedDecorator.prepareDecoration(element, oldText)) {
344: // The decoration is not ready but has been queued for processing
345: decorationReady = false;
346: }
347: }
348: settings.setHasPendingDecorations(!decorationReady);
349: // update icon and label
350:
351: if (provider instanceof ITreePathLabelProvider) {
352: ITreePathLabelProvider pprov = (ITreePathLabelProvider) provider;
353: if (decorationReady || oldText == null
354: || settings.getText().length() == 0) {
355: pprov.updateLabel(settings, elementPath);
356: decorateSettings(settings, elementPath);
357: }
358: } else {
359: if (decorationReady || oldText == null
360: || settings.getText().length() == 0) {
361: settings.setText(getText(element));
362: }
363:
364: Image oldImage = settings.getImage();
365: if (decorationReady || oldImage == null) {
366: settings.setImage(getImage(element));
367: }
368:
369: if (decorationReady) {
370: updateForDecorationReady(settings, element);
371: }
372: }
373:
374: }
375:
376: /**
377: * Decorate the settings
378: * @param settings the settings obtained from the label provider
379: * @param elementPath the element path being decorated
380: */
381: private void decorateSettings(ViewerLabel settings,
382: TreePath elementPath) {
383: Object element = elementPath.getLastSegment();
384: if (decorator != null) {
385: if (decorator instanceof LabelDecorator) {
386: LabelDecorator labelDecorator = (LabelDecorator) decorator;
387: String text = labelDecorator.decorateText(settings
388: .getText(), element, getDecorationContext());
389: if (text != null && text.length() > 0)
390: settings.setText(text);
391: Image image = labelDecorator.decorateImage(settings
392: .getImage(), element, getDecorationContext());
393: if (image != null)
394: settings.setImage(image);
395:
396: } else {
397: String text = decorator.decorateText(
398: settings.getText(), element);
399: if (text != null && text.length() > 0)
400: settings.setText(text);
401: Image image = decorator.decorateImage(settings
402: .getImage(), element);
403: if (image != null)
404: settings.setImage(image);
405: }
406: if (decorator instanceof IColorDecorator) {
407: IColorDecorator colorDecorator = (IColorDecorator) decorator;
408: Color background = colorDecorator
409: .decorateBackground(element);
410: if (background != null)
411: settings.setBackground(background);
412: Color foreground = colorDecorator
413: .decorateForeground(element);
414: if (foreground != null)
415: settings.setForeground(foreground);
416: }
417:
418: if (decorator instanceof IFontDecorator) {
419: Font font = ((IFontDecorator) decorator)
420: .decorateFont(element);
421: if (font != null)
422: settings.setFont(font);
423: }
424: }
425: }
426: }
|