| author | pschonbac | 2009-07-03 06:35:32 (EDT) |
|---|---|---|
| committer | sefftinge | 2009-07-03 06:35:32 (EDT) |
| commit | 590495d558865c6a2deeb552a24ce8ade095a757 (patch) (side-by-side diff) | |
| tree | 1caee4f4f29add23bd9271e09a183cd358e43747 | |
| parent | 4c400e9fe78490ad656e2b894401aba1ffe7381f (diff) | |
| download | org.eclipse.xtext-590495d558865c6a2deeb552a24ce8ade095a757.zip org.eclipse.xtext-590495d558865c6a2deeb552a24ce8ade095a757.tar.gz org.eclipse.xtext-590495d558865c6a2deeb552a24ce8ade095a757.tar.bz2 | |
bug 282033: [UI Accessibility] Display problem marker info in hover and in status line
https://bugs.eclipse.org/bugs/show_bug.cgi?id=282033
6 files changed, 266 insertions, 0 deletions
diff --git a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/XtextUIMessages.java b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/XtextUIMessages.java index 22f751c..3fddabc 100644 --- a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/XtextUIMessages.java +++ b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/XtextUIMessages.java @@ -68,6 +68,11 @@ public class XtextUIMessages extends NLS { } /** + * messages for hovers + */ + public static String AbstractHover_MultipleMarkers; + + /** * messages for tasktag preferences page */ public static String TodoTaskPreferencePage_title; diff --git a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextEditor.java b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextEditor.java index e32487d..41451fa 100644 --- a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextEditor.java +++ b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextEditor.java @@ -8,20 +8,32 @@ *******************************************************************************/ package org.eclipse.xtext.ui.core.editor; +import java.util.Iterator; + import org.apache.log4j.Logger; import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.action.Action; import org.eclipse.jface.preference.IPreferenceStore; +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.text.source.IAnnotationModelExtension2; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.IVerticalRuler; import org.eclipse.jface.text.source.SourceViewerConfiguration; import org.eclipse.jface.text.source.projection.ProjectionSupport; import org.eclipse.jface.text.source.projection.ProjectionViewer; import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.IPostSelectionProvider; import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorSite; @@ -30,6 +42,7 @@ import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.editors.text.TextEditor; import org.eclipse.ui.texteditor.ChainedPreferenceStore; import org.eclipse.ui.texteditor.ITextEditorActionConstants; +import org.eclipse.ui.texteditor.MarkerAnnotation; import org.eclipse.ui.texteditor.SelectMarkerRulerAction; import org.eclipse.ui.texteditor.TextOperationAction; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; @@ -82,6 +95,8 @@ public class XtextEditor extends TextEditor { private ValidationJob validationJob; + private ISelectionChangedListener selectionChangedListener; + private String languageName; public XtextEditor() { @@ -269,6 +284,19 @@ public class XtextEditor extends TextEditor { // TODO Folding stuff installHighlightingHelper(); + selectionChangedListener = new ISelectionChangedListener() { + public void selectionChanged(final SelectionChangedEvent event) { + updateStatusLine(); + } + }; + final ISelectionProvider selectionProvider = getSelectionProvider(); + if (selectionProvider instanceof IPostSelectionProvider) { + final IPostSelectionProvider postSelectionProvider = (IPostSelectionProvider) selectionProvider; + postSelectionProvider.addPostSelectionChangedListener(selectionChangedListener); + } + else { + getSelectionProvider().addSelectionChangedListener(selectionChangedListener); + } } private void installHighlightingHelper() { @@ -291,6 +319,16 @@ public class XtextEditor extends TextEditor { outlinePage = null; } uninstallHighlightingHelper(); + if (selectionChangedListener != null) { + final ISelectionProvider selectionProvider = getSelectionProvider(); + if (selectionProvider instanceof IPostSelectionProvider) { + final IPostSelectionProvider postSelectionProvider = (IPostSelectionProvider) selectionProvider; + postSelectionProvider.removePostSelectionChangedListener(selectionChangedListener); + } + else { + getSelectionProvider().removeSelectionChangedListener(selectionChangedListener); + } + } } /** @@ -360,4 +398,49 @@ public class XtextEditor extends TextEditor { return more; } + protected void updateStatusLine() { + final ITextSelection selection = (ITextSelection) getSelectionProvider().getSelection(); + final Annotation annotation = getAnnotation(selection.getOffset(), selection.getLength()); + String message = null; + if (annotation != null) { + updateMarkerViews(annotation); + if (isProblemMarkerAnnotation(annotation)) { + message = annotation.getText(); + } + } + setStatusLineMessage(message); + } + + private Annotation getAnnotation(final int offset, final int length) { + final IAnnotationModel model = getDocumentProvider().getAnnotationModel(getEditorInput()); + if (model == null) + return null; + + Iterator iterator; + if (model instanceof IAnnotationModelExtension2) { + iterator = ((IAnnotationModelExtension2) model).getAnnotationIterator(offset, length, true, true); + } + else { + iterator = model.getAnnotationIterator(); + } + + while (iterator.hasNext()) { + final Annotation a = (Annotation) iterator.next(); + final Position p = model.getPosition(a); + if (p != null && p.overlapsWith(offset, length)) + return a; + } + return null; + } + + private boolean isProblemMarkerAnnotation(final Annotation annotation) { + if (!(annotation instanceof MarkerAnnotation)) + return false; + try { + return (((MarkerAnnotation) annotation).getMarker().isSubtypeOf(IMarker.PROBLEM)); + } + catch (final CoreException e) { + return false; + } + } } diff --git a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextSourceViewerConfiguration.java b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextSourceViewerConfiguration.java index 2c12ebd..548a99c 100644 --- a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextSourceViewerConfiguration.java +++ b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextSourceViewerConfiguration.java @@ -19,10 +19,12 @@ import org.eclipse.jface.text.hyperlink.IHyperlink; import org.eclipse.jface.text.hyperlink.IHyperlinkDetector; import org.eclipse.jface.text.presentation.IPresentationReconciler; import org.eclipse.jface.text.reconciler.IReconciler; +import org.eclipse.jface.text.source.IAnnotationHover; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.ui.editors.text.TextSourceViewerConfiguration; import org.eclipse.xtext.ui.core.editor.contentassist.IContentAssistantFactory; import org.eclipse.xtext.ui.core.editor.formatting.IContentFormatterFactory; +import org.eclipse.xtext.ui.core.editor.hover.ProblemHover; import org.eclipse.xtext.ui.core.editor.toggleComments.ISingleLineCommentHelper; import com.google.inject.Inject; @@ -54,6 +56,14 @@ public class XtextSourceViewerConfiguration extends TextSourceViewerConfiguratio @Inject private Provider<XtextPresentationReconciler> presentationReconcilerProvider; + /** + * @see org.eclipse.ui.editors.text.TextSourceViewerConfiguration#getAnnotationHover(org.eclipse.jface.text.source.ISourceViewer) + */ + @Override + public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) { + return new ProblemHover(sourceViewer); + } + @Override public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) { return contentAssistantFactory.createConfiguredAssistant(this, sourceViewer); @@ -133,4 +143,5 @@ public class XtextSourceViewerConfiguration extends TextSourceViewerConfiguratio public Provider<XtextPresentationReconciler> getPresentationReconcilerProvider() { return presentationReconcilerProvider; } + } diff --git a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/hover/AbstractHover.java b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/hover/AbstractHover.java new file mode 100644 index 0000000..884b7fd --- a/dev/null +++ b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/hover/AbstractHover.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2008 itemis AG (http://www.itemis.eu) 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 + * + *******************************************************************************/ +package org.eclipse.xtext.ui.core.editor.hover; + +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextHover; +import org.eclipse.jface.text.ITextHoverExtension2; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.source.IAnnotationHover; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.swt.graphics.Point; +import org.eclipse.xtext.ui.core.XtextUIMessages; + +/** + * @author Patrick Schoenbach - Initial API and implementation + */ + +public abstract class AbstractHover implements IAnnotationHover, ITextHover, ITextHoverExtension2 { + + protected final ISourceViewer sourceViewer; + + public AbstractHover(final ISourceViewer sourceViewer) { + if (sourceViewer == null) + throw new IllegalArgumentException(); + + this.sourceViewer = sourceViewer; + } + + public IDocument getDocument() { + return sourceViewer.getDocument(); + } + + public String getHoverInfo(final ISourceViewer sourceViewer, final int lineNumber) { + return getHoverInfoInternal(lineNumber, -1); + } + + public String getHoverInfo(final ITextViewer textViewer, final IRegion hoverRegion) { + return getHoverInfo2(textViewer, hoverRegion); + } + + // for TextHover + public String getHoverInfo2(final ITextViewer textViewer, final IRegion hoverRegion) { + int lineNumber; + try { + lineNumber = getDocument().getLineOfOffset(hoverRegion.getOffset()); + } + catch (final BadLocationException e) { + return null; + } + return getHoverInfoInternal(lineNumber, hoverRegion.getOffset()); + } + + public IRegion getHoverRegion(final ITextViewer textViewer, final int offset) { + final Point selection = textViewer.getSelectedRange(); + if (selection.x <= offset && offset < selection.x + selection.y) + return new Region(selection.x, selection.y); + return new Region(offset, 0); + } + + protected String formatInfo(final List<String> messages) { + final StringBuffer buffer = new StringBuffer(); + if (messages.size() > 1) { + buffer.append(XtextUIMessages.AbstractHover_MultipleMarkers); + final Iterator<String> e = messages.iterator(); + while (e.hasNext()) { + splitInfo("- " + e.next() + "\n", buffer); + } + } + else if (messages.size() == 1) { + splitInfo(messages.get(0), buffer); + } + return buffer.toString(); + } + + protected abstract String getHoverInfoInternal(final int lineNumber, final int offset); + + private String splitInfo(final String message, final StringBuffer buffer) { + String msg = message; + String prefix = ""; + int pos; + do { + pos = msg.indexOf(" ", 60); + if (pos > -1) { + buffer.append(prefix + msg.substring(0, pos) + "\n"); + msg = msg.substring(pos); + prefix = " "; + } + else { + buffer.append(prefix + msg); + } + } while (pos > -1); + return buffer.toString(); + } +} diff --git a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/hover/ProblemHover.java b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/hover/ProblemHover.java new file mode 100644 index 0000000..5476598 --- a/dev/null +++ b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/hover/ProblemHover.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2007 Sven Efftinge (http://www.efftinge.de) 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: + * committers of openArchitectureWare + *******************************************************************************/ +package org.eclipse.xtext.ui.core.editor.hover; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.ui.texteditor.MarkerAnnotation; + +public class ProblemHover extends AbstractHover { + + public ProblemHover(final ISourceViewer sourceViewer) { + super(sourceViewer); + } + + @Override + protected String getHoverInfoInternal(final int lineNumber, + final int offset) { + final IAnnotationModel model = sourceViewer.getAnnotationModel(); + final List<String> messages = new ArrayList<String>(); + + final Iterator<?> iterator = model.getAnnotationIterator(); + while (iterator.hasNext()) { + final Annotation annotation = (Annotation) iterator.next(); + if (!(annotation instanceof MarkerAnnotation)) { + continue; + } + final MarkerAnnotation mAnno = (MarkerAnnotation) annotation; + final int start = model.getPosition(mAnno).getOffset(); + final int end = start + model.getPosition(mAnno).getLength(); + + if (offset > 0 && !(start <= offset && offset <= end)) { + continue; + } + try { + if (lineNumber != sourceViewer.getDocument().getLineOfOffset( + start)) { + continue; + } + } catch (final Exception x) { + continue; + } + messages.add(mAnno.getText().trim()); + } + return formatInfo(messages); + } +} diff --git a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/messages.properties b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/messages.properties index d78db61..c322f1f 100644 --- a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/messages.properties +++ b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/messages.properties @@ -11,6 +11,8 @@ XtextOutlineSortingAction.description=Sorts elements in the outline. XtextOutlineSortingAction.label=Sort XtextOutlineSortingAction.tooltip=Sort +AbstractHover_MultipleMarkers=Multiple markers at this line\\n + ContentAssistProposal.label=Content assist ContentAssistProposal.tooltip=Content assist ContentAssistProposal.description=Provides content assistance |

