问题
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.
回答1:
I am afraid there is no easy way. When you paste you would like to keep original paragraph and avoid new <p>
creation, right? The problem is current paragraph and copied one may have different attributes. E.g. current is left aligned but copied one has right alignment.
How to resolve the case? To simplify this kit just creates <p>
element.
You can try to create an independent HTMLDocument from the clipboard content and iterate through the Document's structure extracting elements (paragraphs and texts) and inserting them in the original document.
回答2:
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);
}
}
来源:https://stackoverflow.com/questions/17437440/inline-copy-paste-jeditorpane-html