eclipse文件编辑器相关概念
编辑器 首先必须实现 IEditorPart 接口 必须要实现他的 createPartControl 方法 这个方法可以使用swt或者jface创建界面来显示文件的内容
swt不依赖于开发工具 jface是对swt的封装 依赖开发工具
编辑器因为有文件的输入 类IEditorInput定义了文件输入的协议,包含定义文件的名字 以及显示在编辑器上的label的图标
平台一般提供了以下几种实现
IFileEditorInput
对文件系统文件的输入
IURIEditorInput 是基于uri的
IStorageEditorInput 基于字节的
如果希望编辑器 能够重复多次使用 可以打开多个文件一起出现 必须实现 IReusableEditor 接口
如果希望编辑器 被记录到导航历史记录中(关闭eclipse后 回到最后次打开的界面 这就是导航历史记录) 必须实现 INavigationLocationProvider.接口
ITextEditor 继承IEditorPart 拓展了代码的层次结构
AbstractTextEditor 实现了支持源代码样式
当用户打开一个文件时 此时就有了 IFileEditorInput.对象,同时创建一个 IDocument,
IDocument,
用来对文本进行控制,此时就必须要有为输入文件IFileEditorInput.对象和 IDocument,关联的对象
这个就是 IDocumentProvider
java编辑器默认使用 org.eclipse.ui.editors.TextFileDocumentProvider 关联
<extension point="org.eclipse.ui.editors.documentProviders"> <provider class="org.eclipse.ui.editors.text.TextFileDocumentProvider" inputTypes="org.eclipse.ui.IStorageEditorInput" id="org.eclipse.ui.editors.text.StorageDocumentProvider"> </provider> </extension>
以上代码是注册document providers与文件后缀的关联 可以自己定义这个document providers
inputTypes就是输入的文件对象
TextFileDocumentProvider会根据inputTypes生成对应的IDocument
<extension id="ExampleJavaDocumentSetupParticipant" name="%documentSetupParticipantName" point="org.eclipse.core.filebuffers.documentSetup"> <participant extensions="jav" class="org.eclipse.ui.examples.javaeditor.JavaDocumentSetupParticipant"> </participant> </extension>
这个拓展用来映射 文件后缀和IDocumentSetupParticipant
IDocumentSetupParticipant对象组装给document对象一些被提供的组件 比如分割器
例如java版本的
public void setup(IDocument document) { IDocumentPartitioner partitioner= new FastPartitioner(JavaEditorExamplePlugin.getDefault().getJavaPartitionScanner( ), JavaPartitionScanner.JAVA_PARTITION_TYPES); partitioner.connect(document); }安装代码会创建一个分割对象
IDocumentPartitioner 用于将文档分割长若干不重叠的区域
表现为 ITypedRegion对象,他的好处在于可以提供比如 语法高亮和格式化等功能
分区对象被提供在 org.eclipse.jface.text.rules
可以使用FastPartitioner 对象进行快去分区
IDocumentPartitioner partitioner= new FastPartitioner(JavaEditorExamplePlugin.getDefault().getJavaPartitionScanner(), JavaPartitionScanner.JAVA_PARTITION_TYPES);RuleBasedPartitionScanner是所有分区扫描对象的父类
他的子类主要用于区分不同的项例如 分隔符,空格,表达式,单行,多行注释,
例如
JavaPartitionScanner
public JavaPartitionScanner() { super(); IToken javaDoc= new Token(JAVA_DOC); IToken comment= new Token(JAVA_MULTILINE_COMMENT); List rules= new ArrayList(); // Add rule for single line comments. rules.add(new EndOfLineRule("//", Token.UNDEFINED)); // Add rule for strings and character constants. rules.add(new SingleLineRule("\"", "\"", Token.UNDEFINED, '\\')); rules.add(new SingleLineRule("'", "'", Token.UNDEFINED, '\\')); // Add special case word rule. rules.add(new WordPredicateRule(comment)); // Add rules for multi-line comments and javadoc. rules.add(new MultiLineRule("/**", "*/", javaDoc, (char) 0, true)); rules.add(new MultiLineRule("/*", "*/", comment, (char) 0, true)); IPredicateRule[] result= new IPredicateRule[rules.size()]; rules.toArray(result); setPredicateRules(result); }
TextViewer对象提供了比较低级的代码着色和格式化
SourceViewer 引进了两个概念
Annotations Rule
注解被展示在编辑器左边的位置
Overview ruler
被展示在编辑器右边的列或者在边框底部的一条有颜色的线
希望annotation展示在overview的位置 必须
将annotation的类型添加到overview中
提供了处理
private void showAnnotationOverview(Object annotationType) { if (fOverviewRuler != null) { Color c= getAnnotationTypeColor(annotationType); fOverviewRuler.setAnnotationTypeColor(annotationType, c); int l= getAnnotationTypeLayer(annotationType); fOverviewRuler.setAnnotationTypeLayer(annotationType, l); fOverviewRuler.addAnnotationType(annotationType); fOverviewRuler.update(); } }IAnnotationAccess
用于处理比较特别的annotation
TextEditor使用DefaultMarkerAnnotationAccess获取 IAnnotationAccess
protected IAnnotationAccess createAnnotationAccess() { return new DefaultMarkerAnnotationAccess(fAnnotationPreferences); }
source viewer提供annotation 在文本上带有着色的标志 比如
source viewer在AbstractDecoratedTextEditor.创建着色annotation 例如
protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) { ... ISourceViewer sourceViewer= new SourceViewer(parent, ruler, fOverviewRuler, isOverviewRulerVisible(), styles); fSourceViewerDecorationSupport= new SourceViewerDecorationSupport(sourceViewer, fOverviewRuler, fAnnotationAccess, sharedColors); configureSourceViewerDecorationSupport(); return sourceViewer; }SourceViewerDecorationSupport 用于控制在文本上的装饰显示
比如文本annotation ,着色边缘,着色光标线,标记等
如果想了解更多研究关于
SourceViewerDecorationSupport 和相关的类
例如AnnotationPainter
AbstractDecoratedTextEditor 对装饰的支持 例如.
protected void configureSourceViewerDecorationSupport() { Iterator e= fAnnotationPreferences.getAnnotationPreferences().iterator(); while (e.hasNext()) fSourceViewerDecorationSupport.setAnnotationPreference((AnnotationPreference) e.next()); fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(DefaultMarkerAnnotationAccess.UNKNOWN, UNKNOWN_INDICATION_COLOR, UNKNOWN_INDICATION, UNKNOWN_INDICATION_IN_OVERVIEW_RULER, 0); fSourceViewerDecorationSupport.setCursorLinePainterPreferenceKeys(CURRENT_LINE, CURRENT_LINE_COLOR); fSourceViewerDecorationSupport.setMarginPainterPreferenceKeys(PRINT_MARGIN, PRINT_MARGIN_COLOR, PRINT_MARGIN_COLUMN); fSourceViewerDecorationSupport.setSymbolicFontName(getFontPropertyPreferenceKey()); }
如何配置source viewer
当sourceviwer实例化时首先需要设置 SourceViewerConfiguration对象 主要是协助生成文档伸缩,代码重做,双击,文本悬浮和高亮等行为的帮助对象
protected void initializeEditor() { super.initializeEditor(); setSourceViewerConfiguration(new JavaSourceViewerConfiguration()); ...普通的SourceViewerConfiguration 并不能满足对编辑器功能的需要 需要覆盖initializeEditor() 方法
例如java的
//创建文件悬浮的帮助对象
public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) { return new JavaAnnotationHover(); } //创建自动伸展的帮助对象 public IAutoIndentStrategy getAutoIndentStrategy(ISourceViewer sourceViewer, String contentType) { return (IDocument.DEFAULT_CONTENT_TYPE.equals(contentType) ? new JavaAutoIndentStrategy() : new DefaultAutoIndentStrategy()); }
文本悬浮
SourceViewerConfiguration对象默认并未提供对文本悬浮的支持 因为并不知道文本究竟会显示什么东西
并需在对象中定义悬浮对象
public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) { return new JavaTextHover(); } public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) { return new JavaAnnotationHover(); }ITextHover接口用户处理悬浮的帮助类
ITextHover 可供偏离度 计算当前代码的位置
public class JavaTextHover implements ITextHover { ... public IRegion getHoverRegion(ITextViewer textViewer, int offset) { 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); } }
同时获取到某个区域的代码
public class JavaTextHover implements ITextHover { public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) { if (hoverRegion != null) { try { if (hoverRegion.getLength() > -1) return textViewer.getDocument().get(hoverRegion.getOffset(), hoverRegion.getLength()); } catch (BadLocationException x) { } } return JavaEditorMessages.getString("JavaTextHover.emptySelection"); } ... }
代码着色
SourceViewerConfiguration 默认没有提供代码着色的支持
需要定义代码着色的装饰器
public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) { PresentationReconciler reconciler= new PresentationReconciler(); ... return reconciler; }
损坏,修复,修改同步
当初始代码构建后 颜色的结构确定了 当插入或者删除一个字符时就会导致文档的格式破坏 着色也应该相应的改变IPresentationDamager表示文档已经修改,已经破坏, 必须需要被重新构造着色,他必须返回损坏的区域,必须对repairer( IPresentationRepairer)是有效的区域
repairer必须从damager中提取足够的信息去修复文档
reconciler
(IPresentationReconciler) 主要是实时同步文档,能够发现文档发生改变 并通知damager
同时计算damager 调用repairer 进行修复
org.eclipse.jface.text.reconciler 定义了
同步的类
基于规则的同步类 定义在 org.eclipse.jface.text.rules包下
演示如何使用PresentationReconciler 和 DefaultDamagerRepairer.
在SourceViewerConfigation中实现
public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) 方法
内容如下
JavaColorProvider provider= JavaEditorEnvironment.getJavaColorProvider(); PresentationReconciler reconciler= new PresentationReconciler(); DefaultDamagerRepairer dr= new DefaultDamagerRepairer(JavaEditorEnvironment.getJavaCodeScanner()); reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE); reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE); dr= new DefaultDamagerRepairer(new SingleTokenScanner(new TextAttribute(provider.getColor(JavaColorProvider.JAVADOC_DEFAULT)))); reconciler.setDamager(dr, JavaPartitionScanner.JAVA_DOC); reconciler.setRepairer(dr, JavaPartitionScanner.JAVA_DOC); dr= new DefaultDamagerRepairer(new SingleTokenScanner(new TextAttribute(provider.getColor(JavaColorProvider.MULTI_LINE_COMMENT)))); reconciler.setDamager(dr, JavaPartitionScanner.JAVA_MULTILINE_COMMENT); reconciler.setRepairer(dr, JavaPartitionScanner.JAVA_MULTILINE_COMMENT); return reconciler;
代码辅助
代码辅助的类主要被定义在org.eclipse.jface.text.contentassist.下
SourceViewerConfigation实现一下方法可以实现代码辅助
public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) { ContentAssistant assistant= new ContentAssistant(); assistant.setContentAssistProcessor(new JavaCompletionProcessor(), IDocument.DEFAULT_CONTENT_TYPE); assistant.setContentAssistProcessor(new JavaDocCompletionProcessor(), JavaPartitionScanner.JAVA_DOC); ... return assistant; }
代码辅助的类必须实现 IContentAssistant.接口
不同的文档类型 使用不同的处理策略 策略类 需要实现 IContentAssistProcessor.接口
JavaCompletionProcessor 例子
public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) { ICompletionProposal[] result= new ICompletionProposal[fgProposals.length]; for (int i= 0; i < fgProposals.length; i++) { IContextInformation info= new ContextInformation(fgProposals[i], MessageFormat.format(JavaEditorMessages.getString("CompletionProcessor.Proposal.ContextInfo.pattern"), new Object[] { fgProposals[i] })); //$NON-NLS-1$ result[i]= new CompletionProposal(fgProposals[i], documentOffset, 0, fgProposals[i].length(), null, fgProposals[i], info, MessageFormat.format(JavaEditorMessages.getString("CompletionProcessor.Proposal.hoverinfo.pattern"), new Object[] { fgProposals[i]})); //$NON-NLS-1$ } return result; }
配置触发代码提示
public char[] getCompletionProposalAutoActivationCharacters() { return new char[] { '.', '(' }; }编辑器中的内容中的对象提示
public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) { IContextInformation[] result= new IContextInformation[5]; for (int i= 0; i < result.length; i++) result[i]= new ContextInformation( MessageFormat.format(JavaEditorMessages.getString("CompletionProcessor.ContextInfo.display.pattern"), new Object[] { new Integer(i), new Integer(documentOffset) }), MessageFormat.format(JavaEditorMessages.getString("CompletionProcessor.ContextInfo.value.pattern"), new Object[] { new Integer(i), new Integer(documentOffset - 5), new Integer(documentOffset + 5)})); return result; }出发代码提示:
public char[] getContextInformationAutoActivationCharacters() { return new char[] { '#' }; }