Eclipse SWT/JFACE 核心应用

来源:互联网 发布:silkn facetite 知乎 编辑:程序博客网 时间:2024/05/17 23:18

EclipseSWT/JFACE核心应用》清华大学出版社 23 RCP开发

23.3 扩展编辑器
   
编辑器与视图一样,是工作台页面内的可视组件。通常用来编辑文件(例如查源代码)或查看输入对象(例如打开的plugin.xml文件时的页面)。用于创建视图的扩展点为org.eclipse.ui.editors

1. 编辑器扩展点
   
在扩展编辑器中新增扩展点,配置好的plugin.xml文件如下:

   <extension         point="org.eclipse.ui.editors">      <editor           class="com.testrcp.myrcp.editors.JsEditor"           contributorClass="com.testrcp.myrcp.editors.JsEditorContributor"           default="false"           icon="icons/alt_about.gif"           id="com.testrcp.myrcp.editors.JsEditor"           name="JsEditor">      </editor>   </extension>


    编辑器扩展点的各元素的说明如下:
   
编辑器的扩展点类型是org.eclipse.ui.editors
   
与视图一样,一个编辑器对应一个class类,该类必须是实现了org.eclipse.ui.IEditorPart的类。
   
id是该编辑器对象的唯一标识,name为编辑器显示的名称。
   
default:表示是否使用默认的编辑器。
   
contributorClass是实现了org.eclipse.ui.IEditorActionBarContributor接口的类,EclipseEditorActionBarContributor类已经实现了该接口,通常的做法是继承该类,然后覆盖父类中的方法实现的。
   
其他需要注意的元素如下:
       
extensions:打开该编辑器的所对应的文件的扩展名,例如“htmhtml”
       
commandlaunchercommand为要运行以启动外部编辑器的命令。launcher为实现了org.eclipse.ui.IEditorLauncher的类。这样启动程序将打开外部编辑器。其中classcommandlauncher都是打开编辑器的方式,属性是互斥的。
       
filenames:编辑器打开文件时可选的文件名。
       
symbolicFontName:编辑器字体的名称。
       
matchingStrategy:实现org.eclipse.ui.IEditorMatchingStrategy的类。这运行编辑器扩展提供一个策略,是编辑器的输入与指定的编辑器输入相匹配。

    一般开发编辑器时通常会用到这些属性,但在RCP开发中,如果不是开发的RCP编辑器程序,一般是用不到这些属性的。

2.
编辑器类
   
本例中的编辑器类是JsEditor,代码如下:

