| /******************************************************************************* |
| * 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.CoreException; |
| 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()) { |
| ILabelDecorator result = definition.getDecorator(); |
| if (result == null) { |
| try { |
| result = definition.internalGetDecorator(); |
| } catch (CoreException e) { |
| WorkbenchPlugin.log(e); |
| } |
| } |
| return result; |
| } |
| 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(); |
| } |
| |
| } |
| |
| } |