X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/ProblemsLabelDecorator.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/ProblemsLabelDecorator.java new file mode 100644 index 0000000..2af4d84 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/ProblemsLabelDecorator.java @@ -0,0 +1,425 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package net.sourceforge.phpdt.ui; + +import java.util.Iterator; + +import net.sourceforge.phpdt.core.ICompilationUnit; +import net.sourceforge.phpdt.core.IJavaElement; +import net.sourceforge.phpdt.core.ISourceRange; +import net.sourceforge.phpdt.core.ISourceReference; +import net.sourceforge.phpdt.core.JavaModelException; +import net.sourceforge.phpdt.internal.ui.PHPUiImages; +import net.sourceforge.phpdt.internal.ui.viewsupport.IProblemChangedListener; +import net.sourceforge.phpdt.internal.ui.viewsupport.ImageDescriptorRegistry; +import net.sourceforge.phpdt.internal.ui.viewsupport.ImageImageDescriptor; +import net.sourceforge.phpeclipse.PHPeclipsePlugin; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; +//incastrix +//import org.eclipse.jface.util.ListenerList; +import org.eclipse.core.runtime.ListenerList; +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.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.ui.part.FileEditorInput; +import org.eclipse.ui.texteditor.MarkerAnnotation; + +/** + * 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 IMarker.PROBLEM. + *

+ * Note: Only images for elements in Java projects are currently updated on + * marker changes. + *

