`
hqs7636
  • 浏览: 221173 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

基于 JFace Text Framework 构建全功能代码编辑器: 第 5 部分:

阅读更多
https://www.ibm.com/developerworks/cn/opensource/os-cn-ecljtf5/

Text Decoration
developerWorks


文档选项
将打印机的版面设置成横向打印模式

打印本页
将此页作为电子邮件发送

将此页作为电子邮件发送


样例代码

级别: 中级

马 若劼 (maruojie@cn.ibm.com), 软件工程师, IBM 中国软件开发中心

2008 年 4 月 10 日

    Text Decoration(文本装饰)是指对文本进行一些附加的视觉效果处理。本文介绍和文本装饰相关的概念并讨论如何在 JTF 中支持文本装饰。

Text Decoration

对于代码编辑器来说,Text Decoration(文本装饰)是一个必需的功能。我们先来看看 Java 编辑器中对文本装饰的应用:

图1. Java 编辑器中的文本装饰
Java 编辑器中的文本装饰

可以看到 Java 编辑器会把错误的部分用一个红色的波浪线标记出来,还可以看到对于模版来说,模版参数周围有一个小矩形,而且在左边还有相应的错误图标显示。这些都叫做文本装饰。

提示:模版会在以后的文章中进行介绍

我们在编辑代码的时候,出错是不可避免的,因此有了文本装饰功能之后,我们可以快速的发现错误位置,这对代码编辑是非常有用的。下面就来看一看要实现文本装饰功能都需要了解哪些概念。

Annotation

Annotation(标注)这个术语已经使用的很泛滥了,在很多地方都可以看到,比如 J2SE 5.0 中也有 Annotation 的概念。放到 JTF 中来讲,标注指的是和某块文本区域绑定的特定信息,至于特定信息是什么,是可以自定义的。可以观察一下 JTF 中 Annotation 这个类,可以看到它有类型信息,有附加的文本信息,同时它还有很多子类,而且子类也都包含了一些扩展信息。

标注包含类型信息是很重要的,通过类型,就可以知道某个标注的目的和作用了,然后可以在界面上反映出来。图 1 中的红色波浪线,实际上是因为在那个位置上有一个错误类型的标注。

Ruler

Ruler(标尺)是显示辅助信息的一块区域,它一般附着在编辑器的周围。比如图1中那两个表示错误的图标就是显示在 VerticalRuler(垂直标尺)上的。标尺可以多于一个,在图 1 中可以看到另外一个用来显示行号的标尺,需要多少个标尺可以定制的。

IAnnotationPresentation

名称里面带了“Presentation”字样的都和界面渲染有关,而 IAnnotationPresentation 就是用来渲染标注的。这个接口只是负责在标尺上绘制标注,图1中表示错误的图标就是出自这里。如果你自己定义的标注没有实现这个接口,那么就不会出现在标尺上了。

IAnnotationModel

IAnnotationModel 是用来管理标注的。它负责管理某个文档上所有的标注,并且负责触发相应的标注事件,比如添加,删除等等。也许这个接口叫做 IAnnotationManager 更合适些。由于 Eclipse 不断在发展中,它的 API 时常需要增强,但是为了不破坏与旧版本的兼容性,这些扩展一般都是以扩展接口的方式出现的。对于 IAnnotationModel 来说,你可以发现还有一个 IAnnotationModelExtension 接口,里面有一些更强更方便的方法。不光是 IAnnotationModel,你在很多地方都可以发现名字是 Extension 结尾的接口,所以请记住这种现象,当我们浏览代码的时候,不要以为某个接口就已经是全部了。

IAnnotationAccess

这个接口可以用来访问标注的一些信息。但是在 3.0 之后,标注的信息都可以通过 Annotation 类访问到,所以这个接口已经过时了,只是为了向下兼容而保留,我就不罗嗦了。

AnnotationPainter

这是 JTF 中和标注绘制相关的重要类。上面提到的 IAnnotationPresentation 负责在标尺上绘制标注,而它是负责在编辑器(也就是 StyledText)里面绘制标注的。我们看到的红色波浪线和矩形框就归它负责。

IDrawingStrategy

这个接口是定义在 AnnotationPainter 内部的,它是绘画工作真正完成的地方。AnnotationPainter 实际上只是调用它来完成绘图操作而已。如果你在 Hierarchy 视图中看一下 IDrawingStrategy,会发现它有很多实现类。那个红色的波浪线就是 SquigglesStrategy 的杰作。

AnnotationPreference

不要以为什么样的标注画成什么样子是规定死了的,实际上它们都是通过 Eclipse 的 Preference 系统来控制的。请打开 Eclipse 的 Preference 设置,找到 General->Editors->Text Editors->Annotations,你会发现原来这里都可以控制。而这些选项就被包装在了 AnnotationPreference 中。如果你想添加一种标注的配置信息,可以通过程序方式,也可以通过 org.eclipse.ui.editors.markerAnnotationSpecification 扩展点。

MarkerAnnotationPreferences

AnnotationPreference 包装的只是一种标注的配置信息,要得到全部的信息,可以通过 MarkerAnnotationPreferences 类。




回页首


实现文本装饰功能

我打算实现一个语法错误检查的功能,如果用户输入的源代码有问题,则把它标记出来。让我们一步步开始这个过程。

SourceViewerDecorationSupport

不得不说和文本装饰相关的概念、接口非常的多,而我列举的只是一些最重要的,还不是全部。这么复杂的功能,要直接写到 SourceViewer 里面去不免显的臃肿,所以 SourceViewer 通过 SourceViewerDecorationSupport 来支持文本装饰功能,避免了把所有代码都塞到一个类里面去。

我在本系列第一部分提过,之所以没有用 Eclipse 标准 editors 扩展点来做演示,是因为 Editor 本身为我们隐藏了一些东西,文本装饰的支持就是其中之一。现在我们手动添加文本装饰的支持,在 ExprViewer 中增加一个 configureDecorationSupport 方法并在 configure 方法中调用它。代码如下:

清单 1. 在 ExprViewer 中使用 SourceViewerDecorationSupport

               
protected void configureDecorationSupport()
{
// create support object
decorationSupport = new SourceViewerDecorationSupport(
  this, null, new DefaultMarkerAnnotationAccess(), ColorManager.getInstance());

// add other annotation preference
MarkerAnnotationPreferences prefs = new MarkerAnnotationPreferences();
MarkerAnnotationPreferences.initializeDefaultValues(
Activator.getDefault().getPreferenceStore());
Iterator<Object> e = prefs.getAnnotationPreferences().iterator();
while(e.hasNext()) {
// add to support
decorationSupport.setAnnotationPreference((AnnotationPreference)e.next());
}

// install support
decorationSupport.install(Activator.getDefault().getPreferenceStore());
}


我没有增加自定义的标注,所以这个方法并不复杂。如果你有自己的标注类型,那么可以用程序方式或者扩展方式定义自己的标注配置信息,然后调用 SourceViewerDecorationSupport 的 setAnnotationPreference 方法将你的配置添加到库中

错误检测支持

下一步再一次和 ANTLR 扯上了关系,如果没有解析器的支持,要知道源代码中的错误恐怕有点困难。幸好我们已经有了很多基础工具,但是仍然有点不够。我稍微修改了一下 ANTLR 的文法,支持把错误保存到一个 Map 中。这样解析完成后,我就可以直接从解析器得到错误列表了。同时 SharedParser 做了少许增强,以便得到最近一次解析时的错误信息。这些修改就不一一列出了,总之我现在具有了得到错误位置与错误信息的能力。

扩展 Annotation

下一步是扩展 Annotation 类,因为 Annotation 类并没有实现 IAnnotationPresentation。我想让错误也在标尺上显示出来,所以要扩展 Annotation。我定义了 ExprAnnotation,它的代码的核心是 paint 方法,作用是在标尺上画一个背景,然后再画一个错误图标。至于画图的具体细节没有必要关心,熟悉 SWT 的 GC 使用方式的话应该不是问题,这里我就略过不提了。

Ruler 支持

提示:注意我们的布局代码也发生了变化,原来是 viewer.getTextWidget().setLayoutData(…), 现在是 viewer.getControl().setLayoutData(…)。因为安装了标尺之后,viewer 内部会对布局做了一些调整,这个时候 StyledText 不再是顶层控件,所以要使用 getControl。如果不了解的话,界面的布局会出乎意料,恐怕一时半会也不知道问题从何而来。

现在的编辑器还没有一个标尺,所以稍微修改一下 JTFDialog,传给 ExprViewer 的构造函数一个 VerticalRuler 实例即可。

触发语法检查

万事具备,只欠东风。现在只要找到一个合适的时机进行语法检查,并安装我们的标注就可以了。文本改变事件是一个选择,也是最简单的选择,所以我新建了一个 SyntaxChecker 类,并把这个类注册为文本事件监听器。让我们看看文本改变时它会做些什么:

清单2. SyntaxChecker

                public void documentChanged(DocumentEvent event) {
// get model
IAnnotationModel model = viewer.getAnnotationModel();
if(model == null || !(model instanceof IAnnotationModelExtension))
return;

// create map contains annotations to be added
Map<Annotation, Position> toBeAdded = new HashMap<Annotation, Position>();

// get annotations to be removed
Annotation[] toBeRemoved = getAnnotations(new String[] {
        "org.eclipse.ui.workbench.texteditor.error"
});

// get document
IDocument doc = event.getDocument();

// parse it
TreeManager.getTree(doc);

// get errors
Map<Token, String> errors = SharedParser.getLastErrors();

// add annotation
for(Token token : errors.keySet()) {
CommonToken ct = (CommonToken)token;
Annotation anno = new ExprAnnotation("org.eclipse.ui.workbench.texteditor.error",
errors.get(token));
Position pos = new Position(
ct.getStartIndex(), ct.getStopIndex() - ct.getStartIndex() + 1);
toBeAdded.put(anno, pos);
}

// replace annotation one time, this provides a better performance
// than remove/add one by one
((IAnnotationModelExtension)model).replaceAnnotations(toBeRemoved, toBeAdded);
}


我只列出了这个最关键的方法。它的基本流程是:

   1. 做一些必要的检查
   2. 得到之前已经存在的错误标注
   3. 解析源代码,得到错误列表
   4. 为每个错误创建一个 ExprAnnotation,并把标注类型设为错误类型
   5. 通过 replaceAnnotations 批量刷新标注

需要解释一下的是第 5 步,为什么要用 replaceAnnotations?主要还是出于性能的考虑,因为你每次添加删除一个标注,都会触发一系列的连锁反应,所以如果你一个个的添加删除,速度会非常慢。replaceAnnotations 解决了这个问题,因为它是一次全部替换。但是这个方法是 IAnnotationModelExtension 接口里面的,为了保险起见,需要先检查类型。当然我们这个例子很简单,并没有显著的性能问题。

效果

下面是运行后的效果,假如我没有输入分号,错误的标注就显示出来了。

图2. 文本装饰效果图
文本装饰效果图




回页首


结束语

让我来指出还是做的不够的地方吧:

   1. 错误检测太过简单,比如不能标注出未声明的变量。要做一个专业的代码编辑器的话,错误检测可不能这样简单。
   2. 语法检查是在文本内容发生变化后立刻触发,当源代码越来越多的时候,这很可能造成性能问题。我们可以从很多方面想办法,比如提高语法解析器的效率,或者减少不必要的语法检查次数,可以考虑用定时器,当用户隔一段时间没有输入动作时再进行语法检查。最好的办法是使用 Reconciler,关于 Reconciler 的概念会在本系列的第 11 部分中提到。
   3. 我没有自定义标注类型,用的是 Eclipse 自带的类型。那么不妨尝试一下定义自己的标注类型,可以通过 org.eclipse.ui.editors.annotationTypes 扩展点。
   4. 我也没有自定义标注的渲染方式,用 IDrawingStrategy 尝试画一个很酷的标注吧。要分两步走,实现 IDrawingStrategy,然后注册你的 IDrawingStrategy。
   5. 我用的是标准的垂直标尺,尝试实现一个自己的标尺,把标注画到上面。
   6. 标注只有界面上的提示,没有任何文字上的信息,用户很难知道到底是什么错误。不过不要担心,这是因为我还没有提到 Text Hover(文本悬浮帮助),以后的文章将完善这个功能。

这些不足的地方留给有兴趣的读者。




回页首


声明

本文仅代表作者的个人观点,不代表 IBM 的立场。
分享到:
评论

相关推荐

    基于_JFace_Text_Framework_构建全功能代码编辑器

    ### 基于_JFace_Text_Framework_构建全功能代码编辑器 #### 引言与概述 _JFace_Text_Framework_(简称JTF),作为Eclipse平台的重要组成部分,为开发者提供了构建高度定制化的代码编辑器的强大能力。JTF不仅支撑了...

    JFace Text Framework教程

    总结来说,IBM的JFace Text Framework教程为开发者提供了一个强大且灵活的工具,用于构建功能丰富的文本编辑器。通过学习和实践,开发者可以掌握如何利用这个框架来提升开发效率,创建出专业级的IDE(集成开发环境)...

    eclipse与MyEclipse代码提示上屏修改后jar包(org.eclipse.jface.text_3.8.101.v20130802-1147)

    标题提及的"org.eclipse.jface.text_3.8.101.v20130802-1147"是Eclipse中的一个关键组件,它负责文本编辑器的相关功能,包括代码提示。 `org.eclipse.jface.text`是Eclipse JFace库的一部分,JFace是构建用户界面的...

    jface.text 3.12.1.zip

    本文将围绕"jface.text 3.12.1.zip"这一特定的Eclipse插件进行深入探讨,该插件是Eclipse文本编辑器的重要组成部分,对于提升Java代码补全体验有着至关重要的作用。 首先,"jface.text"是Eclipse的Java Face (JFace...

    org.eclipse.jface.text_3.12.2.v20180112-1341.zip

    标题中的"org.eclipse.jface.text_3.12.2.v20180112-1341.zip"是Eclipse插件的一个版本,它专注于文本编辑功能。Eclipse是一个开源的集成开发环境(IDE),而JFace是Eclipse的一部分,提供了面向用户的界面组件。...

    org.eclipse.jface.text_3.12.2.v20180112-1341.jar

    Eclipse JFace Text是Eclipse IDE中的一个核心组件,它提供了高级文本编辑功能,广泛用于构建用户界面中的文本编辑器。这个特定的版本号表明它是该组件的一次更新迭代,可能包含错误修复、性能提升或其他新特性。 ...

    org.eclipse.jface.text_3.11.2.v20170220-1911最新修改版

    JFace Text是Eclipse中的一个API,它是构建文本编辑器的基础,提供了文本编辑、搜索、替换、高亮等基本功能。在这个特定的版本中,开发者们对JFace Text进行了优化,特别是对于用户输入行为的处理,比如取消了空格和...

    基于WTP开发自定义的JSP编辑器

    了解和利用WTP中与插件开发相关的其他关键概念,如JFace Text Framework和Eclipse Editor Framework,可以帮助进一步优化编辑器的性能和用户体验。 #### 五、总结 基于WTP开发自定义的JSP编辑器是一个综合性的工程...

    org.eclipse.jface.text_3.8.2.v20121126-164145源码

    深入研究这部分源码,不仅可以提升对Eclipse JFace的理解,也有助于提升开发者在构建文本编辑器组件时的定制能力。同时,这也提醒我们,源码的修改应遵循良好的编程实践,确保软件的稳定性和可维护性。

    org.eclipse.jface.text_3.7.2.v20111213-1208.jar

    《Eclipse JFace Text库与MyEclipse 10.0.0的编辑器功能优化》 在IT行业中,开发工具的效率与便利性对于程序员的工作至关重要。Eclipse作为一款广受欢迎的开源集成开发环境(IDE),其强大的扩展性和自定义能力一直...

    Eclipse SWT/JFace 核心应用的全部源代码

    JFace包括数据绑定、视图管理、对话框和服务等组件,它将许多复杂的SWT操作进行了封装,例如表格和树的数据模型、表单编辑器等。通过研究JFace的源代码,开发者可以学习到如何优雅地组织用户界面,提高代码的可读性...

    org.eclipse.jface.text_3.9.2.v20141003-1326.zip

    这个插件是JFace Text组件的一部分,JFace是Eclipse工作台(Workbench)框架的一个子项目,它提供了基于SWT(Standard Widget Toolkit)的高级用户界面构建工具。版本号"3.9.2"表明这是该插件的第三个主要版本的第九...

    MyEclipse10.7.1代码补全vs风格 jface.text修正版

    因为10.7.1已经完美破解(修正了war文件到处问题),故放上该版本修改过的org.eclipse.jface.text_3.7.2.v20111213-1208.jar 代码补全空格不上屏,适合习惯使用vs等工具的用户 详细描述参见10.0时的插件 ...

    jface源代码不容错过

    7. **视图和编辑器的实现**:Eclipse RCP中的视图和编辑器是通过JFace实现的,源代码能帮助我们理解这两者如何在RCP环境中协同工作。 总之,研究JFace的源代码不仅可以帮助开发者深入理解Eclipse RCP的工作原理,还...

    Eclipse SWT/JFACE 核心应用 配套源代码

    Eclipse SWT(Standard Widget Toolkit)和JFace是用于构建Java GUI应用程序的强大工具,它们与Eclipse IDE紧密集成,提供了一种高效、灵活的方式来创建桌面应用程序。这个压缩包包含的源代码是围绕这两个库的核心...

    JFace教程

    **JFace** 是 Eclipse 平台的一个重要组成部分,它提供了一套丰富的 API 来帮助开发者构建基于 SWT(Standard Widget Toolkit)的用户界面。JFace 的核心目标是简化 GUI 开发流程,使开发者能够更加专注于应用程序...

    Eclipse SWT&JFace开发实战精解 源代码

    5. **视图和编辑器**:了解Eclipse Workbench的工作原理,如何创建和管理视图及编辑器,以及如何实现视图之间的通信。 6. **表单构建**:学习使用JFace的表单构建工具,如`FormToolkit`和`FormBuilder`,创建复杂的...

    SWT,JFACE核心应用源代码,第二部分.rar

    在"SWT,JFACE核心应用源代码,第二部分.rar"这个压缩包中,我们可以预期找到一系列关于SWT和JFace实际应用的源代码示例。这些示例可能涵盖了如何使用SWT创建基本和复杂的用户界面元素,如何利用JFace进行数据绑定,...

    swt JFace的API文档

    7. **Views and Editors**:JFace 提供了用于构建工作台视图和编辑器的框架,支持多窗口和多页编辑环境。 8. **Control Adapters**:这些适配器类可以添加额外的功能,例如在控件上添加右键菜单。 9. **Bindings ...

    org.eclipse.jface.text_3.12.0.v20170523-1043.jar

    总的来说,Eclipse JFace Text模块是Eclipse IDE中不可或缺的一部分,它提供了丰富的文本编辑功能,尤其是自动补全特性,大大提升了开发效率。版本3.12.0.v20170523-1043的JFace Text可能包含了一些优化和改进,使得...

Global site tag (gtag.js) - Google Analytics