From a028674bdbfe013e83c9627039b126798ed583d8 Mon Sep 17 00:00:00 2001 From: Piotr Tomiak Date: Thu, 15 Feb 2024 10:48:47 +0100 Subject: [PATCH] IDEA-346213 QuickDoc: improve wrapping of long qualified names and URLs GitOrigin-RevId: c808dd4c333636dc9dc36e01b3afa57f3037ec0c --- .../documentation/EscapingLink.html | 4 +- .../documentation/LinkBetweenMethods.html | 2 +- .../LinkToPackageSummaryWithReference.html | 2 +- .../documentation/LinkWithReference.html | 8 +- ...erenceStyleDoesntMatchBytecodeVersion.html | 4 +- ...ssWithReferencesToClassesFromJavaLang.html | 4 +- ...ntationForUncheckedExceptionsInSupers.html | 4 +- .../codeInsight/javadocIG/dumbMode.html | 2 +- .../packageInfoWithCopyright/packageInfo.html | 2 +- .../javadocIG/reflectConstructor.html | 4 +- .../javadocIG/syntheticEnumValues.html | 4 +- .../java/codeInsight/JavaDocumentationTest.kt | 4 +- .../DocumentationEditorPane.java | 5 +- .../documentation/DocumentationHtmlUtil.kt | 113 ++++++++++++++++++ .../documentation/DocumentationManager.java | 3 + .../QuickDocHighlightingHelper.kt | 1 - ...leSheetRulesProviderForCodeHighlighting.kt | 2 + .../util/ui/ExtendableHTMLViewFactory.kt | 23 +++- .../com/intellij/util/ui/html/InlineViewEx.kt | 97 +++++++++------ .../src/com/intellij/util/ui/html/WbrView.kt | 38 ++++++ 20 files changed, 260 insertions(+), 66 deletions(-) create mode 100644 platform/util/ui/src/com/intellij/util/ui/html/WbrView.kt diff --git a/java/java-tests/testData/codeInsight/documentation/EscapingLink.html b/java/java-tests/testData/codeInsight/documentation/EscapingLink.html index ecdb2e998945..1fa8f3e8e324 100644 --- a/java/java-tests/testData/codeInsight/documentation/EscapingLink.html +++ b/java/java-tests/testData/codeInsight/documentation/EscapingLink.html @@ -15,8 +15,8 @@ diff --git a/java/java-tests/testData/codeInsight/documentation/LinkBetweenMethods.html b/java/java-tests/testData/codeInsight/documentation/LinkBetweenMethods.html index 3dc5b84e4dcf..046c750ecd23 100644 --- a/java/java-tests/testData/codeInsight/documentation/LinkBetweenMethods.html +++ b/java/java-tests/testData/codeInsight/documentation/LinkBetweenMethods.html @@ -14,7 +14,7 @@
-

com.jetbrains.LinkBetweenMethods

+

com.jetbrains.LinkBetweenMethods

public void m1()
diff --git a/java/java-tests/testData/codeInsight/documentation/LinkToPackageSummaryWithReference.html b/java/java-tests/testData/codeInsight/documentation/LinkToPackageSummaryWithReference.html index 624a1a571ad0..00c2f83c638e 100644 --- a/java/java-tests/testData/codeInsight/documentation/LinkToPackageSummaryWithReference.html +++ b/java/java-tests/testData/codeInsight/documentation/LinkToPackageSummaryWithReference.html @@ -13,7 +13,7 @@ }
-
com.jetbrains
+
com.jetbrains

Interface SimpleInterface

diff --git a/java/java-tests/testData/codeInsight/documentation/LinkWithReference.html b/java/java-tests/testData/codeInsight/documentation/LinkWithReference.html index f352b9b54adc..bfb0fc47554c 100644 --- a/java/java-tests/testData/codeInsight/documentation/LinkWithReference.html +++ b/java/java-tests/testData/codeInsight/documentation/LinkWithReference.html @@ -13,21 +13,21 @@ }
-
com.jetbrains
+
com.jetbrains

