SWT TextEditor 相关的概念

编辑器 首先必须实现 IEditorPart 接口 必须要实现他的 createPartControl 方法 这个方法可以使用swt或者jface创建界面来显示文件的内容 

swt不依赖于开发工具  jface是对swt的封装 依赖开发工具

 

编辑器因为有文件的输入 类IEditorInput定义了文件输入的协议,包含定义文件的名字 以及显示在编辑器上的label的图标

Editor input label

 

平台一般提供了以下几种实现

IFileEditorInput  对文件系统文件的输入

 IURIEditorInput 是基于uri的

 IStorageEditorInput 基于字节的

 

如果希望编辑器 能够重复多次使用 可以打开多个文件一起出现 必须实现 IReusableEditor 接口

如果希望编辑器 被记录到导航历史记录中(关闭eclipse后 回到最后次打开的界面 这就是导航历史记录) 必须实现 INavigationLocationProvider.接口

 ITextEditor 继承IEditorPart 拓展了代码的层次结构

AbstractTextEditor 实现了支持源代码样式

 

 

当用户打开一个文件时 此时就有了 IFileEditorInput.对象,同时创建一个 IDocument

 IDocument, 用来对文本进行控制,此时就必须要有为输入文件IFileEditorInput.对象 IDocument,关联的对象 这个就是 IDocumentProvider

java编辑器默认使用  org.eclipse.ui.editors.TextFileDocumentProvider 关联

 

定义 IDocumentProvider

 <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

注解被展示在编辑器左边的位置 

Vertical ruler

Overview ruler

被展示在编辑器右边的列或者在边框底部的一条有颜色的线

Vertical overview ruler in Java Editor

 

希望annotation展示在overview的位置 必须

annotation的类型添加到overview中

 SourceViewerDecorationSupport

提供了处理 

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 在文本上带有着色的标志 比如

Squiggly mark in Java Editor

 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"); 
	}
	...
}

Hover information on selected region

代码着色

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[] { '#' };
}

猜你喜欢

转载自lifei114.iteye.com/blog/2254461
swt