mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-05 01:50:56 +07:00
[ui][IDEA-334229] add "download sources" button into quick doc popup
GitOrigin-RevId: f74a7f19b1663909c438d4ecb3e4a92677f09f11
This commit is contained in:
committed by
intellij-monorepo-bot
parent
db15d18104
commit
2b94dd7636
@@ -602,3 +602,4 @@ tooltip.computing.classes.for.auto.import=Computing classes to auto-import...
|
||||
jvm.inspections.dependency.configure.button.text=Configure dependency rules
|
||||
checking.code.highlightings.in.background=Loading Code Highlighting
|
||||
title.checking.code.highlightings.in.background.task=Loading code passes
|
||||
documentation.download.button.label=Download documentation
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.documentation;
|
||||
|
||||
import com.intellij.lang.documentation.QuickDocHighlightingHelper;
|
||||
@@ -65,6 +65,7 @@ public final class DocumentationHtmlUtil {
|
||||
".separated { padding: 0 0 4px 0; margin: 0; max-width: 100%;" +
|
||||
" border-bottom: thin solid " + borderColor + "; }",
|
||||
".bottom { padding: 3px 16px 0 " + leftPadding + "px; }",
|
||||
".download-documentation { padding: 0px 0px 18px; }",
|
||||
".separator-container { padding: 18px " + leftPadding + "px 0px; }",
|
||||
".separator-container .separator { border-top: thin solid " + borderColor + "; }",
|
||||
".bottom-no-content { padding: 5px 16px 0 " + leftPadding + "px; }",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.documentation;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightBundle;
|
||||
@@ -10,6 +10,7 @@ import com.intellij.codeInsight.lookup.Lookup;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupManager;
|
||||
import com.intellij.codeWithMe.ClientId;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.BrowserUtil;
|
||||
import com.intellij.ide.IdeEventQueue;
|
||||
import com.intellij.ide.actions.BaseNavigateToSourceAction;
|
||||
@@ -1857,7 +1858,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
@Nullable DocumentationProvider provider
|
||||
) {
|
||||
HtmlChunk locationInfo = getDefaultLocationInfo(element);
|
||||
return decorate(text, locationInfo, getExternalText(element, externalUrl, provider));
|
||||
return decorate(text, locationInfo, getExternalText(element, externalUrl, provider), null);
|
||||
}
|
||||
|
||||
@RequiresReadLock
|
||||
@@ -1897,7 +1898,8 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
|
||||
@Internal
|
||||
@Contract(pure = true)
|
||||
public static @Nls String decorate(@Nls @NotNull String text, @Nullable HtmlChunk location, @Nullable HtmlChunk links) {
|
||||
public static @Nls String decorate(@Nls @NotNull String text, @Nullable HtmlChunk location, @Nullable HtmlChunk links,
|
||||
@Nullable String downloadDocumentationActionLink) {
|
||||
text = StringUtil.replaceIgnoreCase(text, "</html>", "");
|
||||
text = StringUtil.replaceIgnoreCase(text, "</body>", "");
|
||||
text = replaceIgnoreQuotesType(text, SECTIONS_START + SECTIONS_END, "");
|
||||
@@ -1922,10 +1924,21 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
if (!containsIgnoreQuotesType(text, DEFINITION_START)) {
|
||||
text = replaceIgnoreQuotesType(text, "class='content'", "class='content-only'");
|
||||
}
|
||||
if (location != null) {
|
||||
if (downloadDocumentationActionLink != null || location != null) {
|
||||
text += HtmlChunk.div().setClass("separator-container")
|
||||
.child(HtmlChunk.div().setClass("separator"));
|
||||
text += location;
|
||||
if (downloadDocumentationActionLink != null) {
|
||||
text += HtmlChunk.div()
|
||||
.children(
|
||||
HtmlChunk.icon("AllIcons.Plugins.Downloads", AllIcons.Plugins.Downloads),
|
||||
HtmlChunk.nbsp(),
|
||||
HtmlChunk.link(downloadDocumentationActionLink, CodeInsightBundle.message("documentation.download.button.label"))
|
||||
)
|
||||
.setClass("download-documentation");
|
||||
}
|
||||
if (location != null) {
|
||||
text += location;
|
||||
}
|
||||
}
|
||||
if (links != null) {
|
||||
text += getBottom(location != null).child(links);
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.documentation.actions
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Experimental
|
||||
interface DocumentationDownloader {
|
||||
|
||||
suspend fun canHandle(target: PsiElement): Boolean
|
||||
|
||||
suspend fun download(target: VirtualFile)
|
||||
|
||||
companion object {
|
||||
val EP = ExtensionPointName.create<DocumentationDownloader>("com.intellij.documentation.documentationDownloader")
|
||||
const val HREF_PREFIX = "download_sources:"
|
||||
|
||||
fun formatLink(target: PsiElement): String? {
|
||||
val virtualFileUrl: String = target.containingFile?.virtualFile?.url ?: return null
|
||||
return HREF_PREFIX + virtualFileUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
@file:Suppress("TestOnlyProblems") // KTIJ-19938
|
||||
|
||||
package com.intellij.lang.documentation.ide.impl
|
||||
@@ -13,6 +13,7 @@ import com.intellij.platform.backend.documentation.DocumentationContentData
|
||||
import com.intellij.platform.backend.documentation.LinkData
|
||||
import com.intellij.platform.backend.documentation.impl.DocumentationRequest
|
||||
import com.intellij.platform.backend.documentation.impl.computeDocumentation
|
||||
import com.intellij.psi.PsiElement
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
@@ -64,7 +65,7 @@ internal class DocumentationPage(val requests: List<DocumentationRequest>) {
|
||||
}
|
||||
|
||||
private fun prepareContent(content: DocumentationContentData, links: LinkData, uiState: UIState?): DocumentationPageContent.Content {
|
||||
return DocumentationPageContent.Content(content, links, uiState)
|
||||
return DocumentationPageContent.Content(content, links, uiState, content.targetElement)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,5 +112,6 @@ internal sealed class DocumentationPageContent {
|
||||
val content: DocumentationContentData,
|
||||
val links: LinkData,
|
||||
val uiState: UIState?,
|
||||
val targetElement: PsiElement?
|
||||
) : DocumentationPageContent()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.intellij.lang.documentation.ide.ui
|
||||
@@ -9,6 +9,7 @@ import com.intellij.codeInsight.documentation.DocumentationLinkHandler
|
||||
import com.intellij.codeInsight.documentation.DocumentationManager.SELECTED_QUICK_DOC_TEXT
|
||||
import com.intellij.codeInsight.documentation.DocumentationManager.decorate
|
||||
import com.intellij.codeInsight.documentation.DocumentationScrollPane
|
||||
import com.intellij.codeInsight.documentation.actions.DocumentationDownloader
|
||||
import com.intellij.codeInsight.hint.DefinitionSwitcher
|
||||
import com.intellij.ide.DataManager
|
||||
import com.intellij.lang.documentation.DocumentationImageResolver
|
||||
@@ -24,6 +25,7 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import com.intellij.openapi.util.text.HtmlChunk
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.intellij.platform.backend.documentation.impl.DocumentationRequest
|
||||
import com.intellij.platform.backend.presentation.TargetPresentation
|
||||
import com.intellij.platform.ide.documentation.DOCUMENTATION_BROWSER
|
||||
@@ -54,6 +56,9 @@ internal class DocumentationUI(
|
||||
val switcherToolbarComponent: JComponent?
|
||||
|
||||
private val icons = mutableMapOf<String, Icon>()
|
||||
|
||||
@Volatile
|
||||
private var documentationDownloader: DocumentationDownloader? = null
|
||||
private var imageResolver: DocumentationImageResolver? = null
|
||||
private val linkHandler: DocumentationLinkHandler
|
||||
private val cs = CoroutineScope(Dispatchers.EDT)
|
||||
@@ -168,9 +173,17 @@ internal class DocumentationUI(
|
||||
private suspend fun handleContent(presentation: TargetPresentation, pageContent: DocumentationPageContent.Content) {
|
||||
val content = pageContent.content
|
||||
imageResolver = content.imageResolver
|
||||
val locationChunk = getDefaultLocationChunk(presentation)
|
||||
val targetElement = pageContent.targetElement
|
||||
var downloadSourcesLink: String? = null
|
||||
if (targetElement != null) {
|
||||
documentationDownloader = DocumentationDownloader.EP.extensionList.find { it.canHandle(targetElement) }
|
||||
if (documentationDownloader != null) {
|
||||
downloadSourcesLink = DocumentationDownloader.formatLink(targetElement)
|
||||
}
|
||||
}
|
||||
val linkChunk = linkChunk(presentation.presentableText, pageContent.links)
|
||||
val decorated = decorate(content.html, locationChunk, linkChunk)
|
||||
val locationChunk = getDefaultLocationChunk(presentation)
|
||||
val decorated = decorate(content.html, locationChunk, linkChunk, downloadSourcesLink)
|
||||
if (!updateContent(decorated)) {
|
||||
return
|
||||
}
|
||||
@@ -277,6 +290,15 @@ internal class DocumentationUI(
|
||||
if (href.startsWith("#")) {
|
||||
UIUtil.scrollToReference(editorPane, href.removePrefix("#"))
|
||||
}
|
||||
else if (href.startsWith(DocumentationDownloader.HREF_PREFIX) && documentationDownloader != null) {
|
||||
val filePath = href.replaceFirst(DocumentationDownloader.HREF_PREFIX, "")
|
||||
val file = VirtualFileManager.getInstance().findFileByUrl(filePath)
|
||||
if (file != null) {
|
||||
cs.launch(Dispatchers.Default) {
|
||||
documentationDownloader?.download(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
browser.navigateByLink(href)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
@file:Suppress("DEPRECATION", "TestOnlyProblems") // KTIJ-19938
|
||||
|
||||
package com.intellij.lang.documentation.psi
|
||||
@@ -102,6 +102,7 @@ class PsiElementDocumentationTarget private constructor(
|
||||
html = parts.doc,
|
||||
definitionDetails = parts.definitionDetails,
|
||||
imageResolver = pointer.imageResolver,
|
||||
targetElement = targetElement
|
||||
),
|
||||
anchor = pointer.anchor,
|
||||
)
|
||||
@@ -158,6 +159,7 @@ class PsiElementDocumentationTarget private constructor(
|
||||
content = DocumentationContentData(
|
||||
html = doc,
|
||||
imageResolver = imageResolver,
|
||||
targetElement = targetElement
|
||||
),
|
||||
anchor = anchor,
|
||||
links = LinkData(externalUrl = url),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.platform.backend.documentation;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus.NonExtendable;
|
||||
@@ -25,6 +25,6 @@ public interface DocumentationContent {
|
||||
@Nls @NotNull String html,
|
||||
@NotNull Map<@NotNull String, ? extends @NotNull Image> images
|
||||
) {
|
||||
return new DocumentationContentData(html, imageResolver(images), null);
|
||||
return new DocumentationContentData(html, imageResolver(images), null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.platform.backend.documentation
|
||||
|
||||
import com.intellij.lang.documentation.DocumentationImageResolver
|
||||
import com.intellij.model.Pointer
|
||||
import com.intellij.openapi.progress.blockingContext
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.util.AsyncSupplier
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
@@ -21,7 +22,8 @@ import java.util.function.Supplier
|
||||
internal data class DocumentationContentData internal constructor(
|
||||
val html: @Nls String,
|
||||
val imageResolver: DocumentationImageResolver?,
|
||||
val definitionDetails: String? = null
|
||||
val definitionDetails: String? = null,
|
||||
val targetElement: PsiElement? = null
|
||||
) : DocumentationContent
|
||||
|
||||
@Internal
|
||||
|
||||
@@ -568,6 +568,8 @@
|
||||
<extensionPoint name="elementPreviewProvider" interface="com.intellij.codeInsight.preview.ElementPreviewProvider" dynamic="true"/>
|
||||
|
||||
<extensionPoint name="testActionProvider" interface="com.intellij.execution.testframework.ToggleModelActionProvider" dynamic="true"/>
|
||||
<extensionPoint name="documentation.documentationDownloader"
|
||||
interface="com.intellij.codeInsight.documentation.actions.DocumentationDownloader" dynamic="true"/>
|
||||
|
||||
<extensionPoint name="testDiffProvider" beanClass="com.intellij.lang.LanguageExtensionPoint" dynamic="true">
|
||||
<with attribute="implementationClass" implements="com.intellij.execution.testframework.actions.TestDiffProvider"/>
|
||||
|
||||
Reference in New Issue
Block a user