inline copy paste JEditorPane HTML

冷暖自知 提交于 2020-01-15 12:33:52

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!