JEditorPane, HTMLEditorKit - пользовательское действие, вставляющее пользовательский тег
Я верю с 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
элемент. Но я не могу вставить нестандартный тег таким образом. Я могу просто вставить code
, span
и так далее, но не мой тег. Для моего тега я вынужден использовать это:
ekit.insertHTML(doc, offset, "x<bar medium=\"#DEFAULT\" type=\"packaged\" source=\"identifier\" />x", 0, 0, null);
Есть две критические проблемы
- Пользовательский тег должен быть ограничен непропускаемыми символами (здесь x)
- Тело текущего элемента разделено
Когда я вставляю span
элемент в <p>paragraph</p>
, Я получил <p>par<span>ahoj</span>agraph</p>
как и ожидалось. Однако неизвестный тег всегда вставляется как дочерний элемент body
элемент и результат (например, для неизвестного тега x
) является <p>par</p><x>ahoj</x><p>agraph</p>
,
Работа до смерти утомительна. Я верю в это относительно простое задание с нескольких недель. Я уже впустую. Если вставка не сработает, я могу все это удалить...
2 ответа
Я нашел обходной путь. Тег вставляется так:
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
, но я не знаю, позволяет ли мне добавить мои собственные теги.
Надеюсь, что это поможет http://java-sl.com/custom_tag_html_kit.html