Hide certain actions from Swing's undo manager

邮差的信 提交于 2019-12-04 06:58:40

You could intercept the CHANGE edits and wrap each one in another UndoableEdit whose isSignificant() method returns false, before adding it to the UndoManager. Then each Undo command will undo the most recent INSERT or REMOVE edit, plus every CHANGE edit that occurred since then.

Ultimately, I think you'll find that the styling mechanism provided by JTextPane/StyledDocument/etc. is too limited for this kind of thing. It's slow, it uses too much memory, and it's based on the same Element tree that's used to keep track of the lexical structure of the document. It's okay (I guess) for applications in which the styles are applied by the user, like word processors, but not for a syntax highlighter that has to update the styles constantly as the user types.

There are several examples out there of syntax-highlighting editors based on custom implementations of the Swing JTextComponent, View and Document classes. Some, like JEdit, re-implement practically the whole javax.swing.text package, but I don't think you need to go that far.

How are you trying to prevent the CHANGE events from reaching the undo manager?

Can you not send the UndoManager a lastEdit().die() call immediately after the CHANGE is queued?

I can only assume how you are doing the text colouring. If you are doing it in the StyledDocuments change character attribute method you can get the undo listener and temporarily deregister it from the document for that operation and then once the colour change has finshed then you can reregister the listener.

Should be fine for what you are trying to do there.

hope that helps

I have just been through this problem. Here is my solution:

private class UndoManagerFix extends UndoManager {

    private static final long serialVersionUID = 5335352180435980549L;

    @Override
    public synchronized void undo() throws CannotUndoException {
        do {
            UndoableEdit edit = editToBeUndone();
            if (edit instanceof AbstractDocument.DefaultDocumentEvent) {
                AbstractDocument.DefaultDocumentEvent event = (AbstractDocument.DefaultDocumentEvent) edit;
                if (event.getType() == EventType.CHANGE) {
                    super.undo();
                    continue;
                }
            }
            break;
        } while (true);

        super.undo();
    }

    @Override
    public synchronized void redo() throws CannotRedoException {
        super.redo();
        int caretPosition = getCaretPosition();

        do {
            UndoableEdit edit = editToBeRedone();
            if (edit instanceof AbstractDocument.DefaultDocumentEvent) {
                AbstractDocument.DefaultDocumentEvent event = (AbstractDocument.DefaultDocumentEvent) edit;
                if (event.getType() == EventType.CHANGE) {
                    super.redo();
                    continue;
                }
            }
            break;
        } while (true);

        setCaretPosition(caretPosition);
    }

}

It is an inner class in my custom JTextPane, so I can fix the caret position on redo.

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