001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.texteditor;
011:
012: import java.lang.reflect.InvocationTargetException;
013: import java.lang.reflect.Method;
014: import java.util.HashMap;
015: import java.util.Map;
016:
017: import org.eclipse.swt.SWT;
018: import org.eclipse.swt.graphics.GC;
019: import org.eclipse.swt.graphics.Image;
020: import org.eclipse.swt.graphics.Rectangle;
021: import org.eclipse.swt.widgets.Canvas;
022:
023: import org.eclipse.jface.resource.ImageDescriptor;
024: import org.eclipse.jface.resource.ImageRegistry;
025:
026: import org.eclipse.jface.text.quickassist.IQuickAssistAssistant;
027: import org.eclipse.jface.text.quickassist.IQuickFixableAnnotation;
028: import org.eclipse.jface.text.source.Annotation;
029: import org.eclipse.jface.text.source.IAnnotationAccess;
030: import org.eclipse.jface.text.source.IAnnotationAccessExtension;
031: import org.eclipse.jface.text.source.IAnnotationAccessExtension2;
032: import org.eclipse.jface.text.source.IAnnotationPresentation;
033: import org.eclipse.jface.text.source.ImageUtilities;
034:
035: import org.eclipse.ui.ISharedImages;
036: import org.eclipse.ui.PlatformUI;
037: import org.eclipse.ui.ide.IDE;
038: import org.eclipse.ui.internal.editors.text.EditorsPlugin;
039: import org.eclipse.ui.internal.texteditor.AnnotationType;
040: import org.eclipse.ui.internal.texteditor.AnnotationTypeHierarchy;
041:
042: /**
043: * Default class for accessing marker annotation properties.
044: *
045: * @since 2.1
046: */
047: public class DefaultMarkerAnnotationAccess implements
048: IAnnotationAccess, IAnnotationAccessExtension,
049: IAnnotationAccessExtension2 {
050:
051: /**
052: * Constant for the unknown marker type.
053: *
054: * @deprecated As of 3.0, replaced by Annotation.TYPE_UNKNOWN
055: */
056: public static final String UNKNOWN = Annotation.TYPE_UNKNOWN;
057:
058: /**
059: * Constant for the error system image.
060: * Value: <code>error</code>
061: *
062: * @since 3.0
063: */
064: public static final String ERROR_SYSTEM_IMAGE = "error"; //$NON-NLS-1$
065: /**
066: * Constant for the warning system image.
067: * Value: <code>warning</code>
068: *
069: * @since 3.0
070: */
071: public static final String WARNING_SYSTEM_IMAGE = "warning"; //$NON-NLS-1$
072: /**
073: * Constant for the info system image.
074: * Value: <code>info</code>
075: *
076: * @since 3.0
077: */
078: public static final String INFO_SYSTEM_IMAGE = "info"; //$NON-NLS-1$
079: /**
080: * Constant for the task system image.
081: * Value: <code>task</code>
082: *
083: * @since 3.0
084: */
085: public static final String TASK_SYSTEM_IMAGE = "task"; //$NON-NLS-1$
086: /**
087: * Constant for the bookmark system image.
088: * Value: <code>bookmark</code>
089: *
090: * @since 3.0
091: */
092: public static final String BOOKMARK_SYSTEM_IMAGE = "bookmark"; //$NON-NLS-1$
093:
094: /**
095: * The mapping between external and internal symbolic system image names.
096: *
097: * @since 3.0
098: */
099: private final static Map MAPPING;
100:
101: static {
102: MAPPING = new HashMap();
103: MAPPING.put(ERROR_SYSTEM_IMAGE,
104: ISharedImages.IMG_OBJS_ERROR_TSK);
105: MAPPING.put(WARNING_SYSTEM_IMAGE,
106: ISharedImages.IMG_OBJS_WARN_TSK);
107: MAPPING.put(INFO_SYSTEM_IMAGE, ISharedImages.IMG_OBJS_INFO_TSK);
108: MAPPING.put(TASK_SYSTEM_IMAGE,
109: IDE.SharedImages.IMG_OBJS_TASK_TSK);
110: MAPPING.put(BOOKMARK_SYSTEM_IMAGE,
111: IDE.SharedImages.IMG_OBJS_BKMRK_TSK);
112: }
113:
114: /**
115: * The marker annotation preferences.
116: *
117: * @deprecated As of 3.0, no replacement
118: */
119: protected MarkerAnnotationPreferences fMarkerAnnotationPreferences;
120:
121: /**
122: * An optional quick assist processor.
123: *
124: * @since 3.2
125: */
126: private IQuickAssistAssistant fQuickAssistAssistant;
127:
128: /**
129: * Returns a new default marker annotation access with the given preferences.
130: *
131: * @param markerAnnotationPreferences
132: * @deprecated As of 3.0, replaced by {@link org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess#DefaultMarkerAnnotationAccess()}
133: */
134: public DefaultMarkerAnnotationAccess(
135: MarkerAnnotationPreferences markerAnnotationPreferences) {
136: fMarkerAnnotationPreferences = markerAnnotationPreferences;
137: }
138:
139: /**
140: * Creates a new default marker annotation access using the standard
141: * preference lookup strategy which is the one provided by the enclosing
142: * plug-in.
143: *
144: * @since 3.0
145: */
146: public DefaultMarkerAnnotationAccess() {
147: }
148:
149: /*
150: * @see org.eclipse.jface.text.source.IAnnotationAccessExtension2#setQuickAssistAssistant(org.eclipse.jface.text.quickassist.IQuickAssistAssistant)
151: * @since 3.2
152: */
153: public void setQuickAssistAssistant(IQuickAssistAssistant assistant) {
154: fQuickAssistAssistant = assistant;
155: }
156:
157: /**
158: * Returns the annotation preference for the given annotation.
159: *
160: * @param annotation the annotation
161: * @return the annotation preference for the given annotation or <code>null</code>
162: */
163: private AnnotationPreference getAnnotationPreference(
164: Annotation annotation) {
165: AnnotationPreferenceLookup lookup = getAnnotationPreferenceLookup();
166: if (lookup != null)
167: return lookup.getAnnotationPreference(annotation);
168: return null;
169: }
170:
171: /**
172: * Returns the annotation preference lookup used by this annotation access.
173: *
174: * @return the annotation preference lookup
175: * @since 3.0
176: */
177: protected AnnotationPreferenceLookup getAnnotationPreferenceLookup() {
178: return EditorsPlugin.getDefault()
179: .getAnnotationPreferenceLookup();
180: }
181:
182: /*
183: * @see org.eclipse.jface.text.source.IAnnotationAccess#getType(org.eclipse.jface.text.source.Annotation)
184: */
185: public Object getType(Annotation annotation) {
186: return annotation.getType();
187: }
188:
189: /*
190: * @see org.eclipse.jface.text.source.IAnnotationAccess#isMultiLine(org.eclipse.jface.text.source.Annotation)
191: */
192: public boolean isMultiLine(Annotation annotation) {
193: return true;
194: }
195:
196: /*
197: * @see org.eclipse.jface.text.source.IAnnotationAccess#isTemporary(org.eclipse.jface.text.source.Annotation)
198: */
199: public boolean isTemporary(Annotation annotation) {
200: return !annotation.isPersistent();
201: }
202:
203: /*
204: * @see org.eclipse.jface.text.source.IAnnotationAccessExtension#getLabel(org.eclipse.jface.text.source.Annotation)
205: * @since 3.0
206: */
207: public String getTypeLabel(Annotation annotation) {
208: AnnotationPreference preference = getAnnotationPreference(annotation);
209: return preference != null ? preference.getPreferenceLabel()
210: : null;
211: }
212:
213: /*
214: * @see org.eclipse.jface.text.source.IAnnotationAccessExtension#getLayer(org.eclipse.jface.text.source.Annotation)
215: * @since 3.0
216: */
217: public int getLayer(Annotation annotation) {
218: if (annotation instanceof IAnnotationPresentation) {
219: IAnnotationPresentation presentation = (IAnnotationPresentation) annotation;
220: return presentation.getLayer();
221: }
222:
223: AnnotationPreference preference = getAnnotationPreference(annotation);
224: if (preference != null)
225: return preference.getPresentationLayer();
226:
227: // backward compatibility, ignore exceptions, just return default layer
228: try {
229:
230: Method method = annotation.getClass().getMethod(
231: "getLayer", null); //$NON-NLS-1$
232: Integer result = (Integer) method.invoke(annotation, null);
233: return result.intValue();
234:
235: } catch (SecurityException x) {
236: } catch (IllegalArgumentException x) {
237: } catch (NoSuchMethodException x) {
238: } catch (IllegalAccessException x) {
239: } catch (InvocationTargetException x) {
240: }
241:
242: return IAnnotationAccessExtension.DEFAULT_LAYER;
243: }
244:
245: /*
246: * @see org.eclipse.jface.text.source.IAnnotationAccessExtension#paint(org.eclipse.jface.text.source.Annotation, org.eclipse.swt.graphics.GC, org.eclipse.swt.widgets.Canvas, org.eclipse.swt.graphics.Rectangle)
247: * @since 3.0
248: */
249: public void paint(Annotation annotation, GC gc, Canvas canvas,
250: Rectangle bounds) {
251:
252: if (annotation instanceof IAnnotationPresentation) {
253: IAnnotationPresentation presentation = (IAnnotationPresentation) annotation;
254: presentation.paint(gc, canvas, bounds);
255: return;
256: }
257:
258: AnnotationPreference preference = getAnnotationPreference(annotation);
259: if (preference != null) {
260: Object type = getType(annotation);
261: String annotationType = (type == null ? null : type
262: .toString());
263: Image image = getImage(annotation, preference,
264: annotationType);
265: if (image != null) {
266: ImageUtilities.drawImage(image, gc, canvas, bounds,
267: SWT.CENTER, SWT.TOP);
268: return;
269: }
270: }
271:
272: // backward compatibility, ignore exceptions, just don't paint
273: try {
274:
275: Method method = annotation
276: .getClass()
277: .getMethod(
278: "paint", new Class[] { GC.class, Canvas.class, Rectangle.class }); //$NON-NLS-1$
279: method.invoke(annotation,
280: new Object[] { gc, canvas, bounds });
281:
282: } catch (SecurityException x) {
283: } catch (IllegalArgumentException x) {
284: } catch (NoSuchMethodException x) {
285: } catch (IllegalAccessException x) {
286: } catch (InvocationTargetException x) {
287: }
288: }
289:
290: /*
291: * @see org.eclipse.jface.text.source.IAnnotationAccessExtension#isPaintable(org.eclipse.jface.text.source.Annotation)
292: * @since 3.0
293: */
294: public boolean isPaintable(Annotation annotation) {
295: if (annotation instanceof IAnnotationPresentation)
296: return true;
297:
298: AnnotationPreference preference = getAnnotationPreference(annotation);
299: if (preference == null)
300: return false;
301:
302: Object type = getType(annotation);
303: String annotationType = (type == null ? null : type.toString());
304: Image image = getImage(annotation, preference, annotationType);
305: return image != null;
306: }
307:
308: /*
309: * @see org.eclipse.jface.text.source.IAnnotationAccessExtension#isSubtype(java.lang.Object, java.lang.Object)
310: */
311: public boolean isSubtype(Object annotationType,
312: Object potentialSupertype) {
313: AnnotationTypeHierarchy hierarchy = getAnnotationTypeHierarchy();
314: return hierarchy.isSubtype(potentialSupertype.toString(),
315: annotationType.toString());
316: }
317:
318: /*
319: * @see org.eclipse.jface.text.source.IAnnotationAccessExtension#getSupertypes(java.lang.Object)
320: */
321: public Object[] getSupertypes(Object annotationType) {
322: AnnotationTypeHierarchy hierarchy = getAnnotationTypeHierarchy();
323: AnnotationType type = hierarchy
324: .getAnnotationType(annotationType.toString());
325: return type.getSuperTypes();
326: }
327:
328: /**
329: * Returns the annotation type hierarchy used by this annotation access.
330: *
331: * @return the annotation type hierarchy
332: * @since 3.0
333: */
334: protected AnnotationTypeHierarchy getAnnotationTypeHierarchy() {
335: return EditorsPlugin.getDefault().getAnnotationTypeHierarchy();
336: }
337:
338: /**
339: * Translates the given symbolic image name into the according symbolic image name
340: * the {@link org.eclipse.ui.ISharedImages} understands.
341: *
342: * @param symbolicImageName the symbolic system image name to be translated
343: * @return the shared image name
344: * @since 3.0
345: */
346: private String translateSymbolicImageName(String symbolicImageName) {
347: return (String) MAPPING.get(symbolicImageName);
348: }
349:
350: /**
351: * Returns the image for the given annotation and the given annotation preferences or
352: * <code>null</code> if there is no such image.
353: *
354: * @param annotation the annotation
355: * @param preference the annotation preference
356: * @param annotationType the annotation type
357: * @return the image or <code>null</code>
358: * @since 3.0
359: */
360: private Image getImage(Annotation annotation,
361: AnnotationPreference preference, String annotationType) {
362:
363: ImageRegistry registry = EditorsPlugin.getDefault()
364: .getImageRegistry();
365:
366: IAnnotationImageProvider annotationImageProvider = preference
367: .getAnnotationImageProvider();
368: if (annotationImageProvider != null) {
369:
370: Image image = annotationImageProvider
371: .getManagedImage(annotation);
372: if (image != null)
373: return image;
374:
375: String id = annotationImageProvider
376: .getImageDescriptorId(annotation);
377: if (id != null) {
378: image = registry.get(id);
379: if (image == null) {
380: ImageDescriptor descriptor = annotationImageProvider
381: .getImageDescriptor(id);
382: registry.put(id, descriptor);
383: image = registry.get(id);
384: }
385: return image;
386: }
387: }
388:
389: if (annotationType == null)
390: return null;
391:
392: if (hasQuickFix(annotation)) {
393: ImageDescriptor quickFixImageDesc = preference
394: .getQuickFixImageDescriptor();
395: if (quickFixImageDesc != null) {
396: Image image = registry
397: .get(quickFixImageDesc.toString());
398: if (image == null) {
399: registry.put(quickFixImageDesc.toString(),
400: quickFixImageDesc);
401: image = registry.get(quickFixImageDesc.toString());
402: }
403: if (image != null)
404: return image;
405: }
406: }
407:
408: Image image = registry.get(annotationType);
409: if (image == null) {
410: ImageDescriptor descriptor = preference
411: .getImageDescriptor();
412: if (descriptor != null) {
413: registry.put(annotationType, descriptor);
414: image = registry.get(annotationType);
415: } else {
416: String key = translateSymbolicImageName(preference
417: .getSymbolicImageName());
418: if (key != null) {
419: ISharedImages sharedImages = PlatformUI
420: .getWorkbench().getSharedImages();
421: image = sharedImages.getImage(key);
422: }
423: }
424: }
425: return image;
426: }
427:
428: /**
429: * Checks whether there's a quick assist assistant and if so,
430: * whether the assistant has a possible fix for the given
431: * annotation.
432: *
433: * @param annotation the annotation
434: * @return <code>true</code> if there is quick fix
435: * @since 3.2
436: */
437: protected boolean hasQuickFix(Annotation annotation) {
438: if (annotation instanceof IQuickFixableAnnotation) {
439: IQuickFixableAnnotation quickFixableAnnotation = (IQuickFixableAnnotation) annotation;
440: if (!quickFixableAnnotation.isQuickFixableStateSet())
441: quickFixableAnnotation
442: .setQuickFixable(fQuickAssistAssistant != null
443: && fQuickAssistAssistant
444: .canFix(annotation));
445: return quickFixableAnnotation.isQuickFixable();
446: }
447: return false;
448: }
449:
450: }
|