KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > ui > ProblemsLabelDecorator


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.ui;
12
13 import java.util.Iterator JavaDoc;
14
15 import org.eclipse.core.runtime.CoreException;
16 import org.eclipse.core.runtime.ListenerList;
17
18 import org.eclipse.core.resources.IFile;
19 import org.eclipse.core.resources.IMarker;
20 import org.eclipse.core.resources.IResource;
21 import org.eclipse.core.resources.IResourceStatus;
22
23 import org.eclipse.swt.graphics.Image;
24 import org.eclipse.swt.graphics.Point;
25 import org.eclipse.swt.graphics.Rectangle;
26
27 import org.eclipse.jface.resource.ImageDescriptor;
28 import org.eclipse.jface.viewers.IBaseLabelProvider;
29 import org.eclipse.jface.viewers.IDecoration;
30 import org.eclipse.jface.viewers.ILabelDecorator;
31 import org.eclipse.jface.viewers.ILabelProviderListener;
32 import org.eclipse.jface.viewers.ILightweightLabelDecorator;
33 import org.eclipse.jface.viewers.LabelProviderChangedEvent;
34
35 import org.eclipse.jface.text.Position;
36 import org.eclipse.jface.text.source.Annotation;
37 import org.eclipse.jface.text.source.IAnnotationModel;
38
39 import org.eclipse.ui.part.FileEditorInput;
40 import org.eclipse.ui.texteditor.MarkerAnnotation;
41
42 import org.eclipse.jdt.core.ICompilationUnit;
43 import org.eclipse.jdt.core.IJavaElement;
44 import org.eclipse.jdt.core.ISourceRange;
45 import org.eclipse.jdt.core.ISourceReference;
46 import org.eclipse.jdt.core.JavaModelException;
47
48 import org.eclipse.jdt.internal.ui.JavaPlugin;
49 import org.eclipse.jdt.internal.ui.JavaPluginImages;
50 import org.eclipse.jdt.internal.ui.viewsupport.IProblemChangedListener;
51 import org.eclipse.jdt.internal.ui.viewsupport.ImageDescriptorRegistry;
52 import org.eclipse.jdt.internal.ui.viewsupport.ImageImageDescriptor;
53
54 /**
55  * LabelDecorator that decorates an element's image with error and warning overlays that
56  * represent the severity of markers attached to the element's underlying resource. To see
57  * a problem decoration for a marker, the marker needs to be a subtype of <code>IMarker.PROBLEM</code>.
58  * <p>
59  * <b>Important</b>: Although this decorator implements ILightweightLabelDecorator, do not contribute this
60  * class as a decorator to the <code>org.eclipse.ui.decorators</code> extension. Only use this class in your
61  * own views and label providers.
62  *
63  * @since 2.0
64  */

