package com.aptana.editor.php.internal.ui; 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.viewers.IBaseLabelProvider; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ILightweightLabelDecorator; import org.eclipse.jface.viewers.LabelProviderChangedEvent; import com.aptana.core.logging.IdeLog; import com.aptana.editor.php.epl.PHPEplPlugin; import com.aptana.editor.php.internal.ui.viewsupport.IProblemChangedListener; /** * A lightweight label decorator that looks into IResource markers and decorate with errors or warnings. */ public class ProblemsLabelDecorator implements ILightweightLabelDecorator { private static final int ERROR = 0; private static final int WARNING = 1; private ListenerList fListeners; private IProblemChangedListener fProblemChangedListener; /** * 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; } } /* * (non-Javadoc) * @see IBaseLabelProvider#dispose() */ public void dispose() { if (fProblemChangedListener != null) { PHPEplPlugin.getDefault().getProblemMarkerManager().removeListener(fProblemChangedListener); fProblemChangedListener = null; } } /* * (non-Javadoc) * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String) */ public boolean isLabelProperty(Object element, String property) { return false; } /* * (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); } }; PHPEplPlugin.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) { PHPEplPlugin.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); switch (adornmentFlags) { case ERROR: decoration.addOverlay(PHPPluginImages.DESC_OVR_ERROR); break; case WARNING: decoration.addOverlay(PHPPluginImages.DESC_OVR_WARNING); break; } } /** * Compute the flags that were set on the give object. We expect an IResource for this computation, and we return * the flags according to the warnings or errors set on the resource. * * @param obj * A IResource (expected) * @return An integer representing an ERROR or a WARNING; -1 if the give object was not an IResource or when we got * an exception retrieving the {@link IMarker}s from the resource. */ protected int 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 -1; } IdeLog.logWarning(PHPEplPlugin.getDefault(), "Error computing PHP label-decoration adornment flags", e, PHPEplPlugin.DEBUG_SCOPE); //$NON-NLS-1$ } return -1; } private int getErrorTicksFromMarkers(IResource res, int depth) throws CoreException { if (res == null || !res.isAccessible()) { return -1; } int info = -1; IMarker[] markers = res.findMarkers(IMarker.PROBLEM, true, depth); if (markers != null) { for (int i = 0; i < markers.length && info != ERROR; i++) { IMarker curr = markers[i]; int priority = curr.getAttribute(IMarker.SEVERITY, -1); if (priority == IMarker.SEVERITY_WARNING) { info = WARNING; } else if (priority == IMarker.SEVERITY_ERROR) { info = ERROR; } } } return info; } }