/*******************************************************************************
* Copyright (c) 2004, 2010 BREDEX GmbH.
* 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:
* BREDEX GmbH - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.jubula.client.ui.provider;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.DecorationContext;
import org.eclipse.jface.viewers.IColorDecorator;
import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.jface.viewers.IDecorationContext;
import org.eclipse.jface.viewers.IDelayedLabelDecorator;
import org.eclipse.jface.viewers.IFontDecorator;
import org.eclipse.jface.viewers.IFontProvider;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITreePathLabelProvider;
import org.eclipse.jface.viewers.IViewerLabelProvider;
import org.eclipse.jface.viewers.LabelDecorator;
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerLabel;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
/**
* A decorating label provider is a label provider which combines a nested label
* provider and an optional decorator. The decorator decorates the label text,
* image, font and colors provided by the nested label provider.
* @see http://eclip.se/182216
*/
public class DecoratingCellLabelProvider extends CellLabelProvider implements
ILabelProvider, IViewerLabelProvider, IColorProvider, IFontProvider,
ITreePathLabelProvider {
/**
* <code>provider</code>
*/
private ILabelProvider m_provider;
/**
* <code>decorator</code>
*/
private ILabelDecorator m_decorator;
/**
* Need to keep our own list of listeners
* <code>listeners</code>
*/
private ListenerList m_listeners = new ListenerList();
/**
* <code>decorationContext</code>
*/
private IDecorationContext m_decorationContext;
/**
* Creates a decorating label provider which uses the given label decorator
* to decorate labels provided by the given label provider.
*
* @param provider
* the nested label provider
* @param decorator
* the label decorator, or <code>null</code> if no decorator is
* to be used initially
*/
public DecoratingCellLabelProvider(ILabelProvider provider,
ILabelDecorator decorator) {
Assert.isNotNull(provider);
this.m_provider = provider;
this.m_decorator = decorator;
this.m_decorationContext = createDefaultDecorationContext();
}
/**
* Create a decoration context for the receiver that has a
* LocalResourceManager.
*
* @return the DefaultDecorationContext
*/
private IDecorationContext createDefaultDecorationContext() {
return new DecorationContext();
}
/**
* The <code>DecoratingLabelProvider</code> implementation of this
* <code>IBaseLabelProvider</code> method adds the listener to both the
* nested label provider and the label decorator.
*
* @param listener
* a label provider listener
*/
public void addListener(ILabelProviderListener listener) {
super.addListener(listener);
m_provider.addListener(listener);
if (m_decorator != null) {
m_decorator.addListener(listener);
}
m_listeners.add(listener);
}
/**
* The <code>DecoratingLabelProvider</code> implementation of this
* <code>IBaseLabelProvider</code> method disposes both the nested label
* provider and the label decorator.
*/
public void dispose() {
m_provider.dispose();
if (m_decorator != null) {
m_decorator.dispose();
}
}
/**
* The <code>DecoratingLabelProvider</code> implementation of this
* <code>ILabelProvider</code> method returns the image provided by the
* nested label provider's <code>getImage</code> method, decorated with the
* decoration provided by the label decorator's <code>decorateImage</code>
* method.
* @param element the element to get the image for
* @return the image
*/
public Image getImage(Object element) {
Image image = m_provider.getImage(element);
if (m_decorator != null) {
if (m_decorator instanceof LabelDecorator) {
LabelDecorator ld2 = (LabelDecorator)m_decorator;
Image decorated = ld2.decorateImage(image, element,
getDecorationContext());
if (decorated != null) {
return decorated;
}
} else {
Image decorated = m_decorator.decorateImage(image, element);
if (decorated != null) {
return decorated;
}
}
}
return image;
}
/**
* Returns the label decorator, or <code>null</code> if none has been set.
*
* @return the label decorator, or <code>null</code> if none has been set.
*/
public ILabelDecorator getLabelDecorator() {
return m_decorator;
}
/**
* Returns the nested label provider.
*
* @return the nested label provider
*/
public ILabelProvider getLabelProvider() {
return m_provider;
}
/**
* The <code>DecoratingLabelProvider</code> implementation of this
* <code>ILabelProvider</code> method returns the text label provided by the
* nested label provider's <code>getText</code> method, decorated with the
* decoration provided by the label decorator's <code>decorateText</code>
* method.
* @param element the element to get the text for
* @return the text
*/
public String getText(Object element) {
String text = m_provider.getText(element);
if (m_decorator != null) {
if (m_decorator instanceof LabelDecorator) {
LabelDecorator ld2 = (LabelDecorator)m_decorator;
String decorated = ld2.decorateText(text, element,
getDecorationContext());
if (decorated != null) {
return decorated;
}
} else {
String decorated = m_decorator.decorateText(text, element);
if (decorated != null) {
return decorated;
}
}
}
return text;
}
/**
* The <code>DecoratingLabelProvider</code> implementation of this
* <code>IBaseLabelProvider</code> method returns <code>true</code> if the
* corresponding method on the nested label provider returns
* <code>true</code> or if the corresponding method on the decorator returns
* <code>true</code>.
* @param element the element
* @param property the property
* @return true or false
*/
public boolean isLabelProperty(Object element, String property) {
if (m_provider.isLabelProperty(element, property)) {
return true;
}
return m_decorator != null
&& m_decorator.isLabelProperty(element, property);
}
/**
* The <code>DecoratingLabelProvider</code> implementation of this
* <code>IBaseLabelProvider</code> method removes the listener from both the
* nested label provider and the label decorator.
*
* @param listener
* a label provider listener
*/
public void removeListener(ILabelProviderListener listener) {
super.removeListener(listener);
m_provider.removeListener(listener);
if (m_decorator != null) {
m_decorator.removeListener(listener);
}
m_listeners.remove(listener);
}
/**
* Sets the label decorator. Removes all known listeners from the old
* decorator, and adds all known listeners to the new decorator. The old
* decorator is not disposed. Fires a label provider changed event
* indicating that all labels should be updated. Has no effect if the given
* decorator is identical to the current one.
*
* @param decorator
* the label decorator, or <code>null</code> if no decorations
* are to be applied
*/
public void setLabelDecorator(ILabelDecorator decorator) {
ILabelDecorator oldDecorator = this.m_decorator;
if (oldDecorator != decorator) {
Object[] listenerList = this.m_listeners.getListeners();
if (oldDecorator != null) {
for (int i = 0; i < listenerList.length; i++) {
oldDecorator
.removeListener(
(ILabelProviderListener)listenerList[i]);
}
}
this.m_decorator = decorator;
if (decorator != null) {
for (int i = 0; i < listenerList.length; i++) {
decorator
.addListener(
(ILabelProviderListener)listenerList[i]);
}
}
fireLabelProviderChanged(new LabelProviderChangedEvent(this));
}
}
/**
* {@inheritDoc}
*/
public void updateLabel(ViewerLabel settings, Object element) {
ILabelDecorator currentDecorator = getLabelDecorator();
String oldText = settings.getText();
boolean decorationReady = true;
if (currentDecorator instanceof IDelayedLabelDecorator) {
IDelayedLabelDecorator delayedDecorator =
(IDelayedLabelDecorator)currentDecorator;
if (!delayedDecorator.prepareDecoration(element, oldText)) {
// The decoration is not ready but has been queued for
// processing
decorationReady = false;
}
}
// update icon and label
if (decorationReady || oldText == null
|| settings.getText().length() == 0) {
settings.setText(getText(element));
}
Image oldImage = settings.getImage();
if (decorationReady || oldImage == null) {
settings.setImage(getImage(element));
}
if (decorationReady) {
updateForDecorationReady(settings, element);
}
}
/**
* Decoration is ready. Update anything else for the settings.
*
* @param settings
* The object collecting the settings.
* @param element
* The Object being decorated.
* @since 3.1
*/
protected void updateForDecorationReady(ViewerLabel settings,
Object element) {
if (m_decorator instanceof IColorDecorator) {
IColorDecorator colorDecorator = (IColorDecorator)m_decorator;
Color color = colorDecorator.decorateBackground(element);
if (color != null) {
settings.setBackground(color);
}
color = colorDecorator.decorateForeground(element);
if (color != null) {
settings.setForeground(color);
}
}
if (m_decorator instanceof IFontDecorator) {
Font font = ((IFontDecorator)m_decorator).decorateFont(element);
if (font != null) {
settings.setFont(font);
}
}
}
/**
* {@inheritDoc}
*/
public Color getBackground(Object element) {
if (m_provider instanceof IColorProvider) {
return ((IColorProvider)m_provider).getBackground(element);
}
return null;
}
/**
* {@inheritDoc}
*/
public Font getFont(Object element) {
if (m_provider instanceof IFontProvider) {
return ((IFontProvider)m_provider).getFont(element);
}
return null;
}
/**
* {@inheritDoc}
*/
public Color getForeground(Object element) {
if (m_provider instanceof IColorProvider) {
return ((IColorProvider)m_provider).getForeground(element);
}
return null;
}
/**
* {@inheritDoc}
*/
public Color getToolTipBackgroundColor(Object object) {
if (m_provider instanceof CellLabelProvider) {
return ((CellLabelProvider)m_provider)
.getToolTipBackgroundColor(object);
}
return super.getToolTipBackgroundColor(object);
}
/**
* {@inheritDoc}
*/
public int getToolTipDisplayDelayTime(Object object) {
if (m_provider instanceof CellLabelProvider) {
return ((CellLabelProvider)m_provider)
.getToolTipDisplayDelayTime(object);
}
return super.getToolTipDisplayDelayTime(object);
}
/**
* {@inheritDoc}
*/
public Font getToolTipFont(Object object) {
if (m_provider instanceof CellLabelProvider) {
return ((CellLabelProvider)m_provider).getToolTipFont(object);
}
return super.getToolTipFont(object);
}
/**
* {@inheritDoc}
*/
public Color getToolTipForegroundColor(Object object) {
if (m_provider instanceof CellLabelProvider) {
return ((CellLabelProvider)m_provider)
.getToolTipForegroundColor(object);
}
return super.getToolTipForegroundColor(object);
}
/**
* {@inheritDoc}
*/
public Image getToolTipImage(Object object) {
if (m_provider instanceof CellLabelProvider) {
return ((CellLabelProvider)m_provider).getToolTipImage(object);
}
return super.getToolTipImage(object);
}
/**
* {@inheritDoc}
*/
public Point getToolTipShift(Object object) {
if (m_provider instanceof CellLabelProvider) {
return ((CellLabelProvider)m_provider).getToolTipShift(object);
}
return super.getToolTipShift(object);
}
/**
* {@inheritDoc}
*/
public int getToolTipStyle(Object object) {
if (m_provider instanceof CellLabelProvider) {
return ((CellLabelProvider)m_provider).getToolTipStyle(object);
}
return super.getToolTipStyle(object);
}
/**
* {@inheritDoc}
*/
public String getToolTipText(Object object) {
if (m_provider instanceof CellLabelProvider) {
return ((CellLabelProvider)m_provider).getToolTipText(object);
}
return super.getToolTipText(object);
}
/**
* {@inheritDoc}
*/
public int getToolTipTimeDisplayed(Object object) {
if (m_provider instanceof CellLabelProvider) {
return ((CellLabelProvider)m_provider)
.getToolTipTimeDisplayed(object);
}
return super.getToolTipTimeDisplayed(object);
}
/**
* Return the decoration context associated with this label provider. It
* will be passed to the decorator if the decorator is an instance of
* {@link LabelDecorator}.
*
* @return the decoration context associated with this label provider
*
* @since 3.2
*/
public IDecorationContext getDecorationContext() {
return m_decorationContext;
}
/**
* Set the decoration context that will be based to the decorator for this
* label provider if that decorator implements {@link LabelDecorator}.
*
* If this decorationContext has a
* {@link org.eclipse.jface.resource.ResourceManager} stored for the
* {@link DecorationContext#RESOURCE_MANAGER_KEY} property it will be
* disposed when the label provider is disposed.
*
* @param decorationContext
* the decoration context.
*
* @since 3.2
*/
public void setDecorationContext(IDecorationContext decorationContext) {
org.eclipse.core.runtime.Assert.isNotNull(decorationContext);
this.m_decorationContext = decorationContext;
}
/**
* {@inheritDoc}
*/
public void updateLabel(ViewerLabel settings, TreePath elementPath) {
ILabelDecorator currentDecorator = getLabelDecorator();
String oldText = settings.getText();
Object element = elementPath.getLastSegment();
boolean decorationReady = true;
if (currentDecorator instanceof LabelDecorator) {
LabelDecorator labelDecorator = (LabelDecorator)currentDecorator;
if (!labelDecorator.prepareDecoration(element, oldText,
getDecorationContext())) {
// The decoration is not ready but has been queued for
// processing
decorationReady = false;
}
} else if (currentDecorator instanceof IDelayedLabelDecorator) {
IDelayedLabelDecorator delayedDecorator =
(IDelayedLabelDecorator)currentDecorator;
if (!delayedDecorator.prepareDecoration(element, oldText)) {
// The decoration is not ready but has been queued for
// processing
decorationReady = false;
}
}
// settings.setHasPendingDecorations(!decorationReady);
// update icon and label
if (m_provider instanceof ITreePathLabelProvider) {
ITreePathLabelProvider pprov = (ITreePathLabelProvider)m_provider;
if (decorationReady || oldText == null
|| settings.getText().length() == 0) {
pprov.updateLabel(settings, elementPath);
decorateSettings(settings, elementPath);
}
} else {
if (decorationReady || oldText == null
|| settings.getText().length() == 0) {
settings.setText(getText(element));
}
Image oldImage = settings.getImage();
if (decorationReady || oldImage == null) {
settings.setImage(getImage(element));
}
if (decorationReady) {
updateForDecorationReady(settings, element);
}
}
}
/**
* Decorate the settings
*
* @param settings
* the settings obtained from the label provider
* @param elementPath
* the element path being decorated
*/
private void decorateSettings(ViewerLabel settings, TreePath elementPath) {
Object element = elementPath.getLastSegment();
if (m_decorator != null) {
if (m_decorator instanceof LabelDecorator) {
LabelDecorator labelDecorator = (LabelDecorator)m_decorator;
String text = labelDecorator.decorateText(settings.getText(),
element, getDecorationContext());
if (text != null && text.length() > 0) {
settings.setText(text);
}
Image image = labelDecorator.decorateImage(settings.getImage(),
element, getDecorationContext());
if (image != null) {
settings.setImage(image);
}
} else {
String text = m_decorator.decorateText(settings.getText(),
element);
if (text != null && text.length() > 0) {
settings.setText(text);
}
Image image = m_decorator.decorateImage(settings.getImage(),
element);
if (image != null) {
settings.setImage(image);
}
}
if (m_decorator instanceof IColorDecorator) {
IColorDecorator colorDecorator = (IColorDecorator)m_decorator;
Color background = colorDecorator.decorateBackground(element);
if (background != null) {
settings.setBackground(background);
}
Color foreground = colorDecorator.decorateForeground(element);
if (foreground != null) {
settings.setForeground(foreground);
}
}
if (m_decorator instanceof IFontDecorator) {
Font font = ((IFontDecorator)m_decorator).decorateFont(element);
if (font != null) {
settings.setFont(font);
}
}
}
}
/**
* {@inheritDoc}
*/
public void update(ViewerCell cell) {
ViewerLabel label = new ViewerLabel(cell.getText(), cell.getImage());
// Set up the initial settings from the label provider
label.setBackground(getBackground(cell.getElement()));
label.setForeground(getForeground(cell.getElement()));
label.setFont(getFont(cell.getElement()));
updateLabel(label, cell.getElement());
cell.setBackground(label.getBackground());
cell.setForeground(label.getForeground());
cell.setFont(label.getFont());
if (label.hasNewText()) {
cell.setText(label.getText());
}
if (label.hasNewImage()) {
cell.setImage(label.getImage());
}
}
}