• 关于Eclipse插件开发(四)-------给视图加下拉菜单和按钮和加入编辑器.


    本例将给视图加入下拉菜单和按钮,同时再为列表添加一个右键菜单.

    创建ActionGroup类

    加入菜单和按钮的方法与SWT和JFace组件的一样,先创建一个ActionGroup代码如下:

     MyActionGroup.java

     

     1 public class MyActionGroup extends ActionGroup {
     2     // 加入按钮
     3     public void fillActionBars(IActionBars actionBars) {
     4         if (actionBars == null)
     5             return;
     6         IToolBarManager toolBar = actionBars.getToolBarManager();
     7         toolBar.add(new Action1());
     8         toolBar.add(new Action2());
     9     }
    10 
    11     // 加入下拉菜单、右键弹出菜单
    12     public void fillContextMenu(IMenuManager menu) {
    13         if (menu == null)
    14             return;
    15         menu.add(new Action1());
    16         menu.add(new Action2());
    17     }
    18 
    19     private class Action1 extends Action {
    20         public Action1() {
    21             ImageDescriptor imageDesc = WorkbenchImages
    22                     .getImageDescriptor(IWorkbenchGraphicConstants.IMG_ETOOL_NEW_PAGE);
    23                     //.getImageDescriptor(IWorkbenchGraphicConstants.IMG_ETOOL_HOME_NAV);
    24             //这个地放原码是想在在View1上显示一个"小房子"的图标.但是我参看IWorkbenchGraphicConstants的源码
    25             //没有IMG_ETOOL_HOME_NAV这个常量字段.导入Eclipse也报错,我就 换了一个.
    26             setHoverImageDescriptor(imageDesc);
    27             setText("Action1");
    28         }
    29 
    30         public void run() {
    31         }
    32     }
    33 
    34     private class Action2 extends Action {
    35         public Action2() {
    36             ImageDescriptor imageDesc = WorkbenchImages
    37                     .getImageDescriptor(IWorkbenchGraphicConstants.IMG_ETOOL_IMPORT_WIZ);
    38             setHoverImageDescriptor(imageDesc);
    39             setText("Action2");
    40         }
    41 
    42         public void run() {
    43             new LanguageDialog(null).open();
    44         }
    45     }
    46 }

    程序说明:

    1.本程序中含有两个Action类:Action1,Action2,和以往的Action不同之处在于它的图像描述符是直接从Eclipse环境中取得.既然插件在Eclipse环境内运行,那么Eclipse本身的图标就可以直接拿来使用,不过Eclipse会给出 一个警告:"建议不要访问:由于对必须的库...jar 具有一定的限制,一次不能访问类型WorkbenchImages",这是因为该类internal包中,也就是说它仅局限于内部使用.

    2.fillContextMenu方法比起以前单纯的SWT编程少了几句.在后边的总结在红中可以看到它移动到View1类中去了,主要原因是为了此方法兼顾添加视图的下拉菜单.

    修改View1类

    在Viwe1中增加了3中方法,分别用来加入视图的导航栏按钮,下拉菜单,以及加入表List的右键菜单.代码如下:

    (下面的这个View1.java中也加入了编辑器对应的事件.双击视图1的列表项,则打开对应的编辑器,因此在View1类的List对象添加一个鼠标双击视图1的列表项,则打开对应的编辑器,一次在View1类的List对象添加一个鼠标双击事件监听器.另外还要考虑到,如果已经打开了列表项对应的编辑器,则下次再双击时就不应再打开该项的编辑器,而是将其设成当前编辑器.)

    得到编辑器对象:IEditorPart editor = IWorkbenchPage.findEditor(IEditorInput);

    打开编辑器对象:IWorkbenchpage.openEditor(IEditorInput.editorID);

    View1.java

    public class View1 extends ViewPart {
        private List list; // 将列表写成类的实例变量,以扩大它的可访问范围
        //注意这个List并不是java.util包下的.而是org.eclipse.swt.widgets.List;包下的.
        public void createPartControl(Composite parent) {
            IWorkbenchHelpSystem help = PlatformUI.getWorkbench().getHelpSystem();
            help.setHelp(parent, "cn.com.kxh.myplugin.buttonHelpId");
            Composite topComp = new Composite(parent, SWT.NONE);
            topComp.setLayout(new FillLayout());
            list = new List(topComp, SWT.BORDER);
            list.add("中国");
            list.add("美国");
            list.add("法国");
            // 列表选择事件监听
            list.addSelectionListener(new SelectionAdapter() {
                public void widgetSelected(SelectionEvent e) {
                    // 由IWorkbenchPage获得view2对象
                    IWorkbenchPage wbp = getViewSite().getPage();
                    //在插件中IWorkbenchPage对象比较重要,这里再给出一种获得此对象的通用的方法.
                    // Activator.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage();
                    IViewPart view2 = wbp.findView("cn.com.kxh.myplugin.View2");
                    //这个地方的参数是"视图2"在plugin.xml中的id标识.由此可见plugin.xml文件在插件中的地位是极其重要的.
                    // 将当前选择的列表项显示在文本框中
                    Text text = ((View2) view2).getText();
                    text.setText(list.getSelection()[0]);
                }
            });
            // 列表选择事件监听
            list.addSelectionListener(new SelectionAdapter() {
                public void widgetSelected(SelectionEvent e) {
                    // 由IWorkbenchPage获得view2对象
                    IWorkbenchPage wbp = getViewSite().getPage();// Activator.getDefault().getWorkbench().getActiveWorkbenchWindow(). getActivePage();
                    IViewPart view2 = wbp.findView("cn.com.kxh.myplugin.View2");
                    // 将当前选择的列表项显示在文本框中
                    Text text = ((View2) view2).getText();
                    text.setText(list.getSelection()[0]);
                }
            });
            list.addMouseListener(new MouseAdapter() {
                private ChinaEditorInput chinaEditorInput = new ChinaEditorInput();
                private UsaEditorInput usaEditorInput = new UsaEditorInput();
                private FranceEditorInput franceEditorInput = new FranceEditorInput();
    
                public void mouseDoubleClick(MouseEvent e) {
                    // 根据不同列表项得到其相应的editorInput对象和editorID,其中
                    // editorID指该编辑器在plugin.xml文件中设置id标识值
                    List list = (List) e.getSource();// 由MouseEvent得到列表对象
                    String listStr = list.getSelection()[0];// 得到当前列表项的字符
                    IEditorInput editorInput = null;
                    String editorID = null;
                    if (listStr.equals("中国")) {
                        editorInput = chinaEditorInput;
                        editorID = "cn.com.kxh.myplugin.ChinaEditor";
                    } else if (listStr.equals("美国")) {
                        editorInput = usaEditorInput;
                        editorID = "cn.com.kxh.myplugin.UsaEditor";
                    } else if (listStr.equals("法国")) {
                        editorInput = franceEditorInput;
                        editorID = "cn.com.kxh.myplugin.FranceEditor";
                    }
                    // 如果editorInput或editorID为空则中断返回
                    if (editorInput == null || editorID == null)
                        return;
                    // 取得IWorkbenchPage,并搜索使用editorInput对象对应的编辑器
                    IWorkbenchPage workbenchPage = getViewSite().getPage();
                    IEditorPart editor = workbenchPage.findEditor(editorInput);
                    // 如果此编辑器已经存在,则将它设为当前的编辑器(最顶端),否则
                    // 重新打开一个编辑器
                    if (editor != null) {
                        workbenchPage.bringToTop(editor);
                    } else {
                        try {
                            workbenchPage.openEditor(editorInput, editorID);
                        } catch (PartInitException e2) {
                            e2.printStackTrace();
                        }
                    }
                }
            });
    
            // 加入导航栏按钮、下拉菜单、右键菜单
            MyActionGroup actionGroup = new MyActionGroup();
            fillViewAction(actionGroup);// 加入视图的导航栏按钮
            fillViewMenu(actionGroup);// 加入视图的下拉菜单
            fillListMenu(actionGroup);// 加入视图的下拉菜单
        }
        
        // 加入视图的导航栏按钮
        private void fillViewAction(MyActionGroup actionGroup) {
            IActionBars bars = getViewSite().getActionBars();
            actionGroup.fillActionBars(bars);
        }
    
        // 加入视图的下拉菜单
        private void fillViewMenu(MyActionGroup actionGroup) {
            IMenuManager manager = getViewSite().getActionBars().getMenuManager();
            actionGroup.fillContextMenu(manager);
        }
    
        // 加入列表List的右键菜单
        private void fillListMenu(MyActionGroup actionGroup) {
            MenuManager manger = new MenuManager();
            Menu menu = manger.createContextMenu(list);
            list.setMenu(menu);
            actionGroup.fillContextMenu(manger);
        }
        
        @Override
        public void setFocus() {}
    }

    程序说明:视图加按钮,菜单的方式和以前SWT的方式是一样的,只不过以前自己生成MenuManager等对象,而现在只需要使用插件平台提供的MenuManager对象.

    在事件处理方法:本程序中为了便于理解,使用了if...else这种简单的方式来判断被双击的类表项,这适合列表项较少的情况,如果列表项太多,则代码会相当长.解决这个问题,可将IEditorInput中没有用到的getName方法借用一下,把editorID放到此方法里面,这样就可以用下面的方式来得到IEditorInput和editorID了.

    String key = ""+list.getSelectionIndex();

    IEditorInput editorInput = (IEditorInput)list.getData(key);

    String editorID = editorInput.getnName();

    在实际开发综合很多界面都是创建在编辑器上,虽然在这里是只讲了最常用的编辑器使用方法,但已经足够应付大部分开发的需要,如果你想了解更多关于编辑器的信息,可以查阅编辑器的帮助文档,它在帮助中的位置是"平台插件开发者指南--->程序员指南----->编辑器".

    将在透视图中添加上对应的编辑器类:(这种效果就像在Eclipse张双击Java源文件,打开文件的编辑器一样)

    和以前一样,先来修改plugin.xml文件将编辑器的扩展点加入,然后再创建相应的编辑器类.最后编写列表的事件代码.

    plugin.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <?eclipse version="3.4"?>
    <plugin>
     <extension point="org.eclipse.ui.perspectives">
           <perspective
            name="myplugin 透视图"
            icon="icons/selectall.gif"
            class="cn.com.kxh.myplugin.SamplePerspective"
            id="cn.com.kxh.myplugin.SamplePerspective">
        </perspective>
     </extension>
     <extension point="org.eclipse.ui.views">
         <view
                 name="视图1"
                 icon="icons/prev.gif"
                 category="com.glkxh.myplugin.view"
                 class="cn.com.kxh.myplugin.View1"
                 id="cn.com.kxh.myplugin.View1">
         </view>
         <view
                 name="视图2"
                 icon="icons/project.gif"
                 category="com.glkxh.myplugin.view"
                 class="cn.com.kxh.myplugin.View2"
                 id="cn.com.kxh.myplugin.View2">
         </view>
     </extension>
     <extension point="org.eclipse.ui.editors">
      <editor 
            name="中国Editor"
            icon="icons/project.gif"
            class="cn.com.kxh.myplugin.ChinaEditor"
            id="cn.com.kxh.myplugin.ChinaEditor">
      </editor>
      <editor 
            name="美国Editor"
            icon="icons/prev.gif"
            class="cn.com.kxh.myplugin.UsaEditor"
            id="cn.com.kxh.myplugin.UsaEditor">
      </editor>
      <editor 
            name="法国Editor"
            icon="icons/remove.gif"
            class="cn.com.kxh.myplugin.FranceEditor"
            id="cn.com.kxh.myplugin.FranceEditor">
       </editor>
      </extension>
    </plugin>

    上述代码说明:编辑器的扩展点是org.eclipse.ui.editors,它各项的含义和视图扩展点基本一样,可参照视图扩展点的说明,这里强调一点:icon是必填项.

    编辑器必须实现IEditorPart接口,但通常是继承抽象类EditorPart类(EditorPart是IEditorPart的子类).继承EditorPart的子类必须实现父类的7个方法,在此先实现方法init,createPartControl,其他方法空实现.

    代码说明:编辑器的扩展点是org.eclispse.ui.editor

    ChinaEditor.java

     1 public class ChinaEditor extends EditorPart {
     2     private boolean dirty = true; // 编辑器是否为脏的标识
     3 
     4     // Editor的初始化方法。本方法前两句是固定不变的
     5     public void init(IEditorSite site, IEditorInput input) throws PartInitException {
     6         System.out.println("init");
     7         setSite(site);
     8         setInput(input);
     9         // 下一句设置Editor标题栏的显示名称,否则名称用plugin.xml中的name属性
    10         // setPartName(input.getName());
    11         // 下一句设置Editor标题栏的图标,否则会自动使用一个默认的图标
    12         // setTitleImage(input.getImageDescriptor().createImage());
    13     }
    14 
    15     // 在此方法中创建Editor中的界面组件
    16     public void createPartControl(Composite parent) {
    17         System.out.println("createPartControl");
    18         Composite topComp = new Composite(parent, SWT.NONE);
    19         topComp.setLayout(new FillLayout());
    20         Text text = new Text(topComp, SWT.BORDER);
    21         text.setText("中国之编辑器");
    22 
    23         text.addKeyListener(new KeyAdapter() {
    24             public void keyPressed(KeyEvent e) {
    25                 // 如果编辑器不脏(即没有修改),则标志它脏并刷新界面状态
    26                 if (!isDirty()) {
    27                     setDirty(true);
    28                     firePropertyChange(IEditorPart.PROP_DIRTY);
    29                 }
    30             }
    31         });
    32     }
    33 
    34     // 保存的处理代码在这种方法中,当按Ctrl+S键时会执行此方法。
    35     // 最后别忘记标志为非脏及刷新界面状态
    36     public void doSave(IProgressMonitor monitor) {
    37         if (isDirty()) {
    38             // ……保存编辑器事件处理代码(省略)
    39             setDirty(false);
    40             firePropertyChange(IEditorPart.PROP_DIRTY);
    41         }
    42     }
    43 
    44     // 是否允许“另存为”,false不允许
    45     public boolean isSaveAsAllowed() {
    46         return false;
    47     }
    48 
    49     // “另存为”的代码写在这里,本例不实现它
    50     public void doSaveAs() {}
    51 
    52     // dirty标识的set方法,由此方法设置编辑器为脏
    53     public void setDirty(boolean dirty) {
    54         this.dirty = dirty;
    55     }
    56 
    57     // 编辑器的内容是否脏了。true脏,false不脏
    58     public boolean isDirty() {
    59         return dirty;
    60     }
    61 
    62     // 当编辑器获得焦点时会执行此方法,本例空实现
    63     public void setFocus() {}
    64 }

    获取视图对象是用IWorkbenchPage的findView方法,方法参数是视图在plugin.xml中的id标识,获取编辑器对象是用findEditor方法,但该方法的参数却不是id标识,而是一个IEditorInput对象.另外,加载一个编辑器是用IWorkbenchPage的openEditor(editorInput,editorID)方法.

    由上可知,一个编辑器要对应一个IEditorInput和EditorPart,而且在IWorkbenchPage中是根据IEditorInput来取得EditorPart.

    附上关系图:

    ChinaEditorInput.java

     1 public class ChinaEditorInput implements IEditorInput {
     2 
     3     // 返回true,则打开该编辑器后它会出现在Eclipse主菜单“文件”
     4     // 最下部的最近打开的文档栏中。返回flase则不出现在其中。
     5     @Override
     6     public boolean exists() {
     7         return true;
     8     }
     9 
    10     // 编辑器标题栏的图标,不过它还需要在ChinaEditor中用
    11     // setTitleImage方法设置,才能出现在标题栏中。
    12     @Override
    13     public ImageDescriptor getImageDescriptor() {
    14         // return WorkbenchImages.getImageDescriptor(IWorkbenchGraphicConstants.IMG_ETOOL_HOME_NAV);
    15         return null;
    16     }
    17 
    18     // 编辑器标题栏的显示名称,和上面的getImageDescriptor一样也要
    19     // 在ChinaEditor中用setPartName方法设置,才能出现在标题栏中。
    20     @Override
    21     public String getName() {
    22         return "中国的编辑器";
    23     }
    24 
    25     // 编辑器标题栏的小黄条提示文字,不需象getName那样在ChinaEditor中再设置
    26     @Override
    27     public String getToolTipText() {
    28         return "这是视图1列表中的中国项对应的编辑器";
    29     }
    30 
    31     // 返回一个可以用做保存本编辑输入数据状态的对象
    32     @Override
    33     public IPersistableElement getPersistable() {
    34         return null;
    35     }
    36 
    37     // 得到一个编辑器的适配器
    38     // IAdaptable a = new ChinaEditorInput();
    39     // IFoo x = (IFoo)a.getAdapter(IFoo.class);
    40     // if (x != null) [用x来做IFoo的事情....]
    41     @Override
    42     public Object getAdapter(Class adapter) {
    43         return null;
    44     }
    45 }

    FranceEditor.java

     1 public class FranceEditor extends EditorPart {
     2 
     3     public void doSave(IProgressMonitor monitor) {}
     4 
     5     public void doSaveAs() {}
     6 
     7     public void init(IEditorSite site, IEditorInput input) throws PartInitException {
     8         setSite(site);
     9         setInput(input);
    10     }
    11 
    12     public boolean isDirty() {
    13         return false;
    14     }
    15 
    16     public boolean isSaveAsAllowed() {
    17         return false;
    18     }
    19 
    20     public void createPartControl(Composite parent) {
    21         Composite topComp = new Composite(parent, SWT.NONE);
    22         topComp.setLayout(new FillLayout());
    23         Text text = new Text(topComp, SWT.BORDER);
    24         text.setText("法国之编辑器");
    25     }
    26 
    27     public void setFocus() {}
    28 
    29 }

    FranceEditorInput.java

     1 public class FranceEditorInput implements IEditorInput {
     2 
     3     public boolean exists() {
     4         return false;
     5     }
     6 
     7     public ImageDescriptor getImageDescriptor() {
     8         return null;
     9     }
    10 
    11     public String getName() {
    12         return "法国的编辑器";
    13     }
    14 
    15     public IPersistableElement getPersistable() {
    16         return null;
    17     }
    18 
    19     public String getToolTipText() {
    20         return "这是视图1列表中的法国项对应的编辑器";
    21     }
    22 
    23     public Object getAdapter(Class adapter) {
    24         return null;
    25     }
    26 
    27 }

    UsaEditor.java

    public class UsaEditor extends EditorPart {
    
        public void doSave(IProgressMonitor monitor) {}
    
        public void doSaveAs() {}
    
        public void init(IEditorSite site, IEditorInput input) throws PartInitException {
            setSite(site);
            setInput(input);
        }
    
        public boolean isDirty() {
            return false;
        }
    
        public boolean isSaveAsAllowed() {
            return false;
        }
    
        public void createPartControl(Composite parent) {
            Composite topComp = new Composite(parent, SWT.NONE);
            topComp.setLayout(new FillLayout());
            Text text = new Text(topComp, SWT.BORDER);
            text.setText("美国之编辑器");
        }
    
        public void setFocus() {}
    
    }

    UsaEditorInput.java

     1 public class UsaEditorInput implements IEditorInput {
     2 
     3     public boolean exists() {
     4         return false;
     5     }
     6 
     7     public ImageDescriptor getImageDescriptor() {
     8         return null;
     9     }
    10 
    11     public String getName() {
    12         return "美国的编辑器";
    13     }
    14 
    15     public IPersistableElement getPersistable() {
    16         return null;
    17     }
    18 
    19     public String getToolTipText() {
    20         return "这是视图1列表中的美国项对应的编辑器";
    21     }
    22 
    23     public Object getAdapter(Class adapter) {
    24         return null;
    25     }
    26 
    27 }
  • 相关阅读:
    hdu 5648 DZY Loves Math 组合数+深搜(子集法)
    hdu 5647 DZY Loves Connecting 树形DP
    hdu 4550 卡片游戏 贪心
    hdu 5646 DZY Loves Partition 二分+数学分析+递推
    hdu 2196 Computer 树形DP
    poj 2342 Anniversary party 树形DP入门
    Vijos P1003 等价表达式 随机数+单调栈
    【BZOJ】1044: [HAOI2008]木棍分割 二分+区间DP
    【BZOJ】1925: [Sdoi2010]地精部落 DP+滚动数组
    【BZOJ】1012: [JSOI2008]最大数maxnumber 树状数组求区间最值
  • 原文地址:https://www.cnblogs.com/DreamDrive/p/4174566.html
Copyright © 2020-2023  润新知