HTMLEditorKit and Custom tags in the JEditorPane

后端 未结 2 1319
广开言路
广开言路 2021-01-27 09:33

I use the instructions to add my own tag http://java-sl.com/custom_tag_html_kit.html

class MyParserDelegator extends ParserDelegator {
public MyParserDelegator()         


        
相关标签:
2条回答
  • 2021-01-27 09:50

    I looked at the sources of JDK 7: the DTD is no more store in an attribute dtd of javax.swing.text.html.parser.ParserDelegator but in sun.awt.AppContext. Coming from a sun package, AppContext should not be accessed by classes out of the JRE himself. So using the sources of javax.swing.text.html.parser.ParserDelegator, I wrote MyParserDelegator that load the DTD himself. After that, the custom tag can be added in DTD easily.

    The code below also contains the other classes from http://java-sl.com/custom_tag_html_kit.html to get a working example.

    import java.awt.Component;
    import java.io.BufferedInputStream;
    import java.io.DataInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.Reader;
    import java.net.URL;
    
    import javax.swing.JButton;
    import javax.swing.JEditorPane;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.text.BadLocationException;
    import javax.swing.text.ComponentView;
    import javax.swing.text.Document;
    import javax.swing.text.Element;
    import javax.swing.text.MutableAttributeSet;
    import javax.swing.text.View;
    import javax.swing.text.ViewFactory;
    import javax.swing.text.html.HTML;
    import javax.swing.text.html.HTMLDocument;
    import javax.swing.text.html.HTMLEditorKit;
    import javax.swing.text.html.HTMLEditorKit.Parser;
    import javax.swing.text.html.HTMLEditorKit.ParserCallback;
    import javax.swing.text.html.StyleSheet;
    import javax.swing.text.html.parser.DTD;
    import javax.swing.text.html.parser.DocumentParser;
    import javax.swing.text.html.parser.ParserDelegator;
    
    public class CustomTag {
        public static String htmlText = "<html>\n" + "<body>\n" + "<p>\n" + "Text before button\n" + "<button>Text for &lt;button&gt; tag</button>\n"
                + "Text after button\n" + "</p>\n" + "</body>\n" + "</html>";
        JEditorPane edit = new JEditorPane();
    
        public CustomTag() {
            JFrame frame = new JFrame("Custom tag in HTMLEditorKit");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(new JScrollPane(edit));
    
            edit.setEditorKit(new MyHTMLEditorKit());
            edit.setText(htmlText);
    
            frame.setSize(300, 300);
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) throws Exception {
            new CustomTag();
        }
    
    }
    
    class MyHTMLEditorKit extends HTMLEditorKit {
    
        public MyHTMLEditorKit() {
            super();
        }
    
        @Override
        public Document createDefaultDocument() {
            StyleSheet styles = getStyleSheet();
            StyleSheet ss = new StyleSheet();
    
            ss.addStyleSheet(styles);
    
            MyHTMLDocument doc = new MyHTMLDocument(ss);
            doc.setParser(getParser());
            doc.setAsynchronousLoadPriority(4);
            doc.setTokenThreshold(100);
            return doc;
        }
    
        @Override
        public ViewFactory getViewFactory() {
            return new MyHTMLFactory();
        }
    
        Parser defaultParser;
    
        @Override
        protected Parser getParser() {
            if (defaultParser == null) {
                defaultParser = new MyParserDelegator();
            }
            return defaultParser;
        }
    
        class MyHTMLFactory extends HTMLFactory implements ViewFactory {
            public MyHTMLFactory() {
                super();
            }
    
            @Override
            public View create(Element element) {
                HTML.Tag kind = (HTML.Tag) (element.getAttributes().getAttribute(javax.swing.text.StyleConstants.NameAttribute));
    
                if (kind instanceof HTML.UnknownTag && element.getName().equals("button")) {
    
                    return new ComponentView(element) {
                        @Override
                        protected Component createComponent() {
                            JButton button = new JButton("Button : text unknown");
    
                            try {
                                int start = getElement().getStartOffset();
                                int end = getElement().getEndOffset();
                                String text = getElement().getDocument().getText(start, end - start);
                                button.setText(text);
                            } catch (BadLocationException e) {
                                e.printStackTrace();
                            }
    
                            return button;
                        }
                    };
    
                }
                return super.create(element);
            }
        }
    }
    
    class MyHTMLDocument extends HTMLDocument {
        public MyHTMLDocument(StyleSheet styles) {
            super(styles);
        }
    
        @Override
        public HTMLEditorKit.ParserCallback getReader(int pos) {
            Object desc = getProperty(Document.StreamDescriptionProperty);
            if (desc instanceof URL) {
                setBase((URL) desc);
            }
            return new MyHTMLReader(pos);
        }
    
        class MyHTMLReader extends HTMLDocument.HTMLReader {
            public MyHTMLReader(int offset) {
                super(offset);
            }
    
            @Override
            public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
                if (t.toString().equals("button")) {
                    registerTag(t, new BlockAction());
                }
                super.handleStartTag(t, a, pos);
            }
        }
    }
    
    class MyParserDelegator extends Parser {
        private DTD _dtd;
    
        public MyParserDelegator() {
            String nm = "html32";
            try {
                _dtd = DTD.getDTD(nm);
                createDTD(_dtd, nm);
    
                javax.swing.text.html.parser.Element div = _dtd.getElement("div");
                _dtd.defineElement("button", div.getType(), true, true, div.getContent(), null, null, div.getAttributes());
            } catch (IOException e) {
                // (PENDING) UGLY!
                System.out.println("Throw an exception: could not get default dtd: " + nm);
            }
        }
    
        protected static DTD createDTD(DTD dtd, String name) {
            InputStream in = null;
            try {
                String path = name + ".bdtd";
                in = ParserDelegator.class.getResourceAsStream(path);
                if (in != null) {
                    dtd.read(new DataInputStream(new BufferedInputStream(in)));
                    DTD.putDTDHash(name, dtd);
                }
            } catch (Exception e) {
                System.out.println(e);
            }
            return dtd;
        }
    
        @Override
        public void parse(Reader r, ParserCallback cb, boolean ignoreCharSet) throws IOException {
            new DocumentParser(_dtd).parse(r, cb, ignoreCharSet);
        }
    }
    
    0 讨论(0)
  • 2021-01-27 10:04

    It works for me using the following (jdk 1.7):

    Field f = javax.swing.text.html.parser.ParserDelegator.class.getDeclaredField("DTD_KEY");
    

    The only change is the key: "DTD_KEY" upper case!!

    I found the key "DTD_KEY" using

    Field[] flds = javax.swing.text.html.parser.ParserDelegator.class.getDeclaredFields();
    for (Field f: flds)  
    {
           System.err.println(f.getName());
    }
    
    0 讨论(0)
提交回复
热议问题