package com.testrcp.myrcp.editors;import org.eclipse.core.runtime.IProgressMonitor;import org.eclipse.swt.SWT;import org.eclipse.swt.events.ModifyEvent;import org.eclipse.swt.events.ModifyListener;import org.eclipse.swt.widgets.Composite;import org.eclipse.swt.widgets.Text;import org.eclipse.ui.IEditorInput;import org.eclipse.ui.IEditorPart;import org.eclipse.ui.IEditorSite;import org.eclipse.ui.PartInitException;import org.eclipse.ui.part.EditorPart;public class JsEditor extends EditorPart {//对应plugin.xml指定的idpublic static final String ID = "com.testrcp.myrcp.editors.JsEditor";private Text text;//编辑器中的内容是否被修改的标志private boolean bDirty = false;public JsEditor() {   super();}//初始化编辑器public void init(IEditorSite site, IEditorInput input)    throws PartInitException {   this.setSite(site);//设置site   this.setInput(input);//设置输入的IEditorInput对象   this.setPartName(input.getName());//设置编辑器上方显示的名称}//创建编辑器中的控件public void createPartControl(Composite parent) {   text = new Text(parent, SWT.NONE);   //当文本框修改时,设定内容被修改过   text.addModifyListener(new ModifyListener() {    public void modifyText(ModifyEvent e) {     if (!isDirty()) {//如果未修改      setDirty(true);//设置修改      //更改编辑器的状态      firePropertyChange(IEditorPart.PROP_DIRTY);     }    }   });}//编辑器关闭时,保存编辑器内容时所调用的方法public void doSave(IProgressMonitor monitor) {   //将保存状态显示在状态栏中   try {    monitor.beginTask("保存文件...", 100);    for (int i = 0; i < 10 &&!monitor.isCanceled(); i++) {     Thread.sleep(500);     monitor.worked(10);     double d = (i + 1) / 10d;     monitor.subTask("已完成" + d * 100 +"%");// 显示任务状态    }    monitor.done();    if (monitor.isCanceled())     throw new InterruptedException("取消保存");   } catch (InterruptedException e) {    ;   }}//另存为调用的方法public void doSaveAs() {}//判断是否被修改过public boolean isDirty() {   return bDirty;}//是否允许保存public boolean isSaveAsAllowed() {   return true;}//设置焦点public void setFocus() {   text.setFocus();}//设置编辑器内容被修改过public void setDirty(boolean b) {   bDirty = b;}}



    创建编辑器时应注意以下问题:
   
编辑器所对应的类为实现了IEditorPart接口的类。本例中使用的是继承了EditorPart类,例如下文中讲述的多页编辑器则要继承自MultiPageEditorPart类,表单编辑器则要继承FormEditor类。
   
编辑器中显示的控件通过createPartControl方法创建。
   
isDirty():编辑器内容是否被修改过,如果被修改过,标签上会显示一个“*”号。当状态改变时要及时的更新界面效果,使用下面的方法:
      firePropertyChange(IEditorPart.PROP_DIRTY);
       
isSaveAsAllowed():是否允许全部保存。
       
doSaveAs():另存时调用的方法。
       
doSave():保存时调用的方法。
       
setFocus():设置编辑器激活时焦点所在的控件。

3.
打开编辑器
   
与视图不同,编辑器不能直接显示到透视图的某一个区域,而是由一项操作所打开的,通常使用IWorkbenchPage的以下两个方法:
   
openEditor(IEditorInput input, String editorId)input对象为打开文件器时所指定输入到编辑器的内容,为了实现IEditorInput接口,editorId为编辑器的唯一标识。
   
openEditor(IEditorId input, String editorId, boolean activate)activate表示是否打开后并激活该编辑器。
   
本例中所创建的实现了接口的类为JsEditorInput类,代码如下:
package com.testrcp.myrcp.editors;import myrcp.Activator;import org.eclipse.jface.resource.ImageDescriptor;import org.eclipse.ui.IEditorInput;import org.eclipse.ui.IPersistableElement;public class JsEditorInput implements IEditorInput {//输入的字符private String input ;public JsEditorInput ( String input ){   this.input = input ;}//是否将编辑器保存在最近访问记录中public boolean exists() {   return true;}//输入内容的图标public ImageDescriptor getImageDescriptor() {   returnActivator.getImageDescriptor("icons/samples.gif");}//输入信息的名称public String getName() {   return input;}//是否可以持久化该编辑器public IPersistableElement getPersistable() {   return null;}//设置编辑器标签中显示提示信息public String getToolTipText() {   return input;}//返回与该输入相关的类的对象public Object getAdapter(Class adapter) {   return null;}}



    这些方法都是IEditorInput接口中的方法。另外除了可以自己实现该接口的类外,Eclipse中已经有一些实现了该接口的类,可以直接使用或者通过继承的方法。实现IEditorInput接口的类如下:
    CommonSourceNotFoundEditorInput, CompareEditorInput,FileEditorInput, FileInPlaceEditorInput, FileStoreEditorInput,HistoryPageCompareEditorInput, MultiEditorInput, PageCompareEditorInput, ParticipantPageCompareEditorInput,SaveableCompareEditorInput, SyncInfoCompareInput

    创建了打开编辑器输入内容的类,也有了对应的编辑器,就可以打开编辑器了。要想打开编辑器,还需要创建一个视图,视图中放置了一个列表List,然后单击列表中的一项来打开编辑器。plugin.xml中的配置代码如下:
    

 <view           class="com.testrcp.myrcp.views.OpenEditorView"           icon="icons/alt_launcher.ico"           id="com.testrcp.myrcp.views.OpenEditorView"            name="打开编辑器">      </view>



   
后面的代码需要在项目中增加一个jar包:org.eclipse.ui.forms_3.5.0.v20100427.jar,在Eclipse的安装目录下的plugins目录中可以找到。

    对应的视图类如下:

package com.testrcp.myrcp.views;import org.eclipse.swt.SWT;import org.eclipse.swt.events.SelectionAdapter;import org.eclipse.swt.events.SelectionEvent;import org.eclipse.swt.widgets.Composite;import org.eclipse.swt.widgets.List;import org.eclipse.ui.IWorkbenchPage;import org.eclipse.ui.PartInitException;import org.eclipse.ui.internal.part.NullEditorInput;import org.eclipse.ui.part.ViewPart;import com.testrcp.myrcp.editors.JsEditor;import com.testrcp.myrcp.editors.JsEditorInput;import com.testrcp.myrcp.editors.MutiEditorSample;import com.testrcp.myrcp.forms.MyMutiForm;public class OpenEditorView extends ViewPart {public static final String ID ="com.testrcp.myrcp.views.OpenEditorView";public List list;public OpenEditorView() {   super();}public void createPartControl(Composite parent) {   list = new List(parent, SWT.NONE);   list.add("Editor");   list.add("MutiPage Editor");   list.add("Form Editor");   list.add("Master/Detail Page");   list.addSelectionListener(new SelectionAdapter() {    public void widgetSelected(SelectionEvent e) {     String select = list.getSelection()[0];     // 获得当前激活的IWorkbenchPage对象     IWorkbenchPage page =getViewSite().getWorkbenchWindow().getActivePage();     try {      if (select.equals("Editor")) {// 如果选中的"Editor"一项       // 创建输入的内容对象       JsEditorInput editor = newJsEditorInput(select);       // 打开该编辑器       page.openEditor(editor, JsEditor.ID);      } else if(select.equals("MutiPage Editor")) {// 如果选中的"Editor"一项       page.openEditor(new NullEditorInput(),MutiEditorSample.ID);      }else if(select.equals("Form Editor")) {// 如果选中的"Editor"一项        page.openEditor(newNullEditorInput(), MyMutiForm.ID);      }     } catch (PartInitException ee) {      ee.printStackTrace();     }        }   });}public void setFocus() {   list.setFocus();}}




4. 添加编辑器的菜单和工具栏
   
对于编辑器,也可以设置编辑器所对应的菜单、工具栏和上下文菜单。实现这些功能需要实现IEditorActionBarContributor接口,EditorActionBarContributor类实现了该接口。代码如下:
package com.testrcp.myrcp.editors;import org.eclipse.jface.action.Action;import org.eclipse.jface.action.IMenuManager;import org.eclipse.jface.action.IToolBarManager;import org.eclipse.jface.action.MenuManager;import org.eclipse.ui.ISharedImages;import org.eclipse.ui.PlatformUI;import org.eclipse.ui.part.EditorActionBarContributor;public class JsEditorContributor extendsEditorActionBarContributor {private Action action1 ;private Action action2 ;public JsEditorContributor() {   super();   makeActions();}public void makeActions() {   action1 = new Action() {    public void run() {        }   };   action1.setText("Action 1");   action1.setToolTipText("Action 1 tooltip");  action1.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().    getImageDescriptor(ISharedImages.IMG_DEF_VIEW));     action2 = new Action() {    public void run() {        }   };   action2.setText("Action 2");   action2.setToolTipText("Action 2 tooltip");  action2.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().     getImageDescriptor(ISharedImages.IMG_OBJS_WARN_TSK));}//覆盖父类中的方法,创建菜单public void contributeToMenu(IMenuManager menuManager) {   MenuManager editMenu = new MenuManager("编辑器菜单");   editMenu.add( action1 );   editMenu.add( action2 );   menuManager.add( editMenu );}//覆盖父类的方法,创建工具栏public void contributeToToolBar(IToolBarManager toolBarManager) {   toolBarManager.add( action1 );   toolBarManager.add( action2 );}}


    其中,创建菜单栏和工具栏的方法分别是覆盖父类中的contributeToMenucontributeToToolBar方法。

    Perspective类的createInitialLayout方法中只留下下面两行代码:
  

String editorArea = layout.getEditorArea();  layout.addStandaloneView(OpenEditorView.ID,true,IPageLayout.RIGHT,.3f,editorArea);



    运行后的显示效果如下:

    点击“Editor”行,显示效果如下:

多点击几次Editor,出现多个Editor,如下图:


菜单如下图:


点击除“Editor”外的项时,菜单效果如下图:



5. 多页编辑器
   
多页编辑器可以同时打开多个页面,每个页面可以是一个编辑器IEditorPart,也可以是普通控件Control

    plugin.xml配置一个新的编辑器。内容如下:

   <extension        point="org.eclipse.ui.editors">      <editor           class="com.testrcp.myrcp.editors.MutiEditorSample"           default="false"           icon="icons/alt_window_16.gif"           id="com.testrcp.myrcp.editors.MutiEditorSample"            name="多页编辑器">      </editor>   </extension>



   
该编辑器对应的类为MutiEditorSample,该类要继承自MultiPageEditorPart类才可以实现多页显示效果。代码如下:
package com.testrcp.myrcp.editors;import org.eclipse.core.runtime.IProgressMonitor;import org.eclipse.swt.SWT;import org.eclipse.swt.widgets.Label;import org.eclipse.ui.PartInitException;import org.eclipse.ui.part.MultiPageEditorPart;public class MutiEditorSample extends MultiPageEditorPart {//该编辑器的标识public static final String ID ="com.testrcp.myrcp.editors.MutiEditorSample";private JsEditor page1 ;//编辑器对象private JsEditor page2 ;//编辑器对象private Label control1 ;//标签对象//父类中抽象方法protected void createPages() {   //创建页面和标签对象   page1 = new JsEditor();   page2 = new JsEditor();   control1 = new Label ( getContainer(), SWT.NONE);   control1.setText("这是一个标签");   try {    //添加第一页   addPage( page1 , new JsEditorInput("One"));    //设置选项卡的名称    setPageText(0,"One");    //添加第二页    addPage( page2 , new JsEditorInput("Two"));    setPageText(1,"Two");    //添加第三页,为一个标签    addPage(control1);    setPageText(2,"Three");   } catch (PartInitException e) {    e.printStackTrace();   }}public void doSave(IProgressMonitor monitor) {  }public void doSaveAs() {  }public boolean isSaveAsAllowed() {   return false;}}



    创建多页编辑器时应注意以下几个问题:
   
该类必须继承自MultiPageEditorPart类。
   
创建页面的代码是在createPages方法中。
   
每个页面可以是IEditorPart对象,也可以是Control对象。
   
创建完页面后要调用addPage方法,将该页添加。如果不使用该方法,将不会显示页面。
   
addPage方法如下所示:
       
addPage(Control control):添加一个控件,其中control为选项卡中的控件对象。
       
addPage(IEditorPart editor, IEditorInputinput):添加一个编辑页面。
       
addPage(int index, Control control):在指定索引的选项卡中,添加一个控件。
       
addPage(int index, IEditorPart editor,IEditorInput input):在指定索引的选项卡中,添加一个编辑页面。
   
可以使用父类的setPageText(int pageIndex, String text)方法设定显示选项卡的名称。

    注意:MutiEditorSample对应的扩展点是 org.eclipse.ui.editors,而不是 org.eclipse.ui.views,不小心搞错了,在点击“MutiPage Editor”时,总是出现下面的异常:
org.eclipse.ui.PartInitException: Unable to open editor, unknown editor ID:com.testrcp.myrcp.editors.MutiEditorSample

多页编辑器的显示效果如下:

 

原创粉丝点击