Class ClassWithRefLink

    -
  • java.lang.Object
  • +
  • java.lang.Object
    • -
    • com.jetbrains.ClassWithRefLink
    • +
    • com.jetbrains.ClassWithRefLink

public class ClassWithRefLink
-extends java.lang.Object
+extends java.lang.Object diff --git a/java/java-tests/testData/codeInsight/documentation/ReferenceStyleDoesntMatchBytecodeVersion.html b/java/java-tests/testData/codeInsight/documentation/ReferenceStyleDoesntMatchBytecodeVersion.html index 6a29b664f2f4..6a3208a4af40 100644 --- a/java/java-tests/testData/codeInsight/documentation/ReferenceStyleDoesntMatchBytecodeVersion.html +++ b/java/java-tests/testData/codeInsight/documentation/ReferenceStyleDoesntMatchBytecodeVersion.html @@ -15,8 +15,8 @@ diff --git a/java/java-tests/testData/codeInsight/javadocIG/documentationForJdkClassWithReferencesToClassesFromJavaLang.html b/java/java-tests/testData/codeInsight/javadocIG/documentationForJdkClassWithReferencesToClassesFromJavaLang.html index 89470e269877..96284132eee6 100644 --- a/java/java-tests/testData/codeInsight/javadocIG/documentationForJdkClassWithReferencesToClassesFromJavaLang.html +++ b/java/java-tests/testData/codeInsight/javadocIG/documentationForJdkClassWithReferencesToClassesFromJavaLang.html @@ -1,8 +1,8 @@ -
@Contract(pure = true) 
+
@Contract(pure = true) 
 public abstract boolean contains(
Object o
)

Returns true if this list contains the specified element. More formally, returns true if and only if this list contains at least one element e such that - (o==null ? e==null : o.equals(e)). + (o==null ? e==null : o.equals(e)).

Overrides:

contains in interface Collection

Params:

o – element whose presence in this list is to be tested

Returns:

true if this list contains the specified element

Throws:

ClassCastException – if the type of the specified element is incompatible with this list (optional)

NullPointerException – if the specified element is null and this list does not permit null elements (optional)

 < java 1.7 >
\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/documentationForUncheckedExceptionsInSupers.html b/java/java-tests/testData/codeInsight/javadocIG/documentationForUncheckedExceptionsInSupers.html index b066268b5941..2a625f71d427 100644 --- a/java/java-tests/testData/codeInsight/javadocIG/documentationForUncheckedExceptionsInSupers.html +++ b/java/java-tests/testData/codeInsight/javadocIG/documentationForUncheckedExceptionsInSupers.html @@ -1,9 +1,9 @@
 My
@Contract(pure = true)i 
 boolean contains(
Object o
) -throws IOException

From interface:

java.util.Collection
+throws IOException

From interface:

java.util.Collection
Returns true if this collection contains the specified element. More formally, returns true if and only if this collection contains at least one element e such that - (o==null ? e==null : o.equals(e)). + (o==null ? e==null : o.equals(e)).

Overrides:

contains in interface Collection
contains in interface I

Params:

o – element whose presence in this collection is to be tested

Returns:

true if this collection contains the specified element

Throws:

NullPointerException – before if the specified element is null and this collection does not permit null elements (optional) after

IOException

\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/dumbMode.html b/java/java-tests/testData/codeInsight/javadocIG/dumbMode.html index a242f4599409..8ca4c07c71e4 100644 --- a/java/java-tests/testData/codeInsight/javadocIG/dumbMode.html +++ b/java/java-tests/testData/codeInsight/javadocIG/dumbMode.html @@ -1,4 +1,4 @@

class C

some text -

See Also:

System.out

\ No newline at end of file +

See Also:

System.out

