Community
Participate
Working Groups
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);
Adding this bug to my queue.
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.
Fixed in HEAD.
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...
This fix breaks action/menu context help for all clients. See bug 277831.