65 public class ProblemsLabelDecorator implements ILabelDecorator, ILightweightLabelDecorator {
66     
67     /**
68      * This is a special <code>LabelProviderChangedEvent</code> carrying additional
69      * information whether the event origins from a maker change.
70      * <p>
71      * <code>ProblemsLabelChangedEvent</code>s are only generated by <code>
72      * ProblemsLabelDecorator</code>s.
73      * </p>
74      */

75     public static class ProblemsLabelChangedEvent extends LabelProviderChangedEvent {
76
77         private static final long serialVersionUID= 1L;
78         
79         private boolean fMarkerChange;
80
81         /**
82          * Note: This constructor is for internal use only. Clients should not call this constructor.
83          *
84          * @param eventSource the base label provider
85          * @param changedResource the changed resources
86          * @param isMarkerChange <code>true</code> if the change is a marker change; otherwise
87          * <code>false</code>
88          */

89         public ProblemsLabelChangedEvent(IBaseLabelProvider eventSource, IResource[] changedResource, boolean isMarkerChange) {
90             super(eventSource, changedResource);
91             fMarkerChange= isMarkerChange;
92         }
93         
94         /**
95          * Returns whether this event origins from marker changes. If <code>false</code> an annotation
96          * model change is the origin. In this case viewers not displaying working copies can ignore these
97          * events.
98          *
99          * @return if this event origins from a marker change.
100          */

101         public boolean isMarkerChange() {
102             return fMarkerChange;
103         }
104
105     }
106
107     private static final int ERRORTICK_WARNING= JavaElementImageDescriptor.WARNING;
108     private static final int ERRORTICK_ERROR= JavaElementImageDescriptor.ERROR;
109
110     private ImageDescriptorRegistry fRegistry;
111     private boolean fUseNewRegistry= false;
112     private IProblemChangedListener fProblemChangedListener;
113     
114     private ListenerList fListeners;
115     private ISourceRange fCachedRange;
116
117     /**
118      * Creates a new <code>ProblemsLabelDecorator</code>.
119      */

120     public ProblemsLabelDecorator() {
121         this(null);
122         fUseNewRegistry= true;
123     }
124     
125     /**
126      * Note: This constructor is for internal use only. Clients should not call this constructor.
127      *
128      * @param registry The registry to use or <code>null</code> to use the Java plugin's
129      * image registry
130      */

131     public ProblemsLabelDecorator(ImageDescriptorRegistry registry) {
132         fRegistry= registry;
133         fProblemChangedListener= null;
134     }
135     
136     private ImageDescriptorRegistry getRegistry() {
137         if (fRegistry == null) {
138             fRegistry= fUseNewRegistry ? new ImageDescriptorRegistry() : JavaPlugin.getImageDescriptorRegistry();
139         }
140         return fRegistry;
141     }
142     
143
144     /* (non-Javadoc)
145      * @see ILabelDecorator#decorateText(String, Object)
146      */

147     public String JavaDoc decorateText(String JavaDoc text, Object JavaDoc element) {
148         return text;
149     }
150
151     /* (non-Javadoc)
152      * @see ILabelDecorator#decorateImage(Image, Object)
153      */

154     public Image decorateImage(Image image, Object JavaDoc obj) {
155         int adornmentFlags= computeAdornmentFlags(obj);
156         if (adornmentFlags != 0) {
157             ImageDescriptor baseImage= new ImageImageDescriptor(image);
158             Rectangle bounds= image.getBounds();
159             return getRegistry().get(new JavaElementImageDescriptor(baseImage, adornmentFlags, new Point(bounds.width, bounds.height)));
160         }
161         return image;
162     }
163
164     /**
165      * Note: This method is for internal use only. Clients should not call this method.
166      *
167      * @param obj the element to compute the flags for
168      *
169      * @return the adornment flags
170      */

171     protected int computeAdornmentFlags(Object JavaDoc obj) {
172         try {
173             if (obj instanceof IJavaElement) {
174                 IJavaElement element= (IJavaElement) obj;
175                 int type= element.getElementType();
176                 switch (type) {
177                     case IJavaElement.JAVA_MODEL:
178                     case IJavaElement.JAVA_PROJECT:
179                     case IJavaElement.PACKAGE_FRAGMENT_ROOT:
180                         return getErrorTicksFromMarkers(element.getResource(), IResource.DEPTH_INFINITE, null);
181                     case IJavaElement.PACKAGE_FRAGMENT:
182                     case IJavaElement.COMPILATION_UNIT:
183                     case IJavaElement.CLASS_FILE:
184                         return getErrorTicksFromMarkers(element.getResource(), IResource.DEPTH_ONE, null);
185                     case IJavaElement.PACKAGE_DECLARATION:
186                     case IJavaElement.IMPORT_DECLARATION:
187                     case IJavaElement.IMPORT_CONTAINER:
188                     case IJavaElement.TYPE:
189                     case IJavaElement.INITIALIZER:
190                     case IJavaElement.METHOD:
191                     case IJavaElement.FIELD:
192                     case IJavaElement.LOCAL_VARIABLE:
193                         ICompilationUnit cu= (ICompilationUnit) element.getAncestor(IJavaElement.COMPILATION_UNIT);
194                         if (cu != null) {
195                             ISourceReference ref= (type == IJavaElement.COMPILATION_UNIT) ? null : (ISourceReference) element;
196                             // The assumption is that only source elements in compilation unit can have markers
197
IAnnotationModel model= isInJavaAnnotationModel(cu);
198                             int result= 0;
199                             if (model != null) {
200                                 // open in Java editor: look at annotation model
201
result= getErrorTicksFromAnnotationModel(model, ref);
202                             } else {
203                                 result= getErrorTicksFromMarkers(cu.getResource(), IResource.DEPTH_ONE, ref);
204                             }
205                             fCachedRange= null;
206                             return result;
207                         }
208                         break;
209                     default:
210                 }
211             } else if (obj instanceof IResource) {
212                 return getErrorTicksFromMarkers((IResource) obj, IResource.DEPTH_INFINITE, null);
213             }
214         } catch (CoreException e) {
215             if (e instanceof JavaModelException) {
216                 if (((JavaModelException) e).isDoesNotExist()) {
217                     return 0;
218                 }
219             }
220             if (e.getStatus().getCode() == IResourceStatus.MARKER_NOT_FOUND) {
221                 return 0;
222             }
223             
224             JavaPlugin.log(e);
225         }
226         return 0;
227     }
228
229     private int getErrorTicksFromMarkers(IResource res, int depth, ISourceReference sourceElement) throws CoreException {
230         if (res == null || !res.isAccessible()) {
231             return 0;
232         }
233         int severity= 0;
234         if (sourceElement == null) {
235             severity= res.findMaxProblemSeverity(IMarker.PROBLEM, true, depth);
236         } else {
237             IMarker[] markers= res.findMarkers(IMarker.PROBLEM, true, depth);
238             if (markers != null && markers.length > 0) {
239                 for (int i= 0; i < markers.length && (severity != IMarker.SEVERITY_ERROR); i++) {
240                     IMarker curr= markers[i];
241                     if (isMarkerInRange(curr, sourceElement)) {
242                         int val= curr.getAttribute(IMarker.SEVERITY, -1);
243                         if (val == IMarker.SEVERITY_WARNING || val == IMarker.SEVERITY_ERROR) {
244                             severity= val;
245                         }
246                     }
247                 }
248             }
249         }
250         if (severity == IMarker.SEVERITY_ERROR) {
251             return ERRORTICK_ERROR;
252         } else if (severity == IMarker.SEVERITY_WARNING) {
253             return ERRORTICK_WARNING;
254         }
255         return 0;
256     }
257
258     private boolean isMarkerInRange(IMarker marker, ISourceReference sourceElement) throws CoreException {
259         if (marker.isSubtypeOf(IMarker.TEXT)) {
260             int pos= marker.getAttribute(IMarker.CHAR_START, -1);
261             return isInside(pos, sourceElement);
262         }
263         return false;
264     }
265     
266     private IAnnotationModel isInJavaAnnotationModel(ICompilationUnit original) {
267         if (original.isWorkingCopy()) {
268             FileEditorInput editorInput= new FileEditorInput((IFile) original.getResource());
269             return JavaPlugin.getDefault().getCompilationUnitDocumentProvider().getAnnotationModel(editorInput);
270         }
271         return null;
272     }
273     
274     
275     private int getErrorTicksFromAnnotationModel(IAnnotationModel model, ISourceReference sourceElement) throws CoreException {
276         int info= 0;
277         Iterator JavaDoc iter= model.getAnnotationIterator();
278         while ((info != ERRORTICK_ERROR) && iter.hasNext()) {
279             Annotation annot= (Annotation) iter.next();
280             IMarker marker= isAnnotationInRange(model, annot, sourceElement);
281             if (marker != null) {
282                 int priority= marker.getAttribute(IMarker.SEVERITY, -1);
283                 if (priority == IMarker.SEVERITY_WARNING) {
284                     info= ERRORTICK_WARNING;
285                 } else if (priority == IMarker.SEVERITY_ERROR) {
286                     info= ERRORTICK_ERROR;
287                 }
288             }
289         }
290         return info;
291     }
292             
293     private IMarker isAnnotationInRange(IAnnotationModel model, Annotation annot, ISourceReference sourceElement) throws CoreException {
294         if (annot instanceof MarkerAnnotation) {
295             if (sourceElement == null || isInside(model.getPosition(annot), sourceElement)) {
296                 IMarker marker= ((MarkerAnnotation) annot).getMarker();
297                 if (marker.exists() && marker.isSubtypeOf(IMarker.PROBLEM)) {
298                     return marker;
299                 }
300             }
301         }
302         return null;
303     }
304     
305     private boolean isInside(Position pos, ISourceReference sourceElement) throws CoreException {
306         return pos != null && isInside(pos.getOffset(), sourceElement);
307     }
308     
309     /**
310      * Tests if a position is inside the source range of an element.
311      * @param pos Position to be tested.
312      * @param sourceElement Source element (must be a IJavaElement)
313      * @return boolean Return <code>true</code> if position is located inside the source element.
314      * @throws CoreException Exception thrown if element range could not be accessed.
315      *
316      * @since 2.1
317      */

318     protected boolean isInside(int pos, ISourceReference sourceElement) throws CoreException {
319         if (fCachedRange == null) {
320             fCachedRange= sourceElement.getSourceRange();
321         }
322         ISourceRange range= fCachedRange;
323         if (range != null) {
324             int rangeOffset= range.getOffset();
325             return (rangeOffset <= pos && rangeOffset + range.getLength() > pos);
326         }
327         return false;
328     }
329     
330     /* (non-Javadoc)
331      * @see IBaseLabelProvider#dispose()
332      */

333     public void dispose() {
334         if (fProblemChangedListener != null) {
335             JavaPlugin.getDefault().getProblemMarkerManager().removeListener(fProblemChangedListener);
336             fProblemChangedListener= null;
337         }
338         if (fRegistry != null && fUseNewRegistry) {
339             fRegistry.dispose();
340         }
341     }
342
343     /* (non-Javadoc)
344      * @see IBaseLabelProvider#isLabelProperty(Object, String)
345      */

346     public boolean isLabelProperty(Object JavaDoc element, String JavaDoc property) {
347         return true;
348     }
349     
350     /* (non-Javadoc)
351      * @see IBaseLabelProvider#addListener(ILabelProviderListener)
352      */

353     public void addListener(ILabelProviderListener listener) {
354         if (fListeners == null) {
355             fListeners= new ListenerList();
356         }
357         fListeners.add(listener);
358         if (fProblemChangedListener == null) {
359             fProblemChangedListener= new IProblemChangedListener() {
360                 public void problemsChanged(IResource[] changedResources, boolean isMarkerChange) {
361                     fireProblemsChanged(changedResources, isMarkerChange);
362                 }
363             };
364             JavaPlugin.getDefault().getProblemMarkerManager().addListener(fProblemChangedListener);
365         }
366     }
367
368     /* (non-Javadoc)
369      * @see IBaseLabelProvider#removeListener(ILabelProviderListener)
370      */

371     public void removeListener(ILabelProviderListener listener) {
372         if (fListeners != null) {
373             fListeners.remove(listener);
374             if (fListeners.isEmpty() && fProblemChangedListener != null) {
375                 JavaPlugin.getDefault().getProblemMarkerManager().removeListener(fProblemChangedListener);
376                 fProblemChangedListener= null;
377             }
378         }
379     }
380     
381     private void fireProblemsChanged(IResource[] changedResources, boolean isMarkerChange) {
382         if (fListeners != null && !fListeners.isEmpty()) {
383             LabelProviderChangedEvent event= new ProblemsLabelChangedEvent(this, changedResources, isMarkerChange);
384             Object JavaDoc[] listeners= fListeners.getListeners();
385             for (int i= 0; i < listeners.length; i++) {
386                 ((ILabelProviderListener) listeners[i]).labelProviderChanged(event);
387             }
388         }
389     }
390         
391     /* (non-Javadoc)
392      * @see org.eclipse.jface.viewers.ILightweightLabelDecorator#decorate(java.lang.Object, org.eclipse.jface.viewers.IDecoration)
393      */

394     public void decorate(Object JavaDoc element, IDecoration decoration) {
395         int adornmentFlags= computeAdornmentFlags(element);
396         if (adornmentFlags == ERRORTICK_ERROR) {
397             decoration.addOverlay(JavaPluginImages.DESC_OVR_ERROR);
398         } else if (adornmentFlags == ERRORTICK_WARNING) {
399             decoration.addOverlay(JavaPluginImages.DESC_OVR_WARNING);
400         }
401     }
402
403 }
404
Popular Tags