Method: decorateText(String, Object)
1: /*
2: * #%~
3: * org.overture.ide.ui
4: * %%
5: * Copyright (C) 2008 - 2014 Overture
6: * %%
7: * This program is free software: you can redistribute it and/or modify
8: * it under the terms of the GNU General Public License as
9: * published by the Free Software Foundation, either version 3 of the
10: * License, or (at your option) any later version.
11: *
12: * This program is distributed in the hope that it will be useful,
13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: * GNU General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public
18: * License along with this program. If not, see
19: * <http://www.gnu.org/licenses/gpl-3.0.html>.
20: * #~%
21: */
22: package org.overture.ide.ui;
23:
24: import org.eclipse.core.resources.IResource;
25: import org.eclipse.core.runtime.ListenerList;
26: import org.eclipse.jface.resource.ImageDescriptor;
27: import org.eclipse.jface.viewers.IBaseLabelProvider;
28: import org.eclipse.jface.viewers.IDecoration;
29: import org.eclipse.jface.viewers.ILabelDecorator;
30: import org.eclipse.jface.viewers.ILabelProviderListener;
31: import org.eclipse.jface.viewers.ILightweightLabelDecorator;
32: import org.eclipse.jface.viewers.LabelProviderChangedEvent;
33: import org.eclipse.swt.graphics.Image;
34: import org.eclipse.swt.graphics.Point;
35: import org.eclipse.swt.graphics.Rectangle;
36: import org.overture.ide.core.IVdmElement;
37: import org.overture.ide.ui.internal.viewsupport.IProblemChangedListener;
38: import org.overture.ide.ui.internal.viewsupport.ImageDescriptorRegistry;
39: import org.overture.ide.ui.internal.viewsupport.ImageImageDescriptor;
40: import org.overture.ide.ui.internal.viewsupport.VdmElementImageDescriptor;
41:
42: /**
43: * LabelDecorator that decorates an element's image with error and warning overlays that represent the
44: * severity of markers attached to the element's underlying resource. To see a problem decoration for a
45: * marker, the marker needs to be a subtype of <code>IMarker.PROBLEM</code>.
46: * <p>
47: * <b>Important</b>: Although this decorator implements ILightweightLabelDecorator, do not contribute this
48: * class as a decorator to the <code>org.eclipse.ui.decorators</code> extension. Only use this class in your
49: * own views and label providers.
50: *
51: * @since 2.0
52: */
53: public class VdmProblemsLabelDecorator implements ILabelDecorator,
54:                 ILightweightLabelDecorator
55: {
56:
57:         /**
58:          * This is a special <code>LabelProviderChangedEvent</code> carrying additional information whether the
59:          * event origins from a maker change.
60:          * <p>
61:          * <code>ProblemsLabelChangedEvent</code>s are only generated by <code>
62:          * ProblemsLabelDecorator</code>s.
63:          * </p>
64:          */
65:         public static class ProblemsLabelChangedEvent extends
66:                         LabelProviderChangedEvent
67:         {
68:
69:                 private static final long serialVersionUID = 1L;
70:
71:                 private boolean fMarkerChange;
72:
73:                 /**
74:                  * @param eventSource
75:                  * the base label provider
76:                  * @param changedResource
77:                  * the changed resources
78:                  * @param isMarkerChange
79:                  * <code>true</code> if the change is a marker change; otherwise <code>false</code>
80:                  */
81:                 public ProblemsLabelChangedEvent(IBaseLabelProvider eventSource,
82:                                 IResource[] changedResource, boolean isMarkerChange) {
83:                         super(eventSource, changedResource);
84:                         fMarkerChange = isMarkerChange;
85:                 }
86:
87:                 /**
88:                  * Returns whether this event origins from marker changes. If <code>false</code> an annotation model
89:                  * change is the origin. In this case viewers not displaying working copies can ignore these events.
90:                  *
91:                  * @return if this event origins from a marker change.
92:                  */
93:                 public boolean isMarkerChange()
94:                 {
95:                         return fMarkerChange;
96:                 }
97:
98:         }
99:
100:         private static final int ERRORTICK_WARNING = VdmElementImageDescriptor.WARNING;
101:         private static final int ERRORTICK_ERROR = VdmElementImageDescriptor.ERROR;
102:
103:         private ImageDescriptorRegistry fRegistry;
104:         private boolean fUseNewRegistry = false;
105:         private IProblemChangedListener fProblemChangedListener;
106:
107:         private ListenerList fListeners;
108:
109:         // private ISourceRange fCachedRange;
110:
111:         /**
112:          * Creates a new <code>ProblemsLabelDecorator</code>.
113:          */
114:         public VdmProblemsLabelDecorator() {
115:                 this(null);
116:                 fUseNewRegistry = true;
117:         }
118:
119:         /**
120:          * Note: This constructor is for internal use only. Clients should not call this constructor.
121:          *
122:          * @param registry
123:          * The registry to use or <code>null</code> to use the Java plugin's image registry
124:          * @noreference This constructor is not intended to be referenced by clients.
125:          */
126:         public VdmProblemsLabelDecorator(ImageDescriptorRegistry registry) {
127:                 fRegistry = registry;
128:                 fProblemChangedListener = null;
129:         }
130:
131:         private ImageDescriptorRegistry getRegistry()
132:         {
133:                 if (fRegistry == null)
134:                 {
135:                         fRegistry = fUseNewRegistry ? new ImageDescriptorRegistry()
136:                                         : VdmUIPlugin.getImageDescriptorRegistry();
137:                 }
138:                 return fRegistry;
139:         }
140:
141:         /*
142:          * (non-Javadoc)
143:          *
144:          * @see ILabelDecorator#decorateText(String, Object)
145:          */
146:         public String decorateText(String text, Object element)
147:         {
148:                 return text;
149:         }
150:
151:         /*
152:          * (non-Javadoc)
153:          *
154:          * @see ILabelDecorator#decorateImage(Image, Object)
155:          */
156:         public Image decorateImage(Image image, Object obj)
157:         {
158:                 if (image == null)
159:                         return null;
160:
161:                 int adornmentFlags = computeAdornmentFlags(obj);
162:                 if (adornmentFlags != 0)
163:                 {
164:                         ImageDescriptor baseImage = new ImageImageDescriptor(image);
165:                         Rectangle bounds = image.getBounds();
166:                         return getRegistry().get(new VdmElementImageDescriptor(baseImage,
167:                                         0,
168:                                         new Point(bounds.width, bounds.height)));
169:                 }
170:                 return image;
171:         }
172:
173:         /**
174:          * Computes the adornment flags for the given element.
175:          *
176:          * @param obj
177:          * the element to compute the flags for
178:          *
179:          * @return the adornment flags
180:          */
181:         protected int computeAdornmentFlags(Object obj)
182:         {
183: //                try
184: //                {
185:                         if (obj instanceof IVdmElement)
186:                         {
187:                                 IVdmElement element = (IVdmElement) obj;
188:                                 int type = element.getElementType();
189:                                 switch (type)
190:                                 {
191:                                 case IVdmElement.VDM_MODEL:
192:                                 case IVdmElement.VDM_PROJECT:
193:                                         // case IVdmElement.PACKAGE_FRAGMENT_ROOT:
194:                                         // return getErrorTicksFromMarkers(element.getResource(), IResource.DEPTH_INFINITE, null);
195:                                         // case IVdmElement.PACKAGE_FRAGMENT:
196:                                 case IVdmElement.COMPILATION_UNIT:
197:                                         // case IVdmElement.CLASS_FILE:
198:                                         // return getErrorTicksFromMarkers(element.getResource(), IResource.DEPTH_ONE, null);
199:                                         // case IVdmElement.PACKAGE_DECLARATION:
200:                                         // case IVdmElement.IMPORT_DECLARATION:
201:                                         // case IVdmElement.IMPORT_CONTAINER:
202:                                 case IVdmElement.TYPE:
203:                                 case IVdmElement.INITIALIZER:
204:                                 case IVdmElement.METHOD:
205:                                 case IVdmElement.FIELD:
206:                                         // case IVdmElement.LOCAL_VARIABLE:
207:                                         // ICompilationUnit cu= (ICompilationUnit)
208:                                         // element.getAncestor(IVdmElement.COMPILATION_UNIT);
209:                                         // if (cu != null) {
210:                                         // ISourceReference ref= (type == IVdmElement.COMPILATION_UNIT) ? null :
211:                                         // (ISourceReference) element;
212:                                         // // The assumption is that only source elements in compilation unit can have markers
213:                                         // IAnnotationModel model= isInJavaAnnotationModel(cu);
214:                                         // int result= 0;
215:                                         // if (model != null) {
216:                                         // // open in Java editor: look at annotation model
217:                                         // result= getErrorTicksFromAnnotationModel(model, ref);
218:                                         // } else {
219:                                         // result= getErrorTicksFromMarkers(cu.getResource(), IResource.DEPTH_ONE, ref);
220:                                         // }
221:                                         // fCachedRange= null;
222:                                         // return result;
223:                                         // }
224:                                         break;
225:                                 default:
226:                                 }
227:                         }
228: //                        else if (obj instanceof IResource)
229: //                        {
230: //                                return getErrorTicksFromMarkers((IResource) obj,
231: //                                                IResource.DEPTH_INFINITE,
232: //                                                null);
233: //                        }
234: //                } catch (CoreException e)
235: //                {
236: //                        if (e instanceof VdmModelException)
237: //                        {
238: //                                if (((VdmModelException) e).isDoesNotExist())
239: //                                {
240: //                                        return 0;
241: //                                }
242: //                        }
243: //                        if (e.getStatus().getCode() == IResourceStatus.MARKER_NOT_FOUND)
244: //                        {
245: //                                return 0;
246: //                        }
247: //
248: //                        VdmUIPlugin.log(e);
249: //                }
250:                 return 0;
251:         }
252:
253: //        private int getErrorTicksFromMarkers(IResource res, int depth,
254: //                        ISourceReference sourceElement) throws CoreException
255: //        {
256: //                if (res == null || !res.isAccessible())
257: //                {
258: //                        return 0;
259: //                }
260: //                int severity = 0;
261: //                if (sourceElement == null)
262: //                {
263: //                        severity = res.findMaxProblemSeverity(IMarker.PROBLEM, true, depth);
264: //                } else
265: //                {
266: //                        IMarker[] markers = res.findMarkers(IMarker.PROBLEM, true, depth);
267: //                        if (markers != null && markers.length > 0)
268: //                        {
269: //                                for (int i = 0; i < markers.length
270: //                                                && (severity != IMarker.SEVERITY_ERROR); i++)
271: //                                {
272: //                                        IMarker curr = markers[i];
273: //                                        if (isMarkerInRange(curr, sourceElement))
274: //                                        {
275: //                                                int val = curr.getAttribute(IMarker.SEVERITY, -1);
276: //                                                if (val == IMarker.SEVERITY_WARNING
277: //                                                                || val == IMarker.SEVERITY_ERROR)
278: //                                                {
279: //                                                        severity = val;
280: //                                                }
281: //                                        }
282: //                                }
283: //                        }
284: //                }
285: //                if (severity == IMarker.SEVERITY_ERROR)
286: //                {
287: //                        return ERRORTICK_ERROR;
288: //                } else if (severity == IMarker.SEVERITY_WARNING)
289: //                {
290: //                        return ERRORTICK_WARNING;
291: //                }
292: //                return 0;
293: //        }
294: //
295: //        private boolean isMarkerInRange(IMarker marker,
296: //                        ISourceReference sourceElement) throws CoreException
297: //        {
298: //                if (marker.isSubtypeOf(IMarker.TEXT))
299: //                {
300: //                        int pos = marker.getAttribute(IMarker.CHAR_START, -1);
301: //                        return isInside(pos, sourceElement);
302: //                }
303: //                return false;
304: //        }
305:
306:         // private IAnnotationModel isInJavaAnnotationModel(ICompilationUnit original) {
307:         // if (original.isWorkingCopy()) {
308:         // FileEditorInput editorInput= new FileEditorInput((IFile) original.getResource());
309:         // //return JavaPlugin.getDefault().getCompilationUnitDocumentProvider().getAnnotationModel(editorInput);
310:         // }
311:         // return null;
312:         // }
313:
314: //        private int getErrorTicksFromAnnotationModel(IAnnotationModel model,
315: //                        ISourceReference sourceElement) throws CoreException
316: //        {
317: //                int info = 0;
318: //                Iterator iter = model.getAnnotationIterator();
319: //                while ((info != ERRORTICK_ERROR) && iter.hasNext())
320: //                {
321: //                        Annotation annot = (Annotation) iter.next();
322: //                        IMarker marker = isAnnotationInRange(model, annot, sourceElement);
323: //                        if (marker != null)
324: //                        {
325: //                                int priority = marker.getAttribute(IMarker.SEVERITY, -1);
326: //                                if (priority == IMarker.SEVERITY_WARNING)
327: //                                {
328: //                                        info = ERRORTICK_WARNING;
329: //                                } else if (priority == IMarker.SEVERITY_ERROR)
330: //                                {
331: //                                        info = ERRORTICK_ERROR;
332: //                                }
333: //                        }
334: //                }
335: //                return info;
336: //        }
337: //
338: //        private IMarker isAnnotationInRange(IAnnotationModel model,
339: //                        Annotation annot, ISourceReference sourceElement)
340: //                        throws CoreException
341: //        {
342: //                if (annot instanceof MarkerAnnotation)
343: //                {
344: //                        if (sourceElement == null
345: //                                        || isInside(model.getPosition(annot), sourceElement))
346: //                        {
347: //                                IMarker marker = ((MarkerAnnotation) annot).getMarker();
348: //                                if (marker.exists() && marker.isSubtypeOf(IMarker.PROBLEM))
349: //                                {
350: //                                        return marker;
351: //                                }
352: //                        }
353: //                }
354: //                return null;
355: //        }
356: //
357: //        private boolean isInside(Position pos, ISourceReference sourceElement)
358: //                        throws CoreException
359: //        {
360: //                return pos != null && isInside(pos.getOffset(), sourceElement);
361: //        }
362: //
363: //        /**
364: //         * Tests if a position is inside the source range of an element.
365: //         *
366: //         * @param pos
367: //         * Position to be tested.
368: //         * @param sourceElement
369: //         * Source element (must be a IVdmElement)
370: //         * @return boolean Return <code>true</code> if position is located inside the source element.
371: //         * @throws CoreException
372: //         * Exception thrown if element range could not be accessed.
373: //         *
374: //         * @since 2.1
375: //         */
376: //        protected boolean isInside(int pos, ISourceReference sourceElement)
377: //                        throws CoreException
378: //        {
379: //                if (fCachedRange == null)
380: //                {
381: //                        fCachedRange = sourceElement.getSourceRange();
382: //                }
383: //                ISourceRange range = fCachedRange;
384: //                if (range != null)
385: //                {
386: //                        int rangeOffset = range.getOffset();
387: //                        return (rangeOffset <= pos && rangeOffset + range.getLength() > pos);
388: //                }
389: //                return false;
390: //        }
391:
392:         /*
393:          * (non-Javadoc)
394:          *
395:          * @see IBaseLabelProvider#dispose()
396:          */
397:         public void dispose()
398:         {
399:                 if (fProblemChangedListener != null)
400:                 {
401:                         VdmUIPlugin.getDefault()
402:                                         .getProblemMarkerManager()
403:                                         .removeListener(fProblemChangedListener);
404:                         fProblemChangedListener = null;
405:                 }
406:                 if (fRegistry != null && fUseNewRegistry)
407:                 {
408:                         fRegistry.dispose();
409:                 }
410:         }
411:
412:         /*
413:          * (non-Javadoc)
414:          *
415:          * @see IBaseLabelProvider#isLabelProperty(Object, String)
416:          */
417:         public boolean isLabelProperty(Object element, String property)
418:         {
419:                 return true;
420:         }
421:
422:         /*
423:          * (non-Javadoc)
424:          *
425:          * @see IBaseLabelProvider#addListener(ILabelProviderListener)
426:          */
427:         public void addListener(ILabelProviderListener listener)
428:         {
429:                 if (fListeners == null)
430:                 {
431:                         fListeners = new ListenerList();
432:                 }
433:                 fListeners.add(listener);
434:                 if (fProblemChangedListener == null)
435:                 {
436:                         fProblemChangedListener = new IProblemChangedListener() {
437:                                 public void problemsChanged(IResource[] changedResources,
438:                                                 boolean isMarkerChange)
439:                                 {
440:                                         fireProblemsChanged(changedResources, isMarkerChange);
441:                                 }
442:                         };
443:                         VdmUIPlugin.getDefault()
444:                                         .getProblemMarkerManager()
445:                                         .addListener(fProblemChangedListener);
446:                 }
447:         }
448:
449:         /*
450:          * (non-Javadoc)
451:          *
452:          * @see IBaseLabelProvider#removeListener(ILabelProviderListener)
453:          */
454:         public void removeListener(ILabelProviderListener listener)
455:         {
456:                 if (fListeners != null)
457:                 {
458:                         fListeners.remove(listener);
459:                         if (fListeners.isEmpty() && fProblemChangedListener != null)
460:                         {
461:                                 VdmUIPlugin.getDefault()
462:                                                 .getProblemMarkerManager()
463:                                                 .removeListener(fProblemChangedListener);
464:                                 fProblemChangedListener = null;
465:                         }
466:                 }
467:         }
468:
469:         private void fireProblemsChanged(IResource[] changedResources,
470:                         boolean isMarkerChange)
471:         {
472:                 if (fListeners != null && !fListeners.isEmpty())
473:                 {
474:                         LabelProviderChangedEvent event = new ProblemsLabelChangedEvent(this,
475:                                         changedResources,
476:                                         isMarkerChange);
477:                         Object[] listeners = fListeners.getListeners();
478:                         for (int i = 0; i < listeners.length; i++)
479:                         {
480:                                 ((ILabelProviderListener) listeners[i]).labelProviderChanged(event);
481:                         }
482:                 }
483:         }
484:
485:         /*
486:          * (non-Javadoc)
487:          *
488:          * @see org.eclipse.jface.viewers.ILightweightLabelDecorator#decorate(java.lang.Object,
489:          * org.eclipse.jface.viewers.IDecoration)
490:          */
491:         public void decorate(Object element, IDecoration decoration)
492:         {
493:                 int adornmentFlags = computeAdornmentFlags(element);
494:                 if (adornmentFlags == ERRORTICK_ERROR)
495:                 {
496:                         decoration.addOverlay(VdmPluginImages.DESC_OVR_ERROR);
497:                 } else if (adornmentFlags == ERRORTICK_WARNING)
498:                 {
499:                         decoration.addOverlay(VdmPluginImages.DESC_OVR_WARNING);
500:                 }
501:         }
502:
503: }