Community
Participate
Working Groups
EC post "Menus and submenus" by GB on Aug 2, 2001: I am trying to create a cascading menu under my own menu. MyMenu Menu1->Submenu1 Submenu2 I cannot get this to work. I can, using the same technique as outlined in the help, add the submenu to the Window menu, and it works. Window Menu1->Submenu1 Submenu2 But when I try to add the submenu to my menu, the menu shows up but it is grayed and none of the Submenu items are available. MyMenu Menu1 (grayed) The log reports 1 org.eclipse.core.resources 4 Invalid Menu Extension (Path is invalid): SubMenu1Id Here is the sample I based the code on. This is from the Eclipse documentation. <extension point = "org.eclipse.ui.actionSets"> <actionSet id="org_eclipse_ui_examples_readmetool_actionSet" label="ReadMe Actions" visible="true"> <menu id="org_eclipse_ui_examples_readmetool" label="Readme &File Editor" path="window/additions"> <separator name="slot1"/> <separator name="slot2"/> <separator name="slot3"/> </menu> <action id="org_eclipse_ui_examples_readmetool_readmeAction" menubarPath="window/org_eclipse_ui_examples_readmetool/slot1" toolbarPath="readme" label="&Open Readme Browser@Ctrl+R" tooltip="Open Readme Browser" helpContextId="org.eclipse.ui.examples.readmetool.open_browser_action_context" icon="icons/basic/ctool16/openbrwsr.gif" class="org.eclipse.ui.examples.readmetool.WindowActionDelegate" enablesFor="1"> <selection class="org.eclipse.core.resources.IFile" name="*.readme"> </selection> Here is a version that I got to work in my own application. <actionSet id="com.rational.test.ft.wswplugin.TestActionSet" visible="true" label="MyMenu"> <menu id = "MyMenuId" label = "&MyMenu"> <separator name = "Menu1Slot" /> </menu> <menu id="Menu1Id" label = "&Menu1" path ="window/additions"> <separator name="slot1" /> <separator name="slot2" /> <separator name="slot3" /> </menu> <action id = "SubMenu1Id" menubarPath = "window/Menu1Id/slot1" label = "&SubMenu1" class = "com.rational.test.ft.wswplugin.x"> </action> Here is a version that fails in my application. The only difference is that instead of window, I use MyMenu and instead of additions, I use MyMenu1Slot. I tried variations on ids and slots, but nothing changed. <actionSet id="com.rational.test.ft.wswplugin.TestActionSet" visible="true" label="MyMenu"> <menu id = "MyMenuId" label = "&MyMenu"> <separator name = "Menu1Slot" /> </menu> <menu id="Menu1Id" label = "&Menu1" path ="MyMenuId/Menu1Slot"> <separator name="slot1" /> <separator name="slot2" /> <separator name="slot3" /> </menu> <action id = "SubMenu1Id" menubarPath = "MyMenuId/Menu1Id/slot1" label = "&SubMenu1" class = "com.rational.test.ft.wswplugin.x"> </action> NOTES: NE (8/7/01 5:25:18 PM) Reproduced both success case and fail case. Problem is that the call to parent.findMenuUsingPath(mpath) in PlugActionSetBuilder.contributeMenuAction() returns null when mpath has multiple segments. This is because SubMenuManager.findUsingPath calls findUsingPath on the parentMgr, and MenuManager.findUsingPath tests whether the parent menu is an IMenuManager, which it is not in this case. It was wrapped in an ActionSetContributionItem (subclass of SubContributionItem). Should change SubMenuManager.findUsingPath to recurse itself, unwrapping at each stage. NE (08/07/01 6:01:14 PM) Suggested fix: Change SubContributionManager.find() to unwrap (it doesn't currently, but should): public IContributionItem find(String id) { IContributionItem item = parentMgr.find(id); if (item instanceof SubContributionItem) { return ((SubContributionItem)item).getInnerItem(); } else { return item; } } Change SubMenuManager.getWrapper(IMenuManager) to always create wrapper (as spec'ed). Also added @param tag: /** * Returns the menu wrapper for a menu manager. * <p> * The sub menus within this menu are wrapped within a <code>SubMenuManager</code> to * monitor additions and removals. If the visibility of this menu is modified * the visibility of the sub menus is also modified. * <p> * * @param menu the menu manager to wrap * @return the menu wrapper */ private IMenuManager getWrapper(IMenuManager menu) { if (mapMenuToWrapper == null) { mapMenuToWrapper = new HashMap(4); } SubMenuManager wrapper = (SubMenuManager) mapMenuToWrapper.get(menu); if (wrapper == null) { wrapper = wrapMenu(menu); mapMenuToWrapper.put(menu, wrapper); } return wrapper; } Change SubMenuManager.findMenuUsingPath to just call getWrapper() rather than getWrapper then putWrapper if null: public IMenuManager findMenuUsingPath(String path) { IContributionItem item = findUsingPath(path); if (item instanceof IMenuManager) { IMenuManager menu = (IMenuManager)item; return getWrapper(menu); } return null; } Change SubMenuManager.findUsingPath to use same algorithm as MenuManager.findUsingPath, but wrapping submenus along the way: public IContributionItem findUsingPath(String path) { String id = path; String rest = null; int separator = path.indexOf('/'); if (separator != -1) { id = path.substring(0, separator); rest = path.substring(separator + 1); } IContributionItem item = find(id); // unwraps item if (rest != null && item instanceof IMenuManager) { IMenuManager menu = (IMenuManager) item; // wrap menu, just like findMenuUsingPath IMenuManager wrapper = getWrapper(menu); return wrapper.findUsingPath(rest); } return item; } Delete SubMenuManager.putWrapper -- it's no longer needed.
This is fixed. Changes were made to SubContributionManager, SubMenuManager, and ActionSetMenuManager. To test I created the following action sets. The first is for this bug. The 2nd, third and fourth are for a problem reported by a customer (can't find pr), where you turn on A, B, and C, turn off A, turn on A and off B, then turn on B and off C. At this point B used to disappear also. <extension point = "org.eclipse.ui.actionSets"> <actionSet id="com.rational.test.ft.wswplugin.TestActionSet" visible="true" label="MyMenu"> <menu id = "MyMenuId" label = "&MyMenu"> <separator name = "Menu1Slot" /> </menu> <menu id="Menu1Id" label = "&Menu1" path ="MyMenuId/Menu1Slot"> <separator name="slot1" /> <separator name="slot2" /> <separator name="slot3" /> </menu> <action id = "SubMenu1Id" menubarPath = "MyMenuId/Menu1Id/slot1" label = "&SubMenu1" class = "com.rational.test.ft.wswplugin.x"> </action> <action id = "SubMenu2Id" menubarPath = "MyMenuId/Menu1Id/slot1" label = "&SubMenu2" class = "com.rational.test.ft.wswplugin.x"> </action> <action id = "SubMenu3Id" menubarPath = "MyMenuId/Menu1Id/slot1" label = "&SubMenu3" class = "com.rational.test.ft.wswplugin.x"> </action> </actionSet> </extension> <extension point = "org.eclipse.ui.actionSets"> <actionSet id="com.rational.test.ft.wswplugin.TestActionSetA" label="A"> <menu id = "Top" label = "&Top"> <separator name = "a" /> <separator name = "b" /> <separator name = "c" /> </menu> <action id = "SubMenu1Id" menubarPath = "Top/a" label = "a" class = "com.rational.test.ft.wswplugin.x"> </action> </actionSet> </extension> <extension point = "org.eclipse.ui.actionSets"> <actionSet id="com.rational.test.ft.wswplugin.TestActionSetB" label="B"> <menu id = "Top" label = "&Top"> <separator name = "a" /> <separator name = "b" /> <separator name = "c" /> </menu> <action id = "SubMenu1Id" menubarPath = "Top/b" label = "b" class = "com.rational.test.ft.wswplugin.x"> </action> </actionSet> </extension> <extension point = "org.eclipse.ui.actionSets"> <actionSet id="com.rational.test.ft.wswplugin.TestActionSetC" label="C"> <menu id = "Top" label = "&Top"> <separator name = "a" /> <separator name = "b" /> <separator name = "c" /> </menu> <action id = "SubMenu1Id" menubarPath = "Top/c" label = "c" class = "com.rational.test.ft.wswplugin.x"> </action> </actionSet> </extension> Note: I applied all of NEs changes except for one change in findUsingPath. In this code he will wrap any submenu which we drill into. I decided not to do this. There is no reason to wrap a menu unless the user adds a contribution to it. We assume this is only the case when findMenuUsingPath is called, and do the wrapping there. Thus, the SubMenuManager only wraps those subs which are modified.
PRODUCT VERSION: 0.9