/**
* Copyright (c) 2009-2011, The HATS Consortium. All rights reserved.
* This file is licensed under the terms of the Modified BSD License.
*/
package org.absmodels.abs.plugin.editor;
import static org.absmodels.abs.plugin.util.Constants.*;
import static org.absmodels.abs.plugin.util.UtilityFunctions.getDefaultPreferenceStore;
import org.absmodels.abs.plugin.console.ConsoleManager;
import org.absmodels.abs.plugin.console.ConsoleManager.MessageType;
import org.absmodels.abs.plugin.costabslink.CostabsLink;
import org.absmodels.abs.plugin.editor.contentassist.ABSCompletionProcessor;
import org.absmodels.abs.plugin.editor.reconciling.ABSReconcilingStrategy;
import org.absmodels.abs.plugin.util.Preferences;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.*;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.IContentAssistant;
import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
import org.eclipse.jface.text.hyperlink.IHyperlinkPresenter;
import org.eclipse.jface.text.hyperlink.MultipleHyperlinkPresenter;
import org.eclipse.jface.text.presentation.IPresentationReconciler;
import org.eclipse.jface.text.presentation.PresentationReconciler;
import org.eclipse.jface.text.reconciler.IReconciler;
import org.eclipse.jface.text.reconciler.MonoReconciler;
import org.eclipse.jface.text.rules.*;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.DefaultAnnotationHover;
import org.eclipse.jface.text.source.IAnnotationHover;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.texteditor.SimpleMarkerAnnotation;
/**
* Configures the {@link SourceViewer} which is the main part of the {@link ABSEditor}.
* The document is split into different partitions for comments, strings and code using
* a {@link PresentationReconciler} which uses {@link ITokenScanner} to create the partitions.
* Additionally the hovers for error markers and the content assist are initialized here.
*
* @author mweber
*
*/
public class ABSSourceViewerConfiguration extends SourceViewerConfiguration {
private ABSEditor editor;
public ABSSourceViewerConfiguration(ABSEditor editor){
this.editor = editor;
}
@Override
public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {
PresentationReconciler reconciler = new PresentationReconciler();
DefaultDamagerRepairer dr = new ABSDamagerRepairer(new ABSSingleCommentScanner());
reconciler.setDamager(dr, PARTITION_SINLGE_LINE_COMMENT);
reconciler.setRepairer(dr, PARTITION_SINLGE_LINE_COMMENT);
dr = new ABSDamagerRepairer(new ABSMultiCommentScanner());
reconciler.setDamager(dr, PARTITION_MULTI_LINE_COMMENT);
reconciler.setRepairer(dr, PARTITION_MULTI_LINE_COMMENT);
dr = new ABSDamagerRepairer(new ABSStringScanner());
reconciler.setDamager(dr, PARTITION_STRING);
reconciler.setRepairer(dr, PARTITION_STRING);
dr = new ABSDamagerRepairer(new ABSCharacterScanner());
reconciler.setDamager(dr, PARTITION_CHARACTER);
reconciler.setRepairer(dr, PARTITION_CHARACTER);
dr = new ABSDamagerRepairer(new ABSCodeScanner(new IdentifierWordDetector(), editor));
reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
return reconciler;
}
public static class ABSSingleCommentScanner extends RuleBasedScanner {
public ABSSingleCommentScanner() {
IPreferenceStore store = getDefaultPreferenceStore();
IToken token = Preferences.getToken(store, SYNTAXCOLOR_COMMENT);
IRule singleLineRule = new EndOfLineRule("//",token);
setRules(new IRule[] {singleLineRule});
}
}
public static class ABSMultiCommentScanner extends RuleBasedScanner {
public ABSMultiCommentScanner(){
IPreferenceStore store = getDefaultPreferenceStore();
IToken token = Preferences.getToken(store, SYNTAXCOLOR_COMMENT);
IRule multiLineRule = new MultiLineRule("/*", "*/", token, '\\', true);
setRules(new IRule[] {multiLineRule});
}
}
public static class ABSStringScanner extends RuleBasedScanner {
public ABSStringScanner() {
IPreferenceStore store = getDefaultPreferenceStore();
IToken token = Preferences.getToken(store, SYNTAXCOLOR_STRING);
IRule singleLineRule = new SingleLineRule("\"", "\"", token, '\\');
setRules(new IRule[] {singleLineRule});
}
}
public static class ABSCharacterScanner extends RuleBasedScanner {
public ABSCharacterScanner() {
IPreferenceStore store = getDefaultPreferenceStore();
IToken token = Preferences.getToken(store, SYNTAXCOLOR_STRING);
IRule singleLineRule = new SingleLineRule("'", "'", token, '\\');
setRules(new IRule[] {singleLineRule});
}
}
public static class IdentifierWordDetector implements IWordDetector{
@Override
public boolean isWordStart(char c){
return isWordPart(c);
}
@Override
public boolean isWordPart(char c){
return Character.isLetter(c) || Character.isDigit(c) || c == '_';
}
}
@Override
public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) {
return new DefaultAnnotationHover(){
@Override
protected boolean isIncluded(Annotation annotation) {
return isAnnotationIncluded(annotation);
}
};
}
@Override
public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType){
return new DefaultTextHover(sourceViewer){
@Override
protected boolean isIncluded(Annotation annotation) {
return isAnnotationIncluded(annotation);
}
};
}
private boolean isAnnotationIncluded(Annotation annotation) {
if(annotation instanceof SimpleMarkerAnnotation){SimpleMarkerAnnotation markerannotation = (SimpleMarkerAnnotation)annotation;
try {
return markerannotation.getMarker().exists()
&& ( markerannotation.getMarker().isSubtypeOf(MARKER_TYPE)
|| (markerannotation.getMarker().isSubtypeOf(LOCATION_TYPE_INFERENCE_MARKER_TYPE))
|| (markerannotation.getMarker().isSubtypeOf(CostabsLink.MARKER_UB)));
} catch (CoreException e) {
e.printStackTrace(ConsoleManager.getDefault().getPrintStream(MessageType.MESSAGE_ERROR));
}
}
return false;
}
@Override
public IContentAssistant getContentAssistant(ISourceViewer sourceViewer){
ContentAssistant assistant = new ContentAssistant();
assistant.setContentAssistProcessor(new ABSCompletionProcessor(editor), IDocument.DEFAULT_CONTENT_TYPE);
assistant.setInformationControlCreator(getInformationControlCreator(sourceViewer));
assistant.enableAutoActivation(true);
assistant.enableAutoInsert(true);
assistant.setAutoActivationDelay(0);
return assistant;
}
@Override
public IInformationControlCreator getInformationControlCreator(ISourceViewer sourceViewer) {
return new IInformationControlCreator() {
@Override
public IInformationControl createInformationControl(final Shell parent) {
final DefaultInformationControl.IInformationPresenter presenter = new DefaultInformationControl.IInformationPresenter() {
@Override
public String updatePresentation(Display display, String infoText, TextPresentation presentation, int maxWidth, int maxHeight) {
StyleRange range = new StyleRange(0, infoText.length(), null, null);
range.font = new Font(parent.getDisplay(), "Courier New", 10, SWT.NORMAL);
presentation.addStyleRange(range);
return infoText;
}
};
return new DefaultInformationControl(parent, presenter);
}
};
}
@Override
public IHyperlinkDetector[] getHyperlinkDetectors(ISourceViewer sourceViewer) {
return new IHyperlinkDetector[] {
new AbsHyperlinkDetector(editor)
};
}
@Override
public IReconciler getReconciler(ISourceViewer sourceViewer) {
ABSReconcilingStrategy strategy = new ABSReconcilingStrategy(editor);
MonoReconciler r = new MonoReconciler(strategy , false);
// the reconciler repareses the document
// when the user stops typing for 1 second:
r.setDelay(1000);
return r;
}
@Override
public IHyperlinkPresenter getHyperlinkPresenter(ISourceViewer sourceViewer) {
// overridden to allow multiple hyperlinks to be shown
return new MultipleHyperlinkPresenter(new RGB(0, 0, 255));
}
}