JEditorPane удаляет стили шрифтов CSS - PullRequest
4 голосов
/ 09 мая 2011

Я пытаюсь заставить JEditorPane сохранить любой стиль шрифта CSS. К сожалению, кажется, что он полностью исключает теги абзаца (и других тегов) и преобразует его в тег шрифта для тегов А.

Рассмотрим следующий пример:

import java.awt.BorderLayout;
import java.awt.Container;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.WindowConstants;
public class EditorPaneTest
{
    public static void main(String[] args)
    {
        String text = "<html><head></head><body><p style=\"padding-right: 10px; padding-left: 10px; font-size: 14px; line-height: 125%; font-family: Verdana;\">This is a test.</p>"
                + "<p><a href=\"http://www.google.com/\" style=\"font-size: 9px; margin-right: 10px; font-style: normal; font-family: Verdana;\">Google</a></p></body></html>";
        JEditorPane editorPane = new JEditorPane("text/html", text);
        JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        Container contentPane = frame.getContentPane();
        contentPane.setLayout(new BorderLayout());
        contentPane.add(new JScrollPane(editorPane), BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
        text = editorPane.getText();
        System.out.println(text);
    }
}

Создает следующий вывод для тегов p и a:

<p style="padding-left: 10px; padding-right: 10px; line-height: 125%">

и

<a href="http://www.google.com/" style="margin-right: 10px"><font size="9px" face="Verdana">Google</font></a>

Как видите, он сохраняет стили отступов и полей, но удаляет стиль шрифта для тега абзаца и преобразует его в тег шрифта для тега А.

До вызова getText, если вы отобразите его, он на самом деле будет правильно оформлять абзац.

Как мне получить его, чтобы он сохранил атрибут шрифта как есть?

1 Ответ

2 голосов
/ 10 мая 2011

Хорошо,

Разобрался, проблема определенно в классе HTMLWriter. К сожалению, они не позволили переопределить этот класс, но я полагаю, что он у меня есть.

    import java.io.IOException;
    import java.io.Writer;
    import java.util.Enumeration;
    import java.util.Vector;
    import javax.swing.text.AttributeSet;
    import javax.swing.text.MutableAttributeSet;
    import javax.swing.text.SimpleAttributeSet;
    import javax.swing.text.StyleConstants;
    import javax.swing.text.html.CSS;
    import javax.swing.text.html.HTML;
    import javax.swing.text.html.HTMLDocument;
    import javax.swing.text.html.HTMLWriter;

    public class FixedHTMLWriter extends HTMLWriter
    {
        private Vector                      tags                = new Vector(10);
        private Vector                      tagValues       = new Vector(10);
        private Vector                      tagsToRemove    = new Vector(10);
        private MutableAttributeSet convAttr            = new SimpleAttributeSet();
        private MutableAttributeSet oConvAttr       = new SimpleAttributeSet();

        public FixedHTMLWriter(Writer w, HTMLDocument doc, int pos, int len)
        {
            super(w, doc, pos, len);
        }

        AttributeSet convertToHTML(AttributeSet from, MutableAttributeSet to)
        {
            if (to == null)
            {
                to = convAttr;
            }
            to.removeAttributes(to);
            if (from != null)
            {
                Enumeration keys = from.getAttributeNames();
                String value = "";
                while (keys.hasMoreElements())
                {
                           Object key = keys.nextElement();
                    if (key instanceof CSS.Attribute)
                    {
                        value +=  key + ": " + from.getAttribute(key) + ";";
                        if (keys.hasMoreElements())
                            value += " ";
                    }

                    else
                    {
                        to.addAttribute(key, from.getAttribute(key));
                    }
                }
                if (value.length() > 0)
                {
                    to.addAttribute(HTML.Attribute.STYLE, value);
                }
            }
            return to;
        }

