新建菜单里面都是声明过NewWizard的东东
不过既然已经声明了NewWizard还要在ActionSet或者PopupMenus里面再声明一遍不是很痛苦?
其实可以如下做法
先声明一个PullDown的菜单
<action
class=\xxxNewAction\
hoverIcon=\icons/full/objects/new_projectgif\
id=\xxxNewAction\
label=\新建(&N)\
menubarPath=\nusfile/sep\
style=\pulldown\
toolbarPath=\sep\>
</action>
如果这个菜单用Coolbar 那么需要继承IWorkbenchWindowPulldownDelegate接口 如果要用在Menu上 那么继承IWorkbenchWindowPulldownDelegate接口实现基本是一样的
publicclassNewActionimplementsIWorkbenchWindowPulldownDelegateSelectionListener{
privateIWorkbenchworkbench;
@SuppressWarnings(\unused\)
privateIWorkbenchWindowwindow;
privateMenuparent=null;
privateMenuinMenu=null;
privateMenuinToolbar=null;
privateIStructuredSelectionselection;
/***//**
*(nonJavadoc)
*
*@seeorgeclipseuiIWorkbenchWindowActionDelegate#dispose()
*/
publicvoiddispose(){
if(inMenu!=null){
inMenudispose();
inMenu=null;
} [Page]
thisworkbench=null;
thiswindow=null;
}
/***//**
*(nonJavadoc)
*
*@seeorgeclipseuiIWorkbenchWindowActionDelegate#init(orgeclipseuiIWorkbenchWindow)
*/
publicvoidinit(IWorkbenchWindowwindow){
thiswindow=window;
thisworkbench=windowgetWorkbench();
}
/***//**
*(nonJavadoc)
*
*@seeorgeclipseuiIActionDelegate#run(orgeclipsejfaceactionIAction)
*/
publicvoidrun(IActionaction){
}
/***//**
*(nonJavadoc)
*
*@seeorgeclipseuiIActionDelegate#selectionChanged(orgeclipsejfaceactionIAction
*orgeclipsejfaceviewersISelection)
*/
publicvoidselectionChanged(IActionactionISelectionselection){
thisselection=(IStructuredSelection)selection;
if(parent!=null){
//找到新建菜单项
//重新创建其子菜单
MenuItem[]items=parentgetItems();
if(items!=null){
MenuItemparentItem=null;
for(intindex=count=itemslength;index<count;index++){ [Page]
MenuItemitem=items[index];
Objectdata=itemgetData();
if(datainstanceofActionSetContributionItem){
IContributionIteminnerItem=((ActionSetContributionItem)data)
getInnerItem();
if(innerItemgetId()equals(getClass()getName())){
parentItem=item;
break;
}
}
}
if(parentItem!=null){
Menumenu=getMenu(parent);
parentItemsetMenu(menu);
parentItemsetImage(null); [Page]
}
}
}
}
/***//**
*(nonJavadoc)
*
*@seeorgeclipseuiIWorkbenchWindowPulldownDelegate#getMenu(orgeclipseswtwidgetsControl)
*/
publicMenugetMenu(Controlparent){
if(inToolbar!=null)
inToolbardispose();
inToolbar=newMenu(parent);
returncreateMenu(inToolbar);
}
/***//**
*(nonJavadoc)
*
*@seeorgeclipseuiIWorkbenchWindowPulldownDelegate#getMenu(orgeclipseswtwidgetsMenu)
*/
publicMenugetMenu(Menuparent){
if(inMenu!=null)
inMenudispose();
thisparent=parent;
inMenu=newMenu(parent);
returncreateMenu(inMenu);
}
/***//**
*@paramparent
*@return
*/
privateMenucreateMenu(Menumenu){
booleanhasMenu=false;
IWizardRegistryregistry=workbenchgetNewWizardRegistry();
IWizardCategoryrootCategory=registrygetRootCategory();
IWizardCategory[]categories=rootCategorygetCategories(); [Page]
if(categories!=null){
reverseArray(categories);
for(IWizardCategorycategory:categories){
hasMenu=createMenuItems(menucategoryhasMenu)||hasMenu;
}
}
if(hasMenu)
newMenuItem(menuSWTSEPARATOR);
MenuItemmnuOther=newMenuItem(menuSWTNONE);
mnuOthersetText(\其他(&R)\);
mnuOtheraddSelectionListener(newSelectionAdapter(){
/***//**
*(nonJavadoc)
*
*@seeorgeclipseswteventsSelectionAdapter#widgetSelected(orgeclipseswteventsSelectionEvent)
*/
@Override
publicvoidwidgetSelected(SelectionEvente){
NewWizardDialogdialog=newNewWizardDialog(workbenchgetActiveWorkbenchWindow()
getShell()selection);
dialogopen();
}
}); [Page]
returnmenu;
}
/***//**
*创建菜单
*
*@parammenu
*@paramcategory
*@paramhasMenu是否在之前已经有菜单
*@return是否成功创建了菜单
*/
privatebooleancreateMenuItems(MenumenuIWizardCategorycategorybooleanhasMenu){
booleancreate=false;
IWizardDescriptor[]wizards=categorygetWizards();
if(wizards!=null){
reverseArray(wizards);
List<IWizardDescriptor>shown=newArrayList<IWizardDescriptor>();
for(IWizardDescriptorwizard:wizards){
IConfigurationElementelement=(IConfigurationElement)wizard
getAdapter(IConfigurationElementclass);
IConfigurationElement[]children=element
getChildren(IWorkbenchRegistryConstantsTAG_ENABLEMENT);
if(children!=null&&childrenlength!=){
IConfigurationElementenablement=children[];
ActionExpressionexp=newActionExpression(enablement); [Page]
if(!expisEnabledFor(thisselection)){
continue;
}
}
shownadd(wizard);
}
if(shownsize()!=){
create=true;
if(hasMenu){
newMenuItem(menuSWTSEPARATOR);
}
for(IWizardDescriptorwizard:shown){
MenuItemitem=newMenuItem(menuSWTNONE);
itemsetText(wizardgetLabel());
if(wizardgetImageDescriptor()!=null)
itemsetImage(wizardgetImageDescriptor()createImage());
itemsetData(wizard);
itemaddSelectionListener(this); [Page]
}
}
}
returncreate;
}
/***//**
*反转数组
*
*@paramarray
*/
privatevoidreverseArray(Object[]array){
if(array!=null){
intcount=arraylength;
intlast=count;
for(intindex=;index<count/;index++){
Objecttemp=array[index];
array[index]=array[lastindex];
array[last]=temp;
}
}
}
/***//**
*(nonJavadoc)
*
*@seeorgeclipseswteventsSelectionListener#widgetDefaultSelected(orgeclipseswteventsSelectionEvent)
*/
publicvoidwidgetDefaultSelected(SelectionEvente){
//donothing
}
/***//**
*(nonJavadoc)
*
*@seeorgeclipseswteventsSelectionListener#widgetSelected(orgeclipseswteventsSelectionEvent)
*/ [Page]
publicvoidwidgetSelected(SelectionEvente){
MenuItemitem=(MenuItem)egetSource();
IWizardDescriptordesc=(IWizardDescriptor)itemgetData();
try{
IWorkbenchWizardwizard=desccreateWizard();
wizardinit(thisworkbenchthisselection);
WizardDialogdialog=newWizardDialog(workbenchgetActiveWorkbenchWindow()getShell()
wizard);
dialogopen();
}catch(CoreExceptionex){
//TODO处理异常
}
}
}
这里有几个重点 是我自己摸索出来的
第一个是IWorkbenchWindowPulldownDelegate是继承IWorkbenchWindowPulldownDelegate的 因此只要实现这一个就可以在menu和coolbar个地方用了 实际上 如果你只在一个地方用的话 另外一个方法返回null就可以了 因为永远不会被调用的 getMenu(Menu)是用在菜单的 getMenu(Control)是用在Coolbar的
第二个就是getMenu(Menu)方法只会被调用一次 就是初始化的时候 而getMenu(Control)方法每次你打开菜单都会被调用 因此selectionChanged里面也只需要处理菜单的内容 而不需要处理coolbar的内容
第三就是selectionChanged的操作
/***//**
*(nonJavadoc)
*
*@seeorgeclipseuiIActionDelegate#selectionChanged(orgeclipsejfaceactionIAction
*orgeclipsejfaceviewersISelection)
*/
publicvoidselectionChanged(IActionactionISelectionselection){
thisselection=(IStructuredSelection)selection; [Page]
if(parent!=null){
//找到新建菜单项
//重新创建其子菜单
MenuItem[]items=parentgetItems();
if(items!=null){
MenuItemparentItem=null;
for(intindex=count=itemslength;index<count;index++){
MenuItemitem=items[index];
Objectdata=itemgetData();
if(datainstanceofActionSetContributionItem){
IContributionIteminnerItem=((ActionSetContributionItem)data)
getInnerItem();
if(innerItemgetId()equals(getClass()getName())){
parentItem=item;
break;
} [Page]
}
}
if(parentItem!=null){
Menumenu=getMenu(parent);
parentItemsetMenu(menu);
parentItemsetImage(null);
}
}
}
}
parent是在getMenu(menu)中记录下来的 等于是上级菜单 说到这里 我们来说一下SWT里面菜单的构造(不一定对 只是我的理解而已)所有你可以看到的带文字的条目都是MenuItem MenuItem分为种 一种是没有子菜单的 一种是有子菜单的
没有子菜单的很简单 不说了 有子菜单的就是SWTCASCADE类型的 这个时候MenuItem会产生一个Menu 而Menu是一个容器 基本可以认为弹出菜单的整体 里面可以包含很多MenuItem 就是这么个关系
说完这个 我们来看SelectionChanged方法 Parent是个Menu 实际上是[文件]菜单 在里面查找id为类名的MenuItem 注意看Pluginxml的声明 类名和ID是一致的 实际上找到的就是[新建]菜单 然后重新创建菜单 并且设置成为MenuItem的Menu 这样就可以了
实际上JDT就是这么做的 但是具体的实现可能不一样 我也没有仔细的研究他的做法 因为系统比较庞大 研究的话时间太厉害了
至于PopupMenus 处理的方式是差不多的 略微有些修改而已 这里就不再把代码贴出来了
还有这一段
IConfigurationElementelement=(IConfigurationElement)wizard
getAdapter(IConfigurationElementclass);
IConfigurationElement[]children=element [Page]
getChildren(IWorkbenchRegistryConstantsTAG_ENABLEMENT);
if(children!=null&&childrenlength!=){
IConfigurationElementenablement=children[];
ActionExpressionexp=newActionExpression(enablement);
if(!expisEnabledFor(thisselection)){
continue;
}
}
Wizard里面好像只能添加selection的限制 我这里是解析了enablement的限制 和action一样的 怎么判断看ActionExpression类就行了 我什么都没干 哈哈 因为JDT的NewWizard在任何情况下都可以进行 我的不可以 和选择的对象有很大的关系 因此增强一下条件的声明是必要的 顺便说一句 你用Eclipse的工具创建 在NewWizard下没办法创建<enablement/>节点的 但是你再Pluginxml里面写好以后 extensions页面却可以认识 然后就可以在extensions页面里面改了