二级菜单的实现 关于Eclipse中新建菜单的实现方法
关于Eclipse中新建菜单的实现方法
新建菜单里面都是声明过NewWizard的东东
不过既然已经声明了NewWizard还要在ActionSet或者PopupMenus里面再声明一遍不是很痛苦?
其实可以如下做法
先声明一个PullDown的菜单
<action class= xxx NewAction hoverIcon= icons/full/objects/new_project gif id= xxx NewAction label= 新建(&N) menubarPath= nus file/sep style= pulldown toolbarPath= sep ></action>
如果这个菜单用Coolbar 那么需要继承IWorkbenchWindowPulldownDelegate接口 如果要用在Menu上 那么继承IWorkbenchWindowPulldownDelegate 接口 实现基本是一样的
public class NewAction implements IWorkbenchWindowPulldownDelegate SelectionListener { private IWorkbench workbench; @SuppressWarnings( unused ) private IWorkbenchWindow window; private Menu parent = null; private Menu inMenu = null; private Menu inToolbar = null; private IStructuredSelection selection; /** *//** * (non Javadoc) * * @see eclipse ui IWorkbenchWindowActionDelegate#dispose() */ public void dispose() { if (inMenu != null) { inMenu dispose(); inMenu = null; } [Page] this workbench = null; this window = null; } /** *//** * (non Javadoc) * * @see eclipse ui IWorkbenchWindowActionDelegate#init( eclipse ui IWorkbenchWindow) */ public void init(IWorkbenchWindow window) { this window = window; this workbench = window getWorkbench(); } /** *//** * (non Javadoc) * * @see eclipse ui IActionDelegate#run( eclipse jface action IAction) */ public void run(IAction action) { } /** *//** * (non Javadoc) * * @see eclipse ui IActionDelegate#selectionChanged( eclipse jface action IAction * eclipse jface viewers ISelection) */ public void selectionChanged(IAction action ISelection selection) { this selection = (IStructuredSelection) selection; if (parent != null) { // 找到新建菜单项 // 重新创建其子菜单 MenuItem[] items = parent getItems(); if (items != null) { MenuItem parentItem = null; for (int index = count = items length; index < count; index++) { [Page] MenuItem item = items[index]; Object data = item getData(); if (data instanceof ActionSetContributionItem) { IContributionItem innerItem = ((ActionSetContributionItem) data) getInnerItem(); if (innerItem getId() equals(getClass() getName())) { parentItem = item; break; } } } if (parentItem != null) { Menu menu = getMenu(parent); parentItem setMenu(menu); parentItem setImage(null); [Page] } } } } /** *//** * (non Javadoc) * * @see eclipse ui IWorkbenchWindowPulldownDelegate#getMenu( eclipse swt widgets Control) */ public Menu getMenu(Control parent) { if (inToolbar != null) inToolbar dispose(); inToolbar = new Menu(parent); return createMenu(inToolbar); } /** *//** * (non Javadoc) * * @see eclipse ui IWorkbenchWindowPulldownDelegate #getMenu( eclipse swt widgets Menu) */ public Menu getMenu(Menu parent) { if (inMenu != null) inMenu dispose(); this parent = parent; inMenu = new Menu(parent); return createMenu(inMenu); } /** *//** * @param parent * @return */ private Menu createMenu(Menu menu) {boolean hasMenu = false; IWizardRegistry registry = workbench getNewWizardRegistry(); IWizardCategory rootCategory = registry getRootCategory(); IWizardCategory[] categories = rootCategory getCategories(); [Page] if (categories != null) { reverseArray(categories); for (IWizardCategory category : categories) { hasMenu = createMenuItems(menu category hasMenu) || hasMenu; } } if (hasMenu) new MenuItem(menu SWT SEPARATOR); MenuItem mnuOther = new MenuItem(menu SWT NONE); mnuOther setText( 其他(&R) ); mnuOther addSelectionListener(new SelectionAdapter() { /** *//** * (non Javadoc) * * @see eclipse swt events SelectionAdapter#widgetSelected( eclipse swt events SelectionEvent) */ @Override public void widgetSelected(SelectionEvent e) { NewWizardDialog dialog = new NewWizardDialog(workbench getActiveWorkbenchWindow() getShell() selection); dialog open(); } }); [Page] return menu; } /** *//** * 创建菜单 * * @param menu * @param category * @param hasMenu 是否在之前已经有菜单 * @return 是否成功创建了菜单 */ private boolean createMenuItems(Menu menu IWizardCategory category boolean hasMenu) { boolean create = false; IWizardDescriptor[] wizards = category getWizards(); if (wizards != null) { reverseArray(wizards); List<IWizardDescriptor> shown = new ArrayList<IWizardDescriptor>(); for (IWizardDescriptor wizard : wizards) { IConfigurationElement element = (IConfigurationElement) wizard getAdapter(IConfigurationElement class); IConfigurationElement[] children = element getChildren(IWorkbenchRegistryConstants TAG_ENABLEMENT);if (children != null && children length != ) { IConfigurationElement enablement = children[ ]; ActionExpression exp = new ActionExpression(enablement); [Page] if (!exp isEnabledFor(this selection)) { continue; } } shown add(wizard); } if (shown size() != ) { create = true; if (hasMenu) { new MenuItem(menu SWT SEPARATOR); } for (IWizardDescriptor wizard : shown) { MenuItem item = new MenuItem(menu SWT NONE); item setText(wizard getLabel()); if (wizard getImageDescriptor() != null) item setImage(wizard getImageDescriptor() createImage()); item setData(wizard); item addSelectionListener(this); [Page] } } } return create; } /** *//** * 反转数组 * * @param array */ private void reverseArray(Object[] array) { if (array != null) { int count = array length; int last = count ; for (int index = ; index < count / ; index++) { Object temp = array[index]; array[index] = array[last index]; array[last] = temp; } } } /** *//** * (non Javadoc) * * @see eclipse swt events SelectionListener#widgetDefaultSelected( eclipse swt events SelectionEvent) */ public void widgetDefaultSelected(SelectionEvent e) { // do nothing } /** *//** * (non Javadoc) * * @see eclipse swt events SelectionListener#widgetSelected( eclipse swt events SelectionEvent) */ [Page] public void widgetSelected(SelectionEvent e) { MenuItem item = (MenuItem) e getSource(); IWizardDescriptor desc = (IWizardDescriptor) item getData(); try { IWorkbenchWizard wizard = desc createWizard(); wizard init(this workbench this selection); WizardDialog dialog = new WizardDialog(workbench getActiveWorkbenchWindow() getShell() wizard); dialog open(); } catch (CoreException ex) { // TODO 处理异常 } } }
这里有几个重点 是我自己摸索出来的
第一个是IWorkbenchWindowPulldownDelegate 是继承IWorkbenchWindowPulldownDelegate的 因此只要实现这一个就可以在menu和coolbar 个地方用了 实际上 如果你只在一个地方用的话 另外一个方法返回null就可以了 因为永远不会被调用的 getMenu(Menu)是用在菜单的 getMenu(Control)是用在Coolbar的
第二个就是getMenu(Menu)方法只会被调用一次 就是初始化的时候 而getMenu(Control)方法每次你打开菜单都会被调用 因此selectionChanged里面也只需要处理菜单的内容 而不需要处理coolbar的内容
第三就是selectionChanged的操作
/** *//** * (non Javadoc) * * @see eclipse ui IActionDelegate#selectionChanged( eclipse jface action IAction * eclipse jface viewers ISelection) */ public void selectionChanged(IAction action ISelection selection) { this selection = (IStructuredSelection) selection; [Page] if (parent != null) { // 找到新建菜单项 // 重新创建其子菜单 MenuItem[] items = parent getItems(); if (items != null) { MenuItem parentItem = null; for (int index = count = items length; index < count; index++) { MenuItem item = items[index]; Object data = item getData(); if (data instanceof ActionSetContributionItem) { IContributionItem innerItem = ((ActionSetContributionItem) data) getInnerItem();if (innerItem getId() equals(getClass() getName())) { parentItem = item; break; } [Page] } } if (parentItem != null) { Menu menu = getMenu(parent); parentItem setMenu(menu); parentItem setImage(null); } } } }
parent是在getMenu(menu)中记录下来的 等于是上级菜单 说到这里 我们来说一下SWT里面菜单的构造(不一定对 只是我的理解而已) 所有你可以看到的带文字的条目都是MenuItem MenuItem分为 种 一种是没有子菜单的 一种是有子菜单的
没有子菜单的很简单 不说了 有子菜单的就是SWT CASCADE类型的 这个时候MenuItem会产生一个Menu 而Menu是一个容器 基本可以认为弹出菜单的整体 里面可以包含很多MenuItem 就是这么个关系
说完这个 我们来看SelectionChanged方法 Parent是个Menu 实际上是[文件]菜单 在里面查找id为类名的MenuItem 注意看Plugin xml的声明 类名和ID是一致的 实际上找到的就是[新建]菜单 然后重新创建菜单 并且设置成为MenuItem的Menu 这样就可以了
实际上JDT就是这么做的 但是具体的实现可能不一样 我也没有仔细的研究他的做法 因为系统比较庞大 研究的话时间太厉害了
至于PopupMenus 处理的方式是差不多的 略微有些修改而已 这里就不再把代码贴出来了

还有这一段
IConfigurationElement element = (IConfigurationElement) wizard getAdapter(IConfigurationElement class); IConfigurationElement[] children = element [Page] getChildren(IWorkbenchRegistryConstants TAG_ENABLEMENT); if (children != null && children length != ) { IConfigurationElement enablement = children[ ]; ActionExpression exp = new ActionExpression(enablement); if (!exp isEnabledFor(this selection)) { continue; } }
lishixinzhi/Article/program/Java/ky/201311/28387