为视图添加工具栏和菜单(一) 使用窗口上的工具栏和窗口菜单

时间:2021-12-16 08:59:21

例如,新建,打开,删除,剪切,粘帖等等,这些命令通常出现在窗口的菜单和工具栏上

但是,在不同的情况下可能执行不同的操作。

开发这些功能的时候,我们通常无法预料未来将出想哪些新的需求。

所以,这些动能应当随着当前的活动的某些部件的而改变。好的实现方式是把这些功能实现的职责交给对应的部件。

如下图:

为视图添加工具栏和菜单(一) 使用窗口上的工具栏和窗口菜单 

新建的按钮在当前激活的视图为“项目”视图时,应当是新建项目,如果是在文档视图中时,就应当是新建文档,同样删除的按钮也是一样的。

接下来我记录了我的实现方法:

1. 在创建窗口菜单和工具栏的类ApplicationActionBarAdvisor中:

为视图添加工具栏和菜单(一) 使用窗口上的工具栏和窗口菜单为视图添加工具栏和菜单(一) 使用窗口上的工具栏和窗口菜单代码
     protected   void  makeActions(IWorkbenchWindow window) {

        
//  保存
        saveAction  =  ActionFactory.SAVE.create(window);
        register(saveAction);
        
//  保存全部
        saveAllAction  =  ActionFactory.SAVE_ALL.create(window);
        register(saveAllAction);
        
//  保存全部
        saveAsAction  =  ActionFactory.SAVE_AS.create(window);
        register(saveAsAction);
        
//  关闭
        closeAction  =  ActionFactory.CLOSE.create(window);
        register(closeAction);
        
//  关闭全部
        closeAllAction  =  ActionFactory.CLOSE_ALL.create(window);
        register(closeAllAction);
        
        reOpenList 
=  ContributionItemFactory.REOPEN_EDITORS.create(window);

        
//  退出系统
        exitAction  =  ActionFactory.QUIT.create(window);
        register(exitAction);

        
//  编辑菜单
        redoAction  =  ActionFactory.REDO.create(window);
        register(redoAction);
        undoAction 
=  ActionFactory.UNDO.create(window);
        register(undoAction);
        cutAction 
=  ActionFactory.CUT.create(window);
        register(cutAction);
        copyAction 
=  ActionFactory.COPY.create(window);
        register(copyAction);
        pasteAction 
=  ActionFactory.PASTE.create(window);
        register(pasteAction);
        deleteAction 
=  ActionFactory.DELETE.create(window);
        register(deleteAction);

        
//  窗口
        openNewWindowAction  =  ActionFactory.OPEN_NEW_WINDOW.create(window);
        register(openNewWindowAction);

        editActionSetAction 
=  ActionFactory.EDIT_ACTION_SETS.create(window);
        register(editActionSetAction);

        savePerspectiveAction 
=  ActionFactory.SAVE_PERSPECTIVE.create(window);
        register(savePerspectiveAction);

        closePerspectiveAction 
=  ActionFactory.CLOSE_PERSPECTIVE.create(window);
        register(closePerspectiveAction);

        closeAllPerspectiveAction 
=  ActionFactory.CLOSE_ALL_PERSPECTIVES
                .create(window);
        register(closePerspectiveAction);

        resetPerspectiveAction 
=  ActionFactory.RESET_PERSPECTIVE.create(window);
        register(resetPerspectiveAction);

        preferenceAction 
=  ActionFactory.PREFERENCES.create(window);
        register(preferenceAction);

        
//  关于
        helpContentAction  =  ActionFactory.HELP_CONTENTS.create(window);  
        register(helpContentAction);  
        helpSearchAction 
=  ActionFactory.HELP_SEARCH.create(window);  
        register(helpSearchAction);  
        helpDynamicAction 
=  ActionFactory.DYNAMIC_HELP.create(window);  
        register(helpDynamicAction);  
        aboutAction 
=  ActionFactory.ABOUT.create(window);
        register(aboutAction);

    }

这里有很多种方式创建系统的菜单,我只写两种。上面的一种是用程序写,例如:saveAction = ActionFactory.SAVE.create(window);

然后,把这些Action加入到菜单中:

为视图添加工具栏和菜单(一) 使用窗口上的工具栏和窗口菜单为视图添加工具栏和菜单(一) 使用窗口上的工具栏和窗口菜单代码
     protected   void  fillMenuBar(IMenuManager menuBar) {
        MenuManager systemMenu 
=   new  MenuManager( " 开始(&S) " , UIConstants.M_SYSTEM);
        MenuManager editMenu 
=   new  MenuManager( " 编辑(&E) " , UIConstants.M_EDIT);
        MenuManager navigateMenu 
=   new  MenuManager( " 导航(&V) " ,
                UIConstants.M_NAVIGATOR);
        MenuManager searchMenu 
=   new  MenuManager( " 查询(&A) " , UIConstants.M_SEARCH);
        MenuManager windowMenu 
=   new  MenuManager( " 窗口(&W) " ,
                IWorkbenchActionConstants.M_WINDOW);
        MenuManager helpMenu 
=   new  MenuManager( " 帮助(&H) " ,
                IWorkbenchActionConstants.M_HELP);

        menuBar.add(systemMenu);
        menuBar.add(editMenu);
        menuBar.add(navigateMenu);
        menuBar.add(searchMenu);
        menuBar.add(
new  GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
        menuBar.add(windowMenu);
        menuBar.add(helpMenu);

        systemMenu.add(
new  GroupMarker( " intellifmea " ));
        systemMenu.add(
new  Separator(UIConstants.MB_RELOADOBJECT));
        systemMenu.add(saveAction);
        systemMenu.add(saveAllAction);
        systemMenu.add(saveAsAction);
        
        systemMenu.add(
new  Separator());
        systemMenu.add(closeAction);
        systemMenu.add(closeAllAction);
        systemMenu.add(
new  Separator(IWorkbenchActionConstants.MB_ADDITIONS));
        systemMenu.add(reOpenList);
        systemMenu.add(
new  Separator( " blank " ));
        systemMenu.add(exitAction);

        editMenu.add(undoAction);
        editMenu.add(redoAction);
        editMenu.add(
new  Separator());
        editMenu.add(cutAction);
        editMenu.add(copyAction);
        editMenu.add(pasteAction);
        editMenu.add(deleteAction);

        editMenu.add(
new  Separator(IWorkbenchActionConstants.MB_ADDITIONS));

        navigateMenu
                .add(
new  GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));

        windowMenu.add(openNewWindowAction);
        windowMenu.add(
new  Separator());
        windowMenu.add(editActionSetAction);
        windowMenu.add(savePerspectiveAction);
        windowMenu.add(resetPerspectiveAction);
        windowMenu.add(closePerspectiveAction);
        windowMenu.add(closeAllPerspectiveAction);
        windowMenu.add(
new  Separator(IWorkbenchActionConstants.MB_ADDITIONS));
        windowMenu.add(preferenceAction);

        searchMenu.add(
new  Separator(IWorkbenchActionConstants.MB_ADDITIONS));
        
        helpMenu.add(helpContentAction);
        helpMenu.add(helpSearchAction);
        helpMenu.add(helpDynamicAction);
        helpMenu.add(aboutAction);
    }

第二种方法是直接在Plugins.xml上扩展

为视图添加工具栏和菜单(一) 使用窗口上的工具栏和窗口菜单为视图添加工具栏和菜单(一) 使用窗口上的工具栏和窗口菜单代码
       < menuContribution
            locationURI
= " menu:com.sg.hyperobject.ui.systemmenu?after=intellifmea " >
         
< command
               commandId
= " com.sg.intellifmea.commands.CreateProjectWiz "
               disabledIcon
= " icons/newobject_dis.gif "
               icon
= " icons/newobject.gif "
               label
= " 新建(&amp;N)... "
               style
= " push "
               tooltip
= " 创建一个新项目 " >
         
</ command >
         
< command
               commandId
= " com.sg.intellifmea.commands.Open "
               icon
= " icons/Open.gif "
               label
= " 打开(&amp;O)... "
               tooltip
= " 打开 " >
         
</ command >
      
</ menuContribution >

请注意locationURI="menu:com.sg.hyperobject.ui.systemmenu?after=intellifmea"指定了这个菜单应当出现的位置是在intellifmea之后的。intellifmea是什么呢?

