/******************************************************************************* * Copyright (c) 2000, 2012 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.jdt.ui; import melnorme.lang.ide.core.EclipseCore; import melnorme.lang.ide.ui.LangImages; import melnorme.lang.ide.ui.LangUIPlugin; import melnorme.util.swt.jface.resources.ImageDescriptorRegistry; 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.DecorationOverlayIcon; 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.ILightweightLabelDecorator; import org.eclipse.jface.viewers.LabelProviderChangedEvent; import org.eclipse.swt.graphics.Image; import _org.eclipse.jdt.internal.ui.viewsupport.IProblemChangedListener; /** * LabelDecorator that decorates an element's image with error and warning overlays that * represent the severity of markers attached to the element's underlying resource. To see * a problem decoration for a marker, the marker needs to be a subtype of <code>IMarker.PROBLEM</code>. * <p> * <b>Important</b>: Although this decorator implements ILightweightLabelDecorator, do not contribute this * class as a decorator to the <code>org.eclipse.ui.decorators</code> extension. Only use this class in your * own views and label providers. * * @since 2.0 */ public class ProblemsLabelDecorator implements ILabelDecorator, ILightweightLabelDecorator { /** * This is a special <code>LabelProviderChangedEvent</code> carrying additional * information whether the event origins from a maker 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; /** * @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 ImageDescriptorRegistry fRegistry; private boolean fUseNewRegistry= false; private IProblemChangedListener fProblemChangedListener; private ListenerList<ILabelProviderListener> fListeners; /** * Creates a new <code>ProblemsLabelDecorator</code>. */ public ProblemsLabelDecorator() { this(null); fUseNewRegistry= true; } /** * Note: This constructor is for internal use only. Clients should not call this constructor. * * @param registry The registry to use or <code>null</code> to use the Java plugin's image * registry * @noreference This constructor is not intended to be referenced by clients. */ public ProblemsLabelDecorator(ImageDescriptorRegistry registry) { fRegistry= registry; fProblemChangedListener= null; } private ImageDescriptorRegistry getRegistry() { if (fRegistry == null) { fRegistry= fUseNewRegistry ? new ImageDescriptorRegistry() : LangUIPlugin.getDefault().getImageDescriptorRegistry(); } return fRegistry; } @Override public String decorateText(String text, Object element) { return text; } @Override public Image decorateImage(Image image, Object obj) { if(image == null) return null; ImageDescriptor overlayImage = computeAdornmentFlags(obj); if(overlayImage != null) { // ImageDescriptor baseImage = new ImageImageDescriptor(image); return getRegistry().get(new DecorationOverlayIcon(image, overlayImage, IDecoration.BOTTOM_LEFT)); } return image; } /** * Computes the adornment flags for the given element. * * @param obj the element to compute the flags for * * @return the adornment flags */ protected ImageDescriptor computeAdornmentFlags(Object obj) { try { if (obj instanceof IResource) { return getErrorTicksFromMarkers((IResource) obj, IResource.DEPTH_INFINITE); } } catch (CoreException e) { if (e.getStatus().getCode() == IResourceStatus.MARKER_NOT_FOUND) { return null; } EclipseCore.logStatus(e); } return null; } protected ImageDescriptor getErrorTicksFromMarkers(IResource res, int depth) throws CoreException { if (res == null || !res.isAccessible()) { return null; } int severity= 0; // if (res instanceof IProject) { // severity= res.findMaxProblemSeverity(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, true, IResource.DEPTH_ZERO); // if (severity == IMarker.SEVERITY_ERROR) { // return ERRORTICK_BUILDPATH_ERROR; // } // severity= res.findMaxProblemSeverity(JavaRuntime.JRE_CONTAINER_MARKER, true, IResource.DEPTH_ZERO); // if (severity == IMarker.SEVERITY_ERROR) { // return ERRORTICK_BUILDPATH_ERROR; // } // } severity= res.findMaxProblemSeverity(IMarker.PROBLEM, true, depth); if (severity == IMarker.SEVERITY_ERROR) { return LangImages.DESC_OVR_ERROR; } else if (severity == IMarker.SEVERITY_WARNING) { return LangImages.DESC_OVR_WARNING; } return null; } // private int getPackageErrorTicksFromMarkers(IPackageFragment pack) throws CoreException { // // Packages are special: They must not consider markers on subpackages. // // IResource res= pack.getResource(); // if (res == null || !res.isAccessible()) { // return 0; // } // // // markers on package itself (e.g. missing @NonNullByDefault) // int severity= res.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_ZERO); // if (severity == IMarker.SEVERITY_ERROR) // return ERRORTICK_ERROR; // // // markers on CUs // for (ICompilationUnit cu : pack.getCompilationUnits()) { // severity= Math.max(severity, cu.getResource().findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_ZERO)); // if (severity == IMarker.SEVERITY_ERROR) // return ERRORTICK_ERROR; // } // // // markers on files and folders // for (Object object : pack.getNonJavaResources()) { // if (object instanceof IResource) { // IResource resource= (IResource) object; // severity= Math.max(severity, resource.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE)); // if (severity == IMarker.SEVERITY_ERROR) // return ERRORTICK_ERROR; // } // } // // // SEVERITY_ERROR already handled above // if (severity == IMarker.SEVERITY_WARNING) { // return ERRORTICK_WARNING; // } // return 0; // } @Override public void dispose() { if (fProblemChangedListener != null) { LangUIPlugin.getDefault().getProblemMarkerManager().removeListener(fProblemChangedListener); fProblemChangedListener= null; } if (fRegistry != null && fUseNewRegistry) { fRegistry.dispose(); } } @Override public boolean isLabelProperty(Object element, String property) { return true; } @Override public void addListener(ILabelProviderListener listener) { if (fListeners == null) { fListeners= new ListenerList<>(); } fListeners.add(listener); if (fProblemChangedListener == null) { fProblemChangedListener= new IProblemChangedListener() { @Override public void problemsChanged(IResource[] changedResources, boolean isMarkerChange, boolean calledFromDisplayThread) { fireProblemsChanged(changedResources, isMarkerChange); } }; LangUIPlugin.getDefault().getProblemMarkerManager().addListener(fProblemChangedListener); } } @Override public void removeListener(ILabelProviderListener listener) { if (fListeners != null) { fListeners.remove(listener); if (fListeners.isEmpty() && fProblemChangedListener != null) { LangUIPlugin.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); } } } @Override public void decorate(Object element, IDecoration decoration) { ImageDescriptor imageDescriptor= computeAdornmentFlags(element); if(imageDescriptor != null) { decoration.addOverlay(imageDescriptor); } } }