Eclipse插件开发帮助.翻译的只是一部分基本的。
翻译:张新周
第一部分:插件开发
中文 :
1 JDT核心(这个是java的开发环境tool)
1.1 JDT核心(org.eclipse.jdt.core)_也是一个插件.不过它是用来定义核心java元素和API..这个插件是必须的.因为它是用来开发java的.
JDT核心包让你可以进入Java的模型对象和复杂的java IDE基础环境.这个JDT核心包包括:
org.eclipse.jdt.core 定义了描述java模型的类
Org.eclipse.jdt.core.compiler 定义API支持编译器的基础构造
Org.eclipse.jdt.core.dom 用来支持虚拟的系统树(AST).用来检查一个编辑单元的结构.
org.eclipse.jdt.core.eval 支持剪切板中或者调试器中的代码片断的评估.
Org.eclipse.jdt.core.jdom 支持java文档对象模型.用来和java编辑单元的结构同步.
Org.eclipse.jdt.core.search 支持搜索工作区的java模型中指定的java元素匹配的详细描述.
Org.eclipse.jdt.core.util 提供工具类来操作类文件和java模型元素
对 一个在编辑单元的结构操纵已经在org.eclipse.jdt.core.dom 中完成了.代替org.eclipse.jdt.core.jdom. org.eclipse.jdt.core. jdom将在2.2中不在推荐使用.并使用org.eclipse.jdt.core.dom来代替.
1.1.1 java模型
Java模型是指一组类用来模拟对象的创建,编辑和建立一个Java程序.Java模型类在org.eclipse.jdt.core 中定义.这些类实现了java特定的行为.这些行为针对资源并可以将java资源分解为模型元素.
1.1.1.1 Java元素
包org.celipse.jdt.core 定义了很多类来模拟元素分解一个java程序.JDT用一个内存对象模型来描述Java程序的结构.这个结构来源于项目的class path 也就是环境变量指定的地址.这个模型是分等级的.程序的元素可以被分解为子元素.
操作Java元素和操作源文件是非常类似的. 当你工作在一个Java元素上时,你实际上在使用操纵潜在的模型对象.你必须使用exists()方法来判断这个元素是否在当前的工作台中存在.
下面的表格时不同Java类型的元素的一些摘要.
Element Description
IJavaModel
Represents the root Java element, corresponding to the workspace. The parent of all projects with the Java nature. It also gives you access to the projects without the java nature.
描述Java的根元素.和工作台中的是一致的.所有Java类型项目的父
.而且它也使得你可以操纵所有工程.
IJavaProject
Represents a Java project in the workspace. (Child of IJavaModel)
描述工作台中的Java工程 . 是IJavaMode的子类
IPackageFragmentRoot
Represents a set of package fragments, and maps the fragments to an underlying resource which is either a folder, JAR, or ZIP file. (Child of IJavaProject)
描述一个包的的一部分和管理包的底层资源.可能是一个文件夹.jar或者zip文件.
IPackageFragment
Represents the portion of the workspace that corresponds to an entire package, or a portion of the package. (Child of IPackageFragmentRoot )
表示作为平台的一部分.它和一个完整包对应.或者是包的一部分.
ICompilationUnit
Represents a Java source (.java) file. (Child of IPackageFragment )
操作一个java文件.是IPackageFragment的子类.
IPackageDeclaration
Represents a package declaration in a compilation unit. (Child of ICompilationUnit )
呈献操作在编辑的单元中包的声明.
IImportContainer
Represents the collection of package import declarations in a compilation unit. (Child of ICompilationUnit )
呈献操作在编辑的单元中import的声明
IImportDeclaration
Represents a single package import declaration. (Child of IImportContainer )
呈献操作一个单独的import声明
IType
Represents either a source type inside a compilation unit, or a binary type inside a class file.
操作一个在编辑单元中的资源类型或者是class中的二进制类型.
IField
Represents a field inside a type. (Child of IType )
操作一个在一个定义的类中的field变量.
IMethod
Represents a method or constructor inside a type. (Child of IType )
操作一个方法或者一个构造方法在一个类中
IInitializer
Represents a static or instance initializer inside a type. (Child of IType )
操作一个静态的或者instance 初始化方法在一个类中.
IClassFile
Represents a compiled (binary) type. (Child of IPackageFragment )
操作一个编译后的二进制类.
所有的Java元素支持IjavaElement接口.
一些元素在Package view中显示.这些元素都实现了Iopenable接口.因为这他们必须在操纵之前被打开.下面的图形说明了这些元素:
哪些实现了Iopenable接口的Java元素则在信息建立之前就被从资源文件创建.用样的元素也被在导航视图中显示 :
其他和各个条目对应的元素一起组成了Java编辑单元. 下面图形显示了一个Java编辑单元和内容轮廓(outline) :
这些元素实现了ISourceReference接口.所以他们能提供和源代码一致的同步.当这些元素在outline中被选中后,就可以在编辑器中定位到相应的源码位置.
Java元素和他们的资源
很多Java元素对应于普通的资源. 当你想创建一个Java元素时.应该从JavaCore是最好的开始点.下面的代码片断显示怎样从资源中得到相应的Java元素
private void createJavaElementsFrom(IProject myProject, IFolder myFolder, IFile myFile) {
IJavaProject myJavaProject= JavaCore.create(myProject);
if (myJavaProject == null)
// the project is not configured for Java (has no Java nature)
return;
// get a package fragment or package fragment root
IJavaElement myPackageFragment= JavaCore.create(myFolder);
// get a .java (compilation unit), .class (class file), or
// .jar (package fragment root)
IJavaElement myJavaFile = JavaCore.create(myFile);
}.
一旦你拥有了Java元素.你就可以使用JDT API来处理和查询模型.你可以查询包括在Java元素中的非Java资源 .
private void createJavaElementsFrom(IProject myProject, IFolder myFolder, IFile myFile) {
...
// get the non Java resources contained in my project.
Object[] nonJavaChildren = myJavaProject.getNonJavaResources();
...
Java 工程
当 你创建了一个Java工程从 a simple project . JavaCore将检测查看工程是否是Java类型,如果是 new Java Project 创建工程..JDT插件使用工程的类型来指定一个工程具备拥有Java的行为.这个种类就被指派给工程. JavaCore将返回null.
JavaCore通常用来维护Java的类路径.包括定位发现源文件和库.并定位产生输出的.class文件.
如果标示一个java工程呢.这个记录在.classpath文件中.并添加一个Java工程编译到工程的编译说明.否则,他们恰恰是正常的工程且能被通过插件使用其他的种类进行配置. .
IJavaModel接口可以被认为在平台中所有Java工程的父并且可以使用IjavaProject接口进行处理…
目录Platform Plug-in Developer Guide
Programmer’s Guide
Editors
Other text edior responsibilities
这个Java编辑器从AbstractTextEditor继承了很多有用的功能从.你可以覆盖父类中的方法使得文本编辑框架操纵几个其他的一些职责. 看看这个类的实现和他的子类查看怎么定制.
下面的是一些有用的框架可以配置的特征
偏爱的操作:
编 辑器的特色就是提供给用户偏爱操作.可以控制编辑器的行为.例如编辑器的显示颜色等等.让用户可以使用自己喜欢的配置. 文本的框架内,每一个文本编辑器实例都有一个相关的”偏爱”的数据.用存用户喜欢的配置. 这个偏爱的存储可以使用你的编辑器来建立,你可以从框架中已经存在类继承对偏爱存储的定义.
在java的编辑器中.他继承了在TextEditor. 中初始化的偏爱存储. 这是就是工作台中的偏爱存储插件.
实现代码如下:
protected void initializeEditor() {
...
setPreferenceStore(EditorsPlugin.getDefault().getPreferenceStore());
}
编 辑器插件的偏爱可以通过Workbench > Editors 和 Workbench > Editors > Text Editor 到偏爱页面. 如果你不想使用标准的工作台为你的编辑器提供的偏爱设置,也可以设置不同的偏爱存储.那就必须覆盖initializeEditor方法并设置自己的偏爱 存储.如果你使用自己的偏爱存储,则你也需要覆盖handlePreferenceStoreChanged()方法.这个方法用来触发一个偏爱是否更 新.
键盘绑定: 键盘绑定范围对于建立一个键盘绑定的命令的查找是非常有用的.也就是命令是有作用范围的.不能全局.持有上下文范围的可以减少不同插件中键盘命令的冲突的 机会.默认的工作台的操作都是全局的.当一个文本编辑器激活后,它就负责重新安排文本编辑器的范围.因此编辑器特殊的键盘绑定可以被激活.
在文本框架的平台中,每一个文本编辑器实例都有一个相关联的键盘绑定范围,当它激活时负责设置这个范围.TextEditor定义了这个范围.并且关心它的激活.这个范围在构造器中使用指定的方法处理.
protected void initializeKeyBindingScopes() {
setKeyBindingScopes(new String[] { "org.eclipse.ui.textEditorScope" });
}
方法中观点是一个键盘绑定范围的标识,如果你想让你编辑器定义它自己的键盘绑定范围,然活你可以覆盖这个方法在编辑器的类中.或者动态的使用setKeybindingScopes方法.
范围本身必须定义的和org.eclipse.ui.commands扩展点中的一致.下面定义就是编辑器中的范围
<extension
point="org.eclipse.ui.commands">
...
<scope
name="%scope.text.name"
parent="org.eclipse.ui.globalScope"
description="%scope.text.description"
id="org.eclipse.ui.textEditorScope">
</scope>
</extension>
目录:
Platform Plug-in Developer Guide
Programmer’s Guide
Editors
Cotent Outliners
内容轮廓器.
编辑器经常有一个和内容相一致的OUTLINE (内容轮廓).这是个标准的View.不是用户创建的.而是eclipse本身带的四个标准View之一.四个标准的View分别是Outline ,Navigator,Console,PakageExplore.
其中outline是用来帮助用户定位编辑器中的内容. 正式为了这个目的,工作台提供了这个标准的Outline.用户可以通过菜单 Window > ShowView来显示这个视图.
因为一般的TextEditor不能自己发现文档的结构,所以他也不能为Outlne视图提供相应的行为.因此默认的Outline的视图显示为
文本框架内的编辑器可以自己提供自己的内容轮廓到outline view. 当工作台请求IcontentOutlinePage类型的适配器时,这个编辑器的轮廓视图就被指定.
代码如下 :
public Object getAdapter(Class required) {
if (IContentOutlinePage.class.equals(required)) {
if (fOutlinePage == null) {
fOutlinePage= new JavaContentOutlinePage(getDocumentProvider(), this);
if (getEditorInput() != null)
fOutlinePage.setInput(getEditorInput());
}
return fOutlinePage;
}
return super.getAdapter(required);
}
内 容轮廓的页面必须实现IContentOutlinePage接口.这个接口合并了两个接口,包括可以通知outline中选择的改变的接口 (ISelectionProvider)和在视图中作为一个页面的行为(IPage)接口.内容轮廓是一个使用Jface视图的典型示例.默认的实现 IContentOutlinePage接口的类是(ContentOutlinePage)类.他使用一个Jface树视图显示层次结构.这种表示符合 很多轮廓的结构.包括JavaContentOutlinePage就是这种结构.
一起看一下这个页面的实现.当轮廓页面被编辑器创建的片断程序.它的输入的元素就是编辑器中输入的元素.这个输入经常直接被传递到outline的页面.如下所示:
public void createControl(Composite parent) {
super.createControl(parent);
TreeViewer viewer= getTreeViewer();
viewer.setContentProvider(new ContentProvider());
viewer.setLabelProvider(new LabelProvider());
viewer.addSelectionChangedListener(this);
if (fInput != null)
viewer.setInput(fInput);
}
树视图从CongtentOutlinePage类继承创建.需要提供标准的内容和标签.无论编辑器的输入输入或者改变,JavaContentOutlinePage为编辑器内的文本创建了一个文档.
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
...
if (newInput != null) {
IDocument document= fDocumentProvider.getDocument(newInput);
if (document != null) {
document.addPositionCategory(SEGMENTS);
document.addPositionUpdater(fPositionUpdater);
parse(document);
}
}
}
文本被解析为行列,然后在文档内调用程序,上面这个片断可以在outline中显示当前修改文本的位置:
当在outline中选择的改变时,被选择的片断将被从编辑器中被找到. 指定偏移量的文本片断将被设置为高亮,代码如下
public void selectionChanged(SelectionChangedEvent event) {
super.selectionChanged(event);
ISelection selection= event.getSelection();
if (selection.isEmpty())
fTextEditor.resetHighlightRange();
else {
Segment segment= (Segment) ((IStructuredSelection) selection).getFirstElement();
int start= segment.position.getOffset();
int length= segment.position.getLength();
try {
fTextEditor.setHighlightRange(start, length, true);
} catch (IllegalArgumentException x) {
fTextEditor.resetHighlightRange();
}
}
}
要想使用outline tree.必须实现ItreeContentProvider接口.
当你私用一个tree viewer工作时,你需要提供viewer需要的信息异用来传送你的业务对象到界面的tree中.这就是这个接口的目的.必须有一个类来实现这个接口.用你的使用的对象来取代接口代码.你可以创建一个另外的对象来满足树的内容提供者的必要条件.
下面详细说明一下这个接口中的方法.
1, public Object[] getElements(Object inputElement)
这 个方法被tree视图的setinput方法激活.实际上,getElement方法仅仅被调用一次响应tree viewer的setpinput方法..而且应该使用合适的输入业务对象. GetElements方法和getChiledren方法使用方法比较相似.都依赖于我们的业务对象 ,可以让getElements简单的调用getChildren方法.这两个方法被分开的原因是他提供了一个方便的方法来区别根业务对象和其他所有的业 务对象.
2 public Object[] getChildren (Object parent)
当树型视图需要创建或者显示业务parent对象的子元素时,调取他的内容提供者方法getChildren方法.. 这个方法应该回答一个业务对象队列来呈献没有定义的父的子元素.
3 public Object getParent(Object element )
当树型视图需要展现缩起的业务对象时则调取他的内容提供者的getParent方法.并且设置业务对象的展开状态.这个方法应该响应业务对象的父.
4, public Boolean hasChildren (Object elment)
树型视图请求他的内容提供者呈献的业务对象是否有子元素.这个方法通常被树型视图用来测定判断在组件内部显示加号还是减号.
5, public void inputChanged (Viewer viewer ,Object oldInput, Object newInput)
这 个方法真正的微妙的服务两个不同的目的. 这个方法当你设置树型视图的输入时被激活.换句话说,任何时间,只有你经由setInput这个方法改变树型视图的视图时这个inputChanged方 法都会被调用.这个经常用来作为业务改变的容器注册内容提供者并为旧的业务对象提供反注册.
对于大的图像条目,为内容提供者提供的输入对象都要经由视图来管理.
当树型视图通知内容提供者不在使用树型视图时也会被调用.当你设置树型视图时这个就会发生.
例如,我们移动的盒子中不管是一个书,还是棋盘游戏,从盒子中添加还是除去,都会通知他的监听.内容提供者为这些业务模型的改变都注册了监听.因此当业务改变时它就可以更新界面.同样的,它也能当不再查看时从业务对象中移去自己的监听.
关于抽象APIs的讨论足够多了,来看一下实际的代码. 在上面提供的代码中,树型视图的内容提供者被设置为MovingBoxContentProvider的实例.看一下类的内部细节:
public Object[] getChildren(Object parentElement) {
if(parentElement instanceof MovingBox) {
MovingBox box = (MovingBox)parentElement;
return concat(box.getBoxes().toArray(),
box.getBooks().toArray(), box.getGames().toArray());
}
return EMPTY_ARRAY;
}
仅仅当MovingBox业务对象有子时,因此一个空的队列被返回.一个移动盒的子是一个串.包括了书和棋盘类的游戏.
public Object[] getElements(Object inputElement) {
return getChildren(inputElement);
}
这 个getElement方法用来获取树型视图的根元素 .在我们的例子中,树型视图的根元素对象是一个移动的盒子.因此我们可以简单的调用getChildren方法.因为它操纵着移动盒.如果根业务对象被特 别指定了.那getElement方法将很可能不能代理gtChildren方法.
public Object getParent(Object element) {
if(element instanceof Model) {
return ((Model)element).getParent();
}
return null;
}
getParent方法用来获取给定元素的父元素.
Input changed 方法隐藏视图的
第二部分:wizard插件开发
1,wizard插件的开发说明。
Wizard 是向导插件。用户根据向导的界面以次输入需要的参数,设置完毕后,各个page界面将保存用户输入的数据,在向导结束的时候,使用InewWizard接 口的实现类从page中读取数据,并进行处理,处理完毕后,向导结束。注意:InewWizard的实现类只能是一个,page页面可以是多个。Page 页面中可以放入各种可视化的组件。
2,图示:
3,具体操作步骤如下:
下面的操作演示根据两个页面的输入创建一个简单的java文件。
输入为添加变量的名称生成变量的bean。
3.1 首先使用向导的
4, 向导配置完成后,如果任务过重,需要占用大量时间,并需要使用进度条来处理时,就需要使用进度接口来管理:进步管理接口英文说明如下:
org.eclipse.core.runtime.IProgressMonitor
The IProgressMonitor interface is implemented by objects that monitor the progress of an activity;
the methods in this interface are invoked by code that performs the activity.
All activity is broken down into a linear sequence of tasks against which progress is reported. When
a task begins, a beginTask(String, int) notification is reported, followed by any number and mixture
of progress reports (worked()) and subtask notifications (subTask(String)). When the task is
eventually completed, a done() notification is reported. After the done() notification, the progress
monitor cannot be reused; i.e., beginTask(String, int) cannot be called again after the call to
done().
A request to cancel an operation can be signaled using the setCanceled method. Operations taking
a progress monitor are expected to poll the monitor (using isCanceled) periodically and abort at
their earliest convenience. Operation can however choose to ignore cancelation requests.
Since notification is synchronous with the activity itself, the listener should provide a fast and
robust implementation. If the handling of notifications would involve blocking operations, or
operations which might throw uncaught exceptions, the notifications should be queued, and the
actual processing deferred (or perhaps delegated to a separate thread).
Clients may implement this interface.
IProgressMonitor 中最有用的方法是:
• beginTask(),它将在操作开始前被调用。它带有操作的描述和持续时间。
• worked() 报告进度。它通常更新进度条。
• done() 必须在创建项目时进行调用。
• subTask() 可以让您更改描述。
项目创建和进度的长度是用工作单元进行报告的。定义单元所表示的内容则由您来决定。例如,处理文件时,每个单元就可以是一个文件。
要执行线程,请调用容器中的 run() 方法。该容器使自己的进度条与 IProgressMonitor 保持同步。
对上面的一个说明:
对于多个任务使用如下:
IprogressMonitor monitor= 。。
monitor.beginTask(“创建文件”,2);
monitor.subTask(“文件1”);
//TODO
monitor.worked(1);
monitor.subTask(“文件2”);
//TODO
monitor.worked(2);
上面的例子中创建第一个文件时,进度条走一半,创建第二个文件时,走一半.
任务条的进度由monitor.worked(n)中的n来控制.