I'm desperatly trying to implement a customized copy/paste in a JTextPane in HTML mode. The most part is working well, I get the html content using EditorKit.write(), I paste it using editorKit.read(). Perfect world.
BUT, when I have : <p> test </p>
in my editor and I try to copy "es" to obtain
<p> tesest </p>
, I obtain instead
<p>tes</p>
<p>es</p>
<p>t</p>
Knowing that, I m trying to figure out a way to paste "inline" the part supposed to be inline, and in block the part which was in block during the copy. Typically,
if I have :
<p>mon beau sapin</p>
<p>roi des forêts</p>
<p>que j'aime ta verdure</p>
And if I copy :
beau sapin</p>
<p>roi des forêts</p>
<p>que
And paste it after "mon", I expect :
<p>mon beau sapin</p>
<p>roi des forêts</p>
<p>que beau sapin</p>
<p>roi des forêts</p>
<p>que j'aime ta verdure</p>
And I obtain instead :
<p>mon</p>
<p>beau sapin</p>
<p>roi des forêts</p>
<p>que</p>
<p>beau sapin</p>
<p>roi des forêts</p>
<p>que j'aime ta verdure</p>
I tried various approach, like removing the <p></p>
of the first and last lines (EditorKit.read add it back by itself), using editorKit.insertHTML (but what kind of Tag should I put ?), insert line by line (most part of times, I obtain a p
inside another p
) etc.
but the real problem that it's impossible to write what you want in the htmlDocument. How can I write sapin</p> <p>roi
at a specified position ?
EditorKit.read ? it will add <p>sapin</p> <p>roi</p>
Editorkit.insertHTML ? I need to precise a wrapping Tag...
I show you my last try :
private static void insertHTMLContent(JMathTextPane jtp, String html, int offset) {
Document doc = Jsoup.parse(html);
Elements elts = doc.body().children();
//unwrap the last and first element
if(elts.size()>2) { elts.last().unwrap(); }
if(elts.size()>=1) { elts.first().unwrap(); }
//We add a fake DIV element and remove it just at the next line
editorKit.insertHTML(jtp.htmlDoc, offset, "<div id='copie'>"+doc.body().html()+"</div>", 0, 0, HTML.Tag.DIV);
jtp.getHTMLdoc().setOuterHTML(jtp.getHTMLdoc().getElement("copie"),doc.body().html());
}
I can't show you the result : EditorKit.write tries to fix the html by itself. But the HTMLDocument is completely messy.
For you to try :
public class Test {
private static JTextPane editor = new Editor();
private static JMenuBar menu = new Menu();
private static String clipboard = "";
private static Action copy = new Copy();
private static Action paste = new Paste();
public static void main(String[] args) {
JFrame f = new JFrame();
f.setContentPane(editor);
f.setJMenuBar(menu);
f.setSize(600, 400);
f.setVisible(true);
}
public static class Editor extends JTextPane {
public Editor() {
this.setDocument(new HTMLDocument());
this.setEditorKit(new HTMLEditorKit());
}
}
public static class Menu extends JMenuBar {
public Menu() {
add(new JButton(copy));
add(new JButton(paste));
getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK), "copy");
getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK), "paste");
getActionMap().put("copy", copy);
getActionMap().put("paste", paste);
}
}
public static class Copy extends AbstractAction {
public Copy() {super("copy");}
@Override
public void actionPerformed(ActionEvent e) {
StringWriter w = new StringWriter();
try {
editor.getEditorKit().write(w, editor.getDocument(), editor.getCaretPosition(), editor.getSelectedText().length());
} catch (Exception ex) {Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);}
clipboard = w.toString();
}
}
public static class Paste extends AbstractAction {
public Paste() {super("paste");}
@Override
public void actionPerformed(ActionEvent e) {
try {
editor.getEditorKit().read(new StringReader(clipboard), editor.getDocument(), editor.getCaretPosition());
} catch (Exception ex) {Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);}
}
}
}
Sorry I was long. I accept any help.
For further readers, I solved it with a very easy trick. I just removed the \n
added before and after the pasted text when needed.
public static void copyContent(JTextPane jtp, String text, int offset) {
try {
boolean start = offset>0 ? !jtp.getText(offset-1, 1).equals("\n") : false;
Position p = jtp.getDocument().createPosition(offset);
new HTMLEditorKit().read(new StringReader(html), jtp.getHTMLdoc(), offset);
if(start) {jtp.getDocument().remove(offset, 1);}
if(offset>0) {jtp.getDocument().remove(p.getOffset()-1, 1);}
} catch (IOException | BadLocationException ex) {
Logger.getLogger(EditeurIO.class.getName()).log(Level.SEVERE, null, ex);
}
}