| /*************************************************************************************************** |
| * Copyright (c) 2000, 2016 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Sebastian Davids <sdavids@gmx.de> - bug 93374 |
| **************************************************************************************************/ |
| package org.eclipse.help.ui.internal; |
| |
| import java.net.URL; |
| |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.help.IContext; |
| import org.eclipse.help.IHelpResource; |
| import org.eclipse.help.browser.IBrowser; |
| import org.eclipse.help.internal.base.BaseHelpSystem; |
| import org.eclipse.help.internal.base.HelpBasePlugin; |
| import org.eclipse.help.internal.base.IHelpBaseConstants; |
| import org.eclipse.help.ui.internal.util.ErrorUtil; |
| import org.eclipse.help.ui.internal.util.FontUtils; |
| import org.eclipse.help.ui.internal.views.ContextHelpPart; |
| import org.eclipse.help.ui.internal.views.HelpTray; |
| import org.eclipse.help.ui.internal.views.HelpView; |
| import org.eclipse.help.ui.internal.views.ReusableHelpPart; |
| import org.eclipse.jface.dialogs.DialogTray; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.dialogs.TrayDialog; |
| import org.eclipse.osgi.service.environment.Constants; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.IViewPart; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.IWorkbenchPart; |
| import org.eclipse.ui.IWorkbenchWindow; |
| import org.eclipse.ui.PartInitException; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.browser.IWebBrowser; |
| import org.eclipse.ui.browser.IWorkbenchBrowserSupport; |
| import org.eclipse.ui.help.AbstractHelpUI; |
| import org.eclipse.ui.intro.IIntroManager; |
| import org.eclipse.ui.intro.IIntroPart; |
| |
| /** |
| * This class is an implementation of the Help UI. In is registered into the helpSupport extension |
| * point, and is responsible for handling requests to display help. The methods on this class |
| * interact with the actual UI component handling the display. |
| * <p> |
| * Most methods delegate most work to HelpDisplay class; only the UI specific ones implemented in |
| * place. |
| * </p> |
| */ |
| public class DefaultHelpUI extends AbstractHelpUI { |
| |
| private ContextHelpDialog f1Dialog = null; |
| private static DefaultHelpUI instance; |
| private static boolean openingHelpView = false; |
| |
| private static final String HELP_VIEW_ID = "org.eclipse.help.ui.HelpView"; //$NON-NLS-1$ |
| |
| class ExternalWorkbenchBrowser implements IBrowser { |
| |
| public ExternalWorkbenchBrowser() { |
| } |
| |
| private IWebBrowser getExternalBrowser() throws PartInitException { |
| IWorkbenchBrowserSupport support = PlatformUI.getWorkbench().getBrowserSupport(); |
| return support.getExternalBrowser(); |
| } |
| |
| @Override |
| public void close() { |
| } |
| |
| @Override |
| public boolean isCloseSupported() { |
| return false; |
| } |
| |
| @Override |
| public void displayURL(String url) throws Exception { |
| try { |
| IWebBrowser browser = getExternalBrowser(); |
| if (browser != null) { |
| browser.openURL(new URL(url)); |
| } |
| } catch (PartInitException pie) { |
| ErrorUtil.displayErrorDialog(pie.getLocalizedMessage()); |
| } |
| } |
| |
| @Override |
| public boolean isSetLocationSupported() { |
| return false; |
| } |
| |
| @Override |
| public boolean isSetSizeSupported() { |
| return false; |
| } |
| |
| @Override |
| public void setLocation(int x, int y) { |
| } |
| |
| @Override |
| public void setSize(int width, int height) { |
| } |
| } |
| |
| /** |
| * Constructor. |
| */ |
| public DefaultHelpUI() { |
| super(); |
| instance = this; |
| // register external browser. This will cause the help system |
| // to use workbench external browser instead of its own. |
| BaseHelpSystem.getInstance().setBrowserInstance(new ExternalWorkbenchBrowser()); |
| } |
| |
| public static DefaultHelpUI getInstance() { |
| return instance; |
| } |
| |
| /** |
| * Displays help. |
| */ |
| @Override |
| public void displayHelp() { |
| BaseHelpSystem.getHelpDisplay().displayHelp(useExternalBrowser(null)); |
| } |
| |
| /** |
| * Displays search. |
| */ |
| @Override |
| public void displaySearch() { |
| search(null); |
| } |
| |
| /** |
| * Displays dynamic help. |
| */ |
| @Override |
| public void displayDynamicHelp() { |
| IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); |
| Shell activeShell = getActiveShell(); |
| if (window != null && isActiveShell(activeShell, window)) { |
| setIntroStandby(); |
| |
| IWorkbenchPage page = window.getActivePage(); |
| Control c = activeShell.getDisplay().getFocusControl(); |
| if (page != null) { |
| IWorkbenchPart activePart = page.getActivePart(); |
| try { |
| IViewPart part = page.showView(HELP_VIEW_ID, null, IWorkbenchPage.VIEW_ACTIVATE); |
| if (part != null) { |
| HelpView view = (HelpView) part; |
| view.showDynamicHelp(activePart, c); |
| } |
| } catch (PartInitException e) { |
| } |
| } else { |
| // check the dialog |
| Object data = activeShell.getData(); |
| if (data instanceof TrayDialog) { |
| IContext context = ContextHelpPart.findHelpContext(c); |
| displayContextAsHelpTray(activeShell, context); |
| return; |
| } |
| warnNoOpenPerspective(window); |
| } |
| } |
| } |
| |
| /** |
| * Starts the search. |
| */ |
| @Override |
| public void search(final String expression) { |
| IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); |
| Shell activeShell = getActiveShell(); |
| if (window != null && isActiveShell(activeShell, window)) { |
| setIntroStandby(); |
| |
| IWorkbenchPage page = window.getActivePage(); |
| if (page != null) { |
| boolean searchFromBrowser = Platform.getPreferencesService().getBoolean |
| (HelpBasePlugin.PLUGIN_ID, IHelpBaseConstants.P_KEY_SEARCH_FROM_BROWSER, false, null); |
| if (searchFromBrowser) { |
| String parameters = "tab=search"; //$NON-NLS-1$ |
| if (expression != null) { |
| parameters += '&'; |
| parameters += expression; |
| } |
| BaseHelpSystem.getHelpDisplay().displayHelpResource(parameters, false); |
| } else { |
| try { |
| IViewPart part = page.showView(HELP_VIEW_ID); |
| if (part != null) { |
| HelpView view = (HelpView) part; |
| view.startSearch(expression); |
| } |
| } catch (PartInitException e) { |
| } |
| } |
| } else { |
| // check the dialog |
| if (activeShell != null) { |
| Object data = activeShell.getData(); |
| if (data instanceof TrayDialog) { |
| displayContextAsHelpTray(activeShell, null); |
| return; |
| } |
| else { |
| // tried to summon help from a non-tray dialog |
| // not supported |
| return; |
| } |
| } |
| warnNoOpenPerspective(window); |
| } |
| } |
| } |
| |
| public static void showIndex() { |
| HelpView helpView = getHelpView(); |
| if (helpView != null) { |
| helpView.showIndex(); |
| } |
| } |
| |
| private static HelpView getHelpView() { |
| HelpView view = null; |
| IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); |
| Shell activeShell = getActiveShell(); |
| if (window != null && isActiveShell(activeShell, window)) { |
| setIntroStandby(); |
| IWorkbenchPage page = window.getActivePage(); |
| if (page != null) { |
| try { |
| IViewPart part = page.showView(HELP_VIEW_ID); |
| if (part != null) { |
| view = (HelpView) part; |
| } |
| } catch (PartInitException e) { |
| } |
| } |
| } |
| return view; |
| } |
| |
| private static void setIntroStandby() { |
| IIntroManager introMng = PlatformUI.getWorkbench().getIntroManager(); |
| IIntroPart intro = introMng.getIntro(); |
| if (intro != null && !introMng.isIntroStandby(intro)) |
| introMng.setIntroStandby(intro, true); |
| } |
| |
| private void warnNoOpenPerspective(IWorkbenchWindow window) { |
| MessageDialog.openInformation(window.getShell(), Messages.DefaultHelpUI_wtitle, |
| Messages.DefaultHelpUI_noPerspMessage); |
| } |
| |
| /** |
| * Displays a help resource specified as a url. |
| * <ul> |
| * <li>a URL in a format that can be returned by |
| * {@link org.eclipse.help.IHelpResource#getHref() IHelpResource.getHref()} |
| * <li>a URL query in the format format <em>key=value&key=value ...</em> The valid keys |
| * are: "tab", "toc", "topic", "contextId". For example, |
| * <em>toc="/myplugin/mytoc.xml"&topic="/myplugin/references/myclass.html"</em> is valid. |
| * </ul> |
| */ |
| @Override |
| public void displayHelpResource(String href) { |
| BaseHelpSystem.getHelpDisplay().displayHelpResource(href, useExternalBrowser(href)); |
| } |
| |
| /** |
| * Displays context-sensitive help for specified context |
| * |
| * @param context |
| * the context to display |
| * @param x |
| * int positioning information |
| * @param y |
| * int positioning information |
| */ |
| @Override |
| public void displayContext(IContext context, int x, int y) { |
| displayContext(context, x, y, false); |
| } |
| |
| void displayContext(IContext context, int x, int y, boolean noInfopop) { |
| if (context == null) |
| return; |
| boolean winfopop = Platform.getPreferencesService().getBoolean |
| (HelpBasePlugin.PLUGIN_ID, IHelpBaseConstants.P_KEY_WINDOW_INFOPOP, false, null); |
| boolean dinfopop = Platform.getPreferencesService().getBoolean |
| (HelpBasePlugin.PLUGIN_ID, IHelpBaseConstants.P_KEY_DIALOG_INFOPOP, false, null) || FontUtils.isFontTooLargeForTray(); |
| |
| IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); |
| Shell activeShell = getActiveShell(); |
| if (window != null && isActiveShell(activeShell, window)) { |
| IWorkbenchPage page = window.getActivePage(); |
| if (page != null) { |
| if (!noInfopop && winfopop) { |
| Control c = window.getShell().getDisplay().getFocusControl(); |
| displayContextAsInfopop(context, x, y, c); |
| return; |
| } |
| try { |
| /* |
| * If the context help has no description text and exactly one |
| * topic, go straight to the topic and skip context help. |
| */ |
| String contextText = context.getText(); |
| IHelpResource[] topics = context.getRelatedTopics(); |
| boolean isSingleChoiceWithoutDescription = contextText == null && topics.length == 1; |
| String openMode = Platform.getPreferencesService().getString |
| (HelpBasePlugin.PLUGIN_ID, IHelpBaseConstants.P_KEY_HELP_VIEW_OPEN_MODE, IHelpBaseConstants.P_IN_PLACE, null); |
| if (isSingleChoiceWithoutDescription && IHelpBaseConstants.P_IN_EDITOR.equals(openMode)) { |
| showInWorkbenchBrowser(topics[0].getHref(), true); |
| } else if (isSingleChoiceWithoutDescription && IHelpBaseConstants.P_IN_BROWSER.equals(openMode)) { |
| BaseHelpSystem.getHelpDisplay().displayHelpResource(topics[0].getHref(), true); |
| } else { |
| IWorkbenchPart activePart = page.getActivePart(); |
| Control c = window.getShell().getDisplay().getFocusControl(); |
| openingHelpView = true; |
| IViewPart part = page.showView(HELP_VIEW_ID); |
| openingHelpView = false; |
| if (part != null) { |
| HelpView view = (HelpView) part; |
| if (isSingleChoiceWithoutDescription) { |
| view.showHelp(topics[0].getHref()); |
| } else { |
| view.displayContext(context, activePart, c); |
| } |
| } |
| } |
| return; |
| } catch (PartInitException e) { |
| // ignore the exception and let |
| // the code default to the context |
| // help dialog |
| } |
| } |
| } |
| // check the dialog |
| if (HelpTray.isAppropriateFor(activeShell) && (!dinfopop || noInfopop)) { |
| displayContextAsHelpTray(activeShell, context); |
| return; |
| } |
| // we are here either as a fallback or because of the user preferences |
| displayContextAsInfopop(context, x, y, null); |
| } |
| |
| @Override |
| public URL resolve(String href, boolean documentOnly) { |
| return BaseHelpSystem.resolve(href, documentOnly); |
| } |
| |
| public String unresolve(URL url) { |
| return BaseHelpSystem.unresolve(url); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.help.AbstractHelpUI#resolve(java.lang.String, boolean) |
| */ |
| private static Shell getActiveShell() { |
| Display display = PlatformUI.getWorkbench().getDisplay(); |
| return display.getActiveShell(); |
| } |
| |
| static boolean isActiveShell(Shell activeShell, IWorkbenchWindow window) { |
| // Test if the active shell belongs to this window |
| return activeShell != null && activeShell.equals(window.getShell()); |
| } |
| |
| private void displayContextAsInfopop(IContext context, int x, int y, Control c) { |
| if (f1Dialog != null) { |
| f1Dialog.close(); |
| } |
| |
| if (context != 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) { |
| try { |
| PlatformUI.getWorkbench().getHelpSystem().displayHelpResource(topics[0].getHref()); |
| } |
| catch (Exception e) { |
| // should never happen |
| } |
| } |
| else { |
| f1Dialog = new ContextHelpDialog(context, x, y); |
| f1Dialog.open(); |
| } |
| } |
| } |
| |
| private void displayContextAsHelpTray(Shell activeShell, IContext context) { |
| Control controlInFocus = activeShell.getDisplay().getFocusControl(); |
| TrayDialog dialog = (TrayDialog)activeShell.getData(); |
| |
| DialogTray tray = dialog.getTray(); |
| if (tray == null) { |
| tray = new HelpTray(); |
| dialog.openTray(tray); |
| } |
| if (tray instanceof HelpTray) { |
| ReusableHelpPart helpPart = ((HelpTray)tray).getHelpPart(); |
| if (context != null) { |
| IHelpResource[] topics = context.getRelatedTopics(); |
| if (context.getText() == null && topics.length == 1) { |
| helpPart.showURL(topics[0].getHref()); |
| } |
| else { |
| helpPart.showPage(IHelpUIConstants.HV_CONTEXT_HELP_PAGE); |
| helpPart.update(null, context, null, controlInFocus, true); |
| } |
| } |
| else { |
| helpPart.showPage(IHelpUIConstants.HV_FSEARCH_PAGE, true); |
| } |
| helpPart.setFocus(); |
| } |
| else { |
| // someone else was occupying the tray; not supported |
| } |
| } |
| |
| /** |
| * Returns <code>true</code> if the context-sensitive help window is currently being |
| * displayed, <code>false</code> if not. |
| */ |
| @Override |
| public boolean isContextHelpDisplayed() { |
| if (f1Dialog == null) { |
| return false; |
| } |
| return f1Dialog.isShowing(); |
| } |
| |
| private boolean useExternalBrowser(String url) { |
| // On non Windows platforms, use external when modal window is displayed |
| if (!Constants.OS_WIN32.equalsIgnoreCase(Platform.getOS())) { |
| Display display = Display.getCurrent(); |
| if (display != null) { |
| if (insideModalParent(display)) |
| return true; |
| } |
| } |
| |
| // Use external when no help frames are to be displayed, otherwise no |
| // navigation buttons. |
| if (url != null) { |
| if (url.indexOf("?noframes=true") > 0 //$NON-NLS-1$ |
| || url.indexOf("&noframes=true") > 0) { //$NON-NLS-1$ |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private boolean insideModalParent(Display display) { |
| return isDisplayModal(display.getActiveShell()); |
| } |
| |
| public static boolean isDisplayModal(Shell activeShell) { |
| while (activeShell != null) { |
| if ((activeShell.getStyle() & (SWT.APPLICATION_MODAL | SWT.PRIMARY_MODAL | SWT.SYSTEM_MODAL)) > 0) |
| return true; |
| activeShell = (Shell) activeShell.getParent(); |
| } |
| return false; |
| } |
| |
| public static boolean showInWorkbenchBrowser(String url, boolean onlyInternal) { |
| IWorkbenchBrowserSupport support = PlatformUI.getWorkbench().getBrowserSupport(); |
| if (!onlyInternal || support.isInternalWebBrowserAvailable()) { |
| try { |
| IWebBrowser browser = support |
| .createBrowser( |
| IWorkbenchBrowserSupport.AS_EDITOR |
| | IWorkbenchBrowserSupport.NAVIGATION_BAR |
| | IWorkbenchBrowserSupport.STATUS, |
| "org.eclipse.help.ui", Messages.ReusableHelpPart_internalBrowserTitle, url); //$NON-NLS-1$ |
| browser.openURL(BaseHelpSystem.resolve(url, "/help/nftopic")); //$NON-NLS-1$ |
| return true; |
| } catch (PartInitException e) { |
| HelpUIPlugin.logError( |
| Messages.ReusableHelpPart_internalWebBrowserError, e); |
| } |
| } |
| return false; |
| } |
| |
| /* |
| * Used to indicate to the HelpView that we are about to pass in a context |
| */ |
| |
| public static boolean isOpeningHelpView() { |
| return openingHelpView; |
| } |
| } |