blob: e3eded857a8e8c2e2b03ca404a97b28d411987a2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2004 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
* Jens Lukowski/Innoopract - initial renaming/restructuring
*
*******************************************************************************/
package org.eclipse.wst.sse.ui.internal;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Iterator;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.ui.IEditorActionBarContributor;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.part.EditorActionBarContributor;
import org.eclipse.ui.texteditor.AnnotationPreference;
import org.eclipse.ui.texteditor.IEditorStatusLine;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.MarkerAnnotation;
import org.eclipse.ui.texteditor.TextEditorAction;
/**
* Based on org.eclipse.jdt.internal.ui.javaeditor.GotoAnnotationAction and
* the org.eclipse.jdt.internal.ui.JavaEditor's gotoError() method. Rewritten
* based on 3.0M7 version to operate generically.
*
* @deprecated - use org.eclipse.ui.texteditor.GotoAnnotationAction
*
*/
public class GotoAnnotationAction extends TextEditorAction {
private static final boolean _debug = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.ui/gotoNextAnnotation")); //$NON-NLS-1$ //$NON-NLS-2$
/**
* Clears the status line on selection changed.
*/
protected class StatusLineClearer implements ISelectionChangedListener {
IStatusLineManager fStatusLineManager = null;
protected StatusLineClearer(IStatusLineManager mgr) {
super();
fStatusLineManager = mgr;
}
/*
* @see ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
*/
public void selectionChanged(SelectionChangedEvent event) {
getTextEditor().getSelectionProvider().removeSelectionChangedListener(StatusLineClearer.this);
fStatusLineManager.setErrorMessage(null, null);
fStatusLineManager.setMessage(null, null);
}
}
private boolean fForward;
private String fLabel;
private String fPrefix;
/**
* @param prefix
* @param editor
*/
public GotoAnnotationAction(String prefix, boolean forward) {
super(SSEUIMessages.getResourceBundle(), prefix, null);
fForward = forward;
fPrefix = prefix;
fLabel = SSEUIMessages.getResourceBundle().getString(fPrefix);
}
/*
* This is the default label used for description
*/
public String getDefaultLabel() {
return fLabel;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.action.Action#getDescription()
*/
public String getDescription() {
return getDefaultLabel();
}
/**
* Returns the annotation closest to the given range respecting the given
* direction. If an annotation is found, the annotations current position
* is copied into the provided annotation position.
*
* @param offset
* the region offset
* @param length
* the region length
* @param forward
* <code>true</code> for forwards, <code>false</code> for
* backward
* @param annotationPosition
* the position of the found annotation
* @return the found annotation
*/
protected Annotation getNextAnnotation(final int offset, final int length, boolean forward, Position annotationPosition) {
Annotation nextAnnotation = null;
Position nextAnnotationPosition = null;
Annotation containingAnnotation = null;
Position containingAnnotationPosition = null;
boolean currentAnnotation = false;
IDocument document = getTextEditor().getDocumentProvider().getDocument(getTextEditor().getEditorInput());
int endOfDocument = document.getLength();
int distance = Integer.MAX_VALUE;
IAnnotationModel model = getTextEditor().getDocumentProvider().getAnnotationModel(getTextEditor().getEditorInput());
// external files may not have an annotation model
if (model != null) {
Iterator e = model.getAnnotationIterator();
while (e.hasNext()) {
Annotation a = (Annotation) e.next();
if (!isNavigationTarget(a))
continue;
Position p = model.getPosition(a);
if (p == null)
continue;
if (forward && p.offset == offset || !forward && p.offset + p.getLength() == offset + length) {
if (containingAnnotation == null || (forward && p.length >= containingAnnotationPosition.length || !forward && p.length >= containingAnnotationPosition.length)) {
containingAnnotation = a;
containingAnnotationPosition = p;
currentAnnotation = p.length == length;
}
}
else {
int currentDistance = 0;
if (forward) {
currentDistance = p.getOffset() - offset;
if (currentDistance < 0) {
currentDistance = endOfDocument + currentDistance;
}
if (currentDistance < distance || currentDistance == distance && p.length < nextAnnotationPosition.length) {
distance = currentDistance;
nextAnnotation = a;
nextAnnotationPosition = p;
}
}
else {
currentDistance = offset + length - (p.getOffset() + p.length);
if (currentDistance < 0)
currentDistance = endOfDocument + currentDistance;
if (currentDistance < distance || currentDistance == distance && p.length < nextAnnotationPosition.length) {
distance = currentDistance;
nextAnnotation = a;
nextAnnotationPosition = p;
}
}
}
}
}
if (containingAnnotationPosition != null && (!currentAnnotation || nextAnnotation == null)) {
annotationPosition.setOffset(containingAnnotationPosition.getOffset());
annotationPosition.setLength(containingAnnotationPosition.getLength());
return containingAnnotation;
}
if (nextAnnotationPosition != null) {
annotationPosition.setOffset(nextAnnotationPosition.getOffset());
annotationPosition.setLength(nextAnnotationPosition.getLength());
}
return nextAnnotation;
}
private IStatusLineManager getStatusLineManager() {
// The original JavaEditor M7 implementation made use of an adapter,
// but that approach
// fails with a MultiPageEditorSite
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if (window == null)
return null;
IWorkbenchPage page = window.getActivePage();
if (page == null)
return null;
IEditorPart editor = page.getActiveEditor();
if (editor == null)
return null;
IEditorActionBarContributor contributor = editor.getEditorSite().getActionBarContributor();
if (contributor instanceof EditorActionBarContributor) {
return ((EditorActionBarContributor) contributor).getActionBars().getStatusLineManager();
}
return null;
}
public String getText() {
return getDefaultLabel();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.action.Action#getToolTipText()
*/
public String getToolTipText() {
return getDefaultLabel();
}
/**
* Jumps to the error next according to the given direction based off
* JavaEditor#gotoAnnotation()
*
* @param forward
* is the direction
*/
public void gotoAnnotation(boolean forward) {
ITextSelection selection = (ITextSelection) getTextEditor().getSelectionProvider().getSelection();
Position position = new Position(0, 0);
if (false /* delayed - see bug 18316 */) {
getNextAnnotation(selection.getOffset(), selection.getLength(), forward, position);
getTextEditor().selectAndReveal(position.getOffset(), position.getLength());
}
else /* no delay - see bug 18316 */{
Annotation annotation = getNextAnnotation(selection.getOffset(), selection.getLength(), forward, position);
IEditorStatusLine editorStatusLine = (IEditorStatusLine) getTextEditor().getAdapter(IEditorStatusLine.class);
if (editorStatusLine != null) {
editorStatusLine.setMessage(true, null, null);
editorStatusLine.setMessage(false, null, null);
}
else {
IStatusLineManager mgr = getStatusLineManager();
if (mgr != null) {
mgr.setErrorMessage(null);
mgr.setMessage(null, null);
}
}
if (annotation != null) {
updateAnnotationViews(annotation);
if (_debug) {
System.out.println("select and reveal " + annotation.getType() + "@" + position.getOffset() + ":" + position.getLength()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
getTextEditor().selectAndReveal(position.getOffset(), position.getLength());
if (editorStatusLine != null) {
editorStatusLine.setMessage(true, null, null);
editorStatusLine.setMessage(false, annotation.getText(), null);
}
else {
IStatusLineManager mgr = getStatusLineManager();
if (mgr != null) {
mgr.setErrorMessage(null);
mgr.setMessage(null, annotation.getText());
}
getTextEditor().getSelectionProvider().addSelectionChangedListener(new StatusLineClearer(mgr));
}
}
}
}
/**
* Returns whether the given annotation is configured as a target for the
* "Go to Next/Previous Annotation" actions
*
* @param annotation
* the annotation
* @return <code>true</code> if this is a target, <code>false</code>
* otherwise
* @see Eclipse 3.0
*/
protected boolean isNavigationTarget(Annotation annotation) {
Preferences preferences = EditorsUI.getPluginPreferences();
AnnotationPreference preference = EditorsUI.getAnnotationPreferenceLookup().getAnnotationPreference(annotation);
// See bug 41689
// String key= forward ? preference.getIsGoToNextNavigationTargetKey()
// : preference.getIsGoToPreviousNavigationTargetKey();
String key = preference == null ? null : preference.getIsGoToNextNavigationTargetKey();
return (key != null && preferences.getBoolean(key));
}
public void run() {
gotoAnnotation(fForward);
}
public void setEditor(ITextEditor editor) {
super.setEditor(editor);
update();
}
/**
* Updates the annotation views that show the given annotation.
*
* @param annotation
* the annotation
*/
protected void updateAnnotationViews(Annotation annotation) {
IMarker marker = null;
if (annotation instanceof MarkerAnnotation)
marker = ((MarkerAnnotation) annotation).getMarker();
if (marker != null) {
try {
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if (window != null) {
IWorkbenchPage page = window.getActivePage();
if (page != null) {
IViewPart view = null;
if (marker.isSubtypeOf(IMarker.PROBLEM)) {
view = page.findView(IPageLayout.ID_PROBLEM_VIEW);
}
else if (marker.isSubtypeOf(IMarker.TASK)) {
view = page.findView(IPageLayout.ID_TASK_LIST);
}
else if (marker.isSubtypeOf(IMarker.BOOKMARK)) {
view = page.findView(IPageLayout.ID_BOOKMARKS);
}
// If the view isn't open on this perspective, don't
// interact with it
if (view != null) {
Method method = view.getClass().getMethod("setSelection", new Class[]{IStructuredSelection.class, boolean.class}); //$NON-NLS-1$
if (method != null) {
method.invoke(view, new Object[]{new StructuredSelection(marker), Boolean.TRUE});
page.bringToTop(view);
}
}
}
}
}
// ignore exceptions, don't update any of the lists, just set
// statusline
catch (CoreException x) {
//
}
catch (NoSuchMethodException x) {
//
}
catch (IllegalAccessException x) {
//
}
catch (InvocationTargetException x) {
//
}
}
}
}