From 1dcd79b37ba7700726f36902f43b1e319cdef48d Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 24 Aug 2009 20:24:06 +0400 Subject: [PATCH] external documentation: multiple roots --- .../util/xml/DomDocumentationProvider.java | 4 ++- .../CompositeDocumentationProvider.java | 16 ++++----- .../documentation/DocumentationProvider.java | 4 ++- .../QuickDocumentationProvider.java | 4 ++- .../documentation/DocumentationComponent.java | 14 ++++---- .../documentation/DocumentationManager.java | 8 ++--- .../ide/actions/ExternalJavaDocAction.java | 33 ++++++++++++++++--- .../ant/doc/AntDocumentationProvider.java | 5 +-- .../lang/java/JavaDocumentationProvider.java | 16 ++++----- .../HtmlDocumentationProvider.java | 9 +++-- .../XmlDocumentationProvider.java | 7 ++-- 11 files changed, 79 insertions(+), 41 deletions(-) diff --git a/dom/impl/src/com/intellij/util/xml/DomDocumentationProvider.java b/dom/impl/src/com/intellij/util/xml/DomDocumentationProvider.java index 3eecf5724c51..55a76ee29756 100644 --- a/dom/impl/src/com/intellij/util/xml/DomDocumentationProvider.java +++ b/dom/impl/src/com/intellij/util/xml/DomDocumentationProvider.java @@ -4,6 +4,8 @@ import com.intellij.lang.documentation.DocumentationProvider; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiManager; +import java.util.List; + /** * @author Dmitry Avdeev */ @@ -13,7 +15,7 @@ public class DomDocumentationProvider implements DocumentationProvider { return null; } - public String getUrlFor(final PsiElement element, final PsiElement originalElement) { + public List getUrlFor(final PsiElement element, final PsiElement originalElement) { return null; } diff --git a/lang-api/src/com/intellij/lang/documentation/CompositeDocumentationProvider.java b/lang-api/src/com/intellij/lang/documentation/CompositeDocumentationProvider.java index 75db0e851305..eae7d6784f3d 100644 --- a/lang-api/src/com/intellij/lang/documentation/CompositeDocumentationProvider.java +++ b/lang-api/src/com/intellij/lang/documentation/CompositeDocumentationProvider.java @@ -52,20 +52,20 @@ public class CompositeDocumentationProvider implements DocumentationProvider{ String result = provider.getQuickNavigateInfo(element); if ( result != null ) return result; } - for (DocumentationProvider provider : Extensions.getExtensions(DocumentationProvider.EP_NAME)) { + for (DocumentationProvider provider : Extensions.getExtensions(EP_NAME)) { final String result = provider.getQuickNavigateInfo(element); if (result != null) return result; } return null; } - public String getUrlFor(PsiElement element, PsiElement originalElement) { + public List getUrlFor(PsiElement element, PsiElement originalElement) { for ( DocumentationProvider provider : myProviders ) { - String result = provider.getUrlFor(element,originalElement); + List result = provider.getUrlFor(element,originalElement); if ( result != null ) return result; } - for (DocumentationProvider provider : Extensions.getExtensions(DocumentationProvider.EP_NAME)) { - final String result = provider.getUrlFor(element, originalElement); + for (DocumentationProvider provider : Extensions.getExtensions(EP_NAME)) { + final List result = provider.getUrlFor(element, originalElement); if (result != null) return result; } return null; @@ -76,7 +76,7 @@ public class CompositeDocumentationProvider implements DocumentationProvider{ String result = provider.generateDoc(element,originalElement); if ( result != null ) return result; } - for (DocumentationProvider provider : Extensions.getExtensions(DocumentationProvider.EP_NAME)) { + for (DocumentationProvider provider : Extensions.getExtensions(EP_NAME)) { final String result = provider.generateDoc(element, originalElement); if (result != null) return result; } @@ -88,7 +88,7 @@ public class CompositeDocumentationProvider implements DocumentationProvider{ PsiElement result = provider.getDocumentationElementForLookupItem(psiManager,object,element); if ( result != null ) return result; } - for (DocumentationProvider provider : Extensions.getExtensions(DocumentationProvider.EP_NAME)) { + for (DocumentationProvider provider : Extensions.getExtensions(EP_NAME)) { final PsiElement result = provider.getDocumentationElementForLookupItem(psiManager, object, element); if (result != null) return result; } @@ -100,7 +100,7 @@ public class CompositeDocumentationProvider implements DocumentationProvider{ PsiElement result = provider.getDocumentationElementForLink(psiManager,link,context); if ( result != null ) return result; } - for (DocumentationProvider provider : Extensions.getExtensions(DocumentationProvider.EP_NAME)) { + for (DocumentationProvider provider : Extensions.getExtensions(EP_NAME)) { final PsiElement result = provider.getDocumentationElementForLink(psiManager, link, context); if (result != null) return result; } diff --git a/lang-api/src/com/intellij/lang/documentation/DocumentationProvider.java b/lang-api/src/com/intellij/lang/documentation/DocumentationProvider.java index adcf3769bde7..0cc890f61511 100644 --- a/lang-api/src/com/intellij/lang/documentation/DocumentationProvider.java +++ b/lang-api/src/com/intellij/lang/documentation/DocumentationProvider.java @@ -21,6 +21,8 @@ import com.intellij.psi.PsiManager; import com.intellij.openapi.extensions.ExtensionPointName; import org.jetbrains.annotations.Nullable; +import java.util.List; + /** * @see com.intellij.lang.LanguageDocumentation */ @@ -32,7 +34,7 @@ public interface DocumentationProvider { String getQuickNavigateInfo(PsiElement element); @Nullable - String getUrlFor(PsiElement element, PsiElement originalElement); + List getUrlFor(PsiElement element, PsiElement originalElement); @Nullable String generateDoc(PsiElement element, PsiElement originalElement); diff --git a/lang-api/src/com/intellij/lang/documentation/QuickDocumentationProvider.java b/lang-api/src/com/intellij/lang/documentation/QuickDocumentationProvider.java index 5c01d5d8811d..74eca6790b66 100644 --- a/lang-api/src/com/intellij/lang/documentation/QuickDocumentationProvider.java +++ b/lang-api/src/com/intellij/lang/documentation/QuickDocumentationProvider.java @@ -20,10 +20,12 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiManager; import org.jetbrains.annotations.Nullable; +import java.util.List; + public abstract class QuickDocumentationProvider implements DocumentationProvider { @Nullable - public String getUrlFor(PsiElement element, PsiElement originalElement) { + public List getUrlFor(PsiElement element, PsiElement originalElement) { return null; } diff --git a/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java b/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java index cfaaead90af7..1323c14aab9d 100644 --- a/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java +++ b/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java @@ -4,7 +4,7 @@ import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.codeInsight.hint.ElementLocationUtil; import com.intellij.codeInsight.hint.HintManagerImpl; import com.intellij.codeInsight.hint.HintUtil; -import com.intellij.ide.BrowserUtil; +import com.intellij.ide.actions.ExternalJavaDocAction; import com.intellij.lang.documentation.DocumentationProvider; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; @@ -26,6 +26,7 @@ import javax.swing.event.HyperlinkListener; import javax.swing.text.View; import java.awt.*; import java.awt.event.*; +import java.util.List; import java.util.Stack; public class DocumentationComponent extends JPanel implements Disposable{ @@ -360,9 +361,10 @@ public class DocumentationComponent extends JPanel implements Disposable{ if (myElement != null) { final PsiElement element = myElement.getElement(); final DocumentationProvider provider = DocumentationManager.getProviderFromElement(element); - final String url = provider.getUrlFor(element, DocumentationManager.getOriginalElement(element)); - assert url != null; - BrowserUtil.launchBrowser(url); + final List urls = provider.getUrlFor(element, DocumentationManager.getOriginalElement(element)); + assert urls != null; + assert !urls.isEmpty(); + ExternalJavaDocAction.showExternalJavadoc(urls); } } @@ -372,8 +374,8 @@ public class DocumentationComponent extends JPanel implements Disposable{ if (myElement != null) { final PsiElement element = myElement.getElement(); final DocumentationProvider provider = DocumentationManager.getProviderFromElement(element); - final String url = provider.getUrlFor(element, DocumentationManager.getOriginalElement(element)); - presentation.setEnabled(element != null && url!= null); + final List urls = provider.getUrlFor(element, DocumentationManager.getOriginalElement(element)); + presentation.setEnabled(element != null && urls!= null && !urls.isEmpty()); } } } diff --git a/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java index d459a6ae6a9c..9330c8e5c4b0 100644 --- a/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -43,8 +43,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.lang.ref.WeakReference; -import java.util.LinkedHashSet; -import java.util.Set; +import java.util.*; +import java.util.List; public class DocumentationManager { @NonNls public static final String JAVADOC_LOCATION_AND_SIZE = "javadoc.popup"; @@ -558,8 +558,8 @@ public class DocumentationManager { public String getDocumentation() throws Exception { if (docUrl.startsWith(DOC_ELEMENT_PROTOCOL)) { final DocumentationProvider provider = getProviderFromElement(psiElement); - final String url = provider.getUrlFor(psiElement, getOriginalElement(psiElement)); - BrowserUtil.launchBrowser(url != null? url : docUrl); + final List urls = provider.getUrlFor(psiElement, getOriginalElement(psiElement)); + BrowserUtil.launchBrowser(urls != null && !urls.isEmpty() ? urls.get(0) : docUrl); } else { BrowserUtil.launchBrowser(docUrl); } diff --git a/lang-impl/src/com/intellij/ide/actions/ExternalJavaDocAction.java b/lang-impl/src/com/intellij/ide/actions/ExternalJavaDocAction.java index 1bfb64c09527..d5cc4bee7f80 100644 --- a/lang-impl/src/com/intellij/ide/actions/ExternalJavaDocAction.java +++ b/lang-impl/src/com/intellij/ide/actions/ExternalJavaDocAction.java @@ -3,15 +3,23 @@ package com.intellij.ide.actions; import com.intellij.codeInsight.documentation.DocumentationManager; import com.intellij.ide.BrowserUtil; import com.intellij.ide.IdeBundle; +import com.intellij.ide.DataManager; import com.intellij.lang.documentation.DocumentationProvider; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.ui.popup.PopupStep; +import com.intellij.openapi.ui.popup.util.BaseListPopupStep; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.Nullable; +import java.util.List; +import java.util.HashSet; + public class ExternalJavaDocAction extends AnAction { public ExternalJavaDocAction() { @@ -42,9 +50,25 @@ public class ExternalJavaDocAction extends AnAction { PsiElement originalElement = getOriginalElement(context, editor); DocumentationManager.storeOriginalElement(project, originalElement, element); final DocumentationProvider provider = DocumentationManager.getProviderFromElement(element); - final String url = provider.getUrlFor(element, originalElement); - assert url != null; - BrowserUtil.launchBrowser(url); + final List urls = provider.getUrlFor(element, originalElement); + assert urls != null; + assert !urls.isEmpty(); + showExternalJavadoc(urls); + } + + public static void showExternalJavadoc(List urls) { + final HashSet set = new HashSet(urls); + if (set.size() > 1) { + JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep("Choose javadoc root", ArrayUtil.toStringArray(set)) { + public PopupStep onChosen(final String selectedValue, final boolean finalChoice) { + BrowserUtil.launchBrowser(selectedValue); + return FINAL_CHOICE; + } + }).showInBestPositionFor(DataManager.getInstance().getDataContext()); + } + else if (set.size() == 1) { + BrowserUtil.launchBrowser(urls.get(0)); + } } @Nullable @@ -60,7 +84,8 @@ public class ExternalJavaDocAction extends AnAction { final PsiElement originalElement = getOriginalElement(LangDataKeys.PSI_FILE.getData(dataContext), editor); DocumentationManager.storeOriginalElement(PlatformDataKeys.PROJECT.getData(dataContext), originalElement, element); final DocumentationProvider provider = DocumentationManager.getProviderFromElement(element); - boolean enabled = provider.getUrlFor(element, originalElement) != null; + final List urls = provider.getUrlFor(element, originalElement); + boolean enabled = urls != null && !urls.isEmpty(); if (editor != null) { presentation.setEnabled(enabled); if (event.getPlace().equals(ActionPlaces.MAIN_MENU)) { diff --git a/plugins/ant/src/com/intellij/lang/ant/doc/AntDocumentationProvider.java b/plugins/ant/src/com/intellij/lang/ant/doc/AntDocumentationProvider.java index 60a6155601f9..d74af63bf95d 100644 --- a/plugins/ant/src/com/intellij/lang/ant/doc/AntDocumentationProvider.java +++ b/plugins/ant/src/com/intellij/lang/ant/doc/AntDocumentationProvider.java @@ -20,6 +20,7 @@ import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; +import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -205,12 +206,12 @@ public class AntDocumentationProvider implements DocumentationProvider { return null; } - public String getUrlFor(PsiElement element, PsiElement originalElement) { + public List getUrlFor(PsiElement element, PsiElement originalElement) { final VirtualFile helpFile = getHelpFile(originalElement); if (helpFile == null || !(helpFile.getFileSystem() instanceof LocalFileSystem)) { return null; } - return helpFile.getUrl(); + return Collections.singletonList(helpFile.getUrl()); } public PsiElement getDocumentationElementForLookupItem(PsiManager psiManager, Object object, PsiElement element) { diff --git a/source/com/intellij/lang/java/JavaDocumentationProvider.java b/source/com/intellij/lang/java/JavaDocumentationProvider.java index 08a236c7501e..899e598fdadd 100644 --- a/source/com/intellij/lang/java/JavaDocumentationProvider.java +++ b/source/com/intellij/lang/java/JavaDocumentationProvider.java @@ -87,8 +87,8 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider { return null; } - public String getUrlFor(final PsiElement element, final PsiElement originalElement) { - return null; + public List getUrlFor(final PsiElement element, final PsiElement originalElement) { + return getExternalJavaDocUrl(element); } private static void newLine(StringBuffer buffer) { @@ -708,13 +708,11 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider { } else { DocumentationProvider provider = DocumentationManager.getProviderFromElement(element); - if (provider != null) { - final SmartPsiElementPointer originalElementPointer = element.getUserData(DocumentationManager.ORIGINAL_ELEMENT_KEY); - final String url = provider.getUrlFor(element, originalElementPointer != null ? originalElementPointer.getElement() : null); - if (url != null) { - urls = new ArrayList(); - urls.add(url); - } + final SmartPsiElementPointer originalElementPointer = element.getUserData(DocumentationManager.ORIGINAL_ELEMENT_KEY); + final List urlz = provider.getUrlFor(element, originalElementPointer != null ? originalElementPointer.getElement() : null); + if (urlz != null) { + urls = new ArrayList(); + urls.addAll(urlz); } } diff --git a/xml/impl/src/com/intellij/xml/util/documentation/HtmlDocumentationProvider.java b/xml/impl/src/com/intellij/xml/util/documentation/HtmlDocumentationProvider.java index 2bae71a188ad..6900f1c607eb 100644 --- a/xml/impl/src/com/intellij/xml/util/documentation/HtmlDocumentationProvider.java +++ b/xml/impl/src/com/intellij/xml/util/documentation/HtmlDocumentationProvider.java @@ -18,6 +18,9 @@ import com.intellij.xml.util.XmlUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; +import java.util.Collections; +import java.util.List; + /** * Created by IntelliJ IDEA. * User: maxim @@ -43,14 +46,14 @@ public class HtmlDocumentationProvider implements DocumentationProvider { return null; } - public String getUrlFor(PsiElement element, PsiElement originalElement) { + public List getUrlFor(PsiElement element, PsiElement originalElement) { String result = getUrlForHtml(element, PsiTreeUtil.getParentOfType(originalElement,XmlTag.class,false)); if (result == null && ourStyleProvider !=null) { - result = ourStyleProvider.getUrlFor(element, originalElement); + return ourStyleProvider.getUrlFor(element, originalElement); } - return result; + return result != null ? Collections.singletonList(result) : null; } public String getUrlForHtml(PsiElement element, XmlTag context) { diff --git a/xml/impl/src/com/intellij/xml/util/documentation/XmlDocumentationProvider.java b/xml/impl/src/com/intellij/xml/util/documentation/XmlDocumentationProvider.java index 181d2219ca0b..1df366373ba0 100644 --- a/xml/impl/src/com/intellij/xml/util/documentation/XmlDocumentationProvider.java +++ b/xml/impl/src/com/intellij/xml/util/documentation/XmlDocumentationProvider.java @@ -30,6 +30,9 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collections; +import java.util.List; + /** * Created by IntelliJ IDEA. * User: maxim @@ -61,7 +64,7 @@ public class XmlDocumentationProvider implements DocumentationProvider { return sb.toString(); } - public String getUrlFor(PsiElement element, PsiElement originalElement) { + public List getUrlFor(PsiElement element, PsiElement originalElement) { if (element instanceof XmlTag) { XmlTag tag = (XmlTag)element; @@ -76,7 +79,7 @@ public class XmlDocumentationProvider implements DocumentationProvider { } } - return processor.url; + return processor.url != null ? Collections.singletonList(processor.url) : null; } return null; }