IDEA-229503 Display javadoc rendered representation in editor

speed up JEditorPane creation - don't parse CSS rules every time

GitOrigin-RevId: c9a761850eaef49aca627c10049bcb7846280053
This commit is contained in:
Dmitry Batrak
2020-02-20 10:08:26 +03:00
committed by intellij-monorepo-bot
parent 4b81e47a35
commit 3dcd77f14f
3 changed files with 67 additions and 26 deletions

View File

@@ -4,6 +4,7 @@ package com.intellij.codeInsight.documentation.render;
import com.intellij.codeInsight.documentation.DocumentationComponent;
import com.intellij.codeInsight.documentation.DocumentationManager;
import com.intellij.codeInsight.documentation.QuickDocUtil;
import com.intellij.ide.ui.LafManager;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.ActionGroup;
@@ -32,6 +33,7 @@ import com.intellij.util.text.CharArrayUtil;
import com.intellij.util.ui.GraphicsUtil;
import com.intellij.util.ui.JBHtmlEditorKit;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.StartupUiUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -40,6 +42,7 @@ import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.View;
import javax.swing.text.html.ImageView;
import javax.swing.text.html.StyleSheet;
import java.awt.*;
import java.awt.font.TextAttribute;
import java.awt.image.ImageObserver;
@@ -57,6 +60,10 @@ class DocRenderer implements EditorCustomElementRenderer {
private static final int RIGHT_INSET = 20;
private static final int TOP_BOTTOM_INSETS = 8;
private static StyleSheet ourCachedStyleSheet;
private static String ourCachedStyleSheetLaf = "non-existing";
private static String ourCachedStyleSheetFont = "non-existing";
private final DocRenderItem myItem;
private boolean myRepaintRequested;
JEditorPane myPane;
@@ -275,24 +282,37 @@ class DocRenderer implements EditorCustomElementRenderer {
private static JBHtmlEditorKit createEditorKit() {
JBHtmlEditorKit editorKit = new JBHtmlEditorKit(true);
String editorFontName = StringUtil.escapeQuotes(EditorColorsManager.getInstance().getGlobalScheme().getEditorFontName());
editorKit.getStyleSheet().addRule("code {font-family:\"" + editorFontName + "\"}");
editorKit.getStyleSheet().addRule("pre {font-family:\"" + editorFontName + "\"}");
editorKit.getStyleSheet().addRule("h1, h2, h3, h4, h5, h6 { margin-top: 0; padding-top: 1px; }");
editorKit.getStyleSheet().addRule("a { color: #" + ColorUtil.toHex(JBUI.CurrentTheme.Link.linkColor()) + "; text-decoration: none;}");
editorKit.getStyleSheet().addRule("p { padding: 1px 0 2px 0; }");
editorKit.getStyleSheet().addRule("ol { padding: 0 16px 0 0; }");
editorKit.getStyleSheet().addRule("ul { padding: 0 16px 0 0; }");
editorKit.getStyleSheet().addRule("li { padding: 1px 0 2px 0; }");
editorKit.getStyleSheet().addRule("table p { padding-bottom: 0}");
editorKit.getStyleSheet().addRule("td { margin: 4px 0 0 0; padding: 0; }");
editorKit.getStyleSheet().addRule("th { text-align: left; }");
editorKit.getStyleSheet().addRule(".grayed { color: #909090; display: inline;}");
editorKit.getStyleSheet().addRule(".section { color: " + ColorUtil.toHtmlColor(DocumentationComponent.SECTION_COLOR) +
"; padding-right: 4px}");
editorKit.getStyleSheet().addStyleSheet(getStyleSheet());
return editorKit;
}
private static StyleSheet getStyleSheet() {
UIManager.LookAndFeelInfo lookAndFeel = LafManager.getInstance().getCurrentLookAndFeel();
String lafName = lookAndFeel == null ? null : lookAndFeel.getName();
String editorFontName = EditorColorsManager.getInstance().getGlobalScheme().getEditorFontName();
if (!Objects.equals(lafName, ourCachedStyleSheetLaf) || !Objects.equals(editorFontName, ourCachedStyleSheetFont)) {
String escapedFontName = StringUtil.escapeQuotes(editorFontName);
ourCachedStyleSheet = StartupUiUtil.createStyleSheet(
"code {font-family:\"" + escapedFontName + "\"}" +
"pre {font-family:\"" + escapedFontName + "\"}" +
"h1, h2, h3, h4, h5, h6 { margin-top: 0; padding-top: 1px; }" +
"a { color: #" + ColorUtil.toHex(JBUI.CurrentTheme.Link.linkColor()) + "; text-decoration: none;}" +
"p { padding: 1px 0 2px 0; }" +
"ol { padding: 0 16px 0 0; }" +
"ul { padding: 0 16px 0 0; }" +
"li { padding: 1px 0 2px 0; }" +
"table p { padding-bottom: 0}" +
"td { margin: 4px 0 0 0; padding: 0; }" +
"th { text-align: left; }" +
".grayed { color: #909090; display: inline;}" +
".section { color: #" + ColorUtil.toHex(DocumentationComponent.SECTION_COLOR) + "; padding-right: 4px}"
);
ourCachedStyleSheetLaf = lafName;
ourCachedStyleSheetFont = editorFontName;
}
return ourCachedStyleSheet;
}
private static Color getColorFromRegistry(String key) {
String[] values = Registry.stringValue(key).split(",");
try {

View File

@@ -26,8 +26,23 @@ public class JBHtmlEditorKit extends HTMLEditorKit {
private static final Logger LOG = Logger.getInstance(JBHtmlEditorKit.class);
static {
StartupUiUtil.configureHtmlKitStylesheet();
ourCommonStyle = StartupUiUtil.createStyleSheet(
"code { font-size: 100%; }" + // small by Swing's default
"small { font-size: small; }" + // x-small by Swing's default
"a { text-decoration: none;}" +
// override too large default margin "ul {margin-left-ltr: 50; margin-right-rtl: 50}" from javax/swing/text/html/default.css
"ul { margin-left-ltr: 10; margin-right-rtl: 10; }" +
// override too large default margin "ol {margin-left-ltr: 50; margin-right-rtl: 50}" from javax/swing/text/html/default.css
// Select ol margin to have the same indentation as "ul li" and "ol li" elements (seems value 22 suites well)
"ol { margin-left-ltr: 22; margin-right-rtl: 22; }"
);
ourNoGapsBetweenParagraphsStyle = StartupUiUtil.createStyleSheet(
"p { margin-top: 0; }"
);
}
private static final ViewFactory ourViewFactory = new JBHtmlFactory();
private static final StyleSheet ourCommonStyle;
private static final StyleSheet ourNoGapsBetweenParagraphsStyle;
@Override
public Cursor getDefaultCursor() {
@@ -53,7 +68,7 @@ public class JBHtmlEditorKit extends HTMLEditorKit {
public JBHtmlEditorKit(boolean noGapsBetweenParagraphs, boolean disableLinkedCss) {
myDisableLinkedCss = disableLinkedCss;
style = createStyleSheet();
if (noGapsBetweenParagraphs) style.addRule("p { margin-top: 0; }");
if (noGapsBetweenParagraphs) style.addStyleSheet(ourNoGapsBetweenParagraphsStyle);
myHyperlinkListener = new HyperlinkListener() {
@Override
public void hyperlinkUpdate(HyperlinkEvent e) {
@@ -103,16 +118,9 @@ public class JBHtmlEditorKit extends HTMLEditorKit {
public static StyleSheet createStyleSheet() {
StyleSheet style = new StyleSheet();
style.addStyleSheet(StartupUiUtil.isUnderDarcula() ? (StyleSheet)UIManager.getDefaults().get("StyledEditorKit.JBDefaultStyle") : StartupUiUtil.getDefaultHtmlKitCss());
style.addRule("code { font-size: 100%; }"); // small by Swing's default
style.addRule("small { font-size: small; }"); // x-small by Swing's default
style.addRule("a { text-decoration: none;}");
// override too large default margin "ul {margin-left-ltr: 50; margin-right-rtl: 50}" from javax/swing/text/html/default.css
style.addRule("ul { margin-left-ltr: 10; margin-right-rtl: 10; }");
// override too large default margin "ol {margin-left-ltr: 50; margin-right-rtl: 50}" from javax/swing/text/html/default.css
// Select ol margin to have the same indentation as "ul li" and "ol li" elements (seems value 22 suites well)
style.addRule("ol { margin-left-ltr: 22; margin-right-rtl: 22; }");
style.addStyleSheet(StartupUiUtil.isUnderDarcula() ? (StyleSheet)UIManager.getDefaults().get("StyledEditorKit.JBDefaultStyle")
: StartupUiUtil.getDefaultHtmlKitCss());
style.addStyleSheet(ourCommonStyle);
return style;
}

View File

@@ -24,6 +24,8 @@ import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ImageObserver;
import java.io.IOException;
import java.io.StringReader;
import java.util.Locale;
import java.util.Map;
@@ -93,6 +95,17 @@ public final class StartupUiUtil {
activity.end();
}
public static @NotNull StyleSheet createStyleSheet(@NotNull String css) {
StyleSheet styleSheet = new StyleSheet();
try {
styleSheet.loadRules(new StringReader(css), null);
}
catch (IOException e) {
throw new RuntimeException(e); // shouldn't happen
}
return styleSheet;
}
public static boolean isUnderDarcula() {
return UIManager.getLookAndFeel().getName().contains("Darcula");
}