RSyntaxTextArea
RSyntaxTextArea copied to clipboard
Undo removes all entered text
I have written a small test where just a form contains RSyntaxTextArea component. As I see undo/redo should work just out of the box but if I press ctrl+z then all entered text (which contains multiple lines) is removed like the component doesn't have any saved intermediate undo steps. May be I should turn on something in RSyntaxTextArea to save intermediate undo steps?
RSTA's undo will delete all contiguous text. If you moved the caret to another location and typed, it would trigger a separate undo action.
Can you confirm this is the behavior you see?
I see other code editors (at least IntelliJ and VS Code) start a new undo when pressing Enter as well. I'm guessing this is what you expected but aren't seeing?
I made some small screen-cast, may I be have skipped something but looks like there is no new undo for enter pressing, the test program is visible in left part https://user-images.githubusercontent.com/3008810/110342733-6a006e80-8034-11eb-9a34-a7794493812e.mp4
Yes, that's the current behavior - all contiguous text, including line endings, are treated as a single undo. I'll leave this open as a feature request for a new undo to restart on Enter presses.
and is there any way for programmers to replace undo manager in RSyntaxTextArea by custom one? looks like that use of RUndoManager is hard-coded
You'd have to create a custom subclass of RUndoManager that reimplements the logic in undoableEditHappened() so that newlines start a new compound edit. This should be straightforward since RUndoManager
just wraps Swing's standard javax.swing.undo
package's functionality.
Then inject an instance of your custom RUndoManager
subclass via a subclass of RSyntaxTextArea
with createUndoManager() overridden.
Reopening since I meant to actually look at implementing this in the library.
You'd have to create a custom subclass of RUndoManager that reimplements the logic in undoableEditHappened() so that newlines start a new compound edit. This should be straightforward since
RUndoManager
just wraps Swing's standardjavax.swing.undo
package's functionality.Then inject an instance of your custom
RUndoManager
subclass via a subclass ofRSyntaxTextArea
with createUndoManager() overridden.
Unfortunately this isn't so simple due to sub-classes not being able to access compoundEdit
. I figured out a hack using beginInternalAtomicEdit
and endInternalAtomicEdit
though that allows newlines to be counted as their own actions:
private final RTextArea textArea;
public MyUndoManager(RTextArea textArea) {
super(textArea);
this.textArea = textArea;
}
@Override public void undoableEditHappened(UndoableEditEvent e) {
UndoableEdit edit = e.getEdit();
if ("addition".equals(edit.getPresentationName())) {
try {
String inserted = textArea.getText(textArea.getCaretPosition() - 1, 1);
if ("\n".equals(inserted)) {
// Create an edit action just for the newline.
beginInternalAtomicEdit();
super.undoableEditHappened(e);
endInternalAtomicEdit();
return;
}
} catch (BadLocationException ignored) {
// This shouldn't happen...
}
}
super.undoableEditHappened(e);
}
While you are implementing this functionality into RUndoManager, it might also be good to expose some extra methods so that sub-classes can handle the compoundEdit themselves more easily. Also, it would be nice if there was a way to get the undo manager of an RSyntaxTextArea. Currently I have to override createUndoManager()
and then store the undo manager in a field to access it.
Cheers