Скрыть определенные действия от менеджера отмены Swing - PullRequest
5 голосов
/ 06 января 2009

Я пытаюсь написать JTextPane, который поддерживает какую-то раскраску: когда пользователь печатает текст, я запускаю некоторый код, который окрашивает текст в соответствии с определенным алгоритмом. Это хорошо работает.

Проблема в том, что операции раскраски регистрируются менеджером отмены (DefaultDocumentEvent с EventType.CHANGE). Поэтому, когда пользователь нажимает кнопку «Отменить», окраска исчезает. Только при втором запросе отмены сам текст откатывается.

(Обратите внимание, что алгоритм раскраски несколько медленный, поэтому я не могу раскрасить текст при вставке).

Если я пытаюсь предотвратить достижение событий CHANGE менеджером отмены, я получаю исключение после нескольких запросов отмены: это потому, что содержимое документа не соответствует тому, что ожидает объект отмены редактирования.

Есть идеи?

Ответы [ 4 ]

1 голос
/ 07 января 2009

Я могу только предположить, как вы делаете раскраску текста. Если вы делаете это в методе атрибута символа изменения стиля StyledDocuments, вы можете получить прослушиватель отмены и временно отменить его регистрацию в документе для этой операции, а затем, когда изменение цвета закончится, вы можете перерегистрировать слушателя.

Должно быть хорошо для того, что вы пытаетесь сделать там.

надеюсь, что поможет

1 голос
/ 07 января 2009

Вы можете перехватить изменения CHANGE и обернуть каждый в другой UndoableEdit, чей метод isSignificant() возвращает false, прежде чем добавить его в UndoManager. Затем каждая команда отмены будет отменять самое последнее изменение INSERT или REMOVE, а также каждое изменение CHANGE, которое произошло с тех пор.

В конечном счете, я думаю, вы обнаружите, что механизм стилей предоставлен JTextPane / StyledDocument / и т.д. слишком ограничен для такого рода вещей. Он медленный, использует слишком много памяти и основан на том же элементном дереве, которое используется для отслеживания лексической структуры документа. Это нормально (я полагаю) для приложений, в которых стили применяются пользователем, таких как текстовые процессоры, но не для подсветки синтаксиса, которая должна постоянно обновлять стили при вводе пользователем.

Существует несколько примеров редакторов с подсветкой синтаксиса, основанных на пользовательских реализациях классов Swing JTextComponent, View и Document. Некоторые, такие как JEdit, повторно реализуют практически весь пакет javax.swing.text, но я не думаю, что вам нужно заходить так далеко.

1 голос
/ 06 января 2009

Как вы пытаетесь предотвратить попадание событий CHANGE в менеджер отмены?

Разве вы не можете отправить UndoManager вызов lastEdit (). Die () сразу после того, как ИЗМЕНЕНИЕ помещено в очередь?

0 голосов
/ 14 марта 2014

Я только что прошел через эту проблему. Вот мое решение:

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);
    }

}

Это внутренний класс в моем пользовательском JTextPane, так что я могу исправить положение каретки при повторении.

...