package com.sap.ide.refactoring.ui;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.TextPresentation;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.AnnotationModel;
import org.eclipse.jface.text.source.AnnotationPainter;
import org.eclipse.jface.text.source.AnnotationRulerColumn;
import org.eclipse.jface.text.source.CompositeRuler;
import org.eclipse.jface.text.source.IAnnotationAccess;
import org.eclipse.jface.text.source.IAnnotationHover;
import org.eclipse.jface.text.source.ISharedTextColors;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.OverviewRuler;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
import org.eclipse.ltk.ui.refactoring.TextStatusContextViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import textblocks.DocumentNode;
import textblocks.TextBlock;
import com.sap.ide.cts.editor.AbstractGrammarBasedEditor;
import com.sap.ide.cts.editor.AbstractGrammarBasedViewerConfiguration.AnnotationHover;
import com.sap.ide.cts.editor.AnnotationMarkerAccess;
import com.sap.ide.refactoring.core.RefactoringSeverity;
import com.sap.mi.textual.parsing.textblocks.TbUtil;
/**
* An Eclipse refactoring context status viewer extended with source code annotations.
* Can serve as a base class for other context viewers.
*
* @author Stephan Erb (d049157)
*
*/
public abstract class AnnotationEnabledStatusContextViewer extends TextStatusContextViewer {
private class ColorCache implements ISharedTextColors {
@Override
public Color getColor(RGB rgb) {
return new Color(Display.getDefault(), rgb);
}
@Override
public void dispose() {
}
}
private class CodeViewerConfiguration extends SourceViewerConfiguration {
private final AnnotationModel annotationModel;
public CodeViewerConfiguration(AnnotationModel annotationModel) {
this.annotationModel = annotationModel;
}
@Override
public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) {
return new AnnotationHover(annotationModel);
}
}
private static final String ERROR_TYPE = severityAsAnnotationString(RefactoringSeverity.ERROR);
private static final String WARNING_TYPE = severityAsAnnotationString(RefactoringSeverity.WARNING);
private static final RGB ERROR_RGB = new RGB(255, 0, 0);
private static final RGB WARNING_RGB = new RGB(255, 255, 0);
protected final TextPresentation textPresentation = new TextPresentation();
protected SourceViewer sourceViewer;
protected AnnotationModel annotationModel;
protected OverviewRuler overviewRuler;
@Override
protected SourceViewer createSourceViewer(Composite parent) {
annotationModel = new AnnotationModel();
// rulers
IAnnotationAccess annotationAccess = new AnnotationMarkerAccess();
CompositeRuler compositeRuler = new CompositeRuler();
ColorCache colorCache = new ColorCache();
overviewRuler = new OverviewRuler(annotationAccess, 12, colorCache);
AnnotationRulerColumn annotationRuler = new AnnotationRulerColumn(annotationModel, 16, annotationAccess);
compositeRuler.setModel(annotationModel);
overviewRuler.setModel(annotationModel);
// annotation ruler is decorating our composite ruler
compositeRuler.addDecorator(0, annotationRuler);
// add what types are show on the different rulers
annotationRuler.addAnnotationType(ERROR_TYPE);
annotationRuler.addAnnotationType(WARNING_TYPE);
overviewRuler.addAnnotationType(ERROR_TYPE);
overviewRuler.addAnnotationType(WARNING_TYPE);
overviewRuler.addHeaderAnnotationType(ERROR_TYPE);
overviewRuler.addHeaderAnnotationType(WARNING_TYPE);
// set what layer this type is on
overviewRuler.setAnnotationTypeLayer(ERROR_TYPE, 3);
overviewRuler.setAnnotationTypeLayer(WARNING_TYPE, 3);
// set what color is used on the overview ruler for the type
overviewRuler.setAnnotationTypeColor(ERROR_TYPE, new Color(Display.getDefault(), ERROR_RGB));
overviewRuler.setAnnotationTypeColor(WARNING_TYPE, new Color(Display.getDefault(), WARNING_RGB));
sourceViewer = new SourceViewer(parent, compositeRuler, overviewRuler, true, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI | SWT.FULL_SELECTION);
// to paint the annotations
AnnotationPainter ap = new AnnotationPainter(sourceViewer, annotationAccess);
ap.addAnnotationType(ERROR_TYPE);
ap.addAnnotationType(WARNING_TYPE);
ap.setAnnotationTypeColor(ERROR_TYPE, new Color(Display.getDefault(), ERROR_RGB));
ap.setAnnotationTypeColor(WARNING_TYPE, new Color(Display.getDefault(), WARNING_RGB));
sourceViewer.addPainter(ap); // this will draw the squigglies under the text
sourceViewer.configure(new CodeViewerConfiguration(annotationModel));
return sourceViewer;
}
protected void addAnnotation(RefactoringSeverity severity, String message, DocumentNode documentNode) {
Annotation annotation = new Annotation(severityAsAnnotationString(severity), /*persistent*/false, message);
Position position;
position = new Position(TbUtil.getAbsoluteOffsetWithoutBlanks((TextBlock) documentNode), documentNode.getLength());
highlightTextPosition(position);
annotationModel.addAnnotation(annotation, position);
overviewRuler.update();
}
private static String severityAsAnnotationString(RefactoringSeverity severity) {
switch (severity) {
case ERROR:
return AbstractGrammarBasedEditor.ERROR_TYPE;
case FATAL:
return AbstractGrammarBasedEditor.ERROR_TYPE;
case WARNING:
return AbstractGrammarBasedEditor.WARNING_TYPE;
default:
return severity.toString();
}
}
protected void highlightTextPosition(Position position) {
// per default, no highlight
}
protected void setAnnotatedDocumentRegion(IDocument document, IRegion region) {
Control ctrl = getControl();
if (ctrl != null && ctrl.isDisposed()) {
ctrl = null;
}
try {
if (ctrl != null) {
ctrl.setRedraw(false);
}
sourceViewer.setDocument(document, annotationModel);
if (region != null && document != null) {
int offset = region.getOffset();
int length = region.getLength();
if (offset >= 0 && length >= 0) {
sourceViewer.setSelectedRange(offset, length);
sourceViewer.revealRange(offset, length);
}
}
} finally {
if (ctrl != null) {
ctrl.setRedraw(true);
}
}
}
@Override
public void setInput(RefactoringStatusContext input) {
annotationModel.removeAllAnnotations();
textPresentation.clear();
setInputAndAnnotations(input);
}
protected abstract void setInputAndAnnotations(RefactoringStatusContext input);
}