转自 http://hi.baidu.com/if1i/blog/item/500c26f4eadffdd7f2d38546.html
eclipse 3.6 RCP 教程 -4- view 和 editor 介绍以及用 command 调用 editor
下面介绍 view 和 editor 的基础知识,以及如何通过 command 来与 editor 通信,详见:
http://www.vogella.de/articles/EclipseEditors/article.html 不过 tutorial 有点问题,
解决问题要参考它的工程源码:http://www.vogella.de/code/codeeclipse.html
(1)以 "rcp application with a view" 模板来创建一个新的 RCP 工程 "de.ytao.rcp.editor.example",创建如下三个类:
package de.ytao.rcp.editor.example.model;
public class Person {
private String firstName;
private String lastName;
private Address address;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() {
return firstName + " " + lastName;
}
@Override
public int hashCode() { // 重写 hashCode() 和 equals() 方法后,两对象只要 firstName 和 lastName 相等,即认为两对象相等
final int prime = 31;
int result = 1;
result = prime * result
+ ((firstName == null) ? 0 : firstName.hashCode());
result = prime * result
+ ((lastName == null) ? 0 : lastName.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (firstName == null) {
if (other.firstName != null)
return false;
} else if (!firstName.equals(other.firstName))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
} else if (!lastName.equals(other.lastName))
return false;
return true;
}
}
package de.ytao.rcp.editor.example.model;
public class Address {
private String street;
private String number;
private String postalCode;
private String city;
private String country;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String toString() {
return street + " " + number + " " + postalCode + " " + city + " "
+ country;
}
}
package de.ytao.rcp.editor.example.model;
import java.util.ArrayList;
import java.util.List;
public class MyModel {
private List<Person> persons = new ArrayList<Person>();
public List<Person> getPersons() {
return persons;
}
public MyModel() {
// Just for testing we hard-code the persons here:
Person person = new Person("Lars", "Vogel");
person.setAddress(new Address());
person.getAddress().setCountry("Germany");
persons.add(person);
person = new Person("Jim", "Knopf");
person.setAddress(new Address());
person.getAddress().setCountry("Germany");
persons.add(person);
}
}
(2)修改 view.java,主要 tableviewer 变更为 listviewer,并且当用户数据填入,注意以下成员变量和方法:
private ListViewer viewer; public void createPartControl(Composite parent) {
viewer = new ListViewer(parent);
viewer.setContentProvider(ArrayContentProvider.getInstance());
viewer.setLabelProvider(new LabelProvider() {
@Override
public String getText(Object element) {
Person p = (Person) element;
return p.getFirstName() + " " + p.getLastName();
};
});
viewer.setInput(new MyModel().getPersons());
// 使 view 生效,这样 veiw 通过 command 打开相应的 editor。workbench 有一个 site 并用于与其它 workbench 通信。
getSite().setSelectionProvider(viewer); }
public void setFocus() {
viewer.getControl().setFocus();
}
(3)使 editor 可见,注释掉 Perspective.java 中的一行
// layout.setEditorAreaVisible(false);
(4)新建一个 EditorInput,它赋于 editor 内容,这样 Editor 才能打开显示
package: de.ytao.rcp.intro.editor.editors;
Name: MyPersonEditorInput
super class: org.eclipse.ui.IEditorInput
在类中增加如下内容:
private final Person person;
public MyPersonEditorInput(Person person){
this.person = person;
}
public Person getPerson() {
return person;
}
修改 getName() 方法:return person.toString();
修改 getToolTipText() 方法 return person.getFirstName(); 这两个方法都不能返回 null 值
建议增加下面两个过程,它们能决定 editor 是否已经打开
@Override
public boolean equals(Object obj) {
if (super.equals(obj)) {
return true;
}
if (obj instanceof MyPersonEditorInput) {
return person.equals(((MyPersonEditorInput) obj).getPerson());
}
return false;
}
@Override
public int hashCode() {
return person.hashCode();
}
(5)增加 editor 类,注意这种方式与 windowbuidler 方式的不同。windowbuilder 是能直接新建 EditorPart 类型类,
而这种手动方式是先增加扩展点,然后以 EditorPart 作为超类。并能继承 abstarct 方法,也是一种间接依据模板生成代码的方式。
Package: de.ytao.rcp.intro.editor.editors
Name: MyPersonEditor
Superclass: org.eclipse.ui.part.EditorPart
package de.ytao.rcp.intro.editor.editors;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.EditorPart;
import de.ytao.rcp.editor.example.model.Person;
public class MyPersonEditor extends EditorPart {
public static final String ID = "de.ytao.rcp.intro.editor.editors.MyPersonEditor";
private Person person;
private Text text2;
public MyPersonEditor() {
}
@Override
public void doSave(IProgressMonitor monitor) {
// TODO Auto-generated method stub
}
@Override
public void doSaveAs() {
// TODO Auto-generated method stub
}
@Override
public void init(IEditorSite site, IEditorInput input)
throws PartInitException {
setSite(site);
setInput(input);
person = ((MyPersonEditorInput) input).getPerson();
setPartName(person.getFirstName());
}
@Override
public boolean isDirty() {
if (person.getAddress().getCountry().equals(text2.getText())) {
return false;
}
return true;
}
@Override
public boolean isSaveAsAllowed() {
// TODO Auto-generated method stub
return false;
}
@Override
public void createPartControl(Composite parent) {
GridLayout layout = new GridLayout();
layout.numColumns = 2;
parent.setLayout(layout);
Label label1 = new Label(parent, SWT.BORDER);
label1.setText("Person: ");
Label personName = new Label(parent, SWT.BORDER);
personName.setText(person.toString());
Label label2 = new Label(parent, SWT.BORDER);
label2.setText("Country");
text2 = new Text(parent, SWT.BORDER);
text2.setText(person.getAddress().getCountry());
}
@Override
public void setFocus() {
// TODO Auto-generated method stub
}
}
(6)经过以上步骤,还差一个 veiw 来触发 editor 的实现,通道已经建立了,触发有两种方法,加事件或通过 command 调用 editor,下面介绍第二种方法
-> command 建立
新建一个 command :
id: de.vogella.rcp.intro.editor.handler.CallEditor
name: CallEditor
defaultHandler: de.vogella.rcp.intro.editor.handler.CallEditor
然后新建一个 command 命令对应的类:
package: de.vogella.rcp.intro.editor.handler
name: CallEditor
superclass: org.eclipse.core.commands.AbstractHandler
补充完整 CallEditor:
public Object execute(ExecutionEvent event) throws ExecutionException {
// Get the view
IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindow(event);
IWorkbenchPage page = window.getActivePage();
View view = (View) page.findView(View.ID); // 这个 view 是用户自定义的 view.java,就是显示在 RCP 左边
// Get the selection
ISelection selection = view.getSite().getSelectionProvider()
.getSelection();
if (selection != null && selection instanceof IStructuredSelection) {
Object obj = ((IStructuredSelection) selection).getFirstElement();
// If we had a selection lets open the editor
if (obj != null) {
Person person = (Person) obj;
MyPersonEditorInput input = new MyPersonEditorInput(person); // 构造通道
try {
page.openEditor(input, MyPersonEditor.ID); // 将通道跟 editor 绑在一起
} catch (PartInitException e) {
System.out.println(e.getStackTrace());
}
}
}
return null;
}
-> 调用 command
补充(2)提到的 createPartControl 方法,增加 hookDoubleClickCommand(); 调用,然后创建 hookDoubleClickCommand 方法:
private void hookDoubleClickCommand() {
viewer.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
IHandlerService handlerService = (IHandlerService) getSite()
.getService(IHandlerService.class);
try {
handlerService.executeCommand(
"de.ytao.rcp.intro.editor.handler.CallEditor", null);
} catch (Exception ex) {
throw new RuntimeException(
"de.ytao.rcp.intro.editor.handler.CallEditor not found");
}
}
});
}
(7)收尾
运行 application,就能看到左边一个 list,里面有 item,点击右边就能打开一个 editor,显示相应的 person 信息,
反复点击不会重复打开 editor,但界面显示上可以改善一下,比如,窗口可以打开即最大化,
修改 ApplicationWorkbenchWindowAdvisor 类中的 postWindowOpen():
public void postWindowOpen()
{
this.getWindowConfigurer().getWindow().getShell().setMaximized(true);
}
(8)附——针对(6)中的提到的另一种方法,可以这样实现:
删除掉 commands 扩展和 command,以及调用 command 的类,并修改 View.java 中方法:
private void hookDoubleClickCommand() {
viewer.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
try
{
ISelection selection = getSite().getSelectionProvider().getSelection();
if (selection != null && selection instanceof IStructuredSelection) {
Object obj = ((IStructuredSelection) selection).getFirstElement();
// If we had a selection lets open the editor
if (obj != null) {
Person person = (Person) obj;
getViewSite().getWorkbenchWindow().getActivePage().openEditor(new MyPersonEditorInput(person), MyPersonEditor.ID);
}
}
}
catch (Exception ex)
{
System.out.println(ex);
}
}
});
}
也是同样的效果。