/******************************************************************************* * Copyright (c) 2000, 2008 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.decorators; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.StringTokenizer; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.SafeRunner; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker; import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler; import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.resource.LocalResourceManager; import org.eclipse.jface.resource.ResourceManager; import org.eclipse.jface.util.SafeRunnable; import org.eclipse.jface.viewers.DecorationContext; import org.eclipse.jface.viewers.IBaseLabelProvider; import org.eclipse.jface.viewers.IColorDecorator; import org.eclipse.jface.viewers.IDecorationContext; import org.eclipse.jface.viewers.IDelayedLabelDecorator; import org.eclipse.jface.viewers.IFontDecorator; import org.eclipse.jface.viewers.ILabelDecorator; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ILightweightLabelDecorator; import org.eclipse.jface.viewers.LabelDecorator; import org.eclipse.jface.viewers.LabelProviderChangedEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.IDecoratorManager; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.internal.IPreferenceConstants; import org.eclipse.ui.internal.LegacyResourceSupport; import org.eclipse.ui.internal.Workbench; import org.eclipse.ui.internal.WorkbenchMessages; import org.eclipse.ui.internal.WorkbenchPlugin; import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants; import org.eclipse.ui.internal.util.PrefUtil; import org.eclipse.ui.internal.util.Util; import org.eclipse.ui.progress.WorkbenchJob; /** * The DecoratorManager is the class that handles all of the decorators defined * in the image. * * @since 2.0 */ public class DecoratorManager implements ILabelProviderListener, IDecoratorManager, IExtensionChangeHandler { private static String EXTENSIONPOINT_UNIQUE_ID = WorkbenchPlugin.PI_WORKBENCH + "." + IWorkbenchRegistryConstants.PL_DECORATORS; //$NON-NLS-1$ /** * The family for the decorate job. */ public static final Object FAMILY_DECORATE = new Object(); private DecorationScheduler scheduler; private LightweightDecoratorManager lightweightManager; // Hold onto the list of listeners to be told if a change has occured private ListenerList listeners = new ListenerList(); // The full definitions read from the registry. // Initalize to an empty collection as this is rarely used now. private FullDecoratorDefinition[] fullDefinitions; private FullTextDecoratorRunnable fullTextRunnable = new FullTextDecoratorRunnable(); private FullImageDecoratorRunnable fullImageRunnable = new FullImageDecoratorRunnable(); private static final FullDecoratorDefinition[] EMPTY_FULL_DEF = new FullDecoratorDefinition[0]; private final String PREFERENCE_SEPARATOR = ","; //$NON-NLS-1$ private final String VALUE_SEPARATOR = ":"; //$NON-NLS-1$ private final String P_TRUE = "true"; //$NON-NLS-1$ private final String P_FALSE = "false"; //$NON-NLS-1$ private LocalResourceManager resourceManager; /** * ManagedWorkbenchLabelDecorator is the internal LabelDecorator * passed as result of calls to {@link IDecoratorManager#getLabelDecorator()} * @since 3.4 * */ private static class ManagedWorkbenchLabelDecorator extends LabelDecorator implements ILabelDecorator, IDelayedLabelDecorator, IColorDecorator, IFontDecorator { private final DecoratorManager decoratorManager; private LocalResourceManager resourceManager; /** * Create a new instance of the receiver that supports decoratorManager * @param decoratorManager */ public ManagedWorkbenchLabelDecorator(DecoratorManager decoratorManager) { this.decoratorManager = decoratorManager; this.resourceManager = null; } /** * Return a resource manager local to the receiver. * @return {@link LocalResourceManager} */ private LocalResourceManager getResourceManager() { if (resourceManager == null) { resourceManager = new LocalResourceManager(decoratorManager .getResourceManager()); } return resourceManager; } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.LabelDecorator#decorateImage(org.eclipse.swt.graphics.Image, * java.lang.Object, org.eclipse.jface.viewers.IDecorationContext) */ public Image decorateImage(Image image, Object element, IDecorationContext context) { return decoratorManager.decorateImage(image, element, context, getResourceManager()); } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.LabelDecorator#decorateText(java.lang.String, * java.lang.Object, org.eclipse.jface.viewers.IDecorationContext) */ public String decorateText(String text, Object element, IDecorationContext context) { return decoratorManager.decorateText(text, element, context); } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.LabelDecorator#prepareDecoration(java.lang.Object, * java.lang.String, org.eclipse.jface.viewers.IDecorationContext) */ public boolean prepareDecoration(Object element, String originalText, IDecorationContext context) { return decoratorManager.prepareDecoration(element, originalText, context); } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IDelayedLabelDecorator#prepareDecoration(java.lang.Object, * java.lang.String) */ public boolean prepareDecoration(Object element, String originalText) { return prepareDecoration(element, originalText, DecorationContext.DEFAULT_CONTEXT); } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IFontDecorator#decorateFont(java.lang.Object) */ public Font decorateFont(Object element) { return decoratorManager.decorateFont(element); } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IColorDecorator#decorateBackground(java.lang.Object) */ public Color decorateBackground(Object element) { return decoratorManager.decorateBackground(element); } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IColorDecorator#decorateForeground(java.lang.Object) */ public Color decorateForeground(Object element) { return decoratorManager.decorateForeground(element); } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.ILabelDecorator#decorateImage(org.eclipse.swt.graphics.Image, * java.lang.Object) */ public Image decorateImage(Image image, Object element) { return decorateImage(image, element, DecorationContext.DEFAULT_CONTEXT); } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.ILabelDecorator#decorateText(java.lang.String, * java.lang.Object) */ public String decorateText(String text, Object element) { return decorateText(text, element, DecorationContext.DEFAULT_CONTEXT); } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener) */ public void addListener(ILabelProviderListener listener) { decoratorManager.addListener(listener); } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose() */ public void dispose() { if (resourceManager != null) { resourceManager.dispose(); resourceManager = null; } } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, * java.lang.String) */ public boolean isLabelProperty(Object element, String property) { return decoratorManager.isLabelProperty(element, property); } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener) */ public void removeListener(ILabelProviderListener listener) { decoratorManager.removeListener(listener); } } /** * Create a new instance of the receiver and load the settings from the * installed plug-ins. */ public DecoratorManager() { scheduler = new DecorationScheduler(this); IExtensionTracker tracker = PlatformUI.getWorkbench() .getExtensionTracker(); tracker.registerHandler(this, ExtensionTracker .createExtensionPointFilter(getExtensionPointFilter())); resourceManager = null; } /** * Initalize the decorator definitions. */ private void initializeDecoratorDefinitions() { DecoratorRegistryReader reader = new DecoratorRegistryReader(); Collection values = reader .readRegistry(Platform.getExtensionRegistry()); ArrayList full = new ArrayList(); ArrayList lightweight = new ArrayList(); Iterator allDefinitions = values.iterator(); IExtensionTracker configurationElementTracker = PlatformUI .getWorkbench().getExtensionTracker(); while (allDefinitions.hasNext()) { DecoratorDefinition nextDefinition = (DecoratorDefinition) allDefinitions .next(); if (nextDefinition.isFull()) { full.add(nextDefinition); } else { lightweight.add(nextDefinition); } configurationElementTracker.registerObject(nextDefinition .getConfigurationElement().getDeclaringExtension(), nextDefinition, IExtensionTracker.REF_WEAK); } fullDefinitions = new FullDecoratorDefinition[full.size()]; full.toArray(fullDefinitions); LightweightDecoratorDefinition[] lightweightDefinitions = new LightweightDecoratorDefinition[lightweight .size()]; lightweight.toArray(lightweightDefinitions); lightweightManager = new LightweightDecoratorManager( lightweightDefinitions); applyDecoratorsPreference(); } /** * For dynamic UI * * @param definition * the definition to add * @since 3.0 */ public void addDecorator(DecoratorDefinition definition) { if (definition.isFull()) { if (getFullDecoratorDefinition(definition.getId()) == null) { FullDecoratorDefinition[] oldDefs = getFullDefinitions(); fullDefinitions = new FullDecoratorDefinition[fullDefinitions.length + 1]; System .arraycopy(oldDefs, 0, fullDefinitions, 0, oldDefs.length); fullDefinitions[oldDefs.length] = (FullDecoratorDefinition) definition; clearCaches(); updateForEnablementChange(); } } else { if (getLightweightManager().addDecorator( (LightweightDecoratorDefinition) definition)) { clearCaches(); updateForEnablementChange(); } } ((Workbench) PlatformUI.getWorkbench()).getExtensionTracker() .registerObject( definition.getConfigurationElement() .getDeclaringExtension(), definition, IExtensionTracker.REF_WEAK); } /** * See if the supplied decorator cache has a value for the element. If not * calculate it from the enabledDefinitions and update the cache. * * @return Collection of DecoratorDefinition. * @param element * The element being tested. * @param enabledDefinitions * The definitions currently defined for this decorator. */ static Collection getDecoratorsFor(Object element, DecoratorDefinition[] enabledDefinitions) { ArrayList decorators = new ArrayList(); for (int i = 0; i < enabledDefinitions.length; i++) { if (enabledDefinitions[i].isEnabledFor(element)) { decorators.add(enabledDefinitions[i]); } } return decorators; } /** * Add the listener to the list of listeners. */ public void addListener(ILabelProviderListener listener) { listeners.add(listener); } /** * Remove the listener from the list. */ public void removeListener(ILabelProviderListener listener) { listeners.remove(listener); scheduler.listenerRemoved(listener); } /** * Get the list of elements listening to the receiver. * * @return ILabelProviderListener [] */ ILabelProviderListener[] getListeners() { Object[] array = listeners.getListeners(); ILabelProviderListener[] listenerArray = new ILabelProviderListener[array.length]; System.arraycopy(array, 0, listenerArray, 0, listenerArray.length); return listenerArray; } /** * Inform all of the listeners that require an update * * @param listener * The listener we are updating. * @param event * the event with the update details */ void fireListener(final LabelProviderChangedEvent event, final ILabelProviderListener listener) { SafeRunner.run(new SafeRunnable() { public void run() { listener.labelProviderChanged(event); } }); } /** * Inform all of the listeners that require an update * * @param event * the event with the update details */ void fireListeners(final LabelProviderChangedEvent event) { Object[] array = listeners.getListeners(); for (int i = 0; i < array.length; i++) { final ILabelProviderListener l = (ILabelProviderListener) array[i]; SafeRunner.run(new SafeRunnable() { public void run() { l.labelProviderChanged(event); } }); } } /** * Fire any listeners from the UIThread. Used for cases where this may be * invoked outside of the UI by the public API. * * @param event * the event with the update details */ void fireListenersInUIThread(final LabelProviderChangedEvent event) { // No updates if there is no UI if (!PlatformUI.isWorkbenchRunning()) { return; } // Only bother with the job if in the UI Thread if (Thread.currentThread() == PlatformUI.getWorkbench().getDisplay() .getThread()) { fireListeners(event); return; } WorkbenchJob updateJob = new WorkbenchJob( WorkbenchMessages.DecorationScheduler_UpdateJobName) { /* * (non-Javadoc) * * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor) */ public IStatus runInUIThread(IProgressMonitor monitor) { fireListeners(event); return Status.OK_STATUS; } /* * (non-Javadoc) * * @see org.eclipse.core.runtime.jobs.Job#belongsTo(java.lang.Object) */ public boolean belongsTo(Object family) { return FAMILY_DECORATE == family; } }; updateJob.setSystem(true); updateJob.schedule(); } /** * Decorate the text in the reciever using the context. * @param text * @param element * @param context * @return String * @see LabelDecorator#decorateText(String, Object, IDecorationContext) */ public String decorateText(String text, Object element, IDecorationContext context) { // Get any adaptations to IResource Object adapted = getResourceAdapter(element); String result = scheduler.decorateWithText(text, element, adapted, context); FullDecoratorDefinition[] decorators = getDecoratorsFor(element); for (int i = 0; i < decorators.length; i++) { if (decorators[i].isEnabledFor(element)) { String newResult = safeDecorateText(element, result, decorators[i]); if (newResult != null) { result = newResult; } } } if (adapted != null) { decorators = getDecoratorsFor(adapted); for (int i = 0; i < decorators.length; i++) { if (decorators[i].isAdaptable() && decorators[i].isEnabledFor(adapted)) { String newResult = safeDecorateText(adapted, result, decorators[i]); if (newResult != null) { result = newResult; } } } } return result; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ILabelDecorator#decorateText(java.lang.String, java.lang.Object) */ public String decorateText(String text, Object element) { return decorateText(text, element, DecorationContext.DEFAULT_CONTEXT); } /** * Decorate the text in a SafeRunnable. * * @param element * The element we are decorating * @param start * The currently decorated String * @param decorator * The decorator to run. * @return String */ private String safeDecorateText(Object element, String start, FullDecoratorDefinition decorator) { fullTextRunnable.setValues(start, element, decorator); SafeRunner.run(fullTextRunnable); String newResult = fullTextRunnable.getResult(); return newResult; } /** * Decorate the image within the context. Allocate any new images in * localResourceManager * @param image * @param element * @param context * @param localResourceManager * @return Image * @see LabelDecorator#decorateImage(Image, Object, IDecorationContext) */ public Image decorateImage(Image image, Object element, IDecorationContext context, ResourceManager localResourceManager) { Object adapted = getResourceAdapter(element); Image result = scheduler.decorateWithOverlays(image, element, adapted, context, localResourceManager); FullDecoratorDefinition[] decorators = getDecoratorsFor(element); for (int i = 0; i < decorators.length; i++) { if (decorators[i].isEnabledFor(element)) { Image newResult = safeDecorateImage(element, result, decorators[i]); if (newResult != null) { result = newResult; } } } // Get any adaptations to IResource if (adapted != null) { decorators = getDecoratorsFor(adapted); for (int i = 0; i < decorators.length; i++) { if (decorators[i].isAdaptable() && decorators[i].isEnabledFor(adapted)) { Image newResult = safeDecorateImage(adapted, result, decorators[i]); if (newResult != null) { result = newResult; } } } } return result; } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.ILabelDecorator#decorateImage(org.eclipse.swt.graphics.Image, * java.lang.Object) */ public Image decorateImage(Image image, Object element) { return decorateImage(image, element, DecorationContext.DEFAULT_CONTEXT, getResourceManager()); } /** * Decorate the image in a SafeRunnable. * * @param element * The element we are decorating * @param start * The currently decorated Image * @param decorator * The decorator to run. * @return Image */ private Image safeDecorateImage(Object element, Image start, FullDecoratorDefinition decorator) { fullImageRunnable.setValues(start, element, decorator); SafeRunner.run(fullImageRunnable); Image newResult = fullImageRunnable.getResult(); return newResult; } /** * Get the resource adapted object for the supplied element. Return * <code>null</code>. if there isn't one. * * @param element * @return Object or <code>null</code>. */ private Object getResourceAdapter(Object element) { Object adapted = LegacyResourceSupport .getAdaptedContributorResource(element); if (adapted != element) { return adapted; // Avoid applying decorator twice } return null; } /** * Return whether or not the decorator registered for element has a label * property called property name. */ public boolean isLabelProperty(Object element, String property) { return isLabelProperty(element, property, true); } /** * Return whether or not the decorator registered for element has a label * property called property name. Check for an adapted resource if * checkAdapted is true. * * @param element * @param property * @param checkAdapted * @return boolean <code>true</code> if there is a label property for * element or its adapted value */ public boolean isLabelProperty(Object element, String property, boolean checkAdapted) { boolean fullCheck = isLabelProperty(element, property, getDecoratorsFor(element)); if (fullCheck) { return fullCheck; } boolean lightweightCheck = isLabelProperty(element, property, getLightweightManager().getDecoratorsFor(element)); if (lightweightCheck) { return true; } if (checkAdapted) { // Get any adaptions to IResource Object adapted = getResourceAdapter(element); if (adapted == null || adapted == element) { return false; } fullCheck = isLabelProperty(adapted, property, getDecoratorsFor(adapted)); if (fullCheck) { return fullCheck; } return isLabelProperty(adapted, property, lightweightManager .getDecoratorsFor(adapted)); } return false; } private boolean isLabelProperty(Object element, String property, DecoratorDefinition[] decorators) { for (int i = 0; i < decorators.length; i++) { if (decorators[i].isEnabledFor(element) && decorators[i].isLabelProperty(element, property)) { return true; } } return false; } /** * Return the enabled full decorator definitions. * * @return FullDecoratorDefinition[] */ private FullDecoratorDefinition[] enabledFullDefinitions() { FullDecoratorDefinition[] full = getFullDefinitions(); // As this are a deprecated data type optimize for // the undefined case. if (full.length == 0) { return full; } ArrayList result = new ArrayList(); for (int i = 0; i < full.length; i++) { if (full[i].isEnabled()) { result.add(full[i]); } } FullDecoratorDefinition[] returnArray = new FullDecoratorDefinition[result .size()]; result.toArray(returnArray); return returnArray; } /* * @see IBaseLabelProvider#dispose() */ public void dispose() { // do nothing } /** * Clear the caches in the manager. This is required to avoid updates that * may occur due to changes in enablement. */ public void clearCaches() { getLightweightManager().reset(); fullTextRunnable.clearReferences(); fullImageRunnable.clearReferences(); } /** * Enablement had changed. Fire the listeners and write the preference. */ public void updateForEnablementChange() { // Clear any results that may be around as all labels have changed scheduler.clearResults(); fireListenersInUIThread(new LabelProviderChangedEvent(this)); writeDecoratorsPreference(); } /** * Get the DecoratorDefinitions defined on the receiver. * * @return DecoratorDefinition[] */ public DecoratorDefinition[] getAllDecoratorDefinitions() { LightweightDecoratorDefinition[] lightweightDefinitions = getLightweightManager() .getDefinitions(); DecoratorDefinition[] returnValue = new DecoratorDefinition[fullDefinitions.length + lightweightDefinitions.length]; System.arraycopy(fullDefinitions, 0, returnValue, 0, fullDefinitions.length); System.arraycopy(lightweightDefinitions, 0, returnValue, fullDefinitions.length, lightweightDefinitions.length); return returnValue; } /* * @see ILabelProviderListener#labelProviderChanged(LabelProviderChangedEvent) */ public void labelProviderChanged(LabelProviderChangedEvent event) { Object[] elements = event.getElements(); scheduler.clearResults(); // If the elements are not specified send out a general update if (elements == null) { fireListeners(event); } else { // Assume that someone is going to care about the // decoration result and just start it right away for (int i = 0; i < elements.length; i++) { Object adapted = getResourceAdapter(elements[i]); // Force an update in case full decorators are the only ones // enabled scheduler.queueForDecoration(elements[i], adapted, true, null, DecorationContext.DEFAULT_CONTEXT); } } } /** * Store the currently enabled decorators in preference store. */ private void writeDecoratorsPreference() { StringBuffer enabledIds = new StringBuffer(); writeDecoratorsPreference(enabledIds, getFullDefinitions()); writeDecoratorsPreference(enabledIds, getLightweightManager() .getDefinitions()); WorkbenchPlugin.getDefault().getPreferenceStore().setValue( IPreferenceConstants.ENABLED_DECORATORS, enabledIds.toString()); PrefUtil.savePrefs(); } private void writeDecoratorsPreference(StringBuffer enabledIds, DecoratorDefinition[] definitions) { for (int i = 0; i < definitions.length; i++) { enabledIds.append(definitions[i].getId()); enabledIds.append(VALUE_SEPARATOR); if (definitions[i].isEnabled()) { enabledIds.append(P_TRUE); } else { enabledIds.append(P_FALSE); } enabledIds.append(PREFERENCE_SEPARATOR); } } /** * Get the currently enabled decorators in preference store and set the * state of the current definitions accordingly. */ public void applyDecoratorsPreference() { String preferenceValue = WorkbenchPlugin.getDefault() .getPreferenceStore().getString( IPreferenceConstants.ENABLED_DECORATORS); StringTokenizer tokenizer = new StringTokenizer(preferenceValue, PREFERENCE_SEPARATOR); Set enabledIds = new HashSet(); Set disabledIds = new HashSet(); while (tokenizer.hasMoreTokens()) { String nextValuePair = tokenizer.nextToken(); // Strip out the true or false to get the id String id = nextValuePair.substring(0, nextValuePair .indexOf(VALUE_SEPARATOR)); if (nextValuePair.endsWith(P_TRUE)) { enabledIds.add(id); } else { disabledIds.add(id); } } FullDecoratorDefinition[] full = getFullDefinitions(); for (int i = 0; i < full.length; i++) { String id = full[i].getId(); if (enabledIds.contains(id)) { full[i].setEnabled(true); } else { if (disabledIds.contains(id)) { full[i].setEnabled(false); } } } LightweightDecoratorDefinition[] lightweightDefinitions = getLightweightManager() .getDefinitions(); for (int i = 0; i < lightweightDefinitions.length; i++) { String id = lightweightDefinitions[i].getId(); if (enabledIds.contains(id)) { lightweightDefinitions[i].setEnabled(true); } else { if (disabledIds.contains(id)) { lightweightDefinitions[i].setEnabled(false); } } } } /** * Shutdown the decorator manager by disabling all of the decorators so that * dispose() will be called on them. */ public void shutdown() { // Disable all of the enabled decorators // so as to force a dispose of thier decorators FullDecoratorDefinition[] full = getFullDefinitions(); for (int i = 0; i < full.length; i++) { if (full[i].isEnabled()) { full[i].setEnabled(false); } } if (lightweightManager != null) { getLightweightManager().shutdown(); } scheduler.shutdown(); dispose(); } /* * (non-Javadoc) * * @see org.eclipse.ui.IDecoratorManager#getEnabled(java.lang.String) */ public boolean getEnabled(String decoratorId) { DecoratorDefinition definition = getDecoratorDefinition(decoratorId); if (definition == null) { return false; } return definition.isEnabled(); } /** * @see IDecoratorManager#getLabelDecorator() */ public ILabelDecorator getLabelDecorator() { return new ManagedWorkbenchLabelDecorator(this); } /** * Returns the resource manager used to created images for the light weight * decorator. * * @return the resource manager */ public ResourceManager getResourceManager() { if (resourceManager == null) { resourceManager = new LocalResourceManager(JFaceResources .getResources(PlatformUI.getWorkbench().getDisplay())); } return resourceManager; } /** * @see IDecoratorManager#setEnabled(String, boolean) */ public void setEnabled(String decoratorId, boolean enabled) { DecoratorDefinition definition = getDecoratorDefinition(decoratorId); if (definition != null) { definition.setEnabled(enabled); clearCaches(); updateForEnablementChange(); } } /* * @see IDecoratorManager#getBaseLabelProvider(String) */ public IBaseLabelProvider getBaseLabelProvider(String decoratorId) { IBaseLabelProvider fullProvider = getLabelDecorator(decoratorId); if (fullProvider == null) { return getLightweightLabelDecorator(decoratorId); } return fullProvider; } /* * @see IDecoratorManager#getLabelDecorator(String) */ public ILabelDecorator getLabelDecorator(String decoratorId) { FullDecoratorDefinition definition = getFullDecoratorDefinition(decoratorId); // Do not return for a disabled decorator if (definition != null && definition.isEnabled()) { return definition.getDecorator(); } return null; } /* * @see IDecoratorManager#getLightweightLabelDecorator(String) */ public ILightweightLabelDecorator getLightweightLabelDecorator( String decoratorId) { LightweightDecoratorDefinition definition = getLightweightManager() .getDecoratorDefinition(decoratorId); // Do not return for a disabled decorator if (definition != null && definition.isEnabled()) { return definition.getDecorator(); } return null; } /** * Get the DecoratorDefinition with the supplied id * * @return DecoratorDefinition or <code>null</code> if it is not found * @param decoratorId * String */ private DecoratorDefinition getDecoratorDefinition(String decoratorId) { DecoratorDefinition returnValue = getFullDecoratorDefinition(decoratorId); if (returnValue == null) { return getLightweightManager().getDecoratorDefinition(decoratorId); } return returnValue; } /** * Get the FullDecoratorDefinition with the supplied id * * @return FullDecoratorDefinition or <code>null</code> if it is not found * @param decoratorId * the id */ private FullDecoratorDefinition getFullDecoratorDefinition( String decoratorId) { int idx = getFullDecoratorDefinitionIdx(decoratorId); if (idx != -1) { return getFullDefinitions()[idx]; } return null; } /** * Return the index of the definition in the array. * * @param decoratorId * the id * @return the index of the definition in the array or <code>-1</code> * @since 3.1 */ private int getFullDecoratorDefinitionIdx(String decoratorId) { FullDecoratorDefinition[] full = getFullDefinitions(); for (int i = 0; i < full.length; i++) { if (full[i].getId().equals(decoratorId)) { return i; } } return -1; } /** * Get the full decorator definitions registered for elements of this type. * * @param element * The element to look up * @return FullDecoratorDefinition[] */ private FullDecoratorDefinition[] getDecoratorsFor(Object element) { if (element == null) { return EMPTY_FULL_DEF; } Collection decorators = getDecoratorsFor(element, enabledFullDefinitions()); FullDecoratorDefinition[] decoratorArray = EMPTY_FULL_DEF; if (decorators.size() > 0) { decoratorArray = new FullDecoratorDefinition[decorators.size()]; decorators.toArray(decoratorArray); } return decoratorArray; } /** * Returns the lightweightManager. This method is public for use by test * cases. No other classes outside of this package should use this method. * * @return LightweightDecoratorManager */ public LightweightDecoratorManager getLightweightManager() { if (lightweightManager == null) { initializeDecoratorDefinitions(); } return lightweightManager; } /** * @see org.eclipse.ui.IDecoratorManager#update(java.lang.String) */ public void update(String decoratorId) { IBaseLabelProvider provider = getBaseLabelProvider(decoratorId); if (provider != null) { scheduler.clearResults(); fireListeners(new LabelProviderChangedEvent(provider)); } } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.LabelDecorator#prepareDecoration(java.lang.Object, * java.lang.String, org.eclipse.jface.viewers.IDecorationContext) */ public boolean prepareDecoration(Object element, String originalText, IDecorationContext context) { // Check if there is a decoration ready or if there is no lightweight // decorators to be applied if (scheduler.isDecorationReady(element, context) || !getLightweightManager().hasEnabledDefinitions()) { return true; } // Force an update if there is a text already boolean force = true; // If not then do not force as the undecorated value is fine if (originalText == null || originalText.length() == 0) { force = false; } // Queue the decoration. scheduler.queueForDecoration(element, getResourceAdapter(element), force, originalText, context); // If we are going to force an update just let that happen later. return !force; } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IDelayedLabelDecorator#prepareDecoration(java.lang.Object, * java.lang.String) */ public boolean prepareDecoration(Object element, String originalText) { return prepareDecoration(element, originalText, DecorationContext.DEFAULT_CONTEXT); } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IFontDecorator#decorateFont(java.lang.Object) */ public Font decorateFont(Object element) { return scheduler.getFont(element, getResourceAdapter(element)); } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IColorDecorator#decorateBackground(java.lang.Object) */ public Color decorateBackground(Object element) { return scheduler.getBackgroundColor(element, getResourceAdapter(element)); } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.IColorDecorator#decorateForeground(java.lang.Object) */ public Color decorateForeground(Object element) { return scheduler.getForegroundColor(element, getResourceAdapter(element)); } /** * Get all of the defined fullDefinitions. Initalize if required * * @return FullDecoratorDefinition[] */ private FullDecoratorDefinition[] getFullDefinitions() { if (fullDefinitions == null) { initializeDecoratorDefinitions(); } return fullDefinitions; } private IExtensionPoint getExtensionPointFilter() { return Platform.getExtensionRegistry().getExtensionPoint( EXTENSIONPOINT_UNIQUE_ID); } /* * (non-Javadoc) * * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#addExtension(org.eclipse.core.runtime.dynamicHelpers.IExtensionTracker, * org.eclipse.core.runtime.IExtension) */ public void addExtension(IExtensionTracker tracker, IExtension addedExtension) { IConfigurationElement addedElements[] = addedExtension .getConfigurationElements(); for (int i = 0; i < addedElements.length; i++) { DecoratorRegistryReader reader = new DecoratorRegistryReader(); reader.readElement(addedElements[i]); for (Iterator j = reader.getValues().iterator(); j.hasNext();) { addDecorator((DecoratorDefinition) j.next()); } } } /* * (non-Javadoc) * * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension, * java.lang.Object[]) */ public void removeExtension(IExtension source, Object[] objects) { boolean shouldClear = false; for (int i = 0; i < objects.length; i++) { if (objects[i] instanceof DecoratorDefinition) { DecoratorDefinition definition = (DecoratorDefinition) objects[i]; if (definition.isFull()) { int idx = getFullDecoratorDefinitionIdx(definition.getId()); if (idx != -1) { FullDecoratorDefinition[] oldDefs = getFullDefinitions(); Util .arrayCopyWithRemoval( oldDefs, fullDefinitions = new FullDecoratorDefinition[fullDefinitions.length - 1], idx); shouldClear = true; } } else { shouldClear |= getLightweightManager().removeDecorator( (LightweightDecoratorDefinition) definition); } } } if (shouldClear) { clearCaches(); updateForEnablementChange(); } } }