JEdi​​torPane、HTMLEditorKit - 插入自定义标签的自定义操作

发布于 2024-12-07 12:11:05 字数 2138 浏览 1 评论 0原文

我相信 JEditorPane。我需要简单的编辑器。我已经解决了加载和修改包含自定义(两个)标签的 HTML 的问题(请参阅 我的旧帖子)。它可以正确显示文档,我现在甚至可以对其进行编辑。我可以编写文本、删除字符或自定义元素。我赢得了一场战斗,但还没有赢得整个战争。遗憾的是下一步也很成问题。我无法插入自定义标签。

我有一个自定义操作:

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. 当前元素的主体被分割

当我将 span 元素插入

段落

,我明白了

parahojagraph

正如预期的那样。然而,未知标签始终作为 body 元素的子元素插入,结果(例如,对于未知标签 x)是

par

< x>ahoj

agraph

工作实在是太累人了。几周以来我一直对这个相对简单的任务充满信心。我已经废了。如果插入不起作用,我可以全部废弃......

I'm faithing with JEditorPane. I need simple editor. I've solved the problem with loading and modified HTML containing custom (two) tags (see my older post). It displays the document properly and I can even edit it now. I can write text, delete either characters or my custom elements. I won a battle, but haven't won the war. The next step is regrettably very problematical too. I'm unable to insert my custom tags.

I have a custom action:

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);
        }
    }
}

It workts properly. I can insert the span element. But I cannot insert non-standard tag in this way. I can insert just code, span and so on, but not my tag. For my tag I'm forced to use this:

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

There are two critical problems

  1. The custom tag must be bounded with non-whispace characters (here x)
  2. The current element's body is split

When I insert span element into <p>paragraph</p>, I get <p>par<span>ahoj</span>agraph</p> as expected. Howerever unknown tag is allways inserted as child of body element and the result (e.g. for unknown tag x) is <p>par</p><x>ahoj</x><p>agraph</p>.

The work is dead exhausting. I'm faithing with this relatively simple task since weeks. I'm already wasted. If the insertion won't to work, I can scrap it all...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情痴 2024-12-14 12:11:05

我找到了解决方法。标签是这样插入的:

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 的替代品,但我不知道它是否允许我添加自定义标签。

I've found a workaround. The tag is inserted this way:

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

My ModifiedHTMLDocument contains a method insertHTML(), which calls the medhod hidden by reflection:

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);
    }
}

The last piece of our brick-box is a method looking for the current element:

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;
}

This method is also a member of the ModifiedHTMLDocument class.

The solution is not pure, but it solves provisionally the problem. I hope I'll find a better kit. I'm thinking about JWebEngine. That should be replacement for current poor HTMLEditorKit, but I don't know, whether it allows me to add my custom tags.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文