JEdi​​torPane,HTMLEditorKit - 自定义操作插入自定义标记

时间:2011-09-30 09:03:37

标签: java swing jeditorpane htmleditorkit

我对JEditorPane很有信心。我需要简单的编辑器。我已经解决了加载和修改HTML包含自定义(两个)标记的问题(请参阅my older post)。它正确显示文档,我甚至可以立即编辑它。我可以写文字,删除字符或我的自定义元素。我赢了一场战斗,但没有赢得这场战争。令人遗憾的是,下一步非常有问题。我无法插入自定义标签。

我有自定义操作:

import my.own.HTMLEditorKit; //extends standard HTMLEditorKit
import my.own.HTMLDocument; //extends standard HTMLDocument

class InsertElementAction extends StyledTextAction {
    private static final long serialVersionUID = 1L;

    public InsertElementAction(String actionName) {
        super(actionName);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        JEditorPane editor = getEditor(e);

        if (editor == null)
            return;

        HTMLDocument doc = (HTMLDocument) editor.getDocument();
        HTMLEditorKit ekit = (HTMLEditorKit) editor.getEditorKit();
        int offset = editor.getSelectionStart();

        try {
            ekit.insertHTML(doc, offset, "<span>ahoj</span>", 0, 0, HTML.Tag.SPAN);
            Element ele = doc.getRootElements()[0];
            ele = ele.getElement(1).getElement(0);
            doc.setInnerHTML(ele, "<bar medium=\"#DEFAULT\" type=\"packaged\" source=\"identifier\" />");
        }
        catch (BadLocationException ble) {
            throw new Error(ble);
        }
        catch (IOException ioe) {
            throw new Error(ioe);
        }
    }
}

它正常工作。我可以插入span元素。但我不能以这种方式插入非标准标签。我只能插入codespan等,但不能插入我的标记。对于我的标签,我被迫使用它:

ekit.insertHTML(doc, offset, "x<bar medium=\"#DEFAULT\" type=\"packaged\" source=\"identifier\" />x", 0, 0, null);

有两个关键问题

  1. 自定义标记必须以非空格字符(此处为x)
  2. 为界
  3. 当前元素的正文已拆分
  4. 当我将span元素插入<p>paragraph</p>时,我按预期得到<p>par<span>ahoj</span>agraph</p>。总是将未知标记作为body元素的子项插入,结果(例如,对于未知标记x)为<p>par</p><x>ahoj</x><p>agraph</p>

    这项工作令人筋疲力尽。几个星期以来,我一直在相信这个相对简单的任务。我已经浪费了。如果插入不起作用,我可以全部废弃......

2 个答案:

答案 0 :(得分:2)

答案 1 :(得分:1)

我找到了解决方法。标签以这种方式插入:

ModifiedHTMLDocument doc = (ModifiedHTMLDocument) editor.getDocument();
int offset = editor.getSelectionStart();
//insert our special tag (if the tag is not bounded with non-whitespace character, nothing happens)
doc.insertHTML(offset, "-<specialTag />-");
//remove leading and trailing minuses
doc.remove(offset, 1); //at the current position is the minus before tag inserted
doc.remove(offset + 1, 1); //the next sign is minus after new tag (the tag is nowhere)
//Note: no, you really cannot do that: doc.remove(offset, 2), because then the tag is deleted

我的ModifiedHTMLDocument包含一个方法insertHTML(),该方法调用反射隐藏的媒体:

public void insertHTML(int offset, String htmlText) throws BadLocationException, IOException {
    if (getParser() == null)
        throw new IllegalStateException("No HTMLEditorKit.Parser");

    Element elem = getCurrentElement(offset);

    //the method insertHTML is not visible
    try {
        Method insertHTML = javax.swing.text.html.HTMLDocument.class.getDeclaredMethod("insertHTML",
                new Class[] {Element.class, int.class, String.class, boolean.class});
        insertHTML.setAccessible(true);
        insertHTML.invoke(this, new Object[] {elem, offset, htmlText, false});
    }
    catch (Exception e) {
        throw new IOException("The method insertHTML() could not be invoked", e);
    }
}

我们砖箱的最后一块是寻找当前元素的方法:

public Element getCurrentElement(int offset) {
    ElementIterator ei = new ElementIterator(this);
    Element elem, currentElem = null;
    int elemLength = Integer.MAX_VALUE;

    while ((elem = ei.next()) != null) { //looking for closest element
        int start = elem.getStartOffset(), end = elem.getEndOffset(), len = end - start;
        if (elem.isLeaf() || elem.getName().equals("html"))
            continue;
        if (start <= offset && offset < end && len <= elemLength) {
            currentElem = elem;
            elemLength = len;
        }
    }

    return currentElem;
}

此方法也是ModifiedHTMLDocument类的成员。

解决方案并不纯粹,但它暂时解决了这个问题。我希望我能找到一个更好的工具包。我正在考虑JWebEngine。这应该是当前可怜的HTMLEditorKit的替代品,但我不知道,是否允许我添加自定义标签。