Skip to content

Instantly share code, notes, and snippets.

@unix-junkie
Created July 12, 2021 13:18
Show Gist options
  • Save unix-junkie/cac9c3e088ff5ef9ce9166e07c34d969 to your computer and use it in GitHub Desktop.
Save unix-junkie/cac9c3e088ff5ef9ce9166e07c34d969 to your computer and use it in GitHub Desktop.
JMultilineTextField.java
package com.example;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import java.awt.Dimension;
import java.util.stream.Stream;
public class JMultilineTextField extends JTextField {
public JMultilineTextField() {
setupDocument(getDocument());
addActionListener(e -> {
try {
final int selectionStart = getSelectionStart();
final int selectionEnd = getSelectionEnd();
final Document document = getDocument();
if (selectionStart != selectionEnd) {
document.remove(selectionStart, selectionEnd - selectionStart);
}
document.insertString(selectionStart, "\n", null);
} catch (final BadLocationException ble) {
ble.printStackTrace();
}
});
}
@Override
public void setDocument(final Document doc) {
setupDocument(doc);
super.setDocument(doc);
}
private void setupDocument(final Document doc) {
doc.putProperty("filterNewlines", false);
installDocumentListenerIfNecessary(doc);
}
private void installDocumentListenerIfNecessary(final Document doc) {
final DocumentListener documentListeners[] = ((AbstractDocument) doc).getListeners(DocumentListener.class);
if (Stream.of(documentListeners).noneMatch(documentListener -> documentListener instanceof RowCountChangeListener)) {
doc.addDocumentListener(new RowCountChangeListener());
}
}
private final class RowCountChangeListener implements DocumentListener {
@Override
public void insertUpdate(final DocumentEvent e) {
revalidateParentIfNecessary();
}
@Override
public void removeUpdate(final DocumentEvent e) {
revalidateParentIfNecessary();
}
@Override
public void changedUpdate(final DocumentEvent e) {
revalidateParentIfNecessary();
}
private void revalidateParentIfNecessary() {
final JMultilineTextField textField = JMultilineTextField.this;
final Dimension currentSize = textField.getSize();
final Dimension preferredSize = textField.getPreferredSize();
/*
* Grow/shrink vertically as necessary.
*/
if (currentSize.height != preferredSize.height) {
textField.getParent().revalidate();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment