0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2006 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.ui.internal.decorators;
0011:
0012: import java.util.ArrayList;
0013: import java.util.Collection;
0014: import java.util.HashSet;
0015: import java.util.Iterator;
0016: import java.util.Set;
0017: import java.util.StringTokenizer;
0018:
0019: import org.eclipse.core.runtime.IConfigurationElement;
0020: import org.eclipse.core.runtime.IExtension;
0021: import org.eclipse.core.runtime.IExtensionPoint;
0022: import org.eclipse.core.runtime.IProgressMonitor;
0023: import org.eclipse.core.runtime.IStatus;
0024: import org.eclipse.core.runtime.ListenerList;
0025: import org.eclipse.core.runtime.Platform;
0026: import org.eclipse.core.runtime.Status;
0027: import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker;
0028: import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
0029: import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
0030: import org.eclipse.jface.util.SafeRunnable;
0031: import org.eclipse.jface.viewers.DecorationContext;
0032: import org.eclipse.jface.viewers.IBaseLabelProvider;
0033: import org.eclipse.jface.viewers.IColorDecorator;
0034: import org.eclipse.jface.viewers.IDecorationContext;
0035: import org.eclipse.jface.viewers.IDelayedLabelDecorator;
0036: import org.eclipse.jface.viewers.IFontDecorator;
0037: import org.eclipse.jface.viewers.ILabelDecorator;
0038: import org.eclipse.jface.viewers.ILabelProviderListener;
0039: import org.eclipse.jface.viewers.ILightweightLabelDecorator;
0040: import org.eclipse.jface.viewers.LabelDecorator;
0041: import org.eclipse.jface.viewers.LabelProviderChangedEvent;
0042: import org.eclipse.swt.graphics.Color;
0043: import org.eclipse.swt.graphics.Font;
0044: import org.eclipse.swt.graphics.Image;
0045: import org.eclipse.ui.IDecoratorManager;
0046: import org.eclipse.ui.PlatformUI;
0047: import org.eclipse.ui.internal.IPreferenceConstants;
0048: import org.eclipse.ui.internal.LegacyResourceSupport;
0049: import org.eclipse.ui.internal.Workbench;
0050: import org.eclipse.ui.internal.WorkbenchMessages;
0051: import org.eclipse.ui.internal.WorkbenchPlugin;
0052: import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
0053: import org.eclipse.ui.internal.util.PrefUtil;
0054: import org.eclipse.ui.internal.util.Util;
0055: import org.eclipse.ui.progress.WorkbenchJob;
0056:
0057: /**
0058: * The DecoratorManager is the class that handles all of the
0059: * decorators defined in the image.
0060: *
0061: * @since 2.0
0062: */
0063: public class DecoratorManager extends LabelDecorator implements
0064: IDelayedLabelDecorator, ILabelProviderListener,
0065: IDecoratorManager, IFontDecorator, IColorDecorator,
0066: IExtensionChangeHandler {
0067:
0068: private static String EXTENSIONPOINT_UNIQUE_ID = WorkbenchPlugin.PI_WORKBENCH
0069: + "." + IWorkbenchRegistryConstants.PL_DECORATORS; //$NON-NLS-1$
0070:
0071: /**
0072: * The family for the decorate job.
0073: */
0074: public static final Object FAMILY_DECORATE = new Object();
0075:
0076: private DecorationScheduler scheduler;
0077:
0078: private LightweightDecoratorManager lightweightManager;
0079:
0080: //Hold onto the list of listeners to be told if a change has occured
0081: private ListenerList listeners = new ListenerList();
0082:
0083: //The full definitions read from the registry.
0084: //Initalize to an empty collection as this is rarely used now.
0085: private FullDecoratorDefinition[] fullDefinitions;
0086:
0087: private FullTextDecoratorRunnable fullTextRunnable = new FullTextDecoratorRunnable();
0088:
0089: private FullImageDecoratorRunnable fullImageRunnable = new FullImageDecoratorRunnable();
0090:
0091: private static final FullDecoratorDefinition[] EMPTY_FULL_DEF = new FullDecoratorDefinition[0];
0092:
0093: private final String PREFERENCE_SEPARATOR = ","; //$NON-NLS-1$
0094:
0095: private final String VALUE_SEPARATOR = ":"; //$NON-NLS-1$
0096:
0097: private final String P_TRUE = "true"; //$NON-NLS-1$
0098:
0099: private final String P_FALSE = "false"; //$NON-NLS-1$
0100:
0101: /**
0102: * Create a new instance of the receiver and load the
0103: * settings from the installed plug-ins.
0104: */
0105: public DecoratorManager() {
0106:
0107: scheduler = new DecorationScheduler(this );
0108: IExtensionTracker tracker = PlatformUI.getWorkbench()
0109: .getExtensionTracker();
0110: tracker.registerHandler(this , ExtensionTracker
0111: .createExtensionPointFilter(getExtensionPointFilter()));
0112: }
0113:
0114: /**
0115: * Initalize the decorator definitions.
0116: */
0117: private void initializeDecoratorDefinitions() {
0118: DecoratorRegistryReader reader = new DecoratorRegistryReader();
0119: Collection values = reader.readRegistry(Platform
0120: .getExtensionRegistry());
0121:
0122: ArrayList full = new ArrayList();
0123: ArrayList lightweight = new ArrayList();
0124: Iterator allDefinitions = values.iterator();
0125: IExtensionTracker configurationElementTracker = PlatformUI
0126: .getWorkbench().getExtensionTracker();
0127: while (allDefinitions.hasNext()) {
0128: DecoratorDefinition nextDefinition = (DecoratorDefinition) allDefinitions
0129: .next();
0130: if (nextDefinition.isFull()) {
0131: full.add(nextDefinition);
0132: } else {
0133: lightweight.add(nextDefinition);
0134: }
0135:
0136: configurationElementTracker.registerObject(nextDefinition
0137: .getConfigurationElement().getDeclaringExtension(),
0138: nextDefinition, IExtensionTracker.REF_WEAK);
0139: }
0140:
0141: fullDefinitions = new FullDecoratorDefinition[full.size()];
0142: full.toArray(fullDefinitions);
0143:
0144: LightweightDecoratorDefinition[] lightweightDefinitions = new LightweightDecoratorDefinition[lightweight
0145: .size()];
0146: lightweight.toArray(lightweightDefinitions);
0147:
0148: lightweightManager = new LightweightDecoratorManager(
0149: lightweightDefinitions);
0150:
0151: applyDecoratorsPreference();
0152: }
0153:
0154: /**
0155: * For dynamic UI
0156: *
0157: * @param definition the definition to add
0158: * @since 3.0
0159: */
0160: public void addDecorator(DecoratorDefinition definition) {
0161: if (definition.isFull()) {
0162: if (getFullDecoratorDefinition(definition.getId()) == null) {
0163: FullDecoratorDefinition[] oldDefs = getFullDefinitions();
0164: fullDefinitions = new FullDecoratorDefinition[fullDefinitions.length + 1];
0165: System.arraycopy(oldDefs, 0, fullDefinitions, 0,
0166: oldDefs.length);
0167: fullDefinitions[oldDefs.length] = (FullDecoratorDefinition) definition;
0168: clearCaches();
0169: updateForEnablementChange();
0170: }
0171: } else {
0172: if (getLightweightManager().addDecorator(
0173: (LightweightDecoratorDefinition) definition)) {
0174: clearCaches();
0175: updateForEnablementChange();
0176: }
0177: }
0178: ((Workbench) PlatformUI.getWorkbench()).getExtensionTracker()
0179: .registerObject(
0180: definition.getConfigurationElement()
0181: .getDeclaringExtension(), definition,
0182: IExtensionTracker.REF_WEAK);
0183: }
0184:
0185: /**
0186: * See if the supplied decorator cache has a value for the
0187: * element. If not calculate it from the enabledDefinitions and
0188: * update the cache.
0189: * @return Collection of DecoratorDefinition.
0190: * @param element The element being tested.
0191: * @param enabledDefinitions The definitions currently defined for this decorator.
0192: */
0193: static Collection getDecoratorsFor(Object element,
0194: DecoratorDefinition[] enabledDefinitions) {
0195:
0196: ArrayList decorators = new ArrayList();
0197:
0198: for (int i = 0; i < enabledDefinitions.length; i++) {
0199: if (enabledDefinitions[i].isEnabledFor(element)) {
0200: decorators.add(enabledDefinitions[i]);
0201: }
0202: }
0203:
0204: return decorators;
0205:
0206: }
0207:
0208: /**
0209: * Add the listener to the list of listeners.
0210: */
0211: public void addListener(ILabelProviderListener listener) {
0212: listeners.add(listener);
0213: }
0214:
0215: /**
0216: * Remove the listener from the list.
0217: */
0218: public void removeListener(ILabelProviderListener listener) {
0219: listeners.remove(listener);
0220: scheduler.listenerRemoved(listener);
0221: }
0222:
0223: /**
0224: * Get the list of elements listening to the receiver.
0225: * @return ILabelProviderListener []
0226: */
0227: ILabelProviderListener[] getListeners() {
0228: Object[] array = listeners.getListeners();
0229: ILabelProviderListener[] listenerArray = new ILabelProviderListener[array.length];
0230: System.arraycopy(array, 0, listenerArray, 0,
0231: listenerArray.length);
0232: return listenerArray;
0233: }
0234:
0235: /**
0236: * Inform all of the listeners that require an update
0237: * @param listener The listener we are updating.
0238: * @param event
0239: * the event with the update details
0240: */
0241: void fireListener(final LabelProviderChangedEvent event,
0242: final ILabelProviderListener listener) {
0243: Platform.run(new SafeRunnable() {
0244: public void run() {
0245: listener.labelProviderChanged(event);
0246: }
0247: });
0248:
0249: }
0250:
0251: /**
0252: * Inform all of the listeners that require an update
0253: * @param event the event with the update details
0254: */
0255: void fireListeners(final LabelProviderChangedEvent event) {
0256: Object[] array = listeners.getListeners();
0257: for (int i = 0; i < array.length; i++) {
0258: final ILabelProviderListener l = (ILabelProviderListener) array[i];
0259: Platform.run(new SafeRunnable() {
0260: public void run() {
0261: l.labelProviderChanged(event);
0262: }
0263: });
0264: }
0265: }
0266:
0267: /**
0268: * Fire any listeners from the UIThread. Used for cases where this
0269: * may be invoked outside of the UI by the public API.
0270: * @param event the event with the update details
0271: */
0272: void fireListenersInUIThread(final LabelProviderChangedEvent event) {
0273:
0274: //No updates if there is no UI
0275: if (!PlatformUI.isWorkbenchRunning()) {
0276: return;
0277: }
0278:
0279: //Only bother with the job if in the UI Thread
0280: if (Thread.currentThread() == PlatformUI.getWorkbench()
0281: .getDisplay().getThread()) {
0282: fireListeners(event);
0283: return;
0284: }
0285:
0286: WorkbenchJob updateJob = new WorkbenchJob(
0287: WorkbenchMessages.DecorationScheduler_UpdateJobName) {
0288: /*
0289: * (non-Javadoc)
0290: *
0291: * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
0292: */
0293: public IStatus runInUIThread(IProgressMonitor monitor) {
0294: fireListeners(event);
0295: return Status.OK_STATUS;
0296: }
0297:
0298: /* (non-Javadoc)
0299: * @see org.eclipse.core.runtime.jobs.Job#belongsTo(java.lang.Object)
0300: */
0301: public boolean belongsTo(Object family) {
0302: return FAMILY_DECORATE == family;
0303: }
0304: };
0305: updateJob.setSystem(true);
0306: updateJob.schedule();
0307:
0308: }
0309:
0310: /* (non-Javadoc)
0311: * @see org.eclipse.jface.viewers.ILabelDecorator2#decorateText(java.lang.String, java.lang.Object, org.eclipse.jface.viewers.IDecorationContext)
0312: */
0313: public String decorateText(String text, Object element,
0314: IDecorationContext context) {
0315: //Get any adaptations to IResource
0316: Object adapted = getResourceAdapter(element);
0317: String result = scheduler.decorateWithText(text, element,
0318: adapted, context);
0319: FullDecoratorDefinition[] decorators = getDecoratorsFor(element);
0320: for (int i = 0; i < decorators.length; i++) {
0321: if (decorators[i].isEnabledFor(element)) {
0322: String newResult = safeDecorateText(element, result,
0323: decorators[i]);
0324: if (newResult != null) {
0325: result = newResult;
0326: }
0327: }
0328: }
0329:
0330: if (adapted != null) {
0331: decorators = getDecoratorsFor(adapted);
0332: for (int i = 0; i < decorators.length; i++) {
0333: if (decorators[i].isAdaptable()
0334: && decorators[i].isEnabledFor(adapted)) {
0335: String newResult = safeDecorateText(adapted,
0336: result, decorators[i]);
0337: if (newResult != null) {
0338: result = newResult;
0339: }
0340: }
0341: }
0342: }
0343:
0344: return result;
0345: }
0346:
0347: /*
0348: * (non-Javadoc)
0349: * @see org.eclipse.jface.viewers.ILabelDecorator#decorateText(java.lang.String, java.lang.Object)
0350: */
0351: public String decorateText(String text, Object element) {
0352: return decorateText(text, element,
0353: DecorationContext.DEFAULT_CONTEXT);
0354: }
0355:
0356: /**
0357: * Decorate the text in a SafeRunnable.
0358: * @param element The element we are decorating
0359: * @param start The currently decorated String
0360: * @param decorator The decorator to run.
0361: * @param context the decoration context
0362: * @return String
0363: */
0364: private String safeDecorateText(Object element, String start,
0365: FullDecoratorDefinition decorator) {
0366: fullTextRunnable.setValues(start, element, decorator);
0367: Platform.run(fullTextRunnable);
0368: String newResult = fullTextRunnable.getResult();
0369: return newResult;
0370: }
0371:
0372: /* (non-Javadoc)
0373: * @see org.eclipse.jface.viewers.ILabelDecorator2#decorateImage(org.eclipse.swt.graphics.Image, java.lang.Object, org.eclipse.jface.viewers.IDecorationContext)
0374: */
0375: public Image decorateImage(Image image, Object element,
0376: IDecorationContext context) {
0377: Object adapted = getResourceAdapter(element);
0378: Image result = scheduler.decorateWithOverlays(image, element,
0379: adapted, context);
0380: FullDecoratorDefinition[] decorators = getDecoratorsFor(element);
0381:
0382: for (int i = 0; i < decorators.length; i++) {
0383: if (decorators[i].isEnabledFor(element)) {
0384: Image newResult = safeDecorateImage(element, result,
0385: decorators[i]);
0386: if (newResult != null) {
0387: result = newResult;
0388: }
0389: }
0390: }
0391:
0392: //Get any adaptations to IResource
0393:
0394: if (adapted != null) {
0395: decorators = getDecoratorsFor(adapted);
0396: for (int i = 0; i < decorators.length; i++) {
0397: if (decorators[i].isAdaptable()
0398: && decorators[i].isEnabledFor(adapted)) {
0399: Image newResult = safeDecorateImage(adapted,
0400: result, decorators[i]);
0401: if (newResult != null) {
0402: result = newResult;
0403: }
0404: }
0405: }
0406: }
0407:
0408: return result;
0409: }
0410:
0411: /*
0412: * (non-Javadoc)
0413: * @see org.eclipse.jface.viewers.ILabelDecorator#decorateImage(org.eclipse.swt.graphics.Image, java.lang.Object)
0414: */
0415: public Image decorateImage(Image image, Object element) {
0416: return decorateImage(image, element,
0417: DecorationContext.DEFAULT_CONTEXT);
0418: }
0419:
0420: /**
0421: * Decorate the image in a SafeRunnable.
0422: * @param element The element we are decorating
0423: * @param start The currently decorated Image
0424: * @param decorator The decorator to run.
0425: * @param context The decoration context
0426: * @return Image
0427: */
0428: private Image safeDecorateImage(Object element, Image start,
0429: FullDecoratorDefinition decorator) {
0430: fullImageRunnable.setValues(start, element, decorator);
0431: Platform.run(fullImageRunnable);
0432: Image newResult = fullImageRunnable.getResult();
0433: return newResult;
0434: }
0435:
0436: /**
0437: * Get the resource adapted object for the supplied
0438: * element. Return <code>null</code>. if there isn't one.
0439: * @param element
0440: * @return Object or <code>null</code>.
0441: */
0442: private Object getResourceAdapter(Object element) {
0443: Object adapted = LegacyResourceSupport
0444: .getAdaptedContributorResource(element);
0445: if (adapted != element) {
0446: return adapted; //Avoid applying decorator twice
0447: }
0448: return null;
0449: }
0450:
0451: /**
0452: * Return whether or not the decorator registered for element
0453: * has a label property called property name.
0454: */
0455: public boolean isLabelProperty(Object element, String property) {
0456: return isLabelProperty(element, property, true);
0457: }
0458:
0459: /**
0460: * Return whether or not the decorator registered for element
0461: * has a label property called property name.
0462: * Check for an adapted resource if checkAdapted is true.
0463: * @param element
0464: * @param property
0465: * @param checkAdapted
0466: * @return boolean <code>true</code> if there is a label property
0467: * for element or its adapted value
0468: */
0469: public boolean isLabelProperty(Object element, String property,
0470: boolean checkAdapted) {
0471: boolean fullCheck = isLabelProperty(element, property,
0472: getDecoratorsFor(element));
0473:
0474: if (fullCheck) {
0475: return fullCheck;
0476: }
0477:
0478: boolean lightweightCheck = isLabelProperty(element, property,
0479: getLightweightManager().getDecoratorsFor(element));
0480:
0481: if (lightweightCheck) {
0482: return true;
0483: }
0484:
0485: if (checkAdapted) {
0486: //Get any adaptions to IResource
0487: Object adapted = getResourceAdapter(element);
0488: if (adapted == null || adapted == element) {
0489: return false;
0490: }
0491:
0492: fullCheck = isLabelProperty(adapted, property,
0493: getDecoratorsFor(adapted));
0494: if (fullCheck) {
0495: return fullCheck;
0496: }
0497:
0498: return isLabelProperty(adapted, property,
0499: lightweightManager.getDecoratorsFor(adapted));
0500: }
0501: return false;
0502: }
0503:
0504: private boolean isLabelProperty(Object element, String property,
0505: DecoratorDefinition[] decorators) {
0506: for (int i = 0; i < decorators.length; i++) {
0507: if (decorators[i].isEnabledFor(element)
0508: && decorators[i].isLabelProperty(element, property)) {
0509: return true;
0510: }
0511: }
0512:
0513: return false;
0514: }
0515:
0516: /**
0517: * Return the enabled full decorator definitions.
0518: * @return FullDecoratorDefinition[]
0519: */
0520: private FullDecoratorDefinition[] enabledFullDefinitions() {
0521:
0522: FullDecoratorDefinition[] full = getFullDefinitions();
0523: //As this are a deprecated data type optimize for
0524: //the undefined case.
0525: if (full.length == 0) {
0526: return full;
0527: }
0528: ArrayList result = new ArrayList();
0529: for (int i = 0; i < full.length; i++) {
0530: if (full[i].isEnabled()) {
0531: result.add(full[i]);
0532: }
0533: }
0534: FullDecoratorDefinition[] returnArray = new FullDecoratorDefinition[result
0535: .size()];
0536: result.toArray(returnArray);
0537: return returnArray;
0538: }
0539:
0540: /*
0541: * @see IBaseLabelProvider#dispose()
0542: */
0543: public void dispose() {
0544: //do nothing
0545: }
0546:
0547: /**
0548: * Clear the caches in the manager. This is required
0549: * to avoid updates that may occur due to changes in
0550: * enablement.
0551: */
0552: public void clearCaches() {
0553: getLightweightManager().reset();
0554: fullTextRunnable.clearReferences();
0555: fullImageRunnable.clearReferences();
0556: }
0557:
0558: /**
0559: * Enablement had changed. Fire the listeners and write
0560: * the preference.
0561: */
0562: public void updateForEnablementChange() {
0563: //Clear any results that may be around as all labels have changed
0564: scheduler.clearResults();
0565: fireListenersInUIThread(new LabelProviderChangedEvent(this ));
0566: writeDecoratorsPreference();
0567: }
0568:
0569: /**
0570: * Get the DecoratorDefinitions defined on the receiver.
0571: * @return DecoratorDefinition[]
0572: */
0573: public DecoratorDefinition[] getAllDecoratorDefinitions() {
0574: LightweightDecoratorDefinition[] lightweightDefinitions = getLightweightManager()
0575: .getDefinitions();
0576: DecoratorDefinition[] returnValue = new DecoratorDefinition[fullDefinitions.length
0577: + lightweightDefinitions.length];
0578: System.arraycopy(fullDefinitions, 0, returnValue, 0,
0579: fullDefinitions.length);
0580: System.arraycopy(lightweightDefinitions, 0, returnValue,
0581: fullDefinitions.length, lightweightDefinitions.length);
0582: return returnValue;
0583: }
0584:
0585: /*
0586: * @see ILabelProviderListener#labelProviderChanged(LabelProviderChangedEvent)
0587: */
0588: public void labelProviderChanged(LabelProviderChangedEvent event) {
0589: Object[] elements = event.getElements();
0590: scheduler.clearResults();
0591: //If the elements are not specified send out a general update
0592: if (elements == null) {
0593: fireListeners(event);
0594: } else {
0595: //Assume that someone is going to care about the
0596: //decoration result and just start it right away
0597: for (int i = 0; i < elements.length; i++) {
0598: Object adapted = getResourceAdapter(elements[i]);
0599: //Force an update in case full decorators are the only ones enabled
0600: scheduler.queueForDecoration(elements[i], adapted,
0601: true, null, DecorationContext.DEFAULT_CONTEXT);
0602: }
0603: }
0604: }
0605:
0606: /**
0607: * Store the currently enabled decorators in
0608: * preference store.
0609: */
0610: private void writeDecoratorsPreference() {
0611: StringBuffer enabledIds = new StringBuffer();
0612: writeDecoratorsPreference(enabledIds, getFullDefinitions());
0613: writeDecoratorsPreference(enabledIds, getLightweightManager()
0614: .getDefinitions());
0615:
0616: WorkbenchPlugin.getDefault().getPreferenceStore().setValue(
0617: IPreferenceConstants.ENABLED_DECORATORS,
0618: enabledIds.toString());
0619: PrefUtil.savePrefs();
0620: }
0621:
0622: private void writeDecoratorsPreference(StringBuffer enabledIds,
0623: DecoratorDefinition[] definitions) {
0624: for (int i = 0; i < definitions.length; i++) {
0625: enabledIds.append(definitions[i].getId());
0626: enabledIds.append(VALUE_SEPARATOR);
0627: if (definitions[i].isEnabled()) {
0628: enabledIds.append(P_TRUE);
0629: } else {
0630: enabledIds.append(P_FALSE);
0631: }
0632:
0633: enabledIds.append(PREFERENCE_SEPARATOR);
0634: }
0635: }
0636:
0637: /**
0638: * Get the currently enabled decorators in
0639: * preference store and set the state of the
0640: * current definitions accordingly.
0641: */
0642: public void applyDecoratorsPreference() {
0643:
0644: String preferenceValue = WorkbenchPlugin.getDefault()
0645: .getPreferenceStore().getString(
0646: IPreferenceConstants.ENABLED_DECORATORS);
0647:
0648: StringTokenizer tokenizer = new StringTokenizer(
0649: preferenceValue, PREFERENCE_SEPARATOR);
0650: Set enabledIds = new HashSet();
0651: Set disabledIds = new HashSet();
0652: while (tokenizer.hasMoreTokens()) {
0653: String nextValuePair = tokenizer.nextToken();
0654:
0655: //Strip out the true or false to get the id
0656: String id = nextValuePair.substring(0, nextValuePair
0657: .indexOf(VALUE_SEPARATOR));
0658: if (nextValuePair.endsWith(P_TRUE)) {
0659: enabledIds.add(id);
0660: } else {
0661: disabledIds.add(id);
0662: }
0663: }
0664:
0665: FullDecoratorDefinition[] full = getFullDefinitions();
0666: for (int i = 0; i < full.length; i++) {
0667: String id = full[i].getId();
0668: if (enabledIds.contains(id)) {
0669: full[i].setEnabled(true);
0670: } else {
0671: if (disabledIds.contains(id)) {
0672: full[i].setEnabled(false);
0673: }
0674: }
0675: }
0676:
0677: LightweightDecoratorDefinition[] lightweightDefinitions = getLightweightManager()
0678: .getDefinitions();
0679: for (int i = 0; i < lightweightDefinitions.length; i++) {
0680: String id = lightweightDefinitions[i].getId();
0681: if (enabledIds.contains(id)) {
0682: lightweightDefinitions[i].setEnabled(true);
0683: } else {
0684: if (disabledIds.contains(id)) {
0685: lightweightDefinitions[i].setEnabled(false);
0686: }
0687: }
0688: }
0689:
0690: }
0691:
0692: /**
0693: * Shutdown the decorator manager by disabling all
0694: * of the decorators so that dispose() will be called
0695: * on them.
0696: */
0697: public void shutdown() {
0698: //Disable all of the enabled decorators
0699: //so as to force a dispose of thier decorators
0700: FullDecoratorDefinition[] full = getFullDefinitions();
0701: for (int i = 0; i < full.length; i++) {
0702: if (full[i].isEnabled()) {
0703: full[i].setEnabled(false);
0704: }
0705: }
0706: if (lightweightManager != null) {
0707: getLightweightManager().shutdown();
0708: }
0709: scheduler.shutdown();
0710: dispose();
0711: }
0712:
0713: /* (non-Javadoc)
0714: * @see org.eclipse.ui.IDecoratorManager#getEnabled(java.lang.String)
0715: */
0716: public boolean getEnabled(String decoratorId) {
0717: DecoratorDefinition definition = getDecoratorDefinition(decoratorId);
0718: if (definition == null) {
0719: return false;
0720: }
0721: return definition.isEnabled();
0722: }
0723:
0724: /**
0725: * @see IDecoratorManager#getLabelDecorator()
0726: */
0727: public ILabelDecorator getLabelDecorator() {
0728: return this ;
0729: }
0730:
0731: /**
0732: * @see IDecoratorManager#setEnabled(String, boolean)
0733: */
0734: public void setEnabled(String decoratorId, boolean enabled) {
0735: DecoratorDefinition definition = getDecoratorDefinition(decoratorId);
0736: if (definition != null) {
0737: definition.setEnabled(enabled);
0738: clearCaches();
0739: updateForEnablementChange();
0740: }
0741: }
0742:
0743: /*
0744: * @see IDecoratorManager#getBaseLabelProvider(String)
0745: */
0746: public IBaseLabelProvider getBaseLabelProvider(String decoratorId) {
0747: IBaseLabelProvider fullProvider = getLabelDecorator(decoratorId);
0748: if (fullProvider == null) {
0749: return getLightweightLabelDecorator(decoratorId);
0750: }
0751: return fullProvider;
0752: }
0753:
0754: /*
0755: * @see IDecoratorManager#getLabelDecorator(String)
0756: */
0757: public ILabelDecorator getLabelDecorator(String decoratorId) {
0758: FullDecoratorDefinition definition = getFullDecoratorDefinition(decoratorId);
0759:
0760: //Do not return for a disabled decorator
0761: if (definition != null && definition.isEnabled()) {
0762: return definition.getDecorator();
0763: }
0764: return null;
0765: }
0766:
0767: /*
0768: * @see IDecoratorManager#getLightweightLabelDecorator(String)
0769: */
0770: public ILightweightLabelDecorator getLightweightLabelDecorator(
0771: String decoratorId) {
0772: LightweightDecoratorDefinition definition = getLightweightManager()
0773: .getDecoratorDefinition(decoratorId);
0774: //Do not return for a disabled decorator
0775: if (definition != null && definition.isEnabled()) {
0776: return definition.getDecorator();
0777: }
0778: return null;
0779: }
0780:
0781: /**
0782: * Get the DecoratorDefinition with the supplied id
0783: * @return DecoratorDefinition or <code>null</code> if it is not found
0784: * @param decoratorId String
0785: */
0786: private DecoratorDefinition getDecoratorDefinition(
0787: String decoratorId) {
0788: DecoratorDefinition returnValue = getFullDecoratorDefinition(decoratorId);
0789: if (returnValue == null) {
0790: return getLightweightManager().getDecoratorDefinition(
0791: decoratorId);
0792: }
0793: return returnValue;
0794: }
0795:
0796: /**
0797: * Get the FullDecoratorDefinition with the supplied id
0798: * @return FullDecoratorDefinition or <code>null</code> if it is not found
0799: * @param decoratorId the id
0800: */
0801: private FullDecoratorDefinition getFullDecoratorDefinition(
0802: String decoratorId) {
0803: int idx = getFullDecoratorDefinitionIdx(decoratorId);
0804: if (idx != -1) {
0805: return getFullDefinitions()[idx];
0806: }
0807: return null;
0808: }
0809:
0810: /**
0811: * Return the index of the definition in the array.
0812: *
0813: * @param decoratorId the id
0814: * @return the index of the definition in the array or <code>-1</code>
0815: * @since 3.1
0816: */
0817: private int getFullDecoratorDefinitionIdx(String decoratorId) {
0818: FullDecoratorDefinition[] full = getFullDefinitions();
0819: for (int i = 0; i < full.length; i++) {
0820: if (full[i].getId().equals(decoratorId)) {
0821: return i;
0822: }
0823: }
0824: return -1;
0825: }
0826:
0827: /**
0828: * Get the full decorator definitions registered for elements of this type.
0829: * @param element The element to look up
0830: * @return FullDecoratorDefinition[]
0831: */
0832: private FullDecoratorDefinition[] getDecoratorsFor(Object element) {
0833:
0834: if (element == null) {
0835: return EMPTY_FULL_DEF;
0836: }
0837:
0838: Collection decorators = getDecoratorsFor(element,
0839: enabledFullDefinitions());
0840: FullDecoratorDefinition[] decoratorArray = EMPTY_FULL_DEF;
0841: if (decorators.size() > 0) {
0842: decoratorArray = new FullDecoratorDefinition[decorators
0843: .size()];
0844: decorators.toArray(decoratorArray);
0845: }
0846:
0847: return decoratorArray;
0848: }
0849:
0850: /**
0851: * Returns the lightweightManager. This method is
0852: * public for use by test cases. No other classes outside of
0853: * this package should use this method.
0854: * @return LightweightDecoratorManager
0855: */
0856: public LightweightDecoratorManager getLightweightManager() {
0857: if (lightweightManager == null) {
0858: initializeDecoratorDefinitions();
0859: }
0860: return lightweightManager;
0861: }
0862:
0863: /**
0864: * @see org.eclipse.ui.IDecoratorManager#update(java.lang.String)
0865: */
0866: public void update(String decoratorId) {
0867:
0868: IBaseLabelProvider provider = getBaseLabelProvider(decoratorId);
0869: if (provider != null) {
0870: scheduler.clearResults();
0871: fireListeners(new LabelProviderChangedEvent(provider));
0872: }
0873:
0874: }
0875:
0876: public boolean prepareDecoration(Object element,
0877: String originalText, IDecorationContext context) {
0878: // Check if there is a decoration ready or if there is no lightweight decorators to be applied
0879: if (scheduler.isDecorationReady(element, context)
0880: || !getLightweightManager().hasEnabledDefinitions()) {
0881: return true;
0882: }
0883:
0884: // Force an update if there is a text already
0885: boolean force = true;
0886: //If not then do not force as the undecorated value is fine
0887: if (originalText == null || originalText.length() == 0) {
0888: force = false;
0889: }
0890:
0891: // Queue the decoration.
0892: scheduler.queueForDecoration(element,
0893: getResourceAdapter(element), force, originalText,
0894: context);
0895:
0896: //If all that is there is deferred ones then defer decoration.
0897: //For the sake of efficiency we do not test for enablement at this
0898: //point and just abandon deferment if there are any to run right
0899: //away
0900: return getFullDefinitions().length > 0;
0901: }
0902:
0903: /* (non-Javadoc)
0904: * @see org.eclipse.jface.viewers.IDelayedLabelDecorator#prepareDecoration(java.lang.Object, java.lang.String)
0905: */
0906: public boolean prepareDecoration(Object element, String originalText) {
0907: return prepareDecoration(element, originalText,
0908: DecorationContext.DEFAULT_CONTEXT);
0909: }
0910:
0911: /* (non-Javadoc)
0912: * @see org.eclipse.jface.viewers.IFontDecorator#decorateFont(java.lang.Object)
0913: */
0914: public Font decorateFont(Object element) {
0915: return scheduler.getFont(element, getResourceAdapter(element));
0916: }
0917:
0918: /* (non-Javadoc)
0919: * @see org.eclipse.jface.viewers.IColorDecorator#decorateBackground(java.lang.Object)
0920: */
0921: public Color decorateBackground(Object element) {
0922: return scheduler.getBackgroundColor(element,
0923: getResourceAdapter(element));
0924: }
0925:
0926: /* (non-Javadoc)
0927: * @see org.eclipse.jface.viewers.IColorDecorator#decorateForeground(java.lang.Object)
0928: */
0929: public Color decorateForeground(Object element) {
0930: return scheduler.getForegroundColor(element,
0931: getResourceAdapter(element));
0932: }
0933:
0934: /**
0935: * Get all of the defined fullDefinitions. Initalize if
0936: * required
0937: * @return FullDecoratorDefinition[]
0938: */
0939: private FullDecoratorDefinition[] getFullDefinitions() {
0940: if (fullDefinitions == null) {
0941: initializeDecoratorDefinitions();
0942: }
0943: return fullDefinitions;
0944: }
0945:
0946: private IExtensionPoint getExtensionPointFilter() {
0947: return Platform.getExtensionRegistry().getExtensionPoint(
0948: EXTENSIONPOINT_UNIQUE_ID);
0949: }
0950:
0951: /* (non-Javadoc)
0952: * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#addExtension(org.eclipse.core.runtime.dynamicHelpers.IExtensionTracker, org.eclipse.core.runtime.IExtension)
0953: */
0954: public void addExtension(IExtensionTracker tracker,
0955: IExtension addedExtension) {
0956: IConfigurationElement addedElements[] = addedExtension
0957: .getConfigurationElements();
0958: for (int i = 0; i < addedElements.length; i++) {
0959: DecoratorRegistryReader reader = new DecoratorRegistryReader();
0960: reader.readElement(addedElements[i]);
0961: for (Iterator j = reader.getValues().iterator(); j
0962: .hasNext();) {
0963: addDecorator((DecoratorDefinition) j.next());
0964: }
0965: }
0966: }
0967:
0968: /* (non-Javadoc)
0969: * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension, java.lang.Object[])
0970: */
0971: public void removeExtension(IExtension source, Object[] objects) {
0972:
0973: boolean shouldClear = false;
0974: for (int i = 0; i < objects.length; i++) {
0975: if (objects[i] instanceof DecoratorDefinition) {
0976: DecoratorDefinition definition = (DecoratorDefinition) objects[i];
0977: if (definition.isFull()) {
0978: int idx = getFullDecoratorDefinitionIdx(definition
0979: .getId());
0980: if (idx != -1) {
0981: FullDecoratorDefinition[] oldDefs = getFullDefinitions();
0982: Util
0983: .arrayCopyWithRemoval(
0984: oldDefs,
0985: fullDefinitions = new FullDecoratorDefinition[fullDefinitions.length - 1],
0986: idx);
0987: shouldClear = true;
0988: }
0989: } else {
0990: shouldClear |= getLightweightManager()
0991: .removeDecorator(
0992: (LightweightDecoratorDefinition) definition);
0993: }
0994: }
0995: }
0996:
0997: if (shouldClear) {
0998: clearCaches();
0999: updateForEnablementChange();
1000: }
1001:
1002: }
1003:
1004: }
|