I've made a documentlistener that will call a method when text is inserted. It works but the problem is that it acts as if it's in a loop and is kept being called.
The method uses swingutilties.invokelater from inside the method.
private void addNewLine() {
SwingUtilities.invokeLater( () -> {
textArea.append(System.getProperty("line.separator")+"hey");
});
}
private final DocumentListener addNewLine = Handlers.forDocumentUpdate((event) -> {
addNewLine();
});
@SuppressWarnings("serial")
static DocumentListener forDocumentUpdate(Consumer<? super DocumentEvent> eventHandler) {
return new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent event) {
eventHandler.accept(event);
}
@Override
public void removeUpdate(DocumentEvent event) {
}
@Override
public void changedUpdate(DocumentEvent event) {
}
};
}
Before I had used DocumentListener to do the task, but there was a problem with recursive looping. The proper way is to add a DocumentFilter that will simply add a newline along with the code that inserts the original text to be inserted.
((AbstractDocument) textArea.getDocument()).
setDocumentFilter(new NewLineFilter());
public class NewLineFilter extends DocumentFilter {
@Override
public void insertString(FilterBypass fb,int offs,String str,AttributeSet a)
throws BadLocationException {
}
@Override
public void replace(FilterBypass fb, int offs,int length, String str, AttributeSet a)
throws BadLocationException {
System.out.println("in replace");
super.replace(fb,offs,length,str,a);
super.insertString(fb, fb.getDocument().getLength(), System.lineSeparator(), a);
}}
If you know a better way to write this or If you know of a way to make a handler that would create an anonymous class for this that would be great. I couldn't use Consumer because replace() has more than one parameter. I could make another functional interface, but I don't know how useful it would be. I figure could potentially just reuse this class if I need to the same thing again.