Community
Participate
Working Groups
Register a MenuManager, context menu and sub-menu in a View. Then declare an extension using an ExtensionContributionFactory. The sub-menu item appears twice when activated.
Created attachment 259201 [details] Test project demonstrating the bug Attached is a test project showing the problem. It's based on the example RCP project. I added some code in View.java: /** * Hook into a right-click menu */ private void hookContextMenu() { MenuManager menuMgr = new MenuManager("#ViewPopupMenu"); menuMgr.setRemoveAllWhenShown(true); menuMgr.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager manager) { fillContextMenu(manager); } }); Menu menu = menuMgr.createContextMenu(viewer.getControl()); viewer.getControl().setMenu(menu); getSite().registerContextMenu(menuMgr, viewer); } private void fillContextMenu(IMenuManager manager) { IStructuredSelection selection = ((IStructuredSelection)viewer.getSelection()); Object selected = selection.getFirstElement(); boolean isEmpty = selected == null; MenuManager newMenu = new MenuManager("New", "new"); manager.add(newMenu); getSite().registerContextMenu("new_menu", newMenu, viewer); newMenu.add(new Separator("new_additions")); //$NON-NLS-1$ } And added a class TestExtensionContributionFactory, and declared it in plugin.xml: <extension point="org.eclipse.ui.menus"> <menuContribution allPopups="true" class="test.TestExtensionContributionFactory" locationURI="popup:new_menu?after=new_additions"> </menuContribution> </extension>
Created attachment 259202 [details] Screenshot showing the duplicate Screenshot
Note - this bug exists in 4.5 but not in 4.4.
Same here... anybody working on this? :)
Hi, I'm wondering what it takes for a possible fix for this. I've done the best I can by filing the bug report and providing a test project. I'm afraid that I am unable to fix it myself. If it's not possible to fix then OK, I'll move on. Just would like to know if it's something that can be fixed. :-)
Created attachment 261148 [details] Anim gif: created twice at first show, then only once. Verified in Neon (4.6) Build id: I20160419-0800 ExtensionContributionFactory#createContributionItems(..) is called twice: one when showing the parent menu and one when showing the submenus. See attached animation and related code below. YourClass extends ExtensionContributionFactory { public TestExtensionContributionFactory() { super(); } @Override public void createContributionItems(IServiceLocator serviceLocator, IContributionRoot additions) { System.err.println("createContributionItems"); System.err.println(additions.toString()); additions.addContributionItem(new MyItem(), null);//<-- HERE! } //..
Created attachment 262347 [details] Double menus in Archi This is something of a blocker for delivering my RCP app on Neon. See screenshot. Anyone know of a workaround?
This bug occurs also when not using an ExtensionContributionFactory - when declaring a popup sub-menu via the "org.eclipse.ui.menus" extension point. How are other plug-ins managing it?
Here are the interesting parts of the stack traces of it being called twice. First stack track trace when createContributionItems is called first time: com.archimatetool.canvas.NewCanvasExtensionContributionFactory.createContributionItems(NewCanvasExtensionContributionFactory.java:58) org.eclipse.ui.internal.menus.ContributionFactoryGenerator.compute(ContributionFactoryGenerator.java:72) org.eclipse.e4.ui.workbench.renderers.swt.ContributionRecord.mergeFactoryIntoModel(ContributionRecord.java:271) org.eclipse.e4.ui.workbench.renderers.swt.ContributionRecord.mergeIntoModel(ContributionRecord.java:215) org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRenderer.processAddition(MenuManagerRenderer.java:544) org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRenderer.generateContributions(MenuManagerRenderer.java:523) org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRenderer.processContributions(MenuManagerRenderer.java:491) org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRenderer.processContributions(MenuManagerRenderer.java:494) org.eclipse.ui.internal.PopupMenuExtender.addMenuContributions(PopupMenuExtender.java:410) org.eclipse.ui.internal.PopupMenuExtender.menuAboutToShow(PopupMenuExtender.java:382) org.eclipse.jface.action.MenuManager.fireAboutToShow(MenuManager.java:339) org.eclipse.jface.action.MenuManager.handleAboutToShow(MenuManager.java:470) org.eclipse.jface.action.MenuManager.access$1(MenuManager.java:465) org.eclipse.jface.action.MenuManager$2.menuShown(MenuManager.java:497) Second stack trace when createContributionItems is called second time: com.archimatetool.canvas.NewCanvasExtensionContributionFactory.createContributionItems(NewCanvasExtensionContributionFactory.java:58) org.eclipse.ui.internal.menus.ContributionFactoryGenerator.compute(ContributionFactoryGenerator.java:72) org.eclipse.e4.ui.workbench.renderers.swt.ContributionRecord.mergeFactoryIntoModel(ContributionRecord.java:271) org.eclipse.e4.ui.workbench.renderers.swt.ContributionRecord.mergeIntoModel(ContributionRecord.java:215) org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRenderer.processAddition(MenuManagerRenderer.java:544) org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRenderer.generateContributions(MenuManagerRenderer.java:523) org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRenderer.processContributions(MenuManagerRenderer.java:491) org.eclipse.ui.internal.PopupMenuExtender.addMenuContributions(PopupMenuExtender.java:410) org.eclipse.ui.internal.PopupMenuExtender.menuAboutToShow(PopupMenuExtender.java:382) org.eclipse.jface.action.MenuManager.fireAboutToShow(MenuManager.java:339) org.eclipse.jface.action.MenuManager.handleAboutToShow(MenuManager.java:470) org.eclipse.jface.action.MenuManager.access$1(MenuManager.java:465) org.eclipse.jface.action.MenuManager$2.menuShown(MenuManager.java:497) So, in the first stack trace we notice that processContributions is called twice: org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRenderer.processContributions(MenuManagerRenderer.java:491) org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRenderer.processContributions(MenuManagerRenderer.java:494)
So, given that processContributions being called twice is causing us problems, I hacked a really horrible workaround: public void createContributionItems(IServiceLocator serviceLocator, IContributionRoot additions) { int methodCount = 0; for(StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) { if(stackTraceElement.getMethodName().equals("processContributions")) { methodCount++; if(methodCount == 2) { return; } } } // Add contribution items here... } Yes, it's horrible, but as Eclipse bugs are not being fixed what am I to do?
I think we have to accept that this bug will not be fixed and try to workaround it.
(In reply to Phil Beauvoir from comment #11) > I think we have to accept that this bug will not be fixed and try to > workaround it. Wait, I see you signed CLA.. Why don't you clean a bit the code and submit a patch? Instructions are here: https://wiki.eclipse.org/Platform_UI/How_to_Contribute
(In reply to Patrik Suzzi from comment #12) > (In reply to Phil Beauvoir from comment #11) > > I think we have to accept that this bug will not be fixed and try to > > workaround it. > > Wait, I see you signed CLA.. > Why don't you clean a bit the code and submit a patch? > > Instructions are here: > https://wiki.eclipse.org/Platform_UI/How_to_Contribute :sigh: That old chestnut. There are many ways to contribute. Spending many hours to create a reproducible test case and submitting a bug report is one way to contribute, as I have done. If were able to understand and fix the underlying code I would have done. Bu, hey, that's the "Eclipse way", isn't it? "Fix it yourself."
(In reply to Phil Beauvoir from comment #13) > There are many ways to contribute. Spending many hours to create a > reproducible test case and submitting a bug report is one way to contribute, > as I have done. Phil, thank you very much for your efforts. I really appreciate! > But, hey, that's the "Eclipse way", isn't it? "Fix it yourself." Eh he he :D - I think this is to increase the number of developers that can push code. It was harder in last years. Now, with Oomph, the setup is a breeze. TBH: Nowadays I think that the hardest parts are: - identify the issues (-->use Ctrl+Shift+R, Ctrl+Alt+G, Spies, etc..) - push to Gerrit (-->this requires some configuration)
(In reply to Patrik Suzzi from comment #14) > (In reply to Phil Beauvoir from comment #13) > > > There are many ways to contribute. Spending many hours to create a > > reproducible test case and submitting a bug report is one way to contribute, > > as I have done. > > Phil, thank you very much for your efforts. > I really appreciate! > > > But, hey, that's the "Eclipse way", isn't it? "Fix it yourself." > > Eh he he :D - I think this is to increase the number of developers that can > push code. It was harder in last years. Now, with Oomph, the setup is a > breeze. > > TBH: Nowadays I think that the hardest parts are: > - identify the issues (-->use Ctrl+Shift+R, Ctrl+Alt+G, Spies, etc..) > - push to Gerrit (-->this requires some configuration) Sure. I can only be part of the solution. I can find the bug, provide a test case etc, and report the bug. The code for this bug is beyond my understanding, so I cannot do that part. If I knew what caused the bug I would submit a patch. Perhaps someone else would like to join me in this quest?
I have created a small test case for Eclipse 4.11 (2019-03), using a menu defined in plugin.xml as "popup:xxx" with a <VisibleWhen> test. This allows me to show the double menu is only duplicated the first time after opening the view (and right-click) on the item. Subsequent click, the menu is not duplicated any more. For my test, use the menu File to load data into the view.
Created attachment 278055 [details] Test to show duplicated menu, 2 views for easier debugging Developed with 2019-03. Use the menu File to load data into both of the views. Right click-to see the duplicated menu. The menu is entirely generated by Eclipse, defined as "popup:" command handler in plugin.xml. Close the views, and re-load data (menu File) for continous testing.
===1st click menuModel.widget= {} Thread [main] (Suspended (breakpoint at line 548 in MenuManagerRenderer)) MenuManagerRenderer.processAddition(MMenu, MenuManager, MMenuContribution, HashSet<String>, HashSet<String>, boolean) line: 548 MenuManagerRenderer.generateContributions(MMenu, ArrayList<MMenuContribution>, boolean) line: 528 MenuManagerRenderer.processContributions(MMenu, String, boolean, boolean) line: 496 MenuManagerRenderer.createWidget(MUIElement, Object) line: 415 MenuService.registerMenu(Control, MPopupMenu, IEclipseContext) line: 67 MenuManagerRendererFilter.safeHandleEvent(Event) line: 140 MenuManagerRendererFilter.access$1(MenuManagerRendererFilter, Event) line: 107 MenuManagerRendererFilter$SafeWrapper.run() line: 93 SafeRunner.run(ISafeRunnable) line: 45 MenuManagerRendererFilter.handleEvent(Event) line: 104 EventTable.sendEvent(Event) line: 89 Display.filterEvent(Event) line: 1121 Display.sendEvent(EventTable, Event) line: 4358 Menu(Widget).sendEvent(Event) line: 1512 menuModel.widget={Import...2} now menu is added a second time Thread [main] (Suspended (breakpoint at line 548 in MenuManagerRenderer)) MenuManagerRenderer.processAddition(MMenu, MenuManager, MMenuContribution, HashSet<String>, HashSet<String>, boolean) line: 548 MenuManagerRenderer.generateContributions(MMenu, ArrayList<MMenuContribution>, boolean) line: 528 MenuManagerRenderer.processContributions(MMenu, String, boolean, boolean) line: 496 PopupMenuExtender.addMenuContributions(IMenuManager) line: 413 PopupMenuExtender.menuAboutToShow(IMenuManager) line: 385 MenuManager.fireAboutToShow(IMenuManager) line: 342 MenuManager.handleAboutToShow() line: 473 MenuManager.access$1(MenuManager) line: 468 MenuManager$2.menuShown(MenuEvent) line: 500 TypedListener.handleEvent(Event) line: 259 EventTable.sendEvent(Event) line: 89 Display.sendEvent(EventTable, Event) line: 4363 Menu(Widget).sendEvent(Event) line: 1512 menuModel.widget={Import...2, Import...2} ===2nd click menuModel.widget= {Import...2, Import...2} Thread [main] (Suspended (breakpoint at line 548 in MenuManagerRenderer)) MenuManagerRenderer.processAddition(MMenu, MenuManager, MMenuContribution, HashSet<String>, HashSet<String>, boolean) line: 548 MenuManagerRenderer.generateContributions(MMenu, ArrayList<MMenuContribution>, boolean) line: 528 MenuManagerRenderer.processContributions(MMenu, String, boolean, boolean) line: 496 PopupMenuExtender.addMenuContributions(IMenuManager) line: 413 PopupMenuExtender.menuAboutToShow(IMenuManager) line: 385 MenuManager.fireAboutToShow(IMenuManager) line: 342 MenuManager.handleAboutToShow() line: 473 MenuManager.access$1(MenuManager) line: 468 MenuManager$2.menuShown(MenuEvent) line: 500 TypedListener.handleEvent(Event) line: 259 EventTable.sendEvent(Event) line: 89 Display.sendEvent(EventTable, Event) line: 4363 Menu(Widget).sendEvent(Event) line: 1512 Menu(Widget).sendEvent(int, Event, boolean) line: 1535 Menu(Widget).sendEvent(int) line: 1516 menuModel.widget={Import...2} IMHO the bug is in ContributionRecord.mergeIntoModel() line: 209 at line 251 the duplicate menu entry is added } else { generatedElements.add(copy); renderer.linkElementToContributionRecord(copy, this); menuModel.getChildren().add(idx++, copy); } The root cause seems to be that on the first click two events are fired: 1: prepare to open (which adds the popup menu once) 2: do open (which adds it a second time) Eliminating the first event would fix the bug, but that can cause other bugs. The easiest way seems to be to not add the menu a second time, by adding a check before calling generatedElements.add(copy); The check could use the menu ID?
Not sure if this was ever resolved. I just recently ran into the same thing. I'd right-click on a JList to bring up a context pop-up menu. The action would fire consistently in the following pattern: 1st click = 1 fire 2nd click = 2 fires 3rd click = 4 fires 4th click = 8 fires 5th click = 16 fires What I realized is that after the pop-up and subsequent actions were complete, the main window would regain focus and fire window actions. I had a listener and code in windowActivated. One of which was to add controls and action listeners after the window was activated for the first time. The result is that it kept added action listeners to the control. I put a boolean check in the windowActivated to make sure the routine would not fire after the initial window creation. This solved the problem for me. Not saying this is the case for you, but I'd run through the program to see if you have something similar...in this case, the root cause was no where near where the problem manifested.