请看上文中我们为systemMenu留出的扩展菜单的一个GroupMarker,(在fillMenuBar方法中 ) systemMenu.add(new GroupMarker("intellifmea"));

这样,pluins.xml中定义的菜单就加在了指定的位置了(这种扩展同样适用于扩展各种各样的工具栏和菜单,例如视图的菜单工具栏以及右键菜单)

2. 为菜单指定Command

为视图添加工具栏和菜单(一) 使用窗口上的工具栏和窗口菜单为视图添加工具栏和菜单(一) 使用窗口上的工具栏和窗口菜单代码
    < extension
         
point ="org.eclipse.ui.commands" >
      
< category
            
id ="com.sg.intellifmea.project"
            name
="intellifmea project" >
      
</ category >
      
< command
            
categoryId ="com.sg.intellifmea.project"
            id
="com.sg.intellifmea.commands.CreateProjectWiz"
            name
="CreateProjectWiz" >
      
</ command >
      
< command
            
categoryId ="com.sg.intellifmea.project"
            id
="com.sg.intellifmea.commands.Open"
            name
="OpenProject" >
      
</ command >
      
< command
            
categoryId ="com.sg.intellifmea.project"
            id
="com.sg.intellifmea.commands.ProjectProcess"
            name
="ProjectProcess" >
      
</ command >
      
< command
            
categoryId ="com.sg.intellifmea.project"
            id
="com.sg.intellifmea.commands.ProjectPause"
            name
="ProjectPause" >
      
</ command >
      
< command
            
categoryId ="com.sg.intellifmea.project"
            id
="com.sg.intellifmea.commands.ProjectFinish"
            name
="ProjectFinish" >
      
</ command >
      
< command
            
categoryId ="com.sg.intellifmea.project"
            id
="com.sg.intellifmea.commands.ProjectCancel"
            name
="ProjectCancel" >
      
</ command >
      
< command
            
categoryId ="com.sg.intellifmea.project"
            id
="com.sg.intellifmea.commands.ProjectViewerReload"
            name
="ProjectViewerReload" >
      
</ command >
      
< command
            
categoryId ="com.sg.intellifmea.project"
            id
="com.sg.intellifmea.commands.SetCurrentProject"
            name
="SetCurrentProject" >
      
</ command >
      
< command
            
categoryId ="com.sg.intellifmea.project"
            id
="com.sg.intellifmea.commands.CreateDocument"
            name
="CreateDocument" >
      
</ command >
   
</ extension >

扩展org.eclipse.commands扩展点

3. 为command指定Handler

扩展 "org.eclipse.ui.handlers"

这里可以指定commands的调用时执行的方法,可以控制该command的是否可用。当然这里还涉及到一个系统性的知识。包括了表达式,选择等等,这里不详述。

为视图添加工具栏和菜单(一) 使用窗口上的工具栏和窗口菜单为视图添加工具栏和菜单(一) 使用窗口上的工具栏和窗口菜单代码
   < extension
         
point ="org.eclipse.ui.handlers" >
      
< handler
            
class ="com.sg.intellifmea.commands.CreateProjectWiz"
            commandId
="com.sg.intellifmea.commands.CreateProjectWiz" >
      
</ handler >
      
< handler
            
class ="com.sg.intellifmea.commands.Open"
            commandId
="com.sg.intellifmea.commands.Open" >
         
< enabledWhen >
            
< count
                  
value ="1" >
            
</ count >
         
</ enabledWhen >
      
</ handler >
      
< handler
            
class ="com.sg.intellifmea.commands.ProjectProcess"
            commandId
="com.sg.intellifmea.commands.ProjectProcess" >
         
< activeWhen >
            
< count
                  
value ="1" >
            
</ count >
         
</ activeWhen >
         
< enabledWhen >
            
< iterate
                  
ifEmpty ="false" >
               
< test
                     
args ="进行"
                     property
="com.sg.intellifmea.tester.ProjectStatusChangeableTest" >
               
</ test >
            
</ iterate ></ enabledWhen >
      
</ handler >
      
< handler
            
class ="com.sg.intellifmea.commands.ProjectPause"
            commandId
="com.sg.intellifmea.commands.ProjectPause" >
         
< activeWhen >
            
< count
                  
value ="1" >
            
</ count >
         
</ activeWhen >
         
< enabledWhen >
            
< iterate
                  
ifEmpty ="false" >
               
< test
                     
args ="暂停"
                     property
="com.sg.intellifmea.tester.ProjectStatusChangeableTest" >
               
</ test >
            
</ iterate >
         
</ enabledWhen >
      
</ handler >
      
< handler
            
class ="com.sg.intellifmea.commands.ProjectFinish"
            commandId
="com.sg.intellifmea.commands.ProjectFinish" >
         
< activeWhen >
            
< count
                  
value ="1" >
            
</ count >
         
</ activeWhen >
         
< enabledWhen >
            
< iterate
                  
ifEmpty ="false" >
               
< test
                     
args ="完成"
                     property
="com.sg.intellifmea.tester.ProjectStatusChangeableTest" >
               
</ test >
            
</ iterate >
         
</ enabledWhen >
      
</ handler >
      
< handler
            
class ="com.sg.intellifmea.commands.ProjectCancel"
            commandId
="com.sg.intellifmea.commands.ProjectCancel" >
         
< activeWhen >
            
< count
                  
value ="1" >
            
</ count >
         
</ activeWhen >
         
< enabledWhen >
            
< iterate
                  
ifEmpty ="false" >
               
< test
                     
args ="取消"
                     property
="com.sg.intellifmea.tester.ProjectStatusChangeableTest" >
               
</ test >
            
</ iterate >
         
</ enabledWhen >
      
</ handler >
      
< handler
            
class ="com.sg.intellifmea.commands.ProjectViewerReload"
            commandId
="com.sg.intellifmea.commands.ProjectViewerReload" >
      
</ handler >
      
< handler
            
class ="com.sg.intellifmea.commands.SetCurrentProject"
            commandId
="com.sg.intellifmea.commands.SetCurrentProject" >
         
< activeWhen >
            
< count
                  
value ="1" >
            
</ count >
         
</ activeWhen >
         
< enabledWhen >
            
< iterate
                  
ifEmpty ="false" >
               
< and >
                  
< test
                        
args ="工作"
                        property
="com.sg.intellifmea.tester.ProjectStatusChangeableTest" >
                  
</ test >
                  
< not >
                     
< test
                           
property ="com.sg.intellifmea.tester.IsWorkingProject" >
                     
</ test >
                  
</ not >
               
</ and >
            
</ iterate >
         
</ enabledWhen >
      
</ handler >
      
< handler
            
class ="com.sg.intellifmea.commands.CreateDocument"
            commandId
="com.sg.intellifmea.commands.CreateDocument" >
         
< activeWhen >
            
< with
                  
variable ="activePartId" >
               
< equals
                     
value ="com.sg.intellifmea.view.ProjectView" >
               
</ equals >
            
</ with >
         
</ activeWhen >
         
< enabledWhen >
            
< count
                  
value ="1" >
            
</ count >
         
</ enabledWhen >
      
</ handler >
   
</ extension >

4. 指定键盘的快捷键

扩展org.eclipse.ui.bindings设置快捷键,以下是例子

为视图添加工具栏和菜单(一) 使用窗口上的工具栏和窗口菜单为视图添加工具栏和菜单(一) 使用窗口上的工具栏和窗口菜单代码
   < extension
        
point ="org.eclipse.ui.bindings" >
     
< key
           
commandId ="com.sg.hyperobject.commands.dataobject.OpenObject"
           contextId
="org.eclipse.ui.contexts.window"
           schemeId
="org.eclipse.ui.defaultAcceleratorConfiguration"
           sequence
="M1+O" >
     
</ key >
     
< key
           
commandId ="com.sg.hyperobject.commands.dataobject.MakeWipDTO"
           contextId
="org.eclipse.ui.contexts.window"
           schemeId
="org.eclipse.ui.defaultAcceleratorConfiguration"
           sequence
="M2+F2" >
     
</ key >
     
< key
           
commandId ="com.sg.hyperobject.commands.dataobject.DeleteDTO"
           contextId
