Skip to content

Instantly share code, notes, and snippets.

@RustyKnight
Created May 5, 2022 01:29
Show Gist options
  • Save RustyKnight/70c450a9a4fed146f81c5bd806b07f1a to your computer and use it in GitHub Desktop.
Save RustyKnight/70c450a9a4fed146f81c5bd806b07f1a to your computer and use it in GitHub Desktop.
A "simple" demonstration of using a `DocumentFilter` with a `ComboBoxEditor`
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.KeyboardFocusManager;
import java.awt.Toolkit;
import java.awt.event.ActionListener;
import javax.swing.ComboBoxEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
model.addElement("Test");
JComboBox<String> combobox = new JComboBox<>(model);
combobox.setEditor(new FilteredComboBoxEditor());
combobox.setEditable(true);
add(combobox);
}
}
public class FilteredComboBoxEditor implements ComboBoxEditor {
private JTextField textField;
public FilteredComboBoxEditor() {
textField = new JTextField(10);
((AbstractDocument) textField.getDocument()).setDocumentFilter(new DocumentFilter() {
private int maxLength = 10;
protected String filter(String text) {
StringBuilder sb = new StringBuilder(text.length());
for (char c : text.toCharArray()) {
if (Character.isWhitespace(c) || c == '.' || c == '&') {
continue;
}
sb.append(c);
}
return sb.toString();
}
@Override
public void insertString(DocumentFilter.FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException {
String filteredText = filter(text);
if (filteredText.isEmpty()) {
provideErrorFeedback();
return;
}
if ((fb.getDocument().getLength() + filteredText.length()) < maxLength) {
provideErrorFeedback();
return;
}
if (!filteredText.equals(text)) {
provideErrorFeedback();
}
super.insertString(fb, offset, filteredText, attr);
}
@Override
public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
text = filter(text);
int targetLength = fb.getDocument().getLength() - length;
if ((targetLength + text.length()) >= maxLength) {
// Some or all the text is going to be rejected
provideErrorFeedback();
int remainingLength = maxLength - targetLength;
if (remainingLength <= 0) {
return;
}
text = text.substring(0, remainingLength);
}
super.replace(fb, offset, length, text, attrs);
}
protected void provideErrorFeedback() {
LookAndFeel laf = UIManager.getLookAndFeel();
if (laf == null) {
Toolkit.getDefaultToolkit().beep();
} else {
KeyboardFocusManager fm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
Component component = fm.getFocusOwner();
laf.provideErrorFeedback(component);
}
}
});
}
@Override
public Component getEditorComponent() {
return textField;
}
@Override
public void setItem(Object anObject) {
textField.setText(anObject == null ? null : anObject.toString());
}
@Override
public Object getItem() {
return textField.getText();
}
@Override
public void selectAll() {
textField.selectAll();
}
@Override
public void addActionListener(ActionListener l) {
textField.addActionListener(l);
}
@Override
public void removeActionListener(ActionListener l) {
textField.removeActionListener(l);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment