blob: a63143ddbc57fd96b02fb63a1c7b2b2f4acd0f14 [file] [log] [blame]
/*******************************************************************************
* 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;
}
}