Sto cercando di implementare le funzionalità di unod/redo nel mio programma. Ho letto il tutorial Sun e penso di aver capito come funziona (non sembra difficile ) ed ho scritto questo listener:

codice:
    protected UndoManager undoManager = new UndoManager();
    protected UndoAction undoAction = new UndoAction();
    protected RedoAction redoAction = new RedoAction();

    ...

    editor.getDocument().addUndoableEditListener(new UndoableEditListener() {
    public void undoableEditHappened(UndoableEditEvent e) {	
        // non mi interessa annullare/ripristinare il
        // cambiamento dello stile!
        if (e.getEdit().getPresentationName().contains("style")) {
            e.getEdit().die();
        } else {
            undoManager.addEdit(e.getEdit());
        }

        undoAction.updateUndoState();
        redoAction.updateRedoState();
    }
});
Sembra funzionare correttamente ma invece c'è un problema da cui non riesco a venire fuori!
Succede questo:
- Inserisco N caratteri.
- Faccio un po' di undo e redo (funziona tutto perfettamente)
- Poi faccio undo fino a togliere tutti i caratteri inseriti. Se adesso provo a fare redo il programma si inchioda per circa uno/due minuti e poi esegue l'operazione. Chiaramente non è normale...

Da cosa può dipendere?

Per completezza riporto le classi "action" che ho usato (sono quelle del tutorial):

codice:
public class UndoAction extends AbstractAction {
    private static final long serialVersionUID = -5953096349094002607L;

    public UndoAction() {
        super("Undo");
        setEnabled(false);
    }

    public void actionPerformed(ActionEvent e) {
        try {
            undoManager.undo();
        } catch (CannotUndoException ex) {
            System.out.println("Unable to undo: " + ex);
            ex.printStackTrace();
        }
        
        updateUndoState();
        redoAction.updateRedoState();
    }

    protected void updateUndoState() {
        if (undoManager.canUndo()) {
            setEnabled(true);
            putValue(Action.NAME, undoManager.getUndoPresentationName());
        } else {
            setEnabled(false);
            putValue(Action.NAME, "Undo");
        }
    }
}

public class RedoAction extends AbstractAction {
    private static final long serialVersionUID = -6940921240094412788L;

    public RedoAction() {
        super("Redo");
        setEnabled(false);
    }

    public void actionPerformed(ActionEvent e) {
        try {
            undoManager.redo();
        } catch (CannotRedoException ex) {
            System.out.println("Unable to redo: " + ex);
            ex.printStackTrace();
        }
        
        updateRedoState();
        undoAction.updateUndoState();
    }

    protected void updateRedoState() {
        if (undoManager.canRedo()) {
            setEnabled(true);
            putValue(Action.NAME, undoManager.getRedoPresentationName());
        } else {
            setEnabled(false);
            putValue(Action.NAME, "Redo");
        }
    }
}