例如,新建,打开,删除,剪切,粘帖等等,这些命令通常出现在窗口的菜单和工具栏上
但是,在不同的情况下可能执行不同的操作。
开发这些功能的时候,我们通常无法预料未来将出想哪些新的需求。
所以,这些动能应当随着当前的活动的某些部件的而改变。好的实现方式是把这些功能实现的职责交给对应的部件。
如下图:
新建的按钮在当前激活的视图为“项目”视图时,应当是新建项目,如果是在文档视图中时,就应当是新建文档,同样删除的按钮也是一样的。
接下来我记录了我的实现方法:
1. 在创建窗口菜单和工具栏的类ApplicationActionBarAdvisor中:
// 保存
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加入到菜单中:
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上扩展
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="新建(&N)..."
style="push"
tooltip="创建一个新项目">
</command>
<command
commandId="com.sg.intellifmea.commands.Open"
icon="icons/Open.gif"
label="打开(&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
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的是否可用。当然这里还涉及到一个系统性的知识。包括了表达式,选择等等,这里不详述。
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设置快捷键,以下是例子
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就被执行了,而不是执行的文档视图的删除方法。