After a brief debugging I found that RichTextFx is doing some weird behavior when selecting the new range (it is from this range you start typing the text, cursor position does not matter). When selecting the new range, the current range is set to 0,0 and then only moved to the cursor position. However, after performing the undo, the new range is selected to 0,0 and never to the current cursor position. It is because of that when we press undo, though the cursor is highlighted in another position, the text starts getting typed from the 0,0.
I was able to somewhat solve this using reflection. You need to extend the StyleClassedTextArea
, override the undo()
method, perform undo, and then set the position where you need your range in. You could set the range to the current cursor position but the cursor is not always in the correct position especially when the cursor needs to move to another style in another paragraph. I got the correct position range inside the ChangeQueue in the undoManager.
You need to make sure that you are casting properly so, do some debugging before casting.
@Override
public void undo() {
if (isUndoAvailable()) {
super.undo();
UndoManager undoManager = getUndoManager();
try {
Field queueField = UndoManagerImpl.class.getDeclaredField("queue");
queueField.setAccessible(true);
UnlimitedChangeQueue queue = (UnlimitedChangeQueue) queueField
.get(undoManager);
int newRange = ((PlainTextChange) ((List) queue.peekNext()).get(0))
.getRemovalEnd();
selectRange(newRange, newRange);
} catch (NoSuchFieldException | IllegalAccessException e) {
// Handle exception
}
}
}
@Override
public void redo() {
if (isRedoAvailable()) {
super.redo();
UndoManager undoManager = getUndoManager();
try {
Field queueField = UndoManagerImpl.class.getDeclaredField("queue");
queueField.setAccessible(true);
UnlimitedChangeQueue queue = (UnlimitedChangeQueue) queueField
.get(undoManager);
int newRange = ((PlainTextChange) ((List) queue.peekPrev()).get(0))
.getInsertionEnd();
selectRange(newRange, newRange);
} catch (NoSuchFieldException | IllegalAccessException e) {
// Handle
}
}
}