如何为 Editor 开发 Eclipse Outline 视图
2016-02-03 · 百度知道合伙人官方认证企业
定制 Outline 视图开发实例
本节将通过实现一个简单的 XML 文档编辑器及其 Outline Page 来说明如何为 Editor 开发其 Outline 视图。图 3 展示了实例完成时的效果,图片左侧为一个简单的 XML 文本编辑器,右侧的 Outline 视图将文档的 XML 结点以树型的方式展现出来。
图 3. XML Editor 及 Outline 视图
第一步,构建 XML 文档编辑器。XML 文档用来存储、传送及携带数据信息,不用来表现及展现数据。因此在本文的例子中的,我们将 XML 文档编辑器视为一个文本编辑器,通过继承 org.eclipse.ui.editors.text.TextEditor 来实现我们自己的 XML 编辑器。同时我们通过 org.eclipse.core.contenttype.contentTypes 扩展点为 xml 文件绑定为我们自定义的一种内容类型,并将其绑定到我们的新建的编辑器上,当打开后缀为 .xml 的文件时,该编辑器将会被初始化。
清单 2. Editor 扩展点定义
<plugin>
<extension
point="org.eclipse.ui.editors">
<editor
class="cn.com.hf.outline.editor.XMLEditor"
default="true"
extensions="xml"
id="cn.com.hf.outline.XMLEditor"
name="XMLEditor">
<contentTypeBinding
contentTypeId="cn.com.hf.outline.xmlfile">
</contentTypeBinding>
</editor>
</extension>
<extension
point="org.eclipse.core.contenttype.contentTypes">
<content-type
id="cn.com.hf.outline.xmlfile"
name="XMLFile"
priority="high">
</content-type>
<file-association
content-type="cn.com.hf.outline.xmlfile"
file-extensions="xml">
</file-association>
</extension>
</plugin>
第二步,我们该为 Editor 构建 Content Outline Page,用于在 Outline 视图中展于 Editor 中的内容元素。作为 Outline Page,我们需要实现 IContentOutlinePage 接口。我们可以将 XML 文档中的数据构造成一个树型的结构。因此,我们采用 TreeViewer 作为我们 Outline Page 中的主要的 UI 元素。Eclipse 框架为我们提供了一个默认的包含树状视图的 ContentOutlinePage,该类为抽象类,我们通过继承该类来实现我们需要的大纲视图页面。
清单 3. XMLOutlinePage.java
public class XMLOutlinePage extends ContentOutlinePage{
@Override
public void createControl(Composite parent) {
super.createControl(parent);
this.getTreeViewer().setLabelProvider(new XMLOutlineLabelProvider());
this.getTreeViewer().setContentProvider(new XMLOutlineContentProvider());
}
}
大纲页面中的树型控件所展现的为 XML 文档的数据结点,我们为 TreeViewer 提供 ContentProvider 和 LabelProvider,用于遍历结点元素和显示结点的名称。
清单 4. XMLOutlineContentProvider 和 XMLOutlineLabelProvider
public class XMLOutlineContentProvider implements ITreeContentProvider {
@Override
public Object[] getElements(Object inputElement) {
Element root = (Element)inputElement;
return root.getChildren().toArray();
}
@Override
public Object[] getChildren(Object parentElement) {
Element parent = (Element)parentElement;
return parent.getChildren().toArray();
}
@Override
public Object getParent(Object element) {
return ((Element)element).getParent();
}
@Override
public boolean hasChildren(Object element) {
return ((Element)element).getChildren().size() > 0;
}
}
public class XMLOutlineLabelProvider implements ILabelProvider {
@Override
public Image getImage(Object element) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getText(Object element) {
return ((Element)element).getAttributeValue("name");
}
}
第三步,将我们的 XML 编辑器与实现的大纲页面关联起来,如下表所示,在 getAdapter() 方法中,当传入的参数为 IContentOutlinePage 时,说明 Outline 视图向 Editor 查询大纲页面,当函数的返回不为空时,大纲视图将会把页面展现出来。
清单 5. XMLEditor getAdapter 接口
public class XMLEditor extends TextEditor{
@Override
public Object getAdapter(Class adapter) {
if (adapter == IContentOutlinePage.class) {
Element root = this.getRootElement();
if (root != null) {
XMLOutlinePage page = new XMLOutlinePage(root);
this.addListenerObject(page);
return page;
}
}
return super.getAdapter(adapter);
}
}
我们的编辑器是以文本的方式显示 XML 内容,因此我们需要将文本解析成 XML 文档元素,才能将其显示在大纲的树型结点上。在本文的例子中,我们使用 JDOM 类库来解析 XML 文档,我们提供的源代码中包含了该类库,读者也可以通过其官方网站进行下载。
清单 6. XML Editor 的实现
public class XMLEditor extends TextEditor{
public Element getRootElement(){
try {
IDocument doc = this.getDocumentProvider().getDocument(
this.getEditorInput());
String text = doc.get();
SAXBuilder builder = new SAXBuilder();
Reader in = new StringReader(text);
if (builder != null) {
Document document = builder.build(in);
Element root = document.getRootElement();
return root;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
public class XMLOutlinePage extends ContentOutlinePage
public XMLOutlinePage (Element root){
this.root = root;
}
@Override
public void createControl(Composite parent) {
super.createControl(parent);
this.getTreeViewer().setLabelProvider(new XMLOutlineLabelProvider());
this.getTreeViewer().setContentProvider(new XMLOutlineContentProvider());
this.getTreeViewer().setInput(root);
}
}
第四步,为 XML 编辑器注册监听器。当 Editor 的文本发生变化时,Editor 会产生一个属性名为 IEditorPart.PROP_DIRTY 的事件,表明内容被修改,此时,注册在该属性上的监听器就会被调用。我们将 Outline 页面实现为 IEditorPart.PROP_DIRTY 类型的监听器,当文本内容变化时,页面上树型结点也将发生相应的变化。
清单 7. 将 XMLOutlinePage 关联到 XMLEditor
public class XMLOutlinePage extends ContentOutlinePage implements IPropertyListener{
@Override
public void propertyChanged(Object source, int propId) {
if(propId == IEditorPart.PROP_DIRTY){
this.getTreeViewer().setInput(((XMLEditor)source).getRootElement());
}
}
}
public class XMLEditor extends TextEditor {
@Override
public Object getAdapter(Class adapter) {
if (adapter == IContentOutlinePage.class) {
Element root = this.getRootElement();
if (root != null) {
XMLOutlinePage page = new XMLOutlinePage(root);
this.addListenerObject(page);
return page;
}
}
return super.getAdapter(adapter);
}
}
第五步,为 Outline 视图添加工具栏按钮。大纲页面中的结点元素的按列序列是按照其在 XML 文档中出现的先后顺序排列的,这样用户在查找起来就相当的不方便,因此我们可以在 Outline 视图上添加一个排序按钮,将大纲页面中元素按其名称的字母序进行排列,以方便查找。
首先我们在 XMLOutlinePage 中创建一个内部类 SortAction,其作用是给大纲页面的 TreeViewer 设置排序器,主要代码如下所示。在 valueChange() 方法中,当我们选中排序按钮时,为其添加一个字母序的按排序器,否则排序器默认为空,元素按其在文档中出现的顺序排列。
清单 7. SortAction
private ViewerComparator lexComparator = new ViewerComparator(new LexComparator());
private class SortAction extends Action{
public SortAction() {
super();
this.setId("cn.com.hf.outline.page.sortAction");
this.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(
"XMLEditorOutline", "icons/alphab_sort_co.gif"));
this.setDisabledImageDescriptor(AbstractUIPlugin
.imageDescriptorFromPlugin("XMLEditorOutline",
"icons/alphab_sort_co_dl.gif"));
this.setEnabled(true);
this.valueChange(false);
}
@Override
public void run() {
this.valueChange(isChecked());
}
private void valueChange(final boolean on) {
this.setChecked(on);
final TreeViewer viewer = getTreeViewer();
BusyIndicator.showWhile(viewer.getControl().getDisplay(),
new Runnable() {
public void run() {
if (on){
viewer.setComparator(lexComparator);
} else {
viewer.setComparator(null);
}
}
});
}
}
接着,我们能过 pageSite 获得 Outline 视图工具栏实例,将 SortAction 添加到工具栏中。pageSite 是大纲页面与外部 UI 元素进行通信的桥梁,当 Outline 页面初始化时,workbench 会初始化 OutlinePage 的 pageSite 属性,此时,通过 pageSite 就可以获得外部的 UI 元素,如上下文菜单按钮,工具栏等,对页面进行定制。
清单 8. 为 OutlinePage 创建 UI 元素
public class XMLOutlinePage extends ContentOutlinePage implements IPropertyListener{
public void createControl(Composite parent) {
super.createControl(parent);
this.getTreeViewer().setLabelProvider(new XMLOutlineLabelProvider());
this.getTreeViewer().setContentProvider(new XMLOutlineContentProvider());
this.getTreeViewer().setInput(root);
bar = this.getSite().getActionBars();
bar.getToolBarManager().add(new SortAction());
bar.updateActionBars();
}
}
例如,Java Development Tool (JDT) 中的方法和属性大纲,GMF Editor 的 Diagram 的缩略图。由于应用的需求及展示的内容不同,开发者需要为编辑定制属于自己的 Outline 视图。
在 Eclipse 框架中,每个编辑器和 Outline 视图间有种特殊的关系。当编辑器打开时,Outline 视图会被关联到编辑器,如果编辑器为Outline 视图提供了一个模型,该模型就会在 Outline 视图中显示,无论编辑器是否处于活动状态,Outline 视图可以用来浏览内容,或者是在更高抽象层上与编辑器的内容进行交互。
使用过 Java Development Tool (JDT) 的程序员,对 Outline 视图不会陌生。
例如,当我们打开在编辑器中打开一个 java 类文件,Outline 视图中就会显示类中的成员变量,函数等。转载,仅供参考。