2011-09-30 65 views
3

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

我有一个自定义操作:

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

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

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

有两个关键问题

  1. 自定义标签必须与非whispace字符(在此,x)
  2. 来界定当前元素的当我插入span元素为<p>paragraph</p>体拆分

,我得到<p>par<span>ahoj</span>agraph</p>预期。如何将未知标签全部插入body元素的子元素中,结果(例如未知标签x)为<p>par</p><x>ahoj</x><p>agraph</p>

这项工作让人筋疲力尽。自从几周以来,我就相信这个相对简单的任务。我已经浪费了。如果插入不上班,我就废了...所有

+1

什么对象类型是'AppErrors.EDITORKIT_ACTIONFAILURE'?如果'String',为什么不抛出新的Throwable(AppErrors.EDITORKIT_ACTIONFAILURE,ioe);'? –

+0

没关系。我已将帖子更新为更全面。 –

+0

我不确定我是否理解。 HTMLEditorKit用于呈现HTML。如果您使用非HTML标记提供它,您希望它做什么? –

回答

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(),它调用由反射隐藏medhod:

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

2
+0

我在你的帖子的帮助下开始了。但我的东西,还没有什么可以添加。这是如何加载包含未知标签的文件的解决方案。在加载文件后插入自定义标签有没有一些经验?为了能够编辑超文本,我必须能够将我的自定义标记插入到已在我的编辑器窗格中加载的文档中。不幸的是,这非常困难。 –

+0

当你插入HTML时,应调用相同的方法。所以你的标签将被识别并创建适当的结构。 – StanislavL

+0

也许,然而'insertHTML()'方法(在我看来是无意识的)隐藏为私有方法。我只能使用'insertBeforeStart()'等等。尽管如此,当我尝试时,'setInnerHTML()'方法做了什么,它只有在标签被一些非白色字符包装时才起作用。否则它不会采取任何行动。这似乎有点有趣,让我感到困惑...... –