        @Override
        protected void closeOutUnwantedEmbeddedTags(AttributeSet attr) throws IOException
        {
            tagsToRemove.removeAllElements();
            // translate css attributes to html
            attr = convertToHTML(attr, null);
            HTML.Tag t;
            Object tValue;
            int firstIndex = -1;
            int size = tags.size();
            // First, find all the tags that need to be removed.
            for (int i = size - 1; i >= 0; i--)
            {
                t = (HTML.Tag) tags.elementAt(i);
                tValue = tagValues.elementAt(i);
                if ((attr == null) || noMatchForTagInAttributes(attr, t, tValue))
                {
                    firstIndex = i;
                    tagsToRemove.addElement(t);
                }
            }
            if (firstIndex != -1)
            {
                // Then close them out.
                boolean removeAll = ((size - firstIndex) == tagsToRemove.size());
                for (int i = size - 1; i >= firstIndex; i--)
                {
                    t = (HTML.Tag) tags.elementAt(i);
                    if (removeAll || tagsToRemove.contains(t))
                    {
                        tags.removeElementAt(i);
                        tagValues.removeElementAt(i);
                    }
                    write('<');
                    write('/');
                    write(t.toString());
                    write('>');
                }
                // Have to output any tags after firstIndex that still remaing,
                // as we closed them out, but they should remain open.
                size = tags.size();
                for (int i = firstIndex; i < size; i++)
                {
                    t = (HTML.Tag) tags.elementAt(i);
                    write('<');
                    write(t.toString());
                    Object o = tagValues.elementAt(i);
                    if (o != null && o instanceof AttributeSet)
                    {
                        writeAttributes((AttributeSet) o);
                    }
                    write('>');
                }
            }
        }

        private boolean noMatchForTagInAttributes(AttributeSet attr, HTML.Tag t, Object tagValue)
        {
            if (attr != null && attr.isDefined(t))
            {
                Object newValue = attr.getAttribute(t);
                if ((tagValue == null) ? (newValue == null) : (newValue != null && tagValue.equals(newValue)))
                {
                    return false;
                }
            }
            return true;
        }

        @Override
        protected void writeEmbeddedTags(AttributeSet attr) throws IOException
        {
            // translate css attributes to html
            attr = convertToHTML(attr, oConvAttr);
            Enumeration names = attr.getAttributeNames();
            while (names.hasMoreElements())
            {
                Object name = names.nextElement();
                if (name instanceof HTML.Tag)
                {
                    HTML.Tag tag = (HTML.Tag) name;
                    if (tag == HTML.Tag.FORM || tags.contains(tag))
                    {
                        continue;
                    }
                    write('<');
                    write(tag.toString());
                    Object o = attr.getAttribute(tag);
                    if (o != null && o instanceof AttributeSet)
                    {
                        writeAttributes((AttributeSet) o);
                    }
                    write('>');
                    tags.addElement(tag);
                    tagValues.addElement(o);
                }
            }
        }

        @Override
        protected void writeAttributes(AttributeSet attr) throws IOException
        {
            convAttr.removeAttributes(convAttr);
            convertToHTML(attr, convAttr);
            Enumeration names = convAttr.getAttributeNames();
            while (names.hasMoreElements())
            {
                Object name = names.nextElement();
                if (name instanceof HTML.Tag || name instanceof StyleConstants || name == HTML.Attribute.ENDTAG)
                {
                    continue;
                }
                write(" " + name + "=\"" + convAttr.getAttribute(name) + "\"");
            }
        }
    }

И вам необходимо переопределить HTMLEditorKit метод класса write следующим образом:

    public void write(Writer out, Document doc, int pos, int len) throws IOException, BadLocationException
        {
            if (doc instanceof HTMLDocument)
            {
                FixedHTMLWriter w = new FixedHTMLWriter(out, (HTMLDocument) doc, pos, len);
                w.write();
            }
            else if (doc instanceof StyledDocument)
            {
                MinimalHTMLWriter w = new MinimalHTMLWriter(out, (StyledDocument) doc, pos, len);
                w.write();
            }
            else
            {
                super.write(out, doc, pos, len);
            }
        }

И установите переопределенный HTMLEditorKit на JEditorPane, используя вызов setEditorKit.

...