Java tutorial
/******************************************************************************* * Copyright (c) 2007 IBM Corporation. * 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: * Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation *******************************************************************************/ package io.usethesource.impulse.editor; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceStatus; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.ListenerList; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.IBaseLabelProvider; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.ILabelDecorator; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.LabelProviderChangedEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import io.usethesource.impulse.editor.internal.ImageDecoratorController; import io.usethesource.impulse.language.Language; import io.usethesource.impulse.model.ICompilationUnit; import io.usethesource.impulse.model.ISourceEntity; import io.usethesource.impulse.runtime.ImageDescriptorRegistry; import io.usethesource.impulse.runtime.PluginImages; import io.usethesource.impulse.runtime.RuntimePlugin; /** * Decorates an image of a program element to indicate any related errors/warnings. * See org.eclipse.jdt.ui.ProblemsLabelDecorator for inspiration. * @author rfuhrer@watson.ibm.com */ public class ProblemsLabelDecorator implements ILabelDecorator { /** * This is a special <code>LabelProviderChangedEvent</code> carrying additional * information whether the event originates from a marker change. * <p> * <code>ProblemsLabelChangedEvent</code>s are only generated by <code> * ProblemsLabelDecorator</code>s. * </p> */ public static class ProblemsLabelChangedEvent extends LabelProviderChangedEvent { private static final long serialVersionUID = 1L; private boolean fMarkerChange; /** * Note: This constructor is for internal use only. Clients should not call this constructor. * * @param eventSource the base label provider * @param changedResource the changed resources * @param isMarkerChange <code>true<code> if the change is a marker change; otherwise * <code>false</code> */ public ProblemsLabelChangedEvent(IBaseLabelProvider eventSource, IResource[] changedResource, boolean isMarkerChange) { super(eventSource, changedResource); fMarkerChange = isMarkerChange; } /** * Returns whether this event origins from marker changes. If <code>false</code> an annotation * model change is the origin. In this case viewers not displaying working copies can ignore these * events. * * @return if this event origins from a marker change. */ public boolean isMarkerChange() { return fMarkerChange; } } private static final int ERRORTICK_WARNING = 0; private static final int ERRORTICK_ERROR = 1; private ImageDescriptorRegistry fRegistry; private ImageDecoratorController fDecoratorController; private boolean fUseNewRegistry = false; private IProblemChangedListener fProblemChangedListener; private ListenerList fListeners; public ProblemsLabelDecorator(Language lang) { fRegistry = null; fProblemChangedListener = null; fUseNewRegistry = true; fDecoratorController = new ImageDecoratorController(lang); } private ImageDescriptorRegistry getRegistry() { if (fRegistry == null) { fRegistry = fUseNewRegistry ? new ImageDescriptorRegistry() : RuntimePlugin.getImageDescriptorRegistry(); } return fRegistry; } /* (non-Javadoc) * @see ILabelDecorator#decorateText(String, Object) */ public String decorateText(String text, Object element) { return text; } /* (non-Javadoc) * @see ILabelDecorator#decorateImage(Image, Object) */ public Image decorateImage(Image image, Object obj) { int adornmentFlags = computeAdornmentFlags(obj); if (adornmentFlags != 0) { ImageDescriptor baseImage = new ImageImageDescriptor(image); Rectangle bounds = image.getBounds(); Point ptBounds = new Point(bounds.width, bounds.height); return getRegistry().get(fDecoratorController.getImageDescriptor(baseImage, obj, ptBounds)); } return image; } /** * Note: This method is for internal use only. Clients should not call this method. * * @param obj the element to compute the flags for * * @return the adornment flags */ protected int computeAdornmentFlags(Object obj) { try { if (obj instanceof ISourceEntity) { ISourceEntity element = (ISourceEntity) obj; IResource res = element.getResource(); int depth = IResource.DEPTH_INFINITE; if (element instanceof ICompilationUnit) { depth = IResource.DEPTH_ONE; } return getErrorTicksFromMarkers(res, depth); } else if (obj instanceof IResource) { return getErrorTicksFromMarkers((IResource) obj, IResource.DEPTH_INFINITE); } } catch (CoreException e) { if (e.getStatus().getCode() == IResourceStatus.MARKER_NOT_FOUND) { return 0; } RuntimePlugin.getInstance().logException("", e); } return 0; } // TODO The following code used to use the given ISourceReference to determine which markers // lay within the source range of the given entity. We don't yet have ISourceEntity's for // anything smaller than a compilation unit, so that functionality will have to wait for an // API enhancement. private int getErrorTicksFromMarkers(IResource res, int depth /*, ISourceReference sourceElement*/) throws CoreException { if (res == null || !res.isAccessible()) { return 0; } int info = 0; IMarker[] markers = res.findMarkers(IMarker.PROBLEM, true, depth); if (markers != null) { for (int i = 0; i < markers.length && (info != ERRORTICK_ERROR); i++) { IMarker curr = markers[i]; int priority = curr.getAttribute(IMarker.SEVERITY, -1); if (priority == IMarker.SEVERITY_WARNING) { info = ERRORTICK_WARNING; } else if (priority == IMarker.SEVERITY_ERROR) { info = ERRORTICK_ERROR; } } } return info; } /* (non-Javadoc) * @see IBaseLabelProvider#dispose() */ public void dispose() { if (fProblemChangedListener != null) { // TODO RMF reenable // JavaPlugin.getDefault().getProblemMarkerManager().removeListener(fProblemChangedListener); fProblemChangedListener = null; } if (fRegistry != null && fUseNewRegistry) { fRegistry.dispose(); } } /* (non-Javadoc) * @see IBaseLabelProvider#isLabelProperty(Object, String) */ public boolean isLabelProperty(Object element, String property) { return true; } /* (non-Javadoc) * @see IBaseLabelProvider#addListener(ILabelProviderListener) */ public void addListener(ILabelProviderListener listener) { if (fListeners == null) { fListeners = new ListenerList(); } fListeners.add(listener); if (fProblemChangedListener == null) { fProblemChangedListener = new IProblemChangedListener() { public void problemsChanged(IResource[] changedResources, boolean isMarkerChange) { fireProblemsChanged(changedResources, isMarkerChange); } }; // TODO RMF reenable // JavaPlugin.getDefault().getProblemMarkerManager().addListener(fProblemChangedListener); } } /* (non-Javadoc) * @see IBaseLabelProvider#removeListener(ILabelProviderListener) */ public void removeListener(ILabelProviderListener listener) { if (fListeners != null) { fListeners.remove(listener); if (fListeners.isEmpty() && fProblemChangedListener != null) { // TODO RMF reenable // JavaPlugin.getDefault().getProblemMarkerManager().removeListener(fProblemChangedListener); fProblemChangedListener = null; } } } private void fireProblemsChanged(IResource[] changedResources, boolean isMarkerChange) { if (fListeners != null && !fListeners.isEmpty()) { LabelProviderChangedEvent event = new ProblemsLabelChangedEvent(this, changedResources, isMarkerChange); Object[] listeners = fListeners.getListeners(); for (int i = 0; i < listeners.length; i++) { ((ILabelProviderListener) listeners[i]).labelProviderChanged(event); } } } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ILightweightLabelDecorator#decorate(java.lang.Object, org.eclipse.jface.viewers.IDecoration) */ public void decorate(Object element, IDecoration decoration) { int adornmentFlags = computeAdornmentFlags(element); if (adornmentFlags == ERRORTICK_ERROR) { decoration.addOverlay(PluginImages.DESC_OVR_ERROR); } else if (adornmentFlags == ERRORTICK_WARNING) { decoration.addOverlay(PluginImages.DESC_OVR_WARNING); } } }