| /******************************************************************************* |
| * Copyright (c) 2000, 2006 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.List; |
| |
| import org.eclipse.core.runtime.IExtension; |
| import org.eclipse.core.runtime.ISafeRunnable; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker; |
| import org.eclipse.ui.internal.ObjectContributorManager; |
| import org.eclipse.ui.internal.WorkbenchPlugin; |
| import org.eclipse.ui.internal.misc.StatusUtil; |
| import org.eclipse.ui.internal.util.Util; |
| |
| /** |
| * The LightweightDecoratorManager is a decorator manager |
| * that encapsulates the behavior for the lightweight decorators. |
| */ |
| public class LightweightDecoratorManager extends ObjectContributorManager { |
| |
| /** |
| * The runnable is the object used to run the decorations |
| * so that an error in someones decorator will not kill the thread. |
| * It is implemented here to prevent aborting of decoration |
| * i.e. successful decorations will still be applied. |
| */ |
| |
| private class LightweightRunnable implements ISafeRunnable { |
| private Object element; |
| |
| private DecorationBuilder decoration; |
| |
| private LightweightDecoratorDefinition decorator; |
| |
| void setValues(Object object, DecorationBuilder builder, |
| LightweightDecoratorDefinition definition) { |
| element = object; |
| decoration = builder; |
| decorator = definition; |
| |
| } |
| |
| /* |
| * @see ISafeRunnable.handleException(Throwable). |
| */ |
| public void handleException(Throwable exception) { |
| IStatus status = StatusUtil.newStatus(IStatus.ERROR, exception |
| .getMessage(), exception); |
| WorkbenchPlugin.log("Exception in Decorator", status); //$NON-NLS-1$ |
| if (decorator != null) { |
| decorator.crashDisable(); |
| } |
| } |
| |
| /* |
| * @see ISafeRunnable.run |
| */ |
| public void run() throws Exception { |
| decorator.decorate(element, decoration); |
| } |
| |
| /** |
| * Clear decorator references. |
| * @since 3.1 |
| */ |
| void clearReferences() { |
| decorator = null; |
| } |
| } |
| |
| private LightweightRunnable runnable = new LightweightRunnable(); |
| |
| //The lightweight definitionsread from the registry |
| private LightweightDecoratorDefinition[] lightweightDefinitions; |
| |
| private static final LightweightDecoratorDefinition[] EMPTY_LIGHTWEIGHT_DEF = new LightweightDecoratorDefinition[0]; |
| |
| private OverlayCache overlayCache = new OverlayCache(); |
| |
| LightweightDecoratorManager(LightweightDecoratorDefinition[] definitions) { |
| super(); |
| lightweightDefinitions = definitions; |
| buildContributors(); |
| } |
| |
| /** |
| * Get the lightweight definitions for the receiver. |
| * @return LightweightDecoratorDefinition[] |
| */ |
| LightweightDecoratorDefinition[] getDefinitions() { |
| return lightweightDefinitions; |
| } |
| |
| /** |
| * Register the decorators as object contributions so |
| * that adaptable lookup can occur. |
| */ |
| private void buildContributors() { |
| for (int i = 0; i < lightweightDefinitions.length; i++) { |
| LightweightDecoratorDefinition decorator = lightweightDefinitions[i]; |
| String[] types = getTargetTypes(decorator); |
| for (int j = 0; j < types.length; j++) { |
| registerContributor(decorator,types[j]); |
| } |
| } |
| } |
| |
| /** |
| * For dynamic UI |
| * |
| * @param decorator the definition to add |
| * @return whether the definition was added |
| * @since 3.0 |
| */ |
| public boolean addDecorator(LightweightDecoratorDefinition decorator) { |
| if (getLightweightDecoratorDefinition(decorator.getId()) == null) { |
| LightweightDecoratorDefinition[] oldDefs = lightweightDefinitions; |
| lightweightDefinitions = new LightweightDecoratorDefinition[lightweightDefinitions.length + 1]; |
| System.arraycopy(oldDefs, 0, lightweightDefinitions, 0, |
| oldDefs.length); |
| lightweightDefinitions[oldDefs.length] = decorator; |
| // no reset - handled in the DecoratorManager |
| String[] types = getTargetTypes(decorator); |
| for (int i = 0; i < types.length; i++) { |
| registerContributor(decorator,types[i]); |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Get the name of the types that a decorator is registered for. |
| * @param decorator |
| * @return String[] |
| */ |
| private String[] getTargetTypes(LightweightDecoratorDefinition decorator) { |
| return decorator.getObjectClasses(); |
| } |
| |
| /** |
| * For dynamic-ui |
| * @param decorator the definition to remove |
| * @return whether the definition was removed |
| * @since 3.1 |
| */ |
| public boolean removeDecorator(LightweightDecoratorDefinition decorator) { |
| int idx = getLightweightDecoratorDefinitionIdx(decorator.getId()); |
| if (idx != -1) { |
| LightweightDecoratorDefinition[] oldDefs = lightweightDefinitions; |
| Util |
| .arrayCopyWithRemoval( |
| oldDefs, |
| lightweightDefinitions = new LightweightDecoratorDefinition[lightweightDefinitions.length - 1], |
| idx); |
| // no reset - handled in the DecoratorManager |
| String [] types = getTargetTypes(decorator); |
| for (int i = 0; i < types.length; i++) { |
| unregisterContributor(decorator,types[i]); |
| |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Get the LightweightDecoratorDefinition with the supplied id |
| * @return LightweightDecoratorDefinition or <code>null</code> if it is not found |
| * @param decoratorId String |
| * @since 3.0 |
| */ |
| private LightweightDecoratorDefinition getLightweightDecoratorDefinition( |
| String decoratorId) { |
| int idx = getLightweightDecoratorDefinitionIdx(decoratorId); |
| if (idx != -1) { |
| return lightweightDefinitions[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 getLightweightDecoratorDefinitionIdx( |
| String decoratorId) { |
| for (int i = 0; i < lightweightDefinitions.length; i++) { |
| if (lightweightDefinitions[i].getId().equals(decoratorId)) { |
| return i; |
| } |
| } |
| return -1; |
| } |
| |
| /** |
| * Return the enabled lightweight decorator definitions. |
| * @return LightweightDecoratorDefinition[] |
| */ |
| LightweightDecoratorDefinition[] enabledDefinitions() { |
| ArrayList result = new ArrayList(); |
| for (int i = 0; i < lightweightDefinitions.length; i++) { |
| if (lightweightDefinitions[i].isEnabled()) { |
| result.add(lightweightDefinitions[i]); |
| } |
| } |
| LightweightDecoratorDefinition[] returnArray = new LightweightDecoratorDefinition[result |
| .size()]; |
| result.toArray(returnArray); |
| return returnArray; |
| } |
| |
| /** |
| * Return whether there are enabled lightwieght decorators |
| * @return boolean |
| */ |
| boolean hasEnabledDefinitions() { |
| for (int i = 0; i < lightweightDefinitions.length; i++) { |
| if (lightweightDefinitions[i].isEnabled()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Reset any cached values. |
| */ |
| void reset() { |
| runnable.clearReferences(); |
| } |
| |
| /** |
| * Shutdown the decorator manager by disabling all |
| * of the decorators so that dispose() will be called |
| * on them. |
| */ |
| void shutdown() { |
| //Disable all fo the enabled decorators |
| //so as to force a dispose of thier decorators |
| for (int i = 0; i < lightweightDefinitions.length; i++) { |
| if (lightweightDefinitions[i].isEnabled()) { |
| lightweightDefinitions[i].setEnabled(false); |
| } |
| } |
| overlayCache.disposeAll(); |
| } |
| |
| /** |
| * Get the LightweightDecoratorDefinition with the supplied id |
| * @return LightweightDecoratorDefinition or <code>null</code> if it is not found |
| * @param decoratorId String |
| */ |
| LightweightDecoratorDefinition getDecoratorDefinition(String decoratorId) { |
| for (int i = 0; i < lightweightDefinitions.length; i++) { |
| if (lightweightDefinitions[i].getId().equals(decoratorId)) { |
| return lightweightDefinitions[i]; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Get the lightweight registered for elements of this type. |
| */ |
| LightweightDecoratorDefinition[] getDecoratorsFor(Object element) { |
| |
| if (element == null) { |
| return EMPTY_LIGHTWEIGHT_DEF; |
| } |
| |
| List elements = new ArrayList(1); |
| elements.add(element); |
| LightweightDecoratorDefinition[] decoratorArray = EMPTY_LIGHTWEIGHT_DEF; |
| List contributors = getContributors(elements); |
| if (!contributors.isEmpty()) { |
| Collection decorators = DecoratorManager.getDecoratorsFor(element, |
| (DecoratorDefinition[]) contributors.toArray(new DecoratorDefinition[contributors.size()])); |
| if (decorators.size() > 0) { |
| decoratorArray = new LightweightDecoratorDefinition[decorators |
| .size()]; |
| decorators.toArray(decoratorArray); |
| } |
| } |
| |
| return decoratorArray; |
| } |
| |
| /** |
| * Fill the decoration with all of the results of the |
| * decorators. |
| * |
| * @param element The source element |
| * @param context The decoration context |
| * @param decoration The DecorationResult we are working on. |
| * where adaptable is true. |
| */ |
| public void getDecorations(Object element, DecorationBuilder decoration) { |
| |
| LightweightDecoratorDefinition[] decorators = getDecoratorsFor(element); |
| |
| for (int i = 0; i < decorators.length; i++) { |
| //If we are doing the adaptable one make sure we are |
| //only applying the adaptable decorations |
| LightweightDecoratorDefinition dd = decorators[i]; |
| decoration.setCurrentDefinition(dd); |
| decorate(element, decoration, dd); |
| } |
| } |
| |
| /** |
| * Decorate the element receiver in a SafeRunnable. |
| * @param element The Object to be decorated |
| * @param decoration The object building decorations. |
| * @param decorator The decorator being applied. |
| */ |
| private void decorate(Object element, DecorationBuilder decoration, |
| LightweightDecoratorDefinition decorator) { |
| |
| runnable.setValues(element, decoration, decorator); |
| Platform.run(runnable); |
| } |
| |
| /** |
| * Returns the overlayCache. |
| * @return OverlayCache |
| */ |
| OverlayCache getOverlayCache() { |
| return overlayCache; |
| } |
| |
| /** |
| * Method for use by test cases |
| * @param object the object to be decorated |
| * @return the decoration result |
| */ |
| public DecorationResult getDecorationResult(Object object) { |
| DecorationBuilder builder = new DecorationBuilder(); |
| getDecorations(object, builder); |
| return builder.createResult(); |
| |
| } |
| |
| /* (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 extension) { |
| // Do nothing as this is handled by the DecoratorManager |
| //This is not called as canHandleExtensionTracking returns |
| //false. |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.ObjectContributorManager#canHandleExtensionTracking() |
| */ |
| protected boolean canHandleExtensionTracking() { |
| return false; |
| } |
| |
| } |