+ * + * @since 2.0 + */ +public class ProblemsLabelDecorator implements ILabelDecorator, + ILightweightLabelDecorator { + + /** + * This is a special LabelProviderChangedEvent carring + * additional information whether the event orgins from a maker change. + *

+ * ProblemsLabelChangedEvents are only generated by + * ProblemsLabelDecorators. + *

+ */ + public static class ProblemsLabelChangedEvent extends + LabelProviderChangedEvent { + + /** + * + */ + private static final long serialVersionUID = -7557704732816971319L; + private boolean fMarkerChange; + + /** + * Note: This constructor is for internal use only. Clients should not + * call this constructor. + */ + public ProblemsLabelChangedEvent(IBaseLabelProvider source, + IResource[] changedResource, boolean isMarkerChange) { + super(source, changedResource); + fMarkerChange = isMarkerChange; + } + + /** + * Returns whether this event origins from marker changes. If + * false 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 = JavaElementImageDescriptor.WARNING; + + private static final int ERRORTICK_ERROR = JavaElementImageDescriptor.ERROR; + + private ImageDescriptorRegistry fRegistry; + + private boolean fUseNewRegistry = false; + + private IProblemChangedListener fProblemChangedListener; + + private ListenerList fListeners; + + /** + * Creates a new ProblemsLabelDecorator. + */ +// public ProblemsLabelDecorator() { +// this(null); +// fUseNewRegistry = true; +// } + + /* + * Creates decorator with a shared image registry. + * + * @param registry The registry to use or null to use the + * Java plugin's image registry. + */ + /** + * Note: This constructor is for internal use only. Clients should not call + * this constructor. + */ + public ProblemsLabelDecorator(ImageDescriptorRegistry registry) { + fRegistry = registry; + fProblemChangedListener = null; + } + + private ImageDescriptorRegistry getRegistry() { + if (fRegistry == null) { + fRegistry = fUseNewRegistry ? new ImageDescriptorRegistry() + : PHPeclipsePlugin.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(); + return getRegistry().get( + new JavaElementImageDescriptor(baseImage, adornmentFlags, + new Point(bounds.width, bounds.height))); + } + return image; + } + + /** + * Note: This method is for internal use only. Clients should not call this + * method. + */ + protected int computeAdornmentFlags(Object obj) { + try { + if (obj instanceof IJavaElement) { + IJavaElement element = (IJavaElement) obj; + int type = element.getElementType(); + switch (type) { + case IJavaElement.JAVA_PROJECT: + case IJavaElement.PACKAGE_FRAGMENT_ROOT: + return getErrorTicksFromMarkers(element.getResource(), + IResource.DEPTH_INFINITE, null); + case IJavaElement.PACKAGE_FRAGMENT: + case IJavaElement.CLASS_FILE: + return getErrorTicksFromMarkers(element.getResource(), + IResource.DEPTH_ONE, null); + case IJavaElement.COMPILATION_UNIT: + case IJavaElement.PACKAGE_DECLARATION: + case IJavaElement.IMPORT_DECLARATION: + case IJavaElement.IMPORT_CONTAINER: + case IJavaElement.TYPE: + case IJavaElement.INITIALIZER: + case IJavaElement.METHOD: + case IJavaElement.FIELD: + ICompilationUnit cu = (ICompilationUnit) element + .getAncestor(IJavaElement.COMPILATION_UNIT); + if (cu != null) { + ISourceReference ref = (type == IJavaElement.COMPILATION_UNIT) ? null + : (ISourceReference) element; + // The assumption is that only source elements in + // compilation unit can have markers + if (cu.isWorkingCopy()) { + // working copy: look at annotation model + return getErrorTicksFromWorkingCopy( + (ICompilationUnit) cu.getOriginalElement(), + ref); + } + return getErrorTicksFromMarkers(cu.getResource(), + IResource.DEPTH_ONE, ref); + } + break; + default: + } + } else if (obj instanceof IResource) { + return getErrorTicksFromMarkers((IResource) obj, + IResource.DEPTH_INFINITE, null); + } + } catch (CoreException e) { + if (e instanceof JavaModelException) { + if (((JavaModelException) e).isDoesNotExist()) { + return 0; + } + } + PHPeclipsePlugin.log(e); + } + return 0; + } + + 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]; + if (sourceElement == null + || isMarkerInRange(curr, sourceElement)) { + 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; + } + + private boolean isMarkerInRange(IMarker marker, + ISourceReference sourceElement) throws CoreException { + if (marker.isSubtypeOf(IMarker.TEXT)) { + int pos = marker.getAttribute(IMarker.CHAR_START, -1); + return isInside(pos, sourceElement); + } + return false; + } + + private int getErrorTicksFromWorkingCopy(ICompilationUnit original, + ISourceReference sourceElement) throws CoreException { + int info = 0; + FileEditorInput editorInput = new FileEditorInput((IFile) original + .getResource()); + IAnnotationModel model = PHPeclipsePlugin.getDefault() + .getCompilationUnitDocumentProvider().getAnnotationModel( + editorInput); + if (model != null) { + Iterator iter = model.getAnnotationIterator(); + while ((info != ERRORTICK_ERROR) && iter.hasNext()) { + Annotation curr = (Annotation) iter.next(); + IMarker marker = isAnnotationInRange(model, curr, sourceElement); + if (marker != null) { + int priority = marker.getAttribute(IMarker.SEVERITY, -1); + if (priority == IMarker.SEVERITY_WARNING) { + info = ERRORTICK_WARNING; + } else if (priority == IMarker.SEVERITY_ERROR) { + info = ERRORTICK_ERROR; + } + } + } + } + return info; + } + + private IMarker isAnnotationInRange(IAnnotationModel model, + Annotation annot, ISourceReference sourceElement) + throws CoreException { + if (annot instanceof MarkerAnnotation) { + IMarker marker = ((MarkerAnnotation) annot).getMarker(); + if (marker.exists() && marker.isSubtypeOf(IMarker.PROBLEM)) { + Position pos = model.getPosition(annot); + if (sourceElement == null + || isInside(pos.getOffset(), sourceElement)) { + return marker; + } + } + } + return null; + } + + /** + * Tests if a position is inside the source range of an element. + * + * @param pos + * Position to be tested. + * @param sourceElement + * Source element (must be a IJavaElement) + * @return boolean Return true if position is located inside + * the source element. + * @throws CoreException + * Exception thrown if element range could not be accessed. + * + * @since 2.1 + */ + protected boolean isInside(int pos, ISourceReference sourceElement) + throws CoreException { + ISourceRange range = sourceElement.getSourceRange(); + if (range != null) { + int rangeOffset = range.getOffset(); + return (rangeOffset <= pos && rangeOffset + range.getLength() > pos); + } + return false; + } + + /* + * (non-Javadoc) + * + * @see IBaseLabelProvider#dispose() + */ + public void dispose() { + if (fProblemChangedListener != null) { + PHPeclipsePlugin.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); + } + }; + PHPeclipsePlugin.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) { + PHPeclipsePlugin.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(PHPUiImages.DESC_OVR_ERROR); + } else if (adornmentFlags == ERRORTICK_WARNING) { + decoration.addOverlay(PHPUiImages.DESC_OVR_WARNING); + } + } + +}