在本小节中,无论如何先把自己的编辑器给搞出来,为我们后面对wtp提供的JSP编辑器进行定制。
【开发环境准备】
1、Eclipse 3.2 + WTP 1.5
2、对应的GEF(3.2.1)、EMF(2.2.1)系列插件
3、将必要插件导入到工作区,导入插件列表如下:
因为我们暂时只是阅读并不打算修改wtp源码,所以就先以二进制方式导入,以上导入的6个插件以后要和我们常打交道~_~。
说明:
Eclipse 3.3、3.4也可以,wtp 2.0版本也可以,只要是有对应版本的gef和emf与之配套
【JFace Text Framework & Eclipse Editor Framework】
我们知道Eclipse为我们提供了一个文本编辑器框架,个人觉得最核心的角色是:IEditorPart、IDocumentProvider和SourceViewerConfiguration。
【角色介绍】
1、
org.eclipse.ui.IEditorPart:
IWorkbenchPart的一种扩展实现(另一种是IViewPart),编辑器的真正主体,需要和IEditorSite、IWorkbenchPage等协作。Eclipse为我们准备了默认的文本编辑器实现(AbstractTextEditor),继承体系如下:
上图中的StructuredTextEditor就是我们wtp提供的JSP编辑器实现,看得出来是一种文本编辑器实现。
和IEditorPart密切相关的是如何定制和本编辑器类型相关的工作台工具栏和菜单:一个是
org.eclipse.ui.IEditorActionBarContributor接口,和编辑器扩展点org.eclipse.ui.editors配合使用;另一个是
org.eclipse.ui.editorActions扩展点。WTP提供了相应的IEditorActionBarContributor实现:
ISourceViewerActionBarContributor类型及其子类型都是由WTP提供,有兴趣可以看一下。
注意点:IEditorActionBarContributor实现是和编辑器类型绑定的,在多个编辑器实例间共享。
2、
org.eclipse.ui.texteditor.IDocumentProvider:
核心作用就是提供JFace Text Framework中org.eclipse.jface.text.IDocument实现。
上图中的StructuredModelDocumentProvider和StorageModelModelProvider就是WTP提供的两个IDocumentProvider实现。
文本编辑器公共父类中提供了配置IDocumentProvider实现的方法:org.eclipse.ui.texteditor.AbstractDecoratedTextEditor.setDocumentProvider(IEditorInput)。
3、
org.eclipse.jface.text.source.SourceViewerConfiguration:这是JFace Text Framework提供的一个重要概念,用来对SourceViewer(一般是用来显示编辑source code,全名为
org.eclipse.jface.text.source.SourceViewer)进行配置。可以配置的内容包括:自动提示策略、自动编辑器策略等等。SourceViewer中提供了对应的配置行为接口:
SourceViewer.configure(SourceViewerConfiguration configuration),这个配置过程一般发生在IEditorPart.createPartControl过程中,因为source viewer实例的创建包含在IEditorPart.createPartControl过程中。
上图中的StructuredTextViewer就是WTP提供的编辑器各种页面资源代码(包括jsp、html等)所使用的SourceViewer实现。如果我们进行定制,那么就给StructuredTextViewer配置一个我们自己的SourceViewerConfiguration ^_^
上图中的StructuredTextViewerConfigurationJSP就是WTP针对JSP文件类型提供的SourceViewerConfiguration实现。
【角色之间的关系】
1、org.eclipse.ui.editors扩展和IEditorPart之间的关系
一个org.eclipse.ui.editors扩展会指定一个对应的IEditorPart实现,一个IEditorPart实现可以被用在多个org.eclipse.ui.editors扩展中,也就是说IEditorPart相对于org.eclipse.ui.editors扩展是1:N的关系。
例如WTP提供的StructuredTextEditor是一个文本类型editor part实现,其在org.eclipse.jst.jsp.ui、org.eclipse.wst.html.ui等多个插件中被注册,它被WTP用来编辑jsp、html等多种资源。例如:
<!-- 摘自org.eclipse.jst.jsp.ui插件plugin.xml -->
<editor
name="%JSP_Source_Page_Editor.name"
icon="$nl$/icons//full/obj16/sourceEditor.gif"
extensions="jsp, jsf, jspf, jspx, tag, tagf"
contributorClass="org.eclipse.jst.jsp.ui.internal.editor.ActionContributorJSP"
class="org.eclipse.wst.sse.ui.StructuredTextEditor"
symbolicFontName="org.eclipse.wst.sse.ui.textfont"
id="org.eclipse.jst.jsp.core.jspsource.source">
<contentTypeBinding
contentTypeId="org.eclipse.jst.jsp.core.jspsource" />
</editor>
<!-- 摘自org.eclipse.wst.html.ui插件plugin.xml -->
<editor
name="%HTML_Source_Page_Editor.name"
icon="$nl$/icons/full/obj16/sourceEditor.gif"
contributorClass="org.eclipse.wst.html.ui.internal.edit.ui.ActionContributorHTML"
class="org.eclipse.wst.sse.ui.StructuredTextEditor"
symbolicFontName="org.eclipse.wst.sse.ui.textfont"
id="org.eclipse.wst.html.core.htmlsource.source">
<contentTypeBinding
contentTypeId="org.eclipse.wst.html.core.htmlsource" />
</editor>
2、IEditorPart和IEditorActionBarContributor之间的关系
上面已经说过,多个IEditorPart实例共享同一个IEditorActionBarContributor实例。结合具体场景讲,例如用同一种类型的JSP编辑器打开了10个JSP文件,每次都会产生一个新的该类型IEditorPart实例,但是对应的是同一个IEditorActionBarContributor实例。
一个IEditorPart实现可以被注册多次(上面第一个点说过),每次可以配置不同类型的IEditorActionBarContributor实现。
<!-- 摘自org.eclipse.jst.jsp.ui插件plugin.xml -->
<editor
name="%JSP_Source_Page_Editor.name"
icon="$nl$/icons//full/obj16/sourceEditor.gif"
extensions="jsp, jsf, jspf, jspx, tag, tagf"
contributorClass="org.eclipse.jst.jsp.ui.internal.editor.ActionContributorJSP"
class="org.eclipse.wst.sse.ui.StructuredTextEditor"
symbolicFontName="org.eclipse.wst.sse.ui.textfont"
id="org.eclipse.jst.jsp.core.jspsource.source">
<contentTypeBinding
contentTypeId="org.eclipse.jst.jsp.core.jspsource" />
</editor>
<!-- 摘自org.eclipse.wst.html.ui插件plugin.xml -->
<editor
name="%HTML_Source_Page_Editor.name"
icon="$nl$/icons/full/obj16/sourceEditor.gif"
contributorClass="org.eclipse.wst.html.ui.internal.edit.ui.ActionContributorHTML"
class="org.eclipse.wst.sse.ui.StructuredTextEditor"
symbolicFontName="org.eclipse.wst.sse.ui.textfont"
id="org.eclipse.wst.html.core.htmlsource.source">
<contentTypeBinding
contentTypeId="org.eclipse.wst.html.core.htmlsource" />
</editor>
上面可以看出来,当StructuredTextEditor被配置用来绑定jsp文件类型的时候,给它配置的是ActionContributorJSP,当StructuredTextEditor被配置用来绑定html文件类型的时候,给它配置的是ActionContributorHTML。那就是说,当我们用StructuredTextEditor分别开发jsp和html的时候,工作台工具栏和菜单栏可能会有所不同^_^
3、SourceViewer和SourceViewerConfiguration 之间的关系
SourceViewer的很多行为是由SourceViewerConfiguration制定的,前者承担的可以认为是source viewer的核心行为,例如绑定document、annotation model等等,后者可以认为是前者对应的服务接口,提供额外服务。对于同一个SourceViewer实例,可以用不同类型SourceViewerConfiguration进行配置,以达到定制的效果,外在行为则看起来就会有所不同。
上面说过,WTP在编辑jsp、html等页面资源类型的时候其实对应都是StructuredTextEditor,但是使用过的就会知道,自动提示等等行为还是有所不同的。StructuredTextEditor持有的是同种类型的SourceViewer实现:org.eclipse.wst.sse.ui.internal.StructuredTextViewer,但是,如果给StructuredTextViewer配置不同的SourceViewerConfiguration,则就可以定制其行为了^_^。 当用StructuredTextEditor打开jsp文件时,在StructuredTextEditor.createPartControl过程中给其配置StructuredTextViewerConfigurationJSP,当用StructuredTextEditor打开html文件时,在StructuredTextEditor.createPartControl过程中给其配置StructuredTextViewerConfigurationHTML...
【WTP StructuredTextEditor分析】
其实上面已经分析了建立一个编辑器扩展所依赖的关键角色,那么我们看一下WTP提供的用来编辑jsp、html等多种页面资源的StructuredTextEditor是如何配置起来的。
IEditorPart:StructuredTextEditor
IEditorActionBarContributor:提供了ActionContributorJSP等多种实现,通过org.eclipse.ui.editors扩展来和StructuredTextEditor集成
IDocumentProvider:提供了StructuredModelDocumentProvider和StorageModelModelProvider两种实现,通过StructuredTextEditor.setDocumentProvider(IEditorInput)完成
ISourceViewer:StructuredTextViewer
SourceViewerConfiguration:提供StructuredTextViewerConfigurationJSP、StructuredTextViewerConfigurationHTML等多种实现,在StructuredTextEditor.createPartControl过程中对StructuredTextViewer进行配置。
【基于WTP创建自定义的JSP编辑器扩展】
到这里,有关eclipse文本编辑器框架中各个角色以及它们之间的关系都基本上已经清楚了。那我们看一下如何基于WTP创建自定义的JSP编辑器扩展:
1、IEditorPart角色:
创建一个自定义IEditorPart实现,直接继承自WTP的StructuredTextEditor,暂定名字为JSPEditor。因为我们后面要在createPartControl中对WTP的StrcuturedTextViewer进行config。
2、IEditorActionBarContributor角色:目前我们不打算提供定制工作台菜单栏和工具栏,所以直接复用ActionContributorJSP
3、IDocumentProvider角色:直接复用WTP已有的,我们不打算提供我们自定义的IDocument实现,我们只是定制编辑器外在的行为^_^
4、ISourceViewer角色:直接复用WTP提供的StrcuturedTextViewer
5、SourceViewerConfiguration角色:因为是我们要定制WTP的StrcuturedTextViewer,例如后门定制自动提示等等,所以
我们提供一个SourceViewerConfiguration,继承自StructuredTextViewerConfigurationJSP,暂定名为JSPStructuredTextViewerConfiguration。
【主要代码】
首先创建一个插件工程,我这边叫做jspeditor,依赖如下插件:
org.eclipse.ui,
org.eclipse.core.runtime,
org.eclipse.wst.sse.ui,
org.eclipse.jface.text,
org.eclipse.ui.workbench.texteditor,
org.eclipse.jst.jsp.ui
接着创建我们自己的SourceViewerConfiguration:
//JSPStructuredTextViewerConfiguration.java
package jspeditor.configuration;
import org.eclipse.jst.jsp.ui.StructuredTextViewerConfigurationJSP;
/**
* 自定义StructuredTextViewerConfiguration,基于WTP jst提供的StructuredTextViewerConfigurationJSP,
* 后面会提供自定义的自动提示策略等扩展。
*
* @author zhuxing (mailto:zhu_xing@live.cn)
*/
/*
* 修改历史
* $Log$
*/
public class JSPStructuredTextViewerConfiguration extends
StructuredTextViewerConfigurationJSP {
}
暂时还是个空壳子^_^, 后面会往里填充东西的。
再者,创建我们的IEditorPart主体类,并覆写createPartControl过程,用我们自己的JSPStructuredTextViewerConfiguration配置WTP的SourceViewer(StructuredTextViewer):
1 package jspeditor;
2
3 import jspeditor.configuration.JSPStructuredTextViewerConfiguration;
4
5 import org.eclipse.jface.text.source.SourceViewerConfiguration;
6 import org.eclipse.swt.widgets.Composite;
7 import org.eclipse.ui.texteditor.IDocumentProvider;
8 import org.eclipse.wst.sse.ui.StructuredTextEditor;
9
10 /**
11 * 基于WTP的自定义JSP编辑器。
12 *
13 * @author zhuxing (mailto:zhu_xing@live.cn)
14 */
15 /*
16 * 修改历史
17 * $Log$
18 */
19 public class JSPEditor extends StructuredTextEditor {
20
21 /* (non-Javadoc)
22 * @see org.eclipse.wst.sse.ui.StructuredTextEditor#createPartControl(org.eclipse.swt.widgets.Composite)
23 */
24 public void createPartControl(Composite parent) {
25 super.createPartControl(parent);
26
27 //用自定义的source viewer configuration配置WTP提供的SourceViewer实现(StrcuturedTextViewer)
28 SourceViewerConfiguration configuration = new JSPStructuredTextViewerConfiguration();
29 this.setSourceViewerConfiguration(configuration);
30 }
31
32 /*
33 * 保持WTP原有实现
34 *
35 * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#getDocumentProvider()
36 */
37 public IDocumentProvider getDocumentProvider() {
38 // TODO Auto-generated method stub
39 return super.getDocumentProvider();
40 }
41
42 /* (non-Javadoc)
43 * @see org.eclipse.wst.sse.ui.StructuredTextEditor#setSourceViewerConfiguration(org.eclipse.jface.text.source.SourceViewerConfiguration)
44 */
45 protected void setSourceViewerConfiguration(SourceViewerConfiguration configuration) {
46 // TODO Auto-generated method stub
47 super.setSourceViewerConfiguration(configuration);
48 }
49
50 }
最后,查看org.eclipse.ui.eidtors扩展点契约,提供扩展:
<extension
point="org.eclipse.ui.editors">
<editor
class="jspeditor.JSPEditor"
contributorClass="org.eclipse.jst.jsp.ui.internal.editor.ActionContributorJSP"
default="true"
extensions="jsp, jsf, jspf, jspx, tag, tagf"
icon="icons/jsp_editor.JPG"
id="jspeditor.editor"
name="自定义WTP JSP编辑器">
<contentTypeBinding contentTypeId="org.eclipse.jst.jsp.core.jspsource"/>
</editor>
</extension>
我做的编辑器图标^_^:
【效果预览】
^_^,我们第一步完成了。
以后的几个小节,我们需要先停一下了,好好地分析一下WTP的数据模型,这是基础中的基础!!!
【源码下载】
下载链接:
基于WTP自定义JSP编辑器源码
本博客中的所有文章、随笔除了标题中含有引用或者转载字样的,其他均为原创。转载请注明出处,谢谢!