diff --git a/src/main/java/com/couchbase/intellij/tree/iq/ui/HtmlPanel.java b/src/main/java/com/couchbase/intellij/tree/iq/ui/HtmlPanel.java new file mode 100644 index 00000000..d93c392d --- /dev/null +++ b/src/main/java/com/couchbase/intellij/tree/iq/ui/HtmlPanel.java @@ -0,0 +1,111 @@ +// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.couchbase.intellij.tree.iq.ui; + +import com.intellij.openapi.util.NlsSafe; +import com.intellij.openapi.util.text.HtmlBuilder; +import com.intellij.openapi.util.text.HtmlChunk; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vcs.ui.FontUtil; +import com.intellij.ui.BrowserHyperlinkListener; +import com.intellij.ui.ColorUtil; +import com.intellij.util.ui.HTMLEditorKitBuilder; +import com.intellij.util.ui.JBUI; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultCaret; +import javax.swing.text.Document; +import javax.swing.text.Position; +import javax.swing.text.html.HTMLDocument; +import javax.swing.text.html.StyleSheet; +import java.awt.*; +import java.io.IOException; +import java.io.StringWriter; + +public abstract class HtmlPanel extends JEditorPane implements HyperlinkListener { + public HtmlPanel() { + super(UIUtil.HTML_MIME, ""); + setEditable(false); + setOpaque(false); + putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE); + addHyperlinkListener(this); + setEditorKit(new HTMLEditorKitBuilder().withWordWrapViewFactory().build()); + } + + @Override + public void hyperlinkUpdate(HyperlinkEvent e) { + BrowserHyperlinkListener.INSTANCE.hyperlinkUpdate(e); + } + + @Override + public String getSelectedText() { + Document doc = getDocument(); + int start = getSelectionStart(); + int end = getSelectionEnd(); + + try { + Position p0 = doc.createPosition(start); + Position p1 = doc.createPosition(end); + StringWriter sw = new StringWriter(p1.getOffset() - p0.getOffset()); + getEditorKit().write(sw, doc, p0.getOffset(), p1.getOffset() - p0.getOffset()); + + return StringUtil.removeHtmlTags(sw.toString()); + } + catch (BadLocationException | IOException ignored) { + } + return super.getSelectedText(); + } + + public void setBody(@NotNull @Nls String text) { + if (text.isEmpty()) { + setText(""); + } + else { + @NlsSafe String cssFontDeclaration = UIUtil.getCssFontDeclaration(getBodyFont()); + setText(new HtmlBuilder() + .append(HtmlChunk.raw(cssFontDeclaration).wrapWith("head")) + .append(HtmlChunk.raw(text).wrapWith(HtmlChunk.body())) + .wrapWith(HtmlChunk.html()).toString()); + } + } + + @NotNull + protected Font getBodyFont() { + return FontUtil.getCommitMessageFont(); + } + + @NotNull + @Nls + protected abstract String getBody(); + + @Override + public void updateUI() { + super.updateUI(); + + DefaultCaret caret = (DefaultCaret)getCaret(); + caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE); + + update(); + } + + public void update() { + setBody(getBody()); + customizeLinksStyle(); + revalidate(); + repaint(); + } + + private void customizeLinksStyle() { + Document document = getDocument(); + if (document instanceof HTMLDocument) { + StyleSheet styleSheet = ((HTMLDocument)document).getStyleSheet(); + String linkColor = "#" + ColorUtil.toHex(JBUI.CurrentTheme.Link.Foreground.ENABLED); // NON-NLS + styleSheet.addRule("a { color: " + linkColor + "; text-decoration: none;}"); // NON-NLS + } + } +} diff --git a/src/main/java/com/couchbase/intellij/tree/iq/ui/MessagePanel.java b/src/main/java/com/couchbase/intellij/tree/iq/ui/MessagePanel.java index 18c63ee1..0fbbbd4e 100644 --- a/src/main/java/com/couchbase/intellij/tree/iq/ui/MessagePanel.java +++ b/src/main/java/com/couchbase/intellij/tree/iq/ui/MessagePanel.java @@ -1,18 +1,24 @@ package com.couchbase.intellij.tree.iq.ui; import com.couchbase.intellij.tree.iq.text.TextFragment; -import com.couchbase.intellij.tree.iq.ui.view.*; +import com.couchbase.intellij.tree.iq.ui.view.CollapsiblePanelFactory; +import com.couchbase.intellij.tree.iq.ui.view.HyperlinkHandler; +import com.couchbase.intellij.tree.iq.ui.view.LanguageDetector; +import com.couchbase.intellij.tree.iq.ui.view.RSyntaxTextAreaView; import com.couchbase.intellij.tree.iq.util.StandardLanguage; import com.intellij.openapi.project.Project; -import com.intellij.util.ui.*; +import com.intellij.util.ui.ExtendableHTMLViewFactory; +import com.intellij.util.ui.HTMLEditorKitBuilder; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import javax.swing.event.HyperlinkEvent; -import javax.swing.text.*; +import javax.swing.text.AttributeSet; +import javax.swing.text.Element; +import javax.swing.text.StyleConstants; +import javax.swing.text.View; import javax.swing.text.html.HTML; -import javax.swing.text.html.HTMLDocument; -import javax.swing.text.html.StyleSheet; import java.awt.*; public class MessagePanel extends HtmlPanel implements MessageRenderer {