blob: 0048f909ef25f0e54e6b33ed2ec5ce79799cf80e [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.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.osgi.framework.Bundle;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.resources.IMarker;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.StringConverter;
import org.eclipse.ui.internal.editors.text.EditorsPlugin;
import org.eclipse.ui.editors.text.EditorsUI;
/**
* Objects of this class provide access to all extensions declared for the <code>markerAnnotationSpecification</code> extension point.
* The extensions are represented as instances of {@link org.eclipse.ui.texteditor.AnnotationPreference}.
*
* @since 2.1
*/
public class MarkerAnnotationPreferences {
/**
* Initializes the given preference store with the default marker annotation values.
*
* @param store the preference store to be initialized
* @since 3.0
*/
public static void initializeDefaultValues(IPreferenceStore store) {
boolean ignoreAnnotationsPrefPage= store.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.USE_ANNOTATIONS_PREFERENCE_PAGE);
boolean ignoreQuickDiffPrefPage= store.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.USE_QUICK_DIFF_PREFERENCE_PAGE);
MarkerAnnotationPreferences preferences= EditorsPlugin.getDefault().getMarkerAnnotationPreferences();
Iterator<AnnotationPreference> e= preferences.getAnnotationPreferences().iterator();
while (e.hasNext()) {
AnnotationPreference info= e.next();
if (ignoreAnnotationsPrefPage && info.isIncludeOnPreferencePage() && isComplete(info))
continue;
if (ignoreQuickDiffPrefPage && (info.getAnnotationType().equals("org.eclipse.ui.workbench.texteditor.quickdiffChange") //$NON-NLS-1$
|| (info.getAnnotationType().equals("org.eclipse.ui.workbench.texteditor.quickdiffAddition")) //$NON-NLS-1$
|| (info.getAnnotationType().equals("org.eclipse.ui.workbench.texteditor.quickdiffDeletion")) //$NON-NLS-1$
))
continue;
store.setDefault(info.getTextPreferenceKey(), info.getTextPreferenceValue());
store.setDefault(info.getOverviewRulerPreferenceKey(), info.getOverviewRulerPreferenceValue());
if (info.getVerticalRulerPreferenceKey() != null)
store.setDefault(info.getVerticalRulerPreferenceKey(), info.getVerticalRulerPreferenceValue());
PreferenceConverter.setDefault(store, info.getColorPreferenceKey(), info.getColorPreferenceValue());
if (info.getShowInNextPrevDropdownToolbarActionKey() != null)
store.setDefault(info.getShowInNextPrevDropdownToolbarActionKey(), info.isShowInNextPrevDropdownToolbarAction());
if (info.getIsGoToNextNavigationTargetKey() != null)
store.setDefault(info.getIsGoToNextNavigationTargetKey(), info.isGoToNextNavigationTarget());
if (info.getIsGoToPreviousNavigationTargetKey() != null)
store.setDefault(info.getIsGoToPreviousNavigationTargetKey(), info.isGoToPreviousNavigationTarget());
if (info.getHighlightPreferenceKey() != null)
store.setDefault(info.getHighlightPreferenceKey(), info.getHighlightPreferenceValue());
if (info.getTextStylePreferenceKey() != null)
store.setDefault(info.getTextStylePreferenceKey(), info.getTextStyleValue());
}
}
/**
* Removes the marker annotation values which are shown on the
* general Annotations page from the given store and prevents
* setting the default values in the future.
* <p>
* Note: In order to work this method must be called before any
* call to {@link #initializeDefaultValues(IPreferenceStore)}
* </p>
* <p>
* This method is not part of the API and must only be called
* by {@link org.eclipse.ui.editors.text.EditorsUI}
* </p>
*
* @param store the preference store to be initialized
* @throws IllegalStateException if not called by {@link org.eclipse.ui.editors.text.EditorsUI}
* @since 3.0
*/
public static void useAnnotationsPreferencePage(IPreferenceStore store) throws IllegalStateException {
checkAccess();
store.putValue(AbstractDecoratedTextEditorPreferenceConstants.USE_ANNOTATIONS_PREFERENCE_PAGE, Boolean.toString(true));
MarkerAnnotationPreferences preferences= EditorsPlugin.getDefault().getMarkerAnnotationPreferences();
Iterator<AnnotationPreference> e= preferences.getAnnotationPreferences().iterator();
while (e.hasNext()) {
AnnotationPreference info= e.next();
// Only reset annotations shown on Annotations preference page
if (!info.isIncludeOnPreferencePage() || !isComplete(info))
continue;
store.setToDefault(info.getTextPreferenceKey());
store.setToDefault(info.getOverviewRulerPreferenceKey());
if (info.getVerticalRulerPreferenceKey() != null)
store.setToDefault(info.getVerticalRulerPreferenceKey());
store.setToDefault(info.getColorPreferenceKey());
if (info.getShowInNextPrevDropdownToolbarActionKey() != null)
store.setToDefault(info.getShowInNextPrevDropdownToolbarActionKey());
if (info.getIsGoToNextNavigationTargetKey() != null)
store.setToDefault(info.getIsGoToNextNavigationTargetKey());
if (info.getIsGoToPreviousNavigationTargetKey() != null)
store.setToDefault(info.getIsGoToPreviousNavigationTargetKey());
if (info.getHighlightPreferenceKey() != null)
store.setToDefault(info.getHighlightPreferenceKey());
if (info.getTextStylePreferenceKey() != null)
store.setToDefault(info.getTextStylePreferenceKey());
}
}
/**
* Removes the Quick Diff marker annotation values which are shown on the
* general Quick Diff page from the given store and prevents
* setting the default values in the future.
* <p>
* Note: In order to work this method must be called before any
* call to {@link #initializeDefaultValues(IPreferenceStore)}
* </p>
* <p>
* This method is not part of the API and must only be called
* by {@link EditorsUI}
* </p>
*
* @param store the preference store to be initialized
* @throws IllegalStateException if not called by {@link EditorsUI}
* @since 3.0
*/
public static void useQuickDiffPreferencePage(IPreferenceStore store) throws IllegalStateException {
checkAccess();
store.putValue(AbstractDecoratedTextEditorPreferenceConstants.USE_QUICK_DIFF_PREFERENCE_PAGE, Boolean.toString(true));
MarkerAnnotationPreferences preferences= EditorsPlugin.getDefault().getMarkerAnnotationPreferences();
Iterator<AnnotationPreference> e= preferences.getAnnotationPreferences().iterator();
while (e.hasNext()) {
AnnotationPreference info= e.next();
// Only reset annotations shown on Quick Diff preference page
if (!(info.getAnnotationType().equals("org.eclipse.ui.workbench.texteditor.quickdiffChange") //$NON-NLS-1$
|| (info.getAnnotationType().equals("org.eclipse.ui.workbench.texteditor.quickdiffAddition")) //$NON-NLS-1$
|| (info.getAnnotationType().equals("org.eclipse.ui.workbench.texteditor.quickdiffDeletion")) //$NON-NLS-1$
))
continue;
store.setToDefault(info.getTextPreferenceKey());
store.setToDefault(info.getOverviewRulerPreferenceKey());
if (info.getVerticalRulerPreferenceKey() != null)
store.setToDefault(info.getVerticalRulerPreferenceKey());
store.setToDefault(info.getColorPreferenceKey());
if (info.getShowInNextPrevDropdownToolbarActionKey() != null)
store.setToDefault(info.getShowInNextPrevDropdownToolbarActionKey());
if (info.getIsGoToNextNavigationTargetKey() != null)
store.setToDefault(info.getIsGoToNextNavigationTargetKey());
if (info.getIsGoToPreviousNavigationTargetKey() != null)
store.setToDefault(info.getIsGoToPreviousNavigationTargetKey());
if (info.getHighlightPreferenceKey() != null)
store.setToDefault(info.getHighlightPreferenceKey());
if (info.getTextStylePreferenceKey() != null)
store.setToDefault(info.getTextStylePreferenceKey());
}
}
private static final class AccessChecker extends SecurityManager {
@Override
public Class<?>[] getClassContext() {
return super.getClassContext();
}
}
/**
* Checks correct access.
*
* @throws IllegalStateException if not called by {@link EditorsUI}
* @since 3.0
*/
private static void checkAccess() throws IllegalStateException {
Class<?>[] elements = new AccessChecker().getClassContext();
if (!(elements[3].equals(EditorsUI.class)
|| elements[4].equals(EditorsUI.class)))
throw new IllegalStateException();
}
/** The list of extension fragments. */
private List<AnnotationPreference> fFragments;
/** The list of extensions. */
private List<AnnotationPreference> fPreferences;
/**
* Creates a new marker annotation preferences to access
* marker annotation preferences.
*/
public MarkerAnnotationPreferences() {
this(false);
}
/**
* Creates a new marker annotation preferences to access
* marker annotation preferences.
* @param initFromPreferences tells this instance to initialize itself from the preferences
*
* @since 3.2
*/
private MarkerAnnotationPreferences(boolean initFromPreferences) {
if (initFromPreferences)
initializeSharedMakerAnnotationPreferences();
}
/**
* Returns all extensions provided for the <code>markerAnnotationSpecification</code> extension point.
*
* @return all extensions provided for the <code>markerAnnotationSpecification</code> extension point
*/
public List<AnnotationPreference> getAnnotationPreferences() {
if (fPreferences == null)
initialize();
return fPreferences;
}
/**
* Returns all extensions provided for the <code>markerAnnotationSpecification</code>
* extension point including fragments. Fragments share the preference part
* with a marker annotation specifications provided for a super type but do
* change the presentation part.
*
* @return all extensions provided for the <code>markerAnnotationSpecification</code>
* extension point including fragments
*/
public List<AnnotationPreference> getAnnotationPreferenceFragments() {
if (fFragments == null)
initialize();
return fFragments;
}
private void initialize() {
synchronized (EditorsPlugin.getDefault()) {
if (!EditorsPlugin.getDefault().isMarkerAnnotationPreferencesInitialized())
EditorsPlugin.getDefault().setMarkerAnnotationPreferences(new MarkerAnnotationPreferences(true));
}
MarkerAnnotationPreferences sharedPrefs= EditorsPlugin.getDefault().getMarkerAnnotationPreferences();
fFragments= cloneAnnotationPreferences(sharedPrefs.fFragments);
fPreferences= cloneAnnotationPreferences(sharedPrefs.fPreferences);
}
/**
* Reads all extensions provided for the <code>markerAnnotationSpecification</code> extension point and
* translates them into <code>AnnotationPreference</code> objects.
*/
private void initializeSharedMakerAnnotationPreferences() {
// initialize lists - indicates that the initialization happened
fFragments= new ArrayList<>(2);
fPreferences= new ArrayList<>(2);
// populate list
IExtensionPoint extensionPoint= Platform.getExtensionRegistry().getExtensionPoint(EditorsUI.PLUGIN_ID, "markerAnnotationSpecification"); //$NON-NLS-1$
if (extensionPoint != null) {
IConfigurationElement[] elements= extensionPoint.getConfigurationElements();
for (int i= 0; i < elements.length; i++) {
AnnotationPreference spec= createSpec(elements[i]);
if (spec != null)
fFragments.add(spec);
if (isComplete(spec))
fPreferences.add(spec);
}
}
}
/**
* Deeply clones the given list of <code>AnnotationPreference</code>.
*
* @param annotationPreferences a list of <code>AnnotationPreference</code>
* @return the cloned list of cloned annotation preferences
* @since 3.1
*/
private List<AnnotationPreference> cloneAnnotationPreferences(List<AnnotationPreference> annotationPreferences) {
if (annotationPreferences == null)
return null;
List<AnnotationPreference> clone= new ArrayList<>(annotationPreferences.size());
Iterator<AnnotationPreference> iter= annotationPreferences.iterator();
while (iter.hasNext())
clone.add(clone(iter.next()));
return clone;
}
/**
* Clones the given annotation preference.
*
* @param annotationPreference the annotation preference to clone
* @return the cloned annotation preference
* @since 3.1
*/
private AnnotationPreference clone(AnnotationPreference annotationPreference) {
if (annotationPreference == null)
return null;
AnnotationPreference clone= new AnnotationPreference();
if (annotationPreference.getAnnotationType() != null) {
clone.setAnnotationType(annotationPreference.getAnnotationType());
clone.merge(annotationPreference);
}
return clone;
}
/**
* Checks if <code>spec</code> has all the attributes previously required
* by the marker annotation preference extension point. These are: color, text
* and overview ruler preference keys.
*
* @param spec the <code>AnnotationPreference</code> to check
* @return <code>true</code> if <code>spec</code> is complete, <code>false</code> otherwise
* @since 3.0
*/
private static boolean isComplete(AnnotationPreference spec) {
return spec.getColorPreferenceKey() != null
&& spec.getColorPreferenceValue() != null
&& spec.getTextPreferenceKey() != null
&& spec.getOverviewRulerPreferenceKey() != null;
}
/**
* Creates a <code>AnnotationPreference</code> the given configuration element.
*
* @param element the configuration element
* @return the created annotation preference
*/
private AnnotationPreference createSpec(IConfigurationElement element) {
String s;
int i;
boolean b;
ReadOnlyAnnotationPreference info= new ReadOnlyAnnotationPreference();
s= element.getAttribute("annotationType"); //$NON-NLS-1$
if (s == null || s.trim().length() == 0) return null;
info.setAnnotationType(s);
s= element.getAttribute("label"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0)
info.setPreferenceLabel(s);
s= element.getAttribute("markerType"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0)
info.setMarkerType(s);
s= element.getAttribute("markerSeverity"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0) {
i= StringConverter.asInt(s, IMarker.SEVERITY_INFO);
info.setSeverity(i);
}
s= element.getAttribute("textPreferenceKey"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0)
info.setTextPreferenceKey(s);
s= element.getAttribute("textPreferenceValue"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0) {
b= StringConverter.asBoolean(s, false);
info.setTextPreferenceValue(b);
}
s= element.getAttribute("highlightPreferenceKey"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0)
info.setHighlightPreferenceKey(s);
s= element.getAttribute("highlightPreferenceValue"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0) {
b= StringConverter.asBoolean(s, false);
info.setHighlightPreferenceValue(b);
}
s= element.getAttribute("overviewRulerPreferenceKey"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0)
info.setOverviewRulerPreferenceKey(s);
s= element.getAttribute("overviewRulerPreferenceValue"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0) {
b= StringConverter.asBoolean(s, false);
info.setOverviewRulerPreferenceValue(b);
}
s= element.getAttribute("verticalRulerPreferenceKey"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0)
info.setVerticalRulerPreferenceKey(s);
s= element.getAttribute("verticalRulerPreferenceValue"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0) {
b= StringConverter.asBoolean(s, true);
info.setVerticalRulerPreferenceValue(b);
}
s= element.getAttribute("colorPreferenceKey"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0)
info.setColorPreferenceKey(s);
s= element.getAttribute("colorPreferenceValue"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0) {
RGB rgb= StringConverter.asRGB(s);
info.setColorPreferenceValue(rgb == null ? new RGB(0,0,0) : rgb);
}
s= element.getAttribute("presentationLayer"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0) {
i= StringConverter.asInt(s, 0);
info.setPresentationLayer(i);
}
s= element.getAttribute("contributesToHeader"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0) {
b= StringConverter.asBoolean(s, false);
info.setContributesToHeader(b);
}
s= element.getAttribute("showInNextPrevDropdownToolbarActionKey"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0)
info.setShowInNextPrevDropdownToolbarActionKey(s);
s= element.getAttribute("showInNextPrevDropdownToolbarAction"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0) {
b= StringConverter.asBoolean(s, false);
info.setShowInNextPrevDropdownToolbarAction(b);
}
s= element.getAttribute("isGoToNextNavigationTargetKey"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0)
info.setIsGoToNextNavigationTargetKey(s);
s= element.getAttribute("isGoToNextNavigationTarget"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0) {
b= StringConverter.asBoolean(s, false);
info.setIsGoToNextNavigationTarget(b);
}
s= element.getAttribute("isGoToPreviousNavigationTargetKey"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0)
info.setIsGoToPreviousNavigationTargetKey(s);
s= element.getAttribute("isGoToPreviousNavigationTarget"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0) {
b= StringConverter.asBoolean(s, false);
info.setIsGoToPreviousNavigationTarget(b);
}
s= element.getAttribute("symbolicIcon"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0)
info.setSymbolicImageName(s);
s= element.getAttribute("icon"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0)
info.setImageDescriptor(getImageDescriptor(s, element));
s= element.getAttribute("quickFixIcon"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0)
info.setQuickFixImageDescriptor(getImageDescriptor(s, element));
s= element.getAttribute("annotationImageProvider"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0)
info.setAnnotationImageProviderData(element, "annotationImageProvider"); //$NON-NLS-1$
s= element.getAttribute("textStylePreferenceKey"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0)
info.setTextStylePreferenceKey(s);
s= element.getAttribute("textStylePreferenceValue"); //$NON-NLS-1$
if (s != null && s.trim().length() > 0) {
if (AnnotationPreference.STYLE_BOX.equals(s)
|| AnnotationPreference.STYLE_DASHED_BOX.equals(s)
|| AnnotationPreference.STYLE_IBEAM.equals(s)
|| AnnotationPreference.STYLE_SQUIGGLES.equals(s)
|| AnnotationPreference.STYLE_PROBLEM_UNDERLINE.equals(s)
|| AnnotationPreference.STYLE_UNDERLINE.equals(s))
info.setTextStyleValue(s);
else
info.setTextStyleValue(AnnotationPreference.STYLE_NONE);
}
s= element.getAttribute("includeOnPreferencePage"); //$NON-NLS-1$
info.setIncludeOnPreferencePage(s == null || StringConverter.asBoolean(s, true));
info.markReadOnly();
return info;
}
/**
* Returns the image descriptor for the icon path specified by the given configuration
* element.
*
* @param iconPath the icon path
* @param element the configuration element
* @return the image descriptor
* @since 3.0
*/
private ImageDescriptor getImageDescriptor(String iconPath, IConfigurationElement element) {
String pluginId= element.getContributor().getName();
Bundle bundle= Platform.getBundle(pluginId);
if (bundle == null)
return null;
URL url= FileLocator.find(bundle, new Path(iconPath), null);
if (url != null)
return ImageDescriptor.createFromURL(url);
return ImageDescriptor.getMissingImageDescriptor();
}
}