RCP扩展Editor,及如何不重复打开相同内容的page

来源:互联网 发布:手机播放器软件 编辑:程序博客网 时间:2024/06/04 20:54
转自 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);      }
  } });}
也是同样的效果。

原创粉丝点击