I am trying to attach an UndoableEditListener
to a JTextPane
or JTextArea
that queues up edits into an UndoManager
.
textPane.getDocument().addUndoableEditListener(new UndoableEditListener() {
@Override
public void undoableEditHappened(UndoableEditEvent event) {
undoQueue.addEdit(event.getEdit());
}
});
But undoableEditHappened
is never called when I type "aaa" in the text window.
Thinking it's Java's fault, not mine, I crack AbstractDocument.class
open with Eclipse debugger to watch the event trigger. It has a private listeners
array. AbstractDocument
stores all its listeners in odd indices in the listeners
array, with the listeners' type Class<>'s in the even indices.
protected void fireUndoableEditUpdate(UndoableEditEvent e) {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == UndoableEditListener.class) {
// Lazily create the event:
// if (e == null)
// e = new ListSelectionEvent(this, firstIndex, lastIndex);
((UndoableEditListener) listeners[i + 1]).undoableEditHappened(e);
}
}
}
See the line if (listeners[i] == UndoableEditListener.class)
? When I add the undo change listener, the debugger shows listeners
containing my listener, along with UndoableEditListener.class
in the index before it. But, when the debugger comes to that if-statement, all the even indices in the array listeners
show as DocumentListener.class
in the debugger. Consequently, the if-statement is always false
and the listener never called.
What the heck? Is this a Java 8 bug? Or am I missing a step the examples forgot to mention?
The problem was in the JTextPane
. I was overriding its setText
method to force it to call read
, the alternative to setText
that normalizes all kinds of newline while remembering them. But JTextPane.read
appears to not trigger an UndoableEditEvent
on the document.
If I leave setText
alone, then UndoManager.undo
works.