blob: a8466602c4d572a944dc7e05a22d6dd780cf0981 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.texteditor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.jface.text.quickassist.IQuickAssistAssistant;
import org.eclipse.jface.text.quickassist.IQuickFixableAnnotation;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationAccess;
import org.eclipse.jface.text.source.IAnnotationAccessExtension;
import org.eclipse.jface.text.source.IAnnotationAccessExtension2;
import org.eclipse.jface.text.source.IAnnotationPresentation;
import org.eclipse.jface.text.source.ImageUtilities;
import org.eclipse.jface.text.source.projection.AnnotationBag;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.internal.editors.text.EditorsPlugin;
import org.eclipse.ui.internal.texteditor.AnnotationType;
import org.eclipse.ui.internal.texteditor.AnnotationTypeHierarchy;
/**
* Default class for accessing marker annotation properties.
*
* @since 2.1
*/
public class DefaultMarkerAnnotationAccess implements IAnnotationAccess, IAnnotationAccessExtension, IAnnotationAccessExtension2 {
/**
* Constant for the unknown marker type.
*
* @deprecated As of 3.0, replaced by Annotation.TYPE_UNKNOWN
*/
@Deprecated
public static final String UNKNOWN= Annotation.TYPE_UNKNOWN;
/**
* Constant for the error system image.
* Value: <code>error</code>
*
* @since 3.0
*/
public static final String ERROR_SYSTEM_IMAGE= "error"; //$NON-NLS-1$
/**
* Constant for the warning system image.
* Value: <code>warning</code>
*
* @since 3.0
*/
public static final String WARNING_SYSTEM_IMAGE= "warning"; //$NON-NLS-1$
/**
* Constant for the info system image.
* Value: <code>info</code>
*
* @since 3.0
*/
public static final String INFO_SYSTEM_IMAGE= "info"; //$NON-NLS-1$
/**
* Constant for the task system image.
* Value: <code>task</code>
*
* @since 3.0
*/
public static final String TASK_SYSTEM_IMAGE= "task"; //$NON-NLS-1$
/**
* Constant for the bookmark system image.
* Value: <code>bookmark</code>
*
* @since 3.0
*/
public static final String BOOKMARK_SYSTEM_IMAGE= "bookmark"; //$NON-NLS-1$
/**
* The mapping between external and internal symbolic system image names.
*
* @since 3.0
*/
private final static Map<String, String> MAPPING;
static {
MAPPING= new HashMap<>();
MAPPING.put(ERROR_SYSTEM_IMAGE, ISharedImages.IMG_OBJS_ERROR_TSK);
MAPPING.put(WARNING_SYSTEM_IMAGE, ISharedImages.IMG_OBJS_WARN_TSK);
MAPPING.put(INFO_SYSTEM_IMAGE, ISharedImages.IMG_OBJS_INFO_TSK);
MAPPING.put(TASK_SYSTEM_IMAGE, IDE.SharedImages.IMG_OBJS_TASK_TSK);
MAPPING.put(BOOKMARK_SYSTEM_IMAGE, IDE.SharedImages.IMG_OBJS_BKMRK_TSK);
}
/**
* The marker annotation preferences.
*
* @deprecated As of 3.0, no replacement
*/
@Deprecated
protected MarkerAnnotationPreferences fMarkerAnnotationPreferences;
/**
* An optional quick assist processor.
*
* @since 3.2
*/
private IQuickAssistAssistant fQuickAssistAssistant;
/**
* Returns a new default marker annotation access with the given preferences.
*
* @param markerAnnotationPreferences the marker annotation preference
* @deprecated As of 3.0, replaced by
* {@link org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess#DefaultMarkerAnnotationAccess()}
*/
@Deprecated
public DefaultMarkerAnnotationAccess(MarkerAnnotationPreferences markerAnnotationPreferences) {
fMarkerAnnotationPreferences= markerAnnotationPreferences;
}
/**
* Creates a new default marker annotation access using the standard
* preference lookup strategy which is the one provided by the enclosing
* plug-in.
*
* @since 3.0
*/
public DefaultMarkerAnnotationAccess() {
}
@Override
public void setQuickAssistAssistant(IQuickAssistAssistant assistant) {
fQuickAssistAssistant= assistant;
}
/**
* Returns the annotation preference for the given annotation.
*
* @param annotation the annotation
* @return the annotation preference for the given annotation or <code>null</code>
*/
private AnnotationPreference getAnnotationPreference(Annotation annotation) {
AnnotationPreferenceLookup lookup= getAnnotationPreferenceLookup();
if (lookup != null)
return lookup.getAnnotationPreference(annotation);
return null;
}
/**
* Returns the annotation preference lookup used by this annotation access.
*
* @return the annotation preference lookup
* @since 3.0
*/
protected AnnotationPreferenceLookup getAnnotationPreferenceLookup() {
return EditorsPlugin.getDefault().getAnnotationPreferenceLookup();
}
/**
* {@inheritDoc}
*
* @deprecated use <code>Annotation.getType()</code>
*/
@Deprecated
@Override
public Object getType(Annotation annotation) {
return annotation.getType();
}
/**
* {@inheritDoc}
*
* @deprecated assumed to always return <code>true</code>
*/
@Deprecated
@Override
public boolean isMultiLine(Annotation annotation) {
return true;
}
/**
* {@inheritDoc}
*
* @deprecated assumed to always return <code>true</code>
*/
@Deprecated
@Override
public boolean isTemporary(Annotation annotation) {
return !annotation.isPersistent();
}
/*
* @see org.eclipse.jface.text.source.IAnnotationAccessExtension#getLabel(org.eclipse.jface.text.source.Annotation)
* @since 3.0
*/
@Override
public String getTypeLabel(Annotation annotation) {
AnnotationPreference preference= getAnnotationPreference(annotation);
return preference != null ? preference.getPreferenceLabel() : null;
}
@Override
public int getLayer(Annotation annotation) {
if (annotation instanceof IAnnotationPresentation) {
IAnnotationPresentation presentation= (IAnnotationPresentation) annotation;
return presentation.getLayer();
}
AnnotationPreference preference= getAnnotationPreference(annotation);
if (preference != null)
return preference.getPresentationLayer();
// backward compatibility, ignore exceptions, just return default layer
try {
Method method= annotation.getClass().getMethod("getLayer"); //$NON-NLS-1$
Integer result= (Integer) method.invoke(annotation);
return result.intValue();
} catch (SecurityException x) {
} catch (IllegalArgumentException x) {
} catch (NoSuchMethodException x) {
} catch (IllegalAccessException x) {
} catch (InvocationTargetException x) {
}
return IAnnotationAccessExtension.DEFAULT_LAYER;
}
@Override
public void paint(Annotation annotation, GC gc, Canvas canvas, Rectangle bounds) {
if (annotation instanceof IAnnotationPresentation) {
IAnnotationPresentation presentation= (IAnnotationPresentation) annotation;
presentation.paint(gc, canvas, bounds);
return;
}
AnnotationPreference preference= getAnnotationPreference(annotation);
if (preference != null) {
Object type= getType(annotation);
String annotationType= (type == null ? null : type.toString());
Image image= getImage(annotation, preference, annotationType);
if (image != null) {
ImageUtilities.drawImage(image, gc, canvas, bounds, SWT.CENTER, SWT.TOP);
return;
}
}
// backward compatibility, ignore exceptions, just don't paint
try {
Method method= annotation.getClass().getMethod("paint", new Class[] { GC.class, Canvas.class, Rectangle.class }); //$NON-NLS-1$
method.invoke(annotation, new Object[] {gc, canvas, bounds });
} catch (SecurityException x) {
} catch (IllegalArgumentException x) {
} catch (NoSuchMethodException x) {
} catch (IllegalAccessException x) {
} catch (InvocationTargetException x) {
}
}
@Override
public boolean isPaintable(Annotation annotation) {
if (annotation instanceof IAnnotationPresentation)
return true;
AnnotationPreference preference= getAnnotationPreference(annotation);
if (preference == null)
return false;
Object type= getType(annotation);
String annotationType= (type == null ? null : type.toString());
Image image= getImage(annotation, preference, annotationType);
return image != null;
}
@Override
public boolean isSubtype(Object annotationType, Object potentialSupertype) {
AnnotationTypeHierarchy hierarchy= getAnnotationTypeHierarchy();
return hierarchy.isSubtype(potentialSupertype.toString(), annotationType.toString());
}
@Override
public Object[] getSupertypes(Object annotationType) {
AnnotationTypeHierarchy hierarchy= getAnnotationTypeHierarchy();
AnnotationType type= hierarchy.getAnnotationType(annotationType.toString());
return type.getSuperTypes();
}
/**
* Returns the annotation type hierarchy used by this annotation access.
*
* @return the annotation type hierarchy
* @since 3.0
* @noreference This method is not intended to be referenced by clients.
*/
protected AnnotationTypeHierarchy getAnnotationTypeHierarchy() {
return EditorsPlugin.getDefault().getAnnotationTypeHierarchy();
}
/**
* Translates the given symbolic image name into the shared image name as
* defined in {@link org.eclipse.ui.ISharedImages}.
* <p>
* The symbolic image name must be one of the
*
* @param symbolicImageName the symbolic image name, which must be one of
* the valid values defined for the <code>symbolicIcon</code>
* attribute in the
* <code>org.eclipse.ui.editors.markerAnnotationSpecification</code>
* extension point
* @return the shared image name
* @throws IllegalArgumentException if the <code>symbolicImageName</code> is not defined by the
* <code>org.eclipse.ui.editors.markerAnnotationSpecification</code> extension point
* @since 3.4
*/
public static String getSharedImageName(String symbolicImageName) {
Assert.isLegal(symbolicImageName != null);
String sharedImageName= MAPPING.get(symbolicImageName);
Assert.isLegal(sharedImageName != null);
return sharedImageName;
}
/**
* Returns the image for the given annotation and the given annotation preferences or
* <code>null</code> if there is no such image.
*
* @param annotation the annotation
* @param preference the annotation preference
* @param annotationType the annotation type
* @return the image or <code>null</code>
* @since 3.0
*/
private Image getImage(Annotation annotation, AnnotationPreference preference, String annotationType) {
if (annotation instanceof AnnotationBag) {
AnnotationBag bag= (AnnotationBag)annotation;
if (!bag.isEmpty())
annotation= bag.iterator().next();
}
ImageRegistry registry= EditorsPlugin.getDefault().getImageRegistry();
IAnnotationImageProvider annotationImageProvider = preference.getAnnotationImageProvider();
if (annotationImageProvider != null) {
Image image= annotationImageProvider.getManagedImage(annotation);
if (image != null)
return image;
String id= annotationImageProvider.getImageDescriptorId(annotation);
if (id != null) {
image= registry.get(id);
if (image == null) {
ImageDescriptor descriptor= annotationImageProvider.getImageDescriptor(id);
registry.put(id, descriptor);
image= registry.get(id);
}
return image;
}
}
if (annotationType == null)
return null;
if (hasQuickFix(annotation)) {
ImageDescriptor quickFixImageDesc= preference.getQuickFixImageDescriptor();
if (quickFixImageDesc != null) {
Image image= registry.get(quickFixImageDesc.toString());
if (image == null) {
registry.put(quickFixImageDesc.toString(), quickFixImageDesc);
image= registry.get(quickFixImageDesc.toString());
}
if (image != null)
return image;
}
}
Image image= registry.get(annotationType);
if (image == null) {
ImageDescriptor descriptor= preference.getImageDescriptor();
if (descriptor != null) {
registry.put(annotationType, descriptor);
image= registry.get(annotationType);
} else {
String symbolicImageName= preference.getSymbolicImageName();
if (symbolicImageName != null) {
String key= getSharedImageName(preference.getSymbolicImageName());
if (key != null) {
ISharedImages sharedImages= PlatformUI.getWorkbench().getSharedImages();
image= sharedImages.getImage(key);
}
}
}
}
return image;
}
/**
* Checks whether there's a quick assist assistant and if so,
* whether the assistant has a possible fix for the given
* annotation.
*
* @param annotation the annotation
* @return <code>true</code> if there is quick fix
* @since 3.2
*/
protected boolean hasQuickFix(Annotation annotation) {
if (annotation instanceof IQuickFixableAnnotation) {
IQuickFixableAnnotation quickFixableAnnotation= (IQuickFixableAnnotation)annotation;
if (!quickFixableAnnotation.isQuickFixableStateSet())
quickFixableAnnotation.setQuickFixable(fQuickAssistAssistant != null && fQuickAssistAssistant.canFix(annotation));
return quickFixableAnnotation.isQuickFixable();
}
return false;
}
}