转自 http://hi.baidu.com/if1i/blog/item/500c26f4eadffdd7f2d38546.htmleclipse 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: MyPersonEditorInputsuper 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.editorsName: MyPersonEditorSuperclass: 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.CallEditorname: CallEditordefaultHandler: de.vogella.rcp.intro.editor.handler.CallEditor
然后新建一个 command 命令对应的类:
package: de.vogella.rcp.intro.editor.handlername: CallEditorsuperclass: 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); }
} });}
也是同样的效果。