Reputation: 968
I am using a JTextPane
to render some HTML. I am using a HTMLEditorKit
and a StyleSheet
to add rules to the code
property so it looks exactly like the code on StackOverflow. The problem is that the JTextPane
doesn't render the padding on the code (1 pixel top/bottom, 5 pixels left/right), even though the padding
property is listed as one of the properties that is supported by the rendering engine in the documentation.
Here is what I expect to see (As shown by this CSSDeck Lab):
←
↑-↑ ↑-↑
EDIT:
I have switched from using the <code>
tags in my HTML and have switched to <span>
by the suggestion of @Sharcoux. This made the font size of the used-to-be-code the same as the text in the <pre>
tags, making the red background have the same height as the green border, however, the expected result still isn't produced. Here is the original image if you are interested.
This is what actually appears:
I have also tried moving the CSS inline with the text, but to no avail.
MCVE (Also Edited):
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
public class CodePaddingMCVE {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new JFrame("Code Padding Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextPane tp = new JTextPane();
tp.setContentType("text/html");
HTMLEditorKit kit = new HTMLEditorKit();
tp.setEditorKit(kit);
StyleSheet sheet = kit.getStyleSheet();
sheet.addRule("span {padding: 1px 5px; background-color: red}"); //Using span here
sheet.addRule("pre {padding: 0px; background-color: green}");
tp.setDocument(kit.createDefaultDocument());
tp.setText("<html><pre>NotCode<span>Code</span>NotCode</pre></html>"); //Using <span> here too
JScrollPane sp = new JScrollPane(tp) {
private static final long serialVersionUID = 1L;
@Override
public Dimension getPreferredSize() {
return new Dimension(250, 50);
}
};
frame.getContentPane().add(sp);
frame.pack();
frame.setVisible(true);
});
}
}
I am using OS X Yosemite 10.10.15, Eclipse Mars.2 4.5.2, and Java 8 [1.8.0_66].
Upvotes: 1
Views: 637
Reputation: 6085
You're right, the margin and padding seem to not be applied to inline elements. You have 3 options.
1) give up JTextPane and use JavaFX WebView instead.
2) give up HTMLDocument and use another implementation.
3) try to extend HTMLFactory in HTMLEditorKit, and extend InlineView. It would give you something of that sort:
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.Element;
import javax.swing.text.StyleConstants;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.InlineView;
import javax.swing.text.html.StyleSheet;
public class CodePaddingMCVE {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Code Padding Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextPane tp = new JTextPane();
tp.setContentType("text/html");
HTMLEditorKit kit = new HTMLEditorKit() {
public ViewFactory getViewFactory() {
return new HTMLFactory() {
public View create(Element elem) {
AttributeSet attrs = elem.getAttributes();
Object elementName =
attrs.getAttribute(AbstractDocument.ElementNameAttribute);
Object o = (elementName != null) ?
null : attrs.getAttribute(StyleConstants.NameAttribute);
if (o instanceof HTML.Tag) {
HTML.Tag kind = (HTML.Tag) o;
if (kind == HTML.Tag.CONTENT) {
return new InlineView(elem) {
private short left;
private short right;
private short top;
private short bottom;
protected void setPropertiesFromAttributes() {
AttributeSet attr = getAttributes();
if (attr != null) {
top = (short) StyleConstants.getSpaceAbove(attr);
left = (short) StyleConstants.getLeftIndent(attr);
bottom = (short) StyleConstants.getSpaceBelow(attr);
right = (short) StyleConstants.getRightIndent(attr);
}
super.setPropertiesFromAttributes();
}
//TODO : use the top, left, bottom and right properties to draw the margin/padding
};
}
}
return super.create(elem);
}
};
}
};
tp.setEditorKit(kit);
StyleSheet sheet = kit.getStyleSheet();
sheet.addRule("span {padding: 5px 5px 5px 5px; background-color: red}"); //Using span here
sheet.addRule("pre {padding: 0px; background-color: green}");
tp.setDocument(kit.createDefaultDocument());
tp.setText("<html><pre>NotCode<span>Code</span>NotCode</pre></html>"); //Using <span> here too
JScrollPane sp = new JScrollPane(tp) {
private static final long serialVersionUID = 1L;
@Override
public Dimension getPreferredSize() {
return new Dimension(250, 50);
}
};
frame.getContentPane().add(sp);
frame.pack();
frame.setVisible(true);
}
});
}
}
If you wish to pursue this path, you will need to dig inside the LabelView and GlyphView to see how you can implement a padding or a margin. Maybe others could help finish this.
Good luck.
Upvotes: 1