Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 332370 - Contributed menu items previously made invisible become unexpectedly visible
Summary: Contributed menu items previously made invisible become unexpectedly visible
Status: RESOLVED WORKSFORME
Alias: None
Product: e4
Classification: Eclipse Project
Component: UI (show other bugs)
Version: unspecified   Edit
Hardware: PC Mac OS X - Carbon (unsup.)
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords:
Depends on:
Blocks:
 
Reported: 2010-12-11 17:12 EST by Brian de Alwis CLA
Modified: 2019-06-05 07:48 EDT (History)
2 users (show)

See Also:


Attachments
e4photo-about (5.77 KB, application/octet-stream)
2010-12-11 17:14 EST, Brian de Alwis CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Brian de Alwis CLA 2010-12-11 17:12:50 EST
This is a tricky bug!  I have a situation where File > Exit properly has visible set to false by the CocoaUIHandler, but is magically made visible again.  It happens as the Exit item is added through a MenuContribution.

I have an e4 application with an app.e4xmi and fragment.e4xmi.

The app.e4xmi defines a window with a top-level menu containing a "File" menu.

The fragment.e4xmi defines a menu contribution that contributes an "Exit" to the "File" menu.  This exit is a handled menu item for "org.eclipse.ui.file.exit".

The CocoaUIHandler from o.e.e4.ui.workbench.renderer.swt.cocoa correctly causes the Exit item to be made invisible; that menu functionality is now handled through the app's menu.

BUT the "Exit" item magically re-appears when rendering the File menu!

I'll attach a demo app and a patch in a sec.
Comment 1 Brian de Alwis CLA 2010-12-11 17:14:59 EST
Created attachment 185026 [details]
e4photo-about

Bundle providing an e4 fragment demonstrating the bug
Comment 2 Brian de Alwis CLA 2010-12-11 17:18:29 EST
In tracing this through, it turns out that the MenuManagerRenderer$ContributionRecord #updateVisibility is updating the menu item's visibility with its *contribution*'s visibility (stack trace below):

		public void updateVisibility(IEclipseContext context) {
			ExpressionContext exprContext = new ExpressionContext(context);
			boolean isVisible = ContributionsAnalyzer.isVisible(
					menuContribution, exprContext);
			for (MMenuElement item : generatedElements) {
				if (isVisible && item.getVisibleWhen() != null) {
					MenuManagerRenderer.updateVisibility(getManagerForModel(),
							item, exprContext);
				} else {
					item.setVisible(isVisible); //***
				}
			}
			getManagerForModel().markDirty();
		}

At line "***", item is our menu-item-that-should-be-hidden, and isVisible is calculated based on the *contribution* providing that menu item.

I think this code should instead look like:

		public void updateVisibility(IEclipseContext context) {
			ExpressionContext exprContext = new ExpressionContext(context);
			for (MMenuElement item : generatedElements) {
				if (item.getVisibleWhen() != null) {
					MenuManagerRenderer.updateVisibility(getManagerForModel(),
							item, exprContext);
				}
			}
			getManagerForModel().markDirty(); //??
		}

I'm not sure if the last line is necessary either.

At least, this produces the expected results.


Daemon Thread [Thread-0] (Suspended (entry into method setVisible in UIElementImpl))	
	HandledMenuItemImpl(UIElementImpl).setVisible(boolean) line: 327	
	MenuManagerRenderer$ContributionRecord.updateVisibility(IEclipseContext) line: 529	
	MenuManagerRendererFilter.updateElementVisibility(MMenu, MenuManagerRenderer, MenuManager, IEclipseContext, boolean) line: 272	
	MenuManagerRendererFilter.showMenu(Event, Menu, MMenu, MenuManager) line: 248	
	MenuManagerRendererFilter.handleShow(Event, Menu, MMenu, MenuManager) line: 202	
	MenuManagerRendererFilter.safeHandleEvent(Event) line: 184	
	MenuManagerRendererFilter.access$1(MenuManagerRendererFilter, Event) line: 141	
	MenuManagerRendererFilter$SafeWrapper.run() line: 128	
	SafeRunner.run(ISafeRunnable) line: 42	
	MenuManagerRendererFilter.handleEvent(Event) line: 138	
	EventTable.sendEvent(Event) line: 84	
	Display.filterEvent(Event) line: 1044	
	Display.sendEvent(EventTable, Event) line: 3954	
	Menu(Widget).sendEvent(Event) line: 1435	
	Menu(Widget).sendEvent(int, Event, boolean) line: 1458	
	Menu(Widget).sendEvent(int) line: 1439	
	Menu.menuWillOpen(long, long, long) line: 728	
	Display.windowProc(long, long, long) line: 5299	
	OS.objc_msgSendSuper(objc_super, long, long, long, long, boolean) line: not available [native method]	
	Display.applicationNextEventMatchingMask(long, long, long, long, long, long) line: 4701	
	Display.applicationProc(long, long, long, long, long, long) line: 5000	
	OS.objc_msgSend(long, long, long, long, long, boolean) line: not available [native method]	
	NSApplication.nextEventMatchingMask(long, NSDate, NSString, boolean) line: 94	
	Display.readAndDispatch() line: 3448	
	PartRenderingEngine$6.run() line: 808	
	Realm.runWithDefault(Realm, Runnable) line: 332	
	PartRenderingEngine.run(MApplicationElement, IEclipseContext) line: 724	
	E4Workbench.createAndRunUI(MApplicationElement) line: 89	
	E4Application.start(IApplicationContext) line: 131	
	EclipseAppHandle.run(Object) line: 196	
	EclipseAppLauncher.runApplication(Object) line: 110	
	EclipseAppLauncher.start(Object) line: 79	
	EclipseStarter.run(Object) line: 369	
	EclipseStarter.run(String[], Runnable) line: 179	
	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39	
	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25	
	Method.invoke(Object, Object...) line: 597	
	Main.invokeFramework(String[], URL[]) line: 622	
	Main.basicRun(String[]) line: 577	
	Main.run(String[]) line: 1410	
	Main.main(String[]) line: 1386
Comment 3 Paul Webster CLA 2011-01-10 12:38:23 EST
This is where we end up either 1) overly complex or 2) we simply don't have enough states :-)

There's only one visible flag on the MenuItem in the end, which gets propagated to the renderer.  We simply use the expression in the static MMenuContribution to calculate visibility on each SWT.Show.

Do we provide a userVisible flag that can supplant the standard visible flag?  So setting userVisible to TRUE or FALSE will override visible==(true|false)?

PW
Comment 4 Eclipse Genie CLA 2018-11-11 05:06:18 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.
Comment 5 Lars Vogel CLA 2019-06-05 07:48:31 EDT
This is a mass change to close all e4 bugs marked with "stalebug" whiteboard.

If this bug is still valid, please reopen and remove the "stalebug" keyword.