Bug 37359 - [Contributions] popup menu viewer contributions aren't initialized early enough
Summary: [Contributions] popup menu viewer contributions aren't initialized early enough
Status: RESOLVED INVALID
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 2.1   Edit
Hardware: PC Windows XP
: P3 major (vote)
Target Milestone: 2.1.1   Edit
Assignee: Simon Arsenault CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2003-05-07 20:00 EDT by Alan Boxall CLA
Modified: 2003-05-16 14:33 EDT (History)
0 users

See Also:


Attachments
Zip of test plugin (8.03 KB, application/x-zip-compressed)
2003-05-09 15:19 EDT, Alan Boxall CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Alan Boxall CLA 2003-05-07 20:00:45 EDT
This has changed from R2.0.2 and can be considered a regression.

In R2.0.2 the actions were constructed when the workbench was starting up.   I 
understand that for performance reasons it was not a good idea to do it all at 
startup.

In R2.1 it appears that they are not constructed until the user RMB (Right 
Mouse Button) on something in the view.

And that is the problem.   If the view is empty then there is nothing to RMB 
on and therefore the actions are not constructed/initialized.

In my case I have contributed an action that will add something to the view.   
It is now impossible because the view is empty so the action remains disabled.

The actions should be constructed the first time the user RMB in the view even 
if there is nothing in the view.
Comment 1 Alan Boxall CLA 2003-05-09 09:19:15 EDT
I want to increase the priority as I was able to reproduce this on Eclipse, 
WSWB and WSAD.

This problem is consistent on the Eclipse or WSWB workbench.   

When I tested this on WSAD it only fails to create the actions if the view that 
the contributions apply to was visible when the workbench was closed down and 
restarted.

If the view is not visible then the actions are created either as soon as the 
view is given focus or the popup menu is activated.   (It was hard to tell 
which actually caused the actions to be created)
Comment 2 Alan Boxall CLA 2003-05-09 09:22:20 EDT
The following is the stack trace taken in WSAD when the init method of the 
contributed action *was* called.   This doesn't happen when running on just the 
Eclipse workbench.


Thread [main] (Suspended (breakpoint at line 44 in AddExpressionAction))
	AddExpressionAction.init(IViewPart) line: 44
	ViewPluginAction.initDelegate() line: 53
	ViewPluginAction(PluginAction).createDelegate() line: 105
	ViewPluginAction(PluginAction).selectionChanged(ISelection) line: 269
	ViewPluginAction(PartPluginAction).registerSelectionListener
(IWorkbenchPart) line: 39
	ViewPluginAction.<init>(IConfigurationElement, String, IViewPart, 
String, int) line: 35
	ActionDescriptor.createAction(int, IConfigurationElement, Object, 
String, String) line: 192
	ActionDescriptor.<init>(IConfigurationElement, int, Object) line: 128
	ViewerActionBuilder.createActionDescriptor(IConfigurationElement) line: 
46
	ViewerActionBuilder(PluginActionBuilder).readElement
(IConfigurationElement) line: 144
	ViewerActionBuilder.readElement(IConfigurationElement) line: 75
	ViewerActionBuilder(RegistryReader).readElements(IConfigurationElement
[]) line: 130
	ViewerActionBuilder(RegistryReader).readElementChildren
(IConfigurationElement) line: 120
	ViewerActionBuilder(PluginActionBuilder).readElement
(IConfigurationElement) line: 127
	ViewerActionBuilder.readElement(IConfigurationElement) line: 75
	ViewerActionBuilder(RegistryReader).readElements(IConfigurationElement
[]) line: 130
	ViewerActionBuilder(RegistryReader).readExtension(IExtension) line: 139
	ViewerActionBuilder(RegistryReader).readRegistry(IPluginRegistry, 
String, String) line: 156
	ViewerActionBuilder(PluginActionBuilder).readContributions(String, 
String, String) line: 100
	ViewerActionBuilder.readViewerContributions(String, ISelectionProvider, 
IWorkbenchPart) line: 91
	PopupMenuExtender.readStaticActions() line: 73
	PopupMenuExtender.<init>(String, MenuManager, ISelectionProvider, 
IWorkbenchPart) line: 36
	ViewSite(PartSite).registerContextMenu(String, MenuManager, 
ISelectionProvider) line: 151
	ViewSite(PartSite).registerContextMenu(MenuManager, ISelectionProvider) 
