From 8654bb782a2009eff724394cb4bc3bf348f0b4a9 Thu, 12 Aug 2010 13:57:26 +0800 From: Jin Mingjian Date: Sat, 7 Aug 2010 21:10:17 +0800 Subject: [PATCH] Feature#1. Visual indicators of the application of implicit conversions and the provision of implicit parameters. diff --git a/org.scala-ide.sdt.core/plugin.xml b/org.scala-ide.sdt.core/plugin.xml index f6bbe7f..4858327 100644 --- a/org.scala-ide.sdt.core/plugin.xml +++ b/org.scala-ide.sdt.core/plugin.xml @@ -39,6 +39,18 @@ id="org.scala-ide.sdt.core.preferences.Templates" name="Templates"> + + + + @@ -534,6 +546,9 @@ + + diff --git a/org.scala-ide.sdt.core/src/scala/tools/eclipse/ScalaSourceFileEditor.scala b/org.scala-ide.sdt.core/src/scala/tools/eclipse/ScalaSourceFileEditor.scala index 10eb418..5b257ed 100644 --- a/org.scala-ide.sdt.core/src/scala/tools/eclipse/ScalaSourceFileEditor.scala +++ b/org.scala-ide.sdt.core/src/scala/tools/eclipse/ScalaSourceFileEditor.scala @@ -4,7 +4,9 @@ // $Id$ package scala.tools.eclipse + import java.util.ResourceBundle + import org.eclipse.core.runtime.{ IAdaptable, IProgressMonitor } import org.eclipse.jdt.core.IJavaElement import org.eclipse.jdt.core.dom.CompilationUnit @@ -20,10 +22,15 @@ import org.eclipse.ui.{ IWorkbenchPart, ISelectionListener, IFileEditorInput } import org.eclipse.ui.editors.text.{ ForwardingDocumentProvider, TextFileDocumentProvider } import org.eclipse.ui.texteditor.{ IAbstractTextEditorHelpContextIds, ITextEditorActionConstants, IWorkbenchActionDefinitionIds, TextOperationAction } +import org.eclipse.swt.widgets.Composite + import scala.collection.JavaConversions._ import scala.collection.mutable + import scala.tools.eclipse.javaelements.ScalaSourceFile import scala.tools.eclipse.markoccurrences.{ ScalaOccurrencesFinder, Occurrences } +import scala.tools.eclipse.ui.semantic.highlighting.SemanticHighlightingPresenter + class ScalaSourceFileEditor extends CompilationUnitEditor with ScalaEditor { import ScalaSourceFileEditor._ @@ -134,6 +141,16 @@ updateOccurrenceAnnotations(selection.asInstanceOf[ITextSelection], null) } }) + } + + //XXX: By Jin Mingjian + override def createPartControl(parent: Composite){ + super.createPartControl(parent) + // + val presenter = new SemanticHighlightingPresenter(this,getSourceViewer()) + getSourceViewer().getDocument().addDocumentListener(presenter) +// getSourceViewer().addTextInputListener(presenter) +// getSourceViewer().asInstanceOf[org.eclipse.jface.text.TextViewer].addTextPresentationListener(presenter) } } diff --git a/org.scala-ide.sdt.core/src/scala/tools/eclipse/ui/preferences/ScalaEditorColoringPreferencePage.scala b/org.scala-ide.sdt.core/src/scala/tools/eclipse/ui/preferences/ScalaEditorColoringPreferencePage.scala new file mode 100644 index 0000000..b0dcd77 --- /dev/null +++ b/org.scala-ide.sdt.core/src/scala/tools/eclipse/ui/preferences/ScalaEditorColoringPreferencePage.scala @@ -0,0 +1,96 @@ +package scala.tools.eclipse.ui.preferences; + +import org.eclipse.jface.preference._; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.IWorkbench; + +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +import org.eclipse.jface.preference.IPreferenceStore; + +import org.eclipse.swt.graphics.RGB; + +import scala.tools.eclipse.ScalaPlugin; + + +class ScalaEditorColoringPreferencePage extends FieldEditorPreferencePage + with IWorkbenchPreferencePage { + import ScalaEditorColoringPreferencePage._ + + setPreferenceStore(ScalaPlugin.plugin.getPreferenceStore()); + setDescription("Set the highlighting for implicit conversions and implicit parameters."); + + + /** + * Creates the field editors. Field editors are abstractions of + * the common GUI blocks needed to manipulate various types + * of preferences. Each field editor knows how to save and + * restore itself. + */ + override def createFieldEditors() { + addField( + new ColorFieldEditor(P_COLOR, + "Color:", getFieldEditorParent())); + addField( + new BooleanFieldEditor(P_BLOD, + "Blod", + getFieldEditorParent())); + addField( + new BooleanFieldEditor(P_ITALIC, + "Italic", + getFieldEditorParent())); + val entryNamesAndValues = new Array[Array[String]](4, 2) + entryNamesAndValues(0)(0)="Squiggle" + entryNamesAndValues(0)(1)="1" + entryNamesAndValues(1)(0)="Double" + entryNamesAndValues(1)(1)="2" + entryNamesAndValues(2)(0)="Single" + entryNamesAndValues(2)(1)="3" + entryNamesAndValues(3)(0)="None" + entryNamesAndValues(3)(1)="4" + addField( + new ComboFieldEditor(P_UNDERLINE, + "UnderLine Style", + entryNamesAndValues, + getFieldEditorParent())); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) + */ + override def init(workbench: IWorkbench) { + } +} + + +object ScalaEditorColoringPreferencePage { + val P_COLOR = "colorPreference"; + val P_BLOD = "blodPreference"; + val P_ITALIC= "italicPreference"; + val P_UNDERLINE = "underLinePreference"; +} + + + +/** + * Class used to initialize default preference values. + */ +class ScalaEditorColoringPagePreferenceInitializer extends AbstractPreferenceInitializer { + + import ScalaEditorColoringPreferencePage._ + + /* + * (non-Javadoc) + * + * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences() + */ + override def initializeDefaultPreferences() { + val store = ScalaPlugin.plugin.getPreferenceStore(); + val green = new RGB(0, 255, 0); + PreferenceConverter.setDefault(store,P_COLOR, green); + store.setDefault(P_BLOD, true); + store.setDefault(P_ITALIC, true); + store.setDefault(P_UNDERLINE, 1); + } + +} + diff --git a/org.scala-ide.sdt.core/src/scala/tools/eclipse/ui/preferences/ScalaEditorPreferencePage.scala b/org.scala-ide.sdt.core/src/scala/tools/eclipse/ui/preferences/ScalaEditorPreferencePage.scala new file mode 100644 index 0000000..09b09eb --- /dev/null +++ b/org.scala-ide.sdt.core/src/scala/tools/eclipse/ui/preferences/ScalaEditorPreferencePage.scala @@ -0,0 +1,54 @@ +package scala.tools.eclipse.ui.preferences; + +import org.eclipse.jface.preference._; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.IWorkbench; + +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +import org.eclipse.jface.preference.IPreferenceStore; + +import scala.tools.eclipse.ScalaPlugin; + +class ScalaEditorPreferencePage + extends FieldEditorPreferencePage + with IWorkbenchPreferencePage { + + setPreferenceStore(ScalaPlugin.plugin.getPreferenceStore()); + setDescription("Editor preference page"); + + + /** + * Creates the field editors. Field editors are abstractions of + * the common GUI blocks needed to manipulate various types + * of preferences. Each field editor knows how to save and + * restore itself. + */ + override def createFieldEditors() { + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) + */ + override def init(workbench: IWorkbench) { + } + +} + +/** + * Class used to initialize default preference values. + */ +class ScalaEditorPagePreferenceInitializer extends AbstractPreferenceInitializer { + + /* + * (non-Javadoc) + * + * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences() + */ + override def initializeDefaultPreferences() { + val store = ScalaPlugin.plugin.getPreferenceStore(); + } + +} + +object ScalaEditorPagePreferenceConstants { +} \ No newline at end of file diff --git a/org.scala-ide.sdt.core/src/scala/tools/eclipse/ui/semantic/highlighting/ImplicitConversionsOrArgsAnnotation.scala b/org.scala-ide.sdt.core/src/scala/tools/eclipse/ui/semantic/highlighting/ImplicitConversionsOrArgsAnnotation.scala new file mode 100644 index 0000000..758b7a0 --- /dev/null +++ b/org.scala-ide.sdt.core/src/scala/tools/eclipse/ui/semantic/highlighting/ImplicitConversionsOrArgsAnnotation.scala @@ -0,0 +1,36 @@ +package scala.tools.eclipse.ui.semantic.highlighting + +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationPresentation; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.custom.StyleRange +import org.eclipse.swt.graphics.Color +import org.eclipse.jface.text.source.AnnotationPainter; + +class ImplicitConversionsOrArgsAnnotation(kind: String, isPersistent: Boolean, text: String) extends Annotation(kind, isPersistent, text) + +object ImplicitConversionsOrArgsAnnotation { + final val KIND = "scala.tools.eclipse.ui.semantic.highlighting.implicitConversionsOrArgsAnnotation" +} + + +class ImplicitConversionsOrArgsDrawingStrategy(fUnderlineStyle: Int, fFontStyle: Int) extends AnnotationPainter.ITextStyleStrategy { + + def applyTextStyle(styleRange: StyleRange, annotationColor: Color) { + styleRange.fontStyle = fFontStyle + if (fUnderlineStyle==8) { + styleRange.underline= false + return + } + styleRange.underline= true + styleRange.underlineStyle= fUnderlineStyle + styleRange.underlineColor= annotationColor + } + +} \ No newline at end of file diff --git a/org.scala-ide.sdt.core/src/scala/tools/eclipse/ui/semantic/highlighting/SemanticHighlightingPresenter.scala b/org.scala-ide.sdt.core/src/scala/tools/eclipse/ui/semantic/highlighting/SemanticHighlightingPresenter.scala new file mode 100644 index 0000000..282af9e --- /dev/null +++ b/org.scala-ide.sdt.core/src/scala/tools/eclipse/ui/semantic/highlighting/SemanticHighlightingPresenter.scala @@ -0,0 +1,124 @@ +/** + * + */ +package scala.tools.eclipse.ui.semantic.highlighting + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor; +import org.eclipse.jdt.internal.ui.JavaPlugin; + +import org.eclipse.core.runtime.IProgressMonitor; + +import org.eclipse.jface.preference.IPreferenceStore +import org.eclipse.jface.preference.PreferenceConverter + +import org.eclipse.jface.text.source.ISourceViewer; + +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentListener; +import org.eclipse.jface.text.ITextInputListener; +import org.eclipse.jface.text.ITextPresentationListener; +import org.eclipse.jface.text.TextPresentation; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.{IAnnotationAccess,AnnotationPainter,IAnnotationModelExtension}; + +import org.eclipse.swt.SWT + +import scala.tools.eclipse.javaelements.ScalaCompilationUnit; +import scala.tools.nsc.util.RangePosition +import scala.tools.eclipse.util.ColorManager + +import scala.collection._ + +/** + * @author Jin Mingjian + * + */ +class SemanticHighlightingPresenter(fEditor: CompilationUnitEditor, fSourceViewer: ISourceViewer) extends IDocumentListener { + + var currentAnnotations: Array[Annotation] = _ + + val annotationAccess = new IAnnotationAccess() { + def getType(annotation: Annotation) = annotation.getType(); + def isMultiLine(annotation: Annotation) = true + def isTemporary(annotation: Annotation) = true + }; + val painter = new AnnotationPainter(fSourceViewer, annotationAccess); + import scala.tools.eclipse.ui.preferences.ScalaEditorColoringPreferencePage._ + val fUnderlineStyle = getPreferenceStore().getInt(P_UNDERLINE) match { + case 1 => SWT.UNDERLINE_SQUIGGLE + case 2 => SWT.UNDERLINE_DOUBLE + case 3 => SWT.UNDERLINE_SINGLE + case 4 => 8 // for no underline case + } + val fFontStyle1 = getPreferenceStore().getBoolean(P_BLOD) match { + case true => SWT.BOLD + case _ => SWT.NORMAL + } + val fFontStyle2 = getPreferenceStore().getBoolean(P_ITALIC) match { + case true => SWT.ITALIC + case _ => SWT.NORMAL + } + val fColorValue = PreferenceConverter.getColor(getPreferenceStore(),P_COLOR) + painter.addTextStyleStrategy(ImplicitConversionsOrArgsAnnotation.KIND, + new ImplicitConversionsOrArgsDrawingStrategy(fUnderlineStyle,fFontStyle1 | fFontStyle2) ); + painter.addAnnotationType(ImplicitConversionsOrArgsAnnotation.KIND, ImplicitConversionsOrArgsAnnotation.KIND); + painter.setAnnotationTypeColor(ImplicitConversionsOrArgsAnnotation.KIND, + ColorManager.getDefault.getColor(fColorValue)) + fSourceViewer.asInstanceOf[org.eclipse.jface.text.TextViewer].addPainter(painter); + fSourceViewer.asInstanceOf[org.eclipse.jface.text.TextViewer].addTextPresentationListener(painter); + + + /** + * The manipulation described by the document event will be performed. + * + * @param event the document event describing the document change + */ + override def documentAboutToBeChanged(event: DocumentEvent){} + + /** + * The manipulation described by the document event has been performed. + * + * @param event the document event describing the document change + */ + override def documentChanged(event: DocumentEvent) { + update() + } + + + def update() { + val cu = JavaPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(fEditor.getEditorInput()); + val scu = cu.asInstanceOf[ScalaCompilationUnit] + scu.withCompilerResult({ crh => + import crh._ + + val toAdds = new java.util.HashMap[Annotation,org.eclipse.jface.text.Position] + var toAddAnnotations = List[Annotation]() + object viewsCollector extends compiler.Traverser { + override def traverse(t: compiler.Tree): Unit = t match { + case v: compiler.ApplyImplicitView => + val ia = new ImplicitConversionsOrArgsAnnotation(ImplicitConversionsOrArgsAnnotation.KIND, + false, + v.fun.toString) + val pos = new org.eclipse.jface.text.Position(v.pos.start, v.pos.end-v.pos.start); + toAdds.put(ia,pos) + toAddAnnotations = ia::toAddAnnotations + println(v) + super.traverse(t) + case _ => + super.traverse(t) + } + } + viewsCollector.traverse(body) + + fSourceViewer.getAnnotationModel().asInstanceOf[IAnnotationModelExtension].replaceAnnotations(currentAnnotations,toAdds); + currentAnnotations = toAddAnnotations.toArray + }) + } + + def getPreferenceStore(): IPreferenceStore = { + scala.tools.eclipse.ScalaPlugin.plugin.getPreferenceStore() + } + +} \ No newline at end of file diff --git a/org.scala-ide.sdt.core/src/scala/tools/eclipse/util/ColorManager.scala b/org.scala-ide.sdt.core/src/scala/tools/eclipse/util/ColorManager.scala new file mode 100644 index 0000000..6d0bda1 --- /dev/null +++ b/org.scala-ide.sdt.core/src/scala/tools/eclipse/util/ColorManager.scala @@ -0,0 +1,31 @@ +package scala.tools.eclipse.util + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Display; + +class ColorManager private() { + + val fColorTable = scala.collection.mutable.Map.empty[RGB,Color]; + + def getColor(rgb: RGB): Color = { + var color: Option[Color] = fColorTable.get(rgb); + if (color == None ) { + fColorTable(rgb)=new Color(Display.getCurrent(), rgb); + } + return fColorTable(rgb); + } + + def dispose() { + for (c <- fColorTable.values) c.dispose(); + } +} + +object ColorManager { + private val fgColorManager: ColorManager = new ColorManager + def getDefault(): ColorManager = fgColorManager +} \ No newline at end of file -- Git Team Provider UI (Incubation) 0.8.4