| /******************************************************************************* |
| * Copyright (c) 2000, 2016 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * 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 + "." //$NON-NLS-1$ |
| + IWorkbenchRegistryConstants.PL_DECORATORS; |
| |
| /** |
| * 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 occurred |
| private ListenerList<ILabelProviderListener> listeners = new ListenerList<>(); |
| |
| // The full definitions read from the registry. |
| // Initialize 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; |
| } |
| |
| @Override |
| public Image decorateImage(Image image, Object element, IDecorationContext context) { |
| return decoratorManager.decorateImage(image, element, context, getResourceManager()); |
| } |
| |
| @Override |
| public String decorateText(String text, Object element, IDecorationContext context) { |
| return decoratorManager.decorateText(text, element, context); |
| } |
| |
| @Override |
| public boolean prepareDecoration(Object element, String originalText, IDecorationContext context) { |
| return decoratorManager.prepareDecoration(element, originalText, context); |
| } |
| |
| @Override |
| public boolean prepareDecoration(Object element, String originalText) { |
| return prepareDecoration(element, originalText, DecorationContext.DEFAULT_CONTEXT); |
| } |
| |
| @Override |
| public Font decorateFont(Object element) { |
| return decoratorManager.decorateFont(element); |
| } |
| |
| @Override |
| public Color decorateBackground(Object element) { |
| return decoratorManager.decorateBackground(element); |
| } |
| |
| @Override |
| public Color decorateForeground(Object element) { |
| return decoratorManager.decorateForeground(element); |
| } |
| |
| @Override |
| public Image decorateImage(Image image, Object element) { |
| return decorateImage(image, element, DecorationContext.DEFAULT_CONTEXT); |
| } |
| |
| @Override |
| public String decorateText(String text, Object element) { |
| return decorateText(text, element, DecorationContext.DEFAULT_CONTEXT); |
| } |
| |
| @Override |
| public void addListener(ILabelProviderListener listener) { |
| decoratorManager.addListener(listener); |
| } |
| |
| @Override |
| public void dispose() { |
| if (resourceManager != null) { |
| resourceManager.dispose(); |
| resourceManager = null; |
| } |
| } |
| |
| @Override |
| public boolean isLabelProperty(Object element, String property) { |
| return decoratorManager.isLabelProperty(element, property); |
| } |
| |
| @Override |
| 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; |
| } |
| |
| /** |
| * Initialize the decorator definitions. |
| */ |
| private void initializeDecoratorDefinitions() { |
| DecoratorRegistryReader reader = new DecoratorRegistryReader(); |
| Collection<DecoratorDefinition> values = reader.readRegistry(Platform.getExtensionRegistry()); |
| |
| ArrayList<DecoratorDefinition> full = new ArrayList<>(); |
| ArrayList<DecoratorDefinition> lightweight = new ArrayList<>(); |
| Iterator<DecoratorDefinition> allDefinitions = values.iterator(); |
| IExtensionTracker configurationElementTracker = PlatformUI.getWorkbench().getExtensionTracker(); |
| while (allDefinitions.hasNext()) { |
| DecoratorDefinition nextDefinition = 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<DecoratorDefinition> getDecoratorsFor(Object element, DecoratorDefinition[] enabledDefinitions) { |
| |
| ArrayList<DecoratorDefinition> decorators = new ArrayList<>(); |
| |
| for (DecoratorDefinition enabledDefinition : enabledDefinitions) { |
| if (enabledDefinition.isEnabledFor(element)) { |
| decorators.add(enabledDefinition); |
| } |
| } |
| |
| return decorators; |
| |
| } |
| |
| /** |
| * Add the listener to the list of listeners. |
| */ |
| @Override |
| public void addListener(ILabelProviderListener listener) { |
| listeners.add(listener); |
| } |
| |
| /** |
| * Remove the listener from the list. |
| */ |
| @Override |
| 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() { |
| @Override |
| 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) { |
| for (final ILabelProviderListener l : listeners) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| 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) { |
| @Override |
| public IStatus runInUIThread(IProgressMonitor monitor) { |
| fireListeners(event); |
| return Status.OK_STATUS; |
| } |
| |
| @Override |
| public boolean belongsTo(Object family) { |
| return FAMILY_DECORATE == family; |
| } |
| }; |
| updateJob.setSystem(true); |
| updateJob.schedule(); |
| |
| } |
| |
| /** |
| * Decorate the text in the receiver 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); |
| for (FullDecoratorDefinition decorator : getDecoratorsFor(element)) { |
| if (decorator.isEnabledFor(element)) { |
| String newResult = safeDecorateText(element, result, decorator); |
| if (newResult != null) { |
| result = newResult; |
| } |
| } |
| } |
| |
| if (adapted != null) { |
| for (FullDecoratorDefinition decorator : getDecoratorsFor(adapted)) { |
| if (decorator.isAdaptable() && decorator.isEnabledFor(adapted)) { |
| String newResult = safeDecorateText(adapted, result, decorator); |
| if (newResult != null) { |
| result = newResult; |
| } |
| } |
| } |
| } |
| |
| return result; |
| } |
| |
| @Override |
| 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); |
| return fullTextRunnable.getResult(); |
| } |
| |
| /** |
| * 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); |
| |
| for (FullDecoratorDefinition decorator : getDecoratorsFor(element)) { |
| if (decorator.isEnabledFor(element)) { |
| Image newResult = safeDecorateImage(element, result, decorator); |
| if (newResult != null) { |
| result = newResult; |
| } |
| } |
| } |
| |
| // Get any adaptations to IResource |
| |
| if (adapted != null) { |
| for (FullDecoratorDefinition decorator : getDecoratorsFor(adapted)) { |
| if (decorator.isAdaptable() && decorator.isEnabledFor(adapted)) { |
| Image newResult = safeDecorateImage(adapted, result, decorator); |
| if (newResult != null) { |
| result = newResult; |
| } |
| } |
| } |
| } |
| |
| return result; |
| } |
| |
| @Override |
| 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); |
| return fullImageRunnable.getResult(); |
| } |
| |
| /** |
| * 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. |
| */ |
| @Override |
| 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 (DecoratorDefinition decorator : decorators) { |
| if (decorator.isEnabledFor(element) && decorator.isLabelProperty(element, property)) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Return the enabled full decorator definitions. |
| * |
| * @return FullDecoratorDefinition[] |
| */ |
| private FullDecoratorDefinition[] enabledFullDefinitions() { |
| |
| FullDecoratorDefinition[] fullDefinitions = getFullDefinitions(); |
| // As this are a deprecated data type optimize for |
| // the undefined case. |
| if (fullDefinitions.length == 0) { |
| return fullDefinitions; |
| } |
| ArrayList<FullDecoratorDefinition> result = new ArrayList<>(); |
| for (FullDecoratorDefinition element : fullDefinitions) { |
| if (element.isEnabled()) { |
| result.add(element); |
| } |
| } |
| FullDecoratorDefinition[] returnArray = new FullDecoratorDefinition[result.size()]; |
| result.toArray(returnArray); |
| return returnArray; |
| } |
| |
| /* |
| * @see IBaseLabelProvider#dispose() |
| */ |
| @Override |
| 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) |
| */ |
| @Override |
| 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 (Object element : elements) { |
| Object adapted = getResourceAdapter(element); |
| // Force an update in case full decorators are the only ones |
| // enabled |
| scheduler.queueForDecoration(element, adapted, true, null, DecorationContext.DEFAULT_CONTEXT); |
| } |
| } |
| } |
| |
| /** |
| * Store the currently enabled decorators in preference store. |
| */ |
| private void writeDecoratorsPreference() { |
| StringBuilder enabledIds = new StringBuilder(); |
| writeDecoratorsPreference(enabledIds, getFullDefinitions()); |
| writeDecoratorsPreference(enabledIds, getLightweightManager().getDefinitions()); |
| |
| WorkbenchPlugin.getDefault().getPreferenceStore().setValue(IPreferenceConstants.ENABLED_DECORATORS, |
| enabledIds.toString()); |
| PrefUtil.savePrefs(); |
| } |
| |
| private void writeDecoratorsPreference(StringBuilder enabledIds, DecoratorDefinition[] definitions) { |
| for (DecoratorDefinition definition : definitions) { |
| enabledIds.append(definition.getId()); |
| enabledIds.append(VALUE_SEPARATOR); |
| if (definition.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<String> enabledIds = new HashSet<>(); |
| Set<String> 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); |
| } |
| } |
| |
| for (FullDecoratorDefinition element : getFullDefinitions()) { |
| String id = element.getId(); |
| if (enabledIds.contains(id)) { |
| element.setEnabled(true); |
| } else { |
| if (disabledIds.contains(id)) { |
| element.setEnabled(false); |
| } |
| } |
| } |
| |
| LightweightDecoratorDefinition[] lightweightDefinitions = getLightweightManager().getDefinitions(); |
| for (LightweightDecoratorDefinition lightweightDefinition : lightweightDefinitions) { |
| String id = lightweightDefinition.getId(); |
| if (enabledIds.contains(id)) { |
| lightweightDefinition.setEnabled(true); |
| } else { |
| if (disabledIds.contains(id)) { |
| lightweightDefinition.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 (FullDecoratorDefinition element : full) { |
| if (element.isEnabled()) { |
| element.setEnabled(false); |
| } |
| } |
| if (lightweightManager != null) { |
| getLightweightManager().shutdown(); |
| } |
| scheduler.shutdown(); |
| dispose(); |
| } |
| |
| @Override |
| public boolean getEnabled(String decoratorId) { |
| DecoratorDefinition definition = getDecoratorDefinition(decoratorId); |
| if (definition == null) { |
| return false; |
| } |
| return definition.isEnabled(); |
| } |
| |
| /** |
| * @see IDecoratorManager#getLabelDecorator() |
| */ |
| @Override |
| 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) |
| */ |
| @Override |
| public void setEnabled(String decoratorId, boolean enabled) { |
| DecoratorDefinition definition = getDecoratorDefinition(decoratorId); |
| if (definition != null) { |
| definition.setEnabled(enabled); |
| clearCaches(); |
| updateForEnablementChange(); |
| } |
| } |
| |
| /* |
| * @see IDecoratorManager#getBaseLabelProvider(String) |
| */ |
| @Override |
| public IBaseLabelProvider getBaseLabelProvider(String decoratorId) { |
| IBaseLabelProvider fullProvider = getLabelDecorator(decoratorId); |
| if (fullProvider == null) { |
| return getLightweightLabelDecorator(decoratorId); |
| } |
| return fullProvider; |
| } |
| |
| /* |
| * @see IDecoratorManager#getLabelDecorator(String) |
| */ |
| @Override |
| 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) |
| */ |
| @Override |
| 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<DecoratorDefinition> 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) |
| */ |
| @Override |
| public void update(String decoratorId) { |
| |
| IBaseLabelProvider provider = getBaseLabelProvider(decoratorId); |
| if (provider != null) { |
| scheduler.clearResults(); |
| fireListeners(new LabelProviderChangedEvent(provider)); |
| } |
| |
| } |
| |
| 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; |
| } |
| |
| @Override |
| public boolean prepareDecoration(Object element, String originalText) { |
| return prepareDecoration(element, originalText, DecorationContext.DEFAULT_CONTEXT); |
| } |
| |
| public Font decorateFont(Object element) { |
| return scheduler.getFont(element, getResourceAdapter(element)); |
| } |
| |
| public Color decorateBackground(Object element) { |
| return scheduler.getBackgroundColor(element, getResourceAdapter(element)); |
| } |
| |
| 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); |
| } |
| |
| @Override |
| public void addExtension(IExtensionTracker tracker, IExtension addedExtension) { |
| for (IConfigurationElement addedElement : addedExtension.getConfigurationElements()) { |
| DecoratorRegistryReader reader = new DecoratorRegistryReader(); |
| reader.readElement(addedElement); |
| for (DecoratorDefinition decoratorDefinition : reader.getValues()) { |
| addDecorator(decoratorDefinition); |
| } |
| } |
| } |
| |
| @Override |
| public void removeExtension(IExtension source, Object[] objects) { |
| |
| boolean shouldClear = false; |
| for (Object object : objects) { |
| if (object instanceof DecoratorDefinition) { |
| DecoratorDefinition definition = (DecoratorDefinition) object; |
| 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(); |
| } |
| |
| } |
| |
| } |