line: 157
	ExpressionView(AbstractDebugView).createContextMenu(Control) line: 504
	ExpressionView(AbstractDebugView).createPartControl(Composite) line: 289
	PartPane$4.run() line: 138
	InternalPlatform.run(ISafeRunnable) line: 867
	Platform.run(ISafeRunnable) line: 413
	ViewPane(PartPane).createChildControl() line: 134
	ViewPane.createChildControl() line: 202
	ViewPane(PartPane).createControl(Composite) line: 183
	ViewPane.createControl(Composite) line: 181
	PartTabFolder.createPartTab(LayoutPart, String, int) line: 251
	PartTabFolder.createControl(Composite) line: 223
	RootLayoutContainer(PartSashContainer).createControl(Composite) line: 
191
	PerspectivePresentation.activate(Composite) line: 96
	Perspective.onActivate() line: 715
	WorkbenchPage.onActivate() line: 1777
	WorkbenchWindow$7.run() line: 1474
	BusyIndicator.showWhile(Display, Runnable) line: 65
	WorkbenchWindow.setActivePage(IWorkbenchPage) line: 1461
	WorkbenchWindow.restoreState(IMemento, IPerspectiveDescriptor) line: 
1342
	Workbench.restoreState(IMemento) line: 1132
	Workbench.access$9(Workbench, IMemento) line: 1092
	Workbench$10.run() line: 1010
	InternalPlatform.run(ISafeRunnable) line: 867
	Platform.run(ISafeRunnable) line: 413
	Workbench.openPreviousWorkbenchState() line: 962
	Workbench.init(String[]) line: 742
	Workbench.run(Object) line: 1242
	InternalBootLoader.run(String, URL, String, String[], Runnable) line: 
845
	BootLoader.run(String, URL, String, String[], Runnable) line: 461
	Method.invoke(Object, Object[]) line: not available [native method]
	Main.basicRun(String[]) line: 247
	Main.run(String[]) line: 703
	Main.main(String[]) line: 539

Comment 3 Simon Arsenault CLA 2003-05-09 11:05:27 EDT
Alan,

- As the reporter, you can ajust the Severity field based on how important this 
problem is to you. The Priority field is reserved for the eclipse developers. 
So I adjusted both fields.

- Do you have a sample plugin for Eclipse platform that we can use to reproduce 
this problem?

- I'm not sure if I understand properly. Are you saying that if there are no 
elements in the view, no context menu is shown at all? Or does one popup but 
with no menu items in it?
Comment 4 Alan Boxall CLA 2003-05-09 15:19:58 EDT
Created attachment 4839 [details]
Zip of test plugin

Testcase to reproduce bug.
Comment 5 Alan Boxall CLA 2003-05-09 15:28:39 EDT
To reproduce:

1) unzip plugin into workspace of a basic Eclipse R2.1 workbench
2) launch self-hosted version and clear workspace
3) in self-hosted(SH) copy create a default plugin project.
4) RMB (Right Mouse Button) on the plugin.xml in the above project and click 
on the "New submenu"->"New action" to load the plugin.  (console should 
show "plugin loaded")
5) change to the debug perspective and click on the breakpoint view tab.
6) the action is initialized ("init called" in console)
< this is the expected behaviour >

To reproduce error:

7) with the Breakpoint view visible close the SH workbench
8) restart the SH workbench
9) switch to the Resource perspective and click on the plugin.xml and the new 
menu/action to force the plugin to be loaded.
10) switch back to debug perspective and RMB in the breakpoint view and the 
action will not be initialized ("init called" does NOT appear in the console)
Comment 6 Nick Edgar CLA 2003-05-12 23:02:29 EDT
Please investigate a fix for 2.1.1 since this is a regression.
Comment 7 Simon Arsenault CLA 2003-05-13 17:33:57 EDT
The behavior your are seeing with your test plugin is the expected one. Lets 
see if I can explain how the internals are currently working.

