Bug 269228 - [Help][Context] HelpView with F1 does not use IContext of IContextProvider
Summary: [Help][Context] HelpView with F1 does not use IContext of IContextProvider
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: User Assistance (show other bugs)
Version: 3.4.2   Edit
Hardware: PC Windows XP
: P3 major (vote)
Target Milestone: 3.5 M7   Edit
Assignee: Chris Goldthorpe CLA
QA Contact:
URL:
Whiteboard:
Keywords: example, investigate, ui
Depends on:
Blocks:
 
Reported: 2009-03-18 11:48 EDT by Patrick Plitzner CLA
Modified: 2009-05-26 15:52 EDT (History)
3 users (show)

See Also:


Attachments
example plugin project with a view adapted to IContextProvider (6.92 KB, application/zip)
2009-03-18 11:48 EDT, Patrick Plitzner CLA
no flags Details
Patch (814 bytes, patch)
2009-03-20 19:13 EDT, Chris Goldthorpe CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Patrick Plitzner CLA 2009-03-18 11:48:32 EDT
Created attachment 129242 [details]
example plugin project with a view adapted to IContextProvider

If you invoke Dynamic Help by pressing F1 on a WorkbenchPart which adapts to IContextProvider the help context shown in the HelpView is not produced by the IContextProvider.

Steps to Reproduce: 

    1) Import the attached Plug-in project and start it as an Eclipse Application. (Be sure to include org.eclipse.platform.doc.user into your launch configuration to support F1)

    2) Open the View. Window->Show View->Other...->IContext Category->IContext View.

    3) Select one of the three items (One, Three, Two) and click F1.

    4) The HelpView opens and shows the following message:
"About IContext View
The context help for this user interface element could not be found"

    5) Click on any item in the IContext View and it shows the generated IContext from MyContextProvider.

    6) Hit F1 again and the the context changes to the one of 4).


Expected Results: 

     The HelpView should always display the IContext returned by the IContextProvider if the WorkbenchPart adapts to IContextProvider.


Build Date & Platform: 

     Version: 3.4.2
     Build id: M20090211-1700


What I think is wrong:

If you press F1 the HelpListener executes its helpRequested()-method and gets the IContext for the widget. If it can't find any IContext it will get the default "IWorkbenchHelpContextIds.MISSING"-IContext. 
So the IContext will never be null when calling getInstance().displayContext(context, point.x, point.y).
Later when the handleActivation()-method of ContextHelpPart is invoked the getContext()-method of the IContextProvider is only called when "context==null && provider!=null".
But the context will never be null in this scenario because even if it has no IContext it will get the fallback "MISSING"-IContext.

If you just click on an item in the IContext View and the HelpView is opened the handleActivation()-method of the ContextHelpPart class is invoked with the context parameter being null. That's why it works this way.


I have copied the code snippets which are responsible for this scenario.

class WorkbenchHelpListener:
private static class WorkbenchHelpListener implements HelpListener {
		public void helpRequested(HelpEvent event) {

			if (getInstance().getHelpUI() == null) {
				return;
			}

			// get the help context from the widget
			Object object = event.widget.getData(HELP_KEY);
                     
                     .
                     .
                     .

			IContext context = null;
			if (object instanceof String) {
				// context id - this is the norm
				context = HelpSystem.getContext((String) object);
                     .
                     .
                     .

			/*
			 * If can't find it, show the "context is missing" context.
			 */
			if (context == null) {
				context = HelpSystem.getContext(IWorkbenchHelpContextIds.MISSING);
			}
			
			if (context != null) {
				// determine a location in the upper right corner of the
				// widget
				Point point = computePopUpLocation(event.widget.getDisplay());
				// display the help
				getInstance().displayContext(context, point.x, point.y);
			}
		}
	}




class HelpView:
public void displayContext(IContext context, IWorkbenchPart part,
			Control control) {
		if (reusableHelpPart != null) {
			/*
			 * If the context help has no description text and exactly one
			 * topic, go straight to the topic and skip context help.
			 */
			IHelpResource[] topics = context.getRelatedTopics();
			if (context.getText() != null || topics.length != 1) {
				// Ensure that context help is currently showing
				reusableHelpPart.showPage(IHelpUIConstants.HV_CONTEXT_HELP_PAGE);
				// check if there is a dynamic version
				IContextProvider provider = null;
				if (part!=null)
						provider = (IContextProvider) part
						.getAdapter(IContextProvider.class);

				reusableHelpPart.update(provider, context, part, control, true);
			}
			else {
				reusableHelpPart.showURL(topics[0].getHref());
			}
		}
	}





class ContextHelpPart:
public void handleActivation(IContextProvider provider, IContext context, 
			Control c,
			IWorkbenchPart part, boolean isExplicitRequest) {
		if (text.isDisposed())
			return;
		if (DefaultHelpUI.isOpeningHelpView()) {
			return;
		}
		if (checkForRecentExplicitActivation(isExplicitRequest)) {
			return;
		}
		lastControl = c;
		lastProvider = provider;
		lastContext = context;
		lastPart = part;
		if (context==null && provider!=null) { //context is never null when invoked by pressing F1 ?!?!
			lastContext = provider.getContext(c);
		}
		String helpText;
		if (lastContext!=null)
			helpText = formatHelpContext(lastContext);
		else
			helpText = createContextHelp(c);
		updateTitle(c);
		updateDescription(helpText);
		updateDynamicHelp(context!=null);
	}




A possible fix could be:

if (part!=null)
						provider = (IContextProvider) part
						.getAdapter(IContextProvider.class);

				if(provider!=null) reusableHelpPart.update(provider, null, part, control, true);
else reusableHelpPart.update(provider, context, part, control, true);
Comment 1 Chris Goldthorpe CLA 2009-03-19 15:06:34 EDT
Adding this bug to my queue.
Comment 2 Chris Goldthorpe CLA 2009-03-20 19:13:33 EDT
Created attachment 129507 [details]
Patch

The problem is occuring in ContextHelpPart.handleActivation(). When F1 is hit this function is called with an IContext and an IContextProvider neither of which is null. The code currently uses the Icontext rather than the IContextProvider in this case, I think this is incorrect - if there is an IContextProvider it should always be used. I have attached a patch which implements this change but I need to do some more analysis to see if there is any downside to making this change.
Comment 3 Chris Goldthorpe CLA 2009-03-24 18:54:24 EDT
Fixed in HEAD.
Comment 4 Patrick Plitzner CLA 2009-03-26 13:12:41 EDT
I've applied the patch and now it works fine for me.

Thanks for the quick help!

Can't wait for 3.5 to be released...
Comment 5 Dani Megert CLA 2009-05-26 07:14:27 EDT
This fix breaks action/menu context help for all clients. See bug 277831.