Ku4Lg#mK*GsJFace Text Editor是JFace里面
个功能强大,结构复杂而且非常重要
组件,要掌握它还需要花不少
功夫,下面我们将通过"Building an Eclipse Text Editor with JFace Text"
翻译来掌握它
使用方法
^
W(uZw6I提到Text Editor,就不得不提到和的密切相关
SourceViewerConfiguration类,Text Editor
许多功能都是通过该类配置上去
,还有
个是IDocumentProvider接口,Text Editor所要编辑
文件对象就是通过该接口提供
.
JAVA中文站社区门户$p8|'`{O-W@
JAVA中文站社区门户Kv&r,r$T2W/REditor编辑
内容封装在IDocument这个类中,对于编辑内容
遍历,定位都是在IDocument
基础上来实现
,而文档
分割信息以及其他
元数据信息(比如高亮区域)则由Editor来保存,Document中
定位信息将使用
个Position类来加以封装.
JAVA中文站社区门户
jE-\}
\&V
M
P"N;w \)Xa虽然IDocument有区别
实现,但是他们都
个共同点,那就是这些内容都是可分割
,即能被分割成
块
块
互不重叠
文本块.分割(Partition)在Text Editor中是
个非常非常重要
概念,基本上Text Editor
所有功能都是建立在文档分割
基础上
.
JAVA中文站社区门户#WhZ.ou#vs-xk{ f
i
s-zk F;\IDocument接口并不关心文本内容
存储和加载,它
工作就是
化
个文档对象例子,而文档
各种属性
化则交给IDocumentProvider来完成.
JAVA中文站社区门户jwse6@^'V
JAVA中文站社区门户
R"`xm:RI\ X!ka在打开
个文档
时候编辑器将同时进行文档
分割处理,其结果是得到各种区别类型
互不重叠文本块
JAVA中文站社区门户/~"se^I!j9@]
u4\0M }5B8~下面我们来讲讲分割器,分割器
设置是在IDocumentProvider
createDocument
思路方法中实现
,如下代码所示:
JAVA中文站社区门户,oUB? nbP)o6T dyn4IA0m8i9E+tp
java 代码
=dp-j>
=alt>
=keyword>protected IDocument createDocument(Object element) =keyword>
throws CoreException
="">
{
=alt>
IDocument document = =keyword>
super.createDocument(element);
="">
=keyword>
(document != =keyword>
null)
=alt>
{
="">
IDocumentPartitioner partitioner = =keyword>
XMLPartitioner(
=alt>
=keyword>
XMLPartitionScanner, =keyword>
String
="">
{
=alt>
XMLPartitionScanner.XML_TAG, XMLPartitionScanner.XML_COMMENT
="">
});
=alt>
partitioner.connect(document);
="">
document.DocumentPartitioner(partitioner);
=alt>
}
="">
=keyword>
document;
=alt>
}
JAVA中文站社区门户F-Ze7@rT)h JAVA中文站社区门户w4OA%j({ fz;Q
JAVA中文站社区门户3wd%x
R;F E%w
B从上面
代码我们可以看到,
化
个IDocumentPartitioner我们需要两个参数,
个是必须指定
个IPartitionTokenScanner例子,另
个是所支持
内容类型(content type)
.
7I9B3U
h7Q)Zli
jCYEvs和分割相关
还有 3个概念:Scanner, Token和Rule, Scanner
任务就是将当前编辑
文档对象进行扫描并得到每
个文本块所对应
Token,对于Token需要解释
下,它是IToken
个实现,被视为内容类型
唯
标识符.比如
个Token可能表示
是某种语言中
关键字,xml元素名,空格等.
j%v![/|)Ln | h5c*N4|3uO
w.Gw}'~通过下面
代码来介绍说明Scanner是如何来查找各个Token
.
JAVA中文站社区门户{E @.k+vx6WF1}'dI U@'p
java 代码
=dp-j>
=alt>
=keyword>public =keyword>
XMLPartitionScanner =keyword>
extends RuleBasedPartitionScanner
="">
{
=alt>
=keyword>
public =keyword>
final =keyword>
String XML_DEFAULT = =
>"__xml_default"
;
="">
=keyword>
public =keyword>
final =keyword>
String XML_COMMENT = =
>"__xml_comment"
;
=alt>
=keyword>
public =keyword>
final =keyword>
String XML_TAG = =
>"__xml_tag"
;
="">
=alt>
=keyword>
public XMLPartitionScanner
="">
{
=alt>
="">
IToken xmlComment = =keyword>
Token(XML_COMMENT);
=alt>
IToken tag = =keyword>
Token(XML_TAG);
="">
=alt>
IPredicateRule rules = =keyword>
IPredicateRule[=number>2
];
="">
=alt>
rules[=number>0
] = =keyword>
MultiLineRule(=
>""
, xmlComment);
="">
rules[=number>1
] = =keyword>
TagRule(tag);
=alt>
="">
PredicateRules(rules);
=alt>
}
="">
}
=alt>
:CJ1n~x%w }} JAVA中文站社区门户,^*QA:|~ld6E#M
'VY)`R R.S0L*W8UV在
个编辑器中每
种内容类型(content type)都表示为
个
串常量.在上面
代码中,定义了 3个内容类型:默认,xml标签和xml注释.为了简化,这里我们没有对xml中
节点文本内容以及xml指令定义类型, 在XMLPartitionScanner中,每
个内容类型都和
个IToken例子相关联
,而IToken例子非常简单,仅仅只是
个内容类型标识符,用来在XMLPartitionScanner对文档进行扫描
时候,对各种Token进行识别, 由于我们
Scanner是继承RuleBasedPartitionScanner
,因此它
Token将和
系列规则对应,而分割器通过这些规则来将文档分割成所需要
结构,在XMLPartitionScanner中,我们使用了两条规则来将内容类型进行配置:
个是MultiLineRule,对应注释内容类型,
个是TagRule对应xml标签类型,在根据内容类型进行分割时,当找到
个匹配
分割片段的后将返回
个唯
Token,这样就在内容类型,Rule 以及Token的间做到了
对应.
PXqUM1m*d
^k(eH9hHE使用
个基于规则
Scanner对文档进行分割
工作原理如下:
3V.C
u*?6X [
=alt>
1.在RuleBasedPartitionScanner构造器中配置些规则
="">
2.分割时Ruleevaluate思路方法
=alt>
3.在evaluate思路方法中根据配置各种规则实现类将对得到段串片段进行匹配,比如用于查找XML注释MultiLineRule只去匹配那些以注释=comments>开始并以注释结尾
结束片段,这种匹配只有两种结果:成功或失败,还是拿匹配注释MultiLineRule来说,如果匹配串片段为"=tag>
般节点
"那么它会马上返回,匹配串不是以注释开头开始,如果匹配失败,扫描器将重新定位到匹配串起始位置,并返回Token.UNDEFINED,接着下个ruleevaluate思路方法进行匹配处理,如果找到则返回匹配Token,而且Scanner将去获取当前串在整个文档中位置以及长度,并使用TypedPosition类将这些信息和其内容类型加以封装保存到IDocument例子中.
JAVA中文站社区门户|o"sy u?9^)kj7]iIDocumentPartitioner通过computePartitioning
思路方法将得到文档
分割信息,当然了,在得到分割信息的前,必须要将文档对象和IDocumentPartitioner例子关联起来,这个是通过IDocumentPartitioner.connect(document)来实现
.
JAVA中文站社区门户p#go4Zv7gw3_
#[-|)G%U!ff{3hQ ib0G当使用规则对文档进行分割,可能主要
工作就是去定义IPredicateRule
各种实现类,该接口
实现包括MultiLineRule, SingleLineRule 和 PatternRule等,理解该接口
难点在于如何配置这些规则,有时候,我们可能需要提供自己
IPredicateRule实现类
JAVA中文站社区门户Eo1Z]`!{8l3y&a
JAVA中文站社区门户*U!z/b+SO2q'_3Z0W除了自定义规则的外,我们也可以提供自己
ITokenScanner实现.比如在JDT中,就实现了自己
ITokenScanner类FastJavaPartitionScanner,显然这个工作是巨大
,
般我们不这样做,除非有必要.
JAVA中文站社区门户
FD"zto$FA"@{
JAVA中文站社区门户q{8cKa mm对文档进行分割的后,接下来将要介绍如何显示,Text Editor
底层采用StyledTextControl控件来显示编辑
文本内容, ITextViewer提供了
套API来封装StyledText处理IDocument模型
细节,这样Text Editor
使用者就不用再和底层
StyledText打交道了.
$M
i(x)OyW
JAVA中文站社区门户Ye9te.vFVzITextViewer除了对StyledText进行封装的外还提供了其他如Undo Management这样
功能,要了解更多细节可以去看看JavaDoc文档.
a!QjJy7VE
JAVA中文站社区门户1_-F*Y@;_U*z*m3}qx_为了更容易
创建
个结构化文档编辑器,Eclipse在ITextViewer
基础上又提供了
个ISourceViewer接口,它包括
功能更强大,比如
标记, 语法高亮等,下面我们将
进行介绍
Sl8d.sJd?
JAVA中文站社区门户+Z x)_Q~ M1kEJFace Text Editor通过SourceViewerConfiguration类来对Source Viewer进行配置,我们需要做
就是继承SourceViewerConfiguration类来对SourceViewer进行定制,SourceViewer
很多功能比如文本格式化,语法高亮,双击选择,自动提示等等都是通过对SourceViewerConfiguration配置来实现
,足见其重要性不容忽视.
JAVA中文站社区门户
BfRk8qy9x
JAVA中文站社区门户
~[;H6Bi7[LE5M下面将通过在
个增强版
XML编辑器来实战Text Editor
使用方法
|N)aJ*kc6k`
f
V
#Xk U:v_P8bEclipse插件开发套件提供
个向导来帮助用户创建
个简单
XML Editor,下面我们将在该编辑器
基础上来进行扩展
JAVA中文站社区门户*YL*Jm{'e
-T;@r$w2[该XML编辑器将实现下面 5个功能:语法高亮(Syntax hightlighting),
标识(Error marker),格式化(Formating),内容辅助(Content Assistance), 内容大纲(Content Outline)
^;i,cj.q1l6_
8nq`L)B.u进行扩展
第
步就是增加新
分割模型,我们增加了下面 3个分割
内容类型:XML文本, CData内容, XML处理指令.
JAVA中文站社区门户pRB9EO
T
(rh0a#Ff9jz为了在我们
XMLPartionScanner中处理指令类型定义, 先:
JAVA中文站社区门户y0Of:yg-k5?JAVA中文站社区门户|cn~*@8E0]g-f+M
java 代码
=dp-j>
=alt>
=keyword>public =keyword>
final =keyword>
String XML_PI = =
>"__xml_pi"
;
JAVA中文站社区门户&}$TMM)a V&i7^
D{;Tu~#^4^*Z,p3c
JAVA中文站社区门户3]/yQ%Z^eP然后注册到分割器中,这个是在构造IDocumentPartitioner例子时作为参数传递进去
:
hJmu7B/]@1Pe;w ^JAVA中文站社区门户:|*m1ex\%`L
java 代码
=dp-j>
=alt>
=keyword>protected IDocument createDocument(Object element) =keyword>
throws CoreException
="">
{
=alt>
IDocument document = =keyword>
super.createDocument(element);
="">
=keyword>
(document != =keyword>
null)
=alt>
{
="">
IDocumentPartitioner partitioner = =keyword>
XMLPartitioner(
=alt>
=keyword>
XMLPartitionScanner, =keyword>
String
="">
{
=alt>
XMLPartitionScanner.XML_START_TAG,
="">
XMLPartitionScanner.XML_PI,
=alt>
XMLPartitionScanner.XML_DOCTYPE,
="">
XMLPartitionScanner.XML_END_TAG,
=alt>
XMLPartitionScanner.XML_TEXT,
="">
XMLPartitionScanner.XML_CDATA,
=alt>
XMLPartitionScanner.XML_COMMENT
="">
});
=alt>
partitioner.connect(document);
="">
document.DocumentPartitioner(partitioner);
=alt>
}
="">
=keyword>
document;
=alt>
}
E R
C"k'[#|AFb JAVA中文站社区门户W"oY,\!wX+]PP
(``T@CAS
g!t q接下来是创建用于标识区别类型内容
Token和Rule,由于我们使用
是基于规则
Scaner(RuleBasedPartitionScanner),因此我们需要添加
对Token和Rule,这样才能让我们
IPartitionTokenScanner例子能感知我们定义
内容类型
3}y:QS}6]HTh
V&K-q]bv;N根据XML定义规范标准,XML指令必须以结束,因此我们将这样来定义我们
Token和Rule:
JAVA中文站社区门户5M;pQa["lCY*y8B2T(n[s
java 代码
=dp-j>
=alt>
=keyword>public XMLPartitionScanner
="">
{
=alt>
="">
IToken xmlComment = =keyword>
Token(XML_COMMENT);
=alt>
IToken xmlPI = =keyword>
Token(XML_PI);
="">
IToken startTag = =keyword>
Token(XML_START_TAG);
=alt>
IToken endTag = =keyword>
Token(XML_END_TAG);
="">
IToken docType = =keyword>
Token(XML_DOCTYPE);
=alt>
IToken text = =keyword>
Token(XML_TEXT);
="">
=alt>
IPredicateRule rules = =keyword>
IPredicateRule[=number>7
];
="">
=alt>
rules[=number>0
] = =keyword>
NonMatchingRule;
="">
rules[=number>1
] = =keyword>
MultiLineRule(=
>""
, xmlComment);
=alt>
rules[=number>2
] = =keyword>
MultiLineRule(=
>"
, =
>"?>"
, xmlPI);
="">
rules[=number>3
] = =keyword>
MultiLineRule(=
>"
, =
>">"
, endTag);
=alt>
rules[=number>4
] = =keyword>
StartTagRule(startTag);
="">
rules[=number>5
] = =keyword>
MultiLineRule(=
>"
, =
>">"
, docType);
=alt>
rules[=number>6
] = =keyword>
XMLTextPredicateRule(text);
="">
=alt>
PredicateRules(rules);
="">
}
=alt>
^-x0I9JZ0}x2Bv
S
V JAVA中文站社区门户~%`5hd
|RqFEJ6H
E