In part 1, by invoking the action on the plugin.xml file will cause the plugin 
to load. So when you switch to the debug perspective and open the breakpoints 
view, we build up the collection of "static" context menu contributions for 
this view - which includes yours. Then we send a selectionChange event to them 
with the current selection (could be empty as in this case). When we hit your 
action contribution, we notice the plugin is already loaded so we load in the 
delegate.

In part 2, when the workbench comes up, your plugin is not yet loaded. So when 
we build the "static" context menu contributions for the breakpoint view (since 
its visible). Then we send a selectionChange event to them with the current 
selection (could be empty as in this case). When we hit your action 
contribution, we notice the plugin is NOT loaded so we do NOT load in the 
delegate. Its not until your plugin gets loaded (by the action on plugin.xml) 
and the selection changes in the breakpoints view that the delegate gets loaded.

We've always said that we will wait until the last possible moment before 
loading plugin code. In the case of the action delegate, that could be until 
the moment the user clicks on it to run it. Everything I mentionned above is 
how the internal currently behave and will change from release to release so 
don't depend on it. There were some problems with 2.0 which caused code to load 
way to early and was fixed in 2.1 release.

In your situation, we recommend that your action be optimistic and set itself 
as enabled in the XML. When you are asked to run, your delegate will be asked 
to load, update the enablement state, and if we detect if becomes disable, we 
warn the user for you that the action is not available.

So here are the rules to go by:
- enablement should be done in XML if at all possible
- there is never any guarantee when the action delegate will be loaded except 
when the action is to be run, then we guarantee your action delegate will be 
loaded (and note, it could get unloaded later on...not something we do in 2.1 
but 3.0 might do this - for example, nothing in plugin A has been used in last 
30 minutes so unload it).
Comment 8 Alan Boxall CLA 2003-05-14 12:31:23 EDT
I always worry about the behaviour of an extension point that requires 
discussing the internals to explain. ;-)

I understand that you are trying to defer the loading as much as possible.

Not ideal but why not load the delegates just before that action on the popup 
menu is requested?  Give them a chance to determine its correct enablement 
state just before it is shown.

For now I will try changing the enablement of my actions to always enable them.
Comment 9 Simon Arsenault CLA 2003-05-14 13:33:09 EDT
Because we would be loading a bunch of plugins extending the popup menu - 
most/all of them never to be used.
Comment 10 Alan Boxall CLA 2003-05-15 16:01:30 EDT
I tried enabling my actions in the plugin.xml and it looks really bad.

I add 5 actions using view contribution to the breakpoint view.   At first 
they are all enabled (change to plugin.xml to remove enablesFor) and the first 
one that the user selects they get the action not enabled message and only 
that action is disabled.   The other 4 actions are still enabled because they 
have not been created.   The user would have to select each one and they will 
get an error for each one.

The call to an action delegate should re-attempt creating other action 
delegates for that view that might have their plugin(s) loaded now.   

I still don't think that this is a closed issue.
Comment 11 Simon Arsenault CLA 2003-05-16 10:59:59 EDT
You can push to have it reopen.

In normal usuage, how often will the user end up in this situation. Maybe you 
can talk to your usuability group if they have any data on this.

Making changes to preload delegates from plugins already loaded is not 
a "minor" change. It can have far reaching consequences which may not show up 
right away. So there needs to be a good arguments to consider this path.
Comment 12 Alan Boxall CLA 2003-05-16 14:33:07 EDT
Let me think about it over the long weekend.

I will most likely leave it enabled for this release but I feel that 
enablement in general needs to allow for code to be called to determine the 
initial state.

Could the extension point all for an attribute that would force the plugin to 
be loaded?   That way plugins could determine if they need to be loaded to 
properly set the initial state.