/*******************************************************************************
* 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);
}
}
}