="org.eclipse.ui.contexts.window"
           schemeId
="org.eclipse.ui.defaultAcceleratorConfiguration"
           sequence
="M2+DEL" >
     
</ key >
     
< key
           
commandId ="com.sg.hyperobject.commands.dataobject.CopySelectionDTO"
           contextId
="org.eclipse.ui.contexts.window"
           schemeId
="org.eclipse.ui.defaultAcceleratorConfiguration"
           sequence
="M1+M2+T" >
     
</ key >
     
< key
           
commandId ="com.sg.hyperobject.commands.search.FindInResult"
           contextId
="org.eclipse.ui.contexts.window"
           schemeId
="org.eclipse.ui.defaultAcceleratorConfiguration"
           sequence
="M1+F3" >
     
</ key >
     
< key
           
commandId ="com.sg.hyperobject.commands.search.FindInResultNext"
           contextId
="org.eclipse.ui.contexts.window"
           schemeId
="org.eclipse.ui.defaultAcceleratorConfiguration"
           sequence
="F3" >
     
</ key >
     
< key
           
commandId ="com.sg.hyperobject.commands.tableediting.InsertItem"
           contextId
="org.eclipse.ui.contexts.window"
           schemeId
="org.eclipse.ui.defaultAcceleratorConfiguration"
           sequence
="M1+I" >
     
</ key >
     
< key
           
commandId ="com.sg.hyperobject.commands.tableediting.AppendItem"
           contextId
="org.eclipse.ui.contexts.window"
           schemeId
="org.eclipse.ui.defaultAcceleratorConfiguration"
           sequence
="M1+A" >
     
</ key >
     
< key
           
commandId ="com.sg.hyperobject.commands.tableediting.MoveUp"
           contextId
="org.eclipse.ui.contexts.window"
           schemeId
="org.eclipse.ui.defaultAcceleratorConfiguration"
           sequence
="M1+ARROW_UP" >
     
</ key >
     
< key
           
commandId ="com.sg.hyperobject.commands.tableediting.MoveDown"
           contextId
="org.eclipse.ui.contexts.window"
           schemeId
="org.eclipse.ui.defaultAcceleratorConfiguration"
           sequence
="M1+ARROW_DOWN" >
     
</ key >
     
< key
           
commandId ="com.sg.hyperobject.commands.tableediting.LinkItem"
           contextId
="org.eclipse.ui.contexts.window"
           schemeId
="org.eclipse.ui.defaultAcceleratorConfiguration"
           sequence
="M1+L" >
     
</ key >
     
< key
           
commandId ="com.sg.hyperobject.commands.ui.HideAssistant"
           contextId
="org.eclipse.ui.contexts.window"
           schemeId
="org.eclipse.ui.defaultAcceleratorConfiguration"
           sequence
="M1+H" >
     
</ key >
     
< key
           
commandId ="com.sg.hyperobject.commands.tableediting.CopyItem"
           contextId
="org.eclipse.ui.contexts.window"
           schemeId
="org.eclipse.ui.defaultAcceleratorConfiguration"
           sequence
="M1+M2+C" >
     
</ key >
     
< key
           
commandId ="com.sg.hyperobject.commands.tableediting.PasteItem"
           contextId
="org.eclipse.ui.contexts.window"
           schemeId
="org.eclipse.ui.defaultAcceleratorConfiguration"
           sequence
="M1+M2+P" >
     
</ key >
  
</ extension >

到此为止,我们基于Plugins.xml实现了菜单。

5. 不同的部件中具有不同的功能的全局菜单和工具栏

我们只需要在该部件中加入以下代码,这个id的菜单功能就被替换了。

奇怪的是,似乎这个替换并不需要我们主动地在侦听激活或者非激活状态。也无需我们主动地clear

getViewSite().getActionBars().setGlobalActionHandler(ActionFactory.DELETE.getId(), deleteAction);

我们在创建文档视图的方法中,加上上面的一句话,那么在文档视图中,点击删除按钮,deleteAction就被执行了

同样,我们在创建项目视图的方法中, 加上上面的一句话,那么在项目视图中,点击删除按钮,项目视图的deleteAction就被执行了,而不是执行的文档视图的删除方法。