\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/packageInfoWithCopyright/packageInfo.html b/java/java-tests/testData/codeInsight/javadocIG/packageInfoWithCopyright/packageInfo.html index 317b5b0278cd..187473cec99f 100644 --- a/java/java-tests/testData/codeInsight/javadocIG/packageInfoWithCopyright/packageInfo.html +++ b/java/java-tests/testData/codeInsight/javadocIG/packageInfoWithCopyright/packageInfo.html @@ -1,3 +1,3 @@
 packageInfoWithCopyright
-

This package contains nothing but package-info.java +

This package contains nothing but package-info.java

\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/reflectConstructor.html b/java/java-tests/testData/codeInsight/javadocIG/reflectConstructor.html index e04069ccd330..e5cf83b6625f 100644 --- a/java/java-tests/testData/codeInsight/javadocIG/reflectConstructor.html +++ b/java/java-tests/testData/codeInsight/javadocIG/reflectConstructor.html @@ -1,5 +1,5 @@ -
@CallerSensitive 
+
@CallerSensitive 
 @NotNull 
 @Contract(pure = true) 
-public java.lang.reflect.Constructor<?>[] getDeclaredConstructors()
+public java.lang.reflect.Constructor<?>[] getDeclaredConstructors()
 throws SecurityException

Throws:

SecurityException

 < java 10 >
\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/syntheticEnumValues.html b/java/java-tests/testData/codeInsight/javadocIG/syntheticEnumValues.html index 9d63edfa68eb..bab3a49a624e 100644 --- a/java/java-tests/testData/codeInsight/javadocIG/syntheticEnumValues.html +++ b/java/java-tests/testData/codeInsight/javadocIG/syntheticEnumValues.html @@ -4,8 +4,8 @@ type, in the order they're declared. This method may be used to iterate over the constants as follows:
-     for(E c : E.values())
-         System.out.println(c);
+     for(E c : E.values())
+         System.out.println(c);
   

Returns:

an array containing the constants of this enum type, in the order they're declared

\ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/JavaDocumentationTest.kt b/java/java-tests/testSrc/com/intellij/java/codeInsight/JavaDocumentationTest.kt index 09d548394b9a..62920f7bb498 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/JavaDocumentationTest.kt +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/JavaDocumentationTest.kt @@ -289,7 +289,7 @@ class JavaDocumentationTest : LightJavaCodeInsightFixtureTestCase() { val actual = JavaExternalDocumentationTest.getDocumentationText(myFixture.project, input) - val expected = "
Candidates for method call s.regionMatches() are:
" + + val expected = "
Candidates for method call s.regionMatches() are:
" + "
" + "  boolean regionMatches(int, String, int, int)
" + "  boolean regionMatches(boolean, int, String, int, int)
" + @@ -309,7 +309,7 @@ class JavaDocumentationTest : LightJavaCodeInsightFixtureTestCase() { val documentationManager = DocumentationManager.getInstance(myFixture.project) JavaExternalDocumentationTest.getDocumentationText(myFixture.project, input) { component -> - val expected = "
Candidates for method call s.regionMatches() are:
" + + val expected = "
Candidates for method call s.regionMatches() are:
" + "
" + "  boolean regionMatches(int, String, int, int)
" + "  boolean regionMatches(boolean, int, String, int, int)
" + diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationEditorPane.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationEditorPane.java index 52c8b1b0c4df..7ee7d364de0c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationEditorPane.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationEditorPane.java @@ -81,10 +81,11 @@ public abstract class DocumentationEditorPane extends JEditorPane implements Dis } setBackground(BACKGROUND_COLOR); HTMLEditorKit editorKit = new HTMLEditorKitBuilder() - .replaceViewFactoryExtensions(DocumentationHtmlUtil.getIconsExtension(iconResolver), + .replaceViewFactoryExtensions(getIconsExtension(iconResolver), Extensions.BASE64_IMAGES, Extensions.INLINE_VIEW_EX, - Extensions.FIT_TO_WIDTH_IMAGES) + Extensions.FIT_TO_WIDTH_IMAGES, + Extensions.WBR_SUPPORT) .withFontResolver(EditorCssFontResolver.getGlobalInstance()).build(); updateDocumentationPaneDefaultCssRules(editorKit); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationHtmlUtil.kt b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationHtmlUtil.kt index 12c6356be314..d51b1c23a833 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationHtmlUtil.kt +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationHtmlUtil.kt @@ -16,6 +16,7 @@ import com.intellij.util.ui.JBUI import com.intellij.util.ui.UIUtil import org.intellij.lang.annotations.Language import org.jetbrains.annotations.ApiStatus +import org.jetbrains.annotations.Contract import java.awt.Color import java.util.function.Function import javax.swing.Icon @@ -79,6 +80,7 @@ object DocumentationHtmlUtil { val contentSpacing = scale(contentSpacing) val contentInnerPadding = scale(contentInnerPadding) + @Suppress("CssUnusedSymbol") @Language("CSS") val result = ContainerUtil.newLinkedList( """ @@ -116,4 +118,115 @@ object DocumentationHtmlUtil { result.addAll(getDefaultFormattingStyles(contentSpacing)) return result } + + @JvmStatic + @Contract(pure = true) + fun addWordBreaks(text: String): String { + val codePoints = text.codePoints().iterator() + if (!codePoints.hasNext()) return "" + val result = StringBuilder(text.length + 50) + var codePoint = codePoints.nextInt() + val tagName = StringBuilder() + + fun next(builder: StringBuilder = result) { + builder.appendCodePoint(codePoint) + codePoint = if (codePoints.hasNext()) + codePoints.nextInt() + else + -1 + } + + while (codePoint >= 0) { + // break after dot if surrounded by letters + when { + Character.isLetter(codePoint) -> { + next() + if (codePoint == '.'.code) { + next() + if (Character.isLetter(codePoint)) { + result.append("") + } + } + } + // break after ], ) or / followed by a char or digit + codePoint == ')'.code || codePoint == ']'.code || codePoint == '/'.code -> { + next() + if (Character.isLetterOrDigit(codePoint)) { + result.append("") + } + } + // skip tag + codePoint == '<'.code -> { + next() + if (codePoint == '/'.code) + next() + if (!Character.isLetter(codePoint)) + continue + tagName.clear() + while (Character.isLetterOrDigit(codePoint) || codePoint == '-'.code) { + next(tagName) + } + result.append(tagName) + if (tagName.contentEquals("style", true) + || tagName.contentEquals("title", true) + || tagName.contentEquals("script", true)) { + val curTag = tagName.toString() + do { + if (codePoint == '<'.code) { + next() + if (codePoint == '/'.code) { + next() + tagName.clear() + while (Character.isLetterOrDigit(codePoint) || codePoint == '-'.code) { + next(tagName) + } + result.append(tagName) + if (tagName.contentEquals(curTag, true)) { + while (codePoint >= 0 && codePoint != '>'.code) { + next() + } + break + } + } + } + else next() + } + while (true) + } + else { + while (codePoint >= 0) { + when (codePoint) { + '>'.code -> { + next() + break + } + '\''.code, '"'.code -> { + val quoteStyle = codePoint + next() + while (codePoint >= 0) { + when (codePoint) { + '\\'.code -> { + next() + if (codePoint >= 0) + next() + } + quoteStyle -> { + next() + break + } + else -> next() + } + } + } + else -> next() + } + } + } + } + else -> next() + } + } + + return result.toString() + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java index 3c69c3176825..b2343e2b40d0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -112,6 +112,7 @@ import static com.intellij.lang.documentation.DocumentationMarkup.*; * * @deprecated Unused in v2 implementation. Unsupported: use at own risk. */ +@SuppressWarnings("removal") @Deprecated(forRemoval = true) public class DocumentationManager extends DockablePopupManager { public static final String JAVADOC_LOCATION_AND_SIZE = "javadoc.popup"; @@ -1942,6 +1943,7 @@ public class DocumentationManager extends DockablePopupManager" + text.substring(nextChar); } } @@ -1970,6 +1972,7 @@ public class DocumentationManager extends DockablePopupManager\\s*(<(?:[uo]l|h\\d|p|tr|td))", "$1"); text = addExternalLinksIcon(text); + text = DocumentationHtmlUtil.addWordBreaks(text); return text; } diff --git a/platform/lang-impl/src/com/intellij/lang/documentation/QuickDocHighlightingHelper.kt b/platform/lang-impl/src/com/intellij/lang/documentation/QuickDocHighlightingHelper.kt index e2e41e5a0b32..eab2bb93724e 100644 --- a/platform/lang-impl/src/com/intellij/lang/documentation/QuickDocHighlightingHelper.kt +++ b/platform/lang-impl/src/com/intellij/lang/documentation/QuickDocHighlightingHelper.kt @@ -289,7 +289,6 @@ object QuickDocHighlightingHelper { "li { padding: ${scale(1)}px 0 ${scale(2)}px 0; }", "li p { padding-top: 0; padding-bottom: 0; }", "th { text-align: left; }", - "table { width: 100%}", "tr, table { margin: 0 0 0 0; padding: 0 0 0 0; }", "td { margin: 0 0 0 0; padding: 0 0 ${spacing}px 0; }", "td p { padding-top: 0; padding-bottom: 0; }", diff --git a/platform/platform-impl/src/com/intellij/ide/ui/html/StyleSheetRulesProviderForCodeHighlighting.kt b/platform/platform-impl/src/com/intellij/ide/ui/html/StyleSheetRulesProviderForCodeHighlighting.kt index 0cace6532832..ad76f2563bbc 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/html/StyleSheetRulesProviderForCodeHighlighting.kt +++ b/platform/platform-impl/src/com/intellij/ide/ui/html/StyleSheetRulesProviderForCodeHighlighting.kt @@ -79,6 +79,8 @@ object StyleSheetRulesProviderForCodeHighlighting { if (enableInlineCodeBackground) { val selectors = inlineCodeParentSelectors.asSequence().map { "$it code" }.joinToString(", ") result.add("$selectors $codeColorStyle") + // 'caption-side' is a hack to support 'border-radius'. + // See also: com.intellij.util.ui.html.InlineViewEx result.add("$selectors { padding: 1px 4px; margin: 1px 0px; caption-side: 10px; }") } if (enableCodeBlocksBackground) { diff --git a/platform/util/ui/src/com/intellij/util/ui/ExtendableHTMLViewFactory.kt b/platform/util/ui/src/com/intellij/util/ui/ExtendableHTMLViewFactory.kt index 0bbae2e0d913..1d152535ebca 100644 --- a/platform/util/ui/src/com/intellij/util/ui/ExtendableHTMLViewFactory.kt +++ b/platform/util/ui/src/com/intellij/util/ui/ExtendableHTMLViewFactory.kt @@ -6,9 +6,10 @@ import com.intellij.openapi.util.IconLoader import com.intellij.openapi.util.text.HtmlChunk import com.intellij.ui.scale.JBUIScale import com.intellij.util.text.nullize +import com.intellij.util.ui.html.FitToWidthImageView import com.intellij.util.ui.html.HiDpiScalingImageView import com.intellij.util.ui.html.InlineViewEx -import com.intellij.util.ui.html.FitToWidthImageView +import com.intellij.util.ui.html.WbrView import java.awt.* import java.awt.image.BufferedImage import java.io.ByteArrayInputStream @@ -48,7 +49,7 @@ class ExtendableHTMLViewFactory internal constructor( companion object { @JvmField val DEFAULT_EXTENSIONS: List = listOf(Extensions.ICONS, Extensions.BASE64_IMAGES, Extensions.HIDPI_IMAGES, - Extensions.INLINE_VIEW_EX) + Extensions.INLINE_VIEW_EX, Extensions.WBR_SUPPORT) @JvmField val DEFAULT: ExtendableHTMLViewFactory = ExtendableHTMLViewFactory(DEFAULT_EXTENSIONS) @@ -134,6 +135,12 @@ class ExtendableHTMLViewFactory internal constructor( @JvmField val FIT_TO_WIDTH_IMAGES: Extension = FitToWidthImageViewExtension() + /** + * Adds support for `` tags + */ + @JvmField + val WBR_SUPPORT: Extension = WbrSupportExtension() + private class IconsExtension(private val existingIconsProvider: (key: String) -> Icon?) : Extension { constructor(preloadedIcons: Map) : this(preloadedIconsProvider(preloadedIcons)) @@ -361,7 +368,7 @@ class ExtendableHTMLViewFactory internal constructor( } } - private class InlineViewExExtension: Extension { + private class InlineViewExExtension : Extension { override fun invoke(element: Element, view: View): View? { if (view.javaClass != InlineView::class.java) return null val attrs = view.attributes @@ -381,10 +388,18 @@ class ExtendableHTMLViewFactory internal constructor( } } - private class FitToWidthImageViewExtension: Extension { + private class FitToWidthImageViewExtension : Extension { override fun invoke(element: Element, view: View): View? = if (view is ImageView) FitToWidthImageView(element) else null } + + private class WbrSupportExtension : Extension { + override fun invoke(elem: Element, defaultView: View): View? = + if (elem.name.equals("wbr", true)) + WbrView(elem) + else + null + } } private class HiDpiImagesExtension : ExtendableHTMLViewFactory.Extension { diff --git a/platform/util/ui/src/com/intellij/util/ui/html/InlineViewEx.kt b/platform/util/ui/src/com/intellij/util/ui/html/InlineViewEx.kt index 704a69203cdc..c28b12b8fa1d 100644 --- a/platform/util/ui/src/com/intellij/util/ui/html/InlineViewEx.kt +++ b/platform/util/ui/src/com/intellij/util/ui/html/InlineViewEx.kt @@ -46,20 +46,6 @@ internal class InlineViewEx(elem: Element) : InlineView(elem) { override fun setPropertiesFromAttributes() { super.setPropertiesFromAttributes() - val parentView = parent - val index = (0..parentView.viewCount).firstOrNull { parentView.getView(it) === this } ?: -1 - - - // Heuristics to determine whether we are within the same inline (e.g. ) element with paddings. - // Nested inline element insets are not supported, because hierarchy of inline elements is not preserved. - val prevSibling = if (index > 0) parentView.getView(index - 1) else null - val nextSibling = if (index < parentView.viewCount - 1) parentView.getView(index + 1) else null - - padding = this.cssPadding - margin = this.cssMargin - - startView = prevSibling?.cssPadding != padding || prevSibling.cssMargin != margin - endView = nextSibling?.cssPadding != padding || nextSibling.cssMargin != margin // "caption-side" is used as "border-radius" borderRadius = attributes.getAttribute(CAPTION_SIDE) @@ -69,27 +55,7 @@ internal class InlineViewEx(elem: Element) : InlineView(elem) { ?.toIntOrNull() ?.let { JBUI.scale(it) } ?: 0 - - padding.set( - padding.top, - if (startView) padding.left else 0, - padding.bottom, - if (endView) padding.right else 0, - ) - - margin.set( - margin.top, - if (startView) margin.left else 0, - margin.bottom, - if (endView) margin.right else 0, - ) - - insets = JBInsets( - padding.top + margin.top, - padding.left + margin.left, - padding.bottom + margin.bottom, - padding.right + margin.right, - ) + updatePaddingsAndMargins(true) } override fun getPartialSpan(p0: Int, p1: Int): Float { @@ -103,12 +69,14 @@ internal class InlineViewEx(elem: Element) : InlineView(elem) { return offset + super.getPartialSpan(p0, p1) } - override fun getPreferredSpan(axis: Int): Float = - super.getPreferredSpan(axis) + when (axis) { + override fun getPreferredSpan(axis: Int): Float { + updatePaddingsAndMargins(false) + return super.getPreferredSpan(axis) + when (axis) { View.X_AXIS -> insets.width() View.Y_AXIS -> insets.height() else -> throw IllegalArgumentException("Invalid axis: $axis") } + } override fun getTabbedSpan(x: Float, e: TabExpander?): Float = super.getTabbedSpan(x, e) + insets.width() @@ -173,4 +141,59 @@ internal class InlineViewEx(elem: Element) : InlineView(elem) { return super.getAlignment(axis) } + private fun getSibling(parentView: View, curIndex: Int, direction: Int): View? { + var siblingIndex = curIndex + direction + val viewCount = parentView.viewCount + while (siblingIndex in 0..) element with paddings. + // Nested inline element insets are not supported, because hierarchy of inline elements is not preserved. + val prevSibling = getSibling(parentView, index, -1) + val nextSibling = getSibling(parentView, index, 1) + + val cssPadding = this.cssPadding + val cssMargin = this.cssMargin + + val startView = prevSibling?.cssPadding != cssPadding || prevSibling.cssMargin != cssMargin + val endView = nextSibling?.cssPadding != cssPadding || nextSibling.cssMargin != cssMargin + + if (!force && startView == this.startView && endView == this.endView) { + return + } + this.startView = startView + this.endView = endView + + padding = JBInsets( + cssPadding.top, + if (startView) cssPadding.left else 0, + cssPadding.bottom, + if (endView) cssPadding.right else 0, + ) + + margin = JBInsets( + cssMargin.top, + if (startView) cssMargin.left else 0, + cssMargin.bottom, + if (endView) cssMargin.right else 0, + ) + + insets = JBInsets( + padding.top + margin.top, + padding.left + margin.left, + padding.bottom + margin.bottom, + padding.right + margin.right, + ) + } + } \ No newline at end of file diff --git a/platform/util/ui/src/com/intellij/util/ui/html/WbrView.kt b/platform/util/ui/src/com/intellij/util/ui/html/WbrView.kt new file mode 100644 index 000000000000..932579c24d1c --- /dev/null +++ b/platform/util/ui/src/com/intellij/util/ui/html/WbrView.kt @@ -0,0 +1,38 @@ +// 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.util.ui.html + +import java.awt.Shape +import javax.swing.text.Element +import javax.swing.text.Position +import javax.swing.text.Segment +import javax.swing.text.View +import javax.swing.text.html.InlineView + +class WbrView(elem: Element) : InlineView(elem) { + + override fun getMinimumSpan(axis: Int): Float = 0f + + override fun getMaximumSpan(axis: Int): Float = + if (axis == View.X_AXIS) + 0f + else + Int.MAX_VALUE.toFloat() + + override fun getViewIndex(pos: Int, b: Position.Bias?): Int = -1 + + override fun getViewIndex(x: Float, y: Float, allocation: Shape?): Int = -1 + + override fun getResizeWeight(axis: Int): Int = 0 + + override fun setSize(width: Float, height: Float) { + super.setSize(0f, 0f) + } + + override fun getPreferredSpan(axis: Int): Float = 0f + + override fun getText(p0: Int, p1: Int): Segment = Segment() + + override fun breakView(axis: Int, offset: Int, pos: Float, len: Float): View = this + + override fun getBreakWeight(axis: Int, pos: Float, len: Float): Int = ExcellentBreakWeight +} \ No newline at end of file