172 lines
5.0 KiB
Java
172 lines
5.0 KiB
Java
Auto complete or search in a JComboBox
|
|
|
|
import java.awt.Component;
|
|
import java.util.*;
|
|
import javax.swing.*;
|
|
import javax.swing.plaf.basic.BasicComboBoxEditor;
|
|
import javax.swing.text.*;
|
|
|
|
public class AutoCompleteComboBox extends JComboBox
|
|
{
|
|
private static final Locale[] INSTALLED_LOCALES = Locale.getAvailableLocales();
|
|
private ComboBoxModel model = null;
|
|
public static void main(String[] args)
|
|
{
|
|
JFrame f = new JFrame("AutoCompleteComboBox");
|
|
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
AutoCompleteComboBox box = new AutoCompleteComboBox(INSTALLED_LOCALES, false);
|
|
f.getContentPane().add(box);
|
|
f.pack();
|
|
f.setLocationRelativeTo(null);
|
|
f.setVisible(true);
|
|
}
|
|
/** * Constructor for AutoCompleteComboBox -
|
|
* The Default Model is a TreeSet which is alphabetically sorted and doesnt allow
|
|
duplicates. * @param items */
|
|
public AutoCompleteComboBox(Object[] items, boolean caseSensitive)
|
|
{
|
|
super(items);
|
|
model = new ComboBoxModel(items);
|
|
setModel(model);
|
|
setEditable(true);
|
|
setEditor(new AutoCompleteEditor(this, caseSensitive));
|
|
}
|
|
/** * Constructor for AutoCompleteComboBox -
|
|
* The Default Model is a TreeSet which is alphabetically sorted and doesnt allow
|
|
duplicates. * @param items */
|
|
public AutoCompleteComboBox(Vector items, boolean caseSensitive)
|
|
{
|
|
super(items);
|
|
model = new ComboBoxModel(items);
|
|
setModel(model);
|
|
setEditable(true);
|
|
setEditor(new AutoCompleteEditor(this, caseSensitive));
|
|
}
|
|
/** * Constructor for AutoCompleteComboBox -
|
|
* This constructor uses JComboBox's Default Model which is a Vector.
|
|
* @param caseSensitive */
|
|
public AutoCompleteComboBox(boolean caseSensitive)
|
|
{
|
|
super();
|
|
setEditable(true);
|
|
setEditor(new AutoCompleteEditor(this, caseSensitive));
|
|
}
|
|
|
|
/* * ComboBoxModel.java */
|
|
public class ComboBoxModel extends DefaultComboBoxModel
|
|
{
|
|
/** * The TreeSet which holds the combobox's data (ordered no duplicates)
|
|
*/
|
|
private TreeSet values = null;
|
|
public ComboBoxModel(List items)
|
|
{
|
|
super();
|
|
this.values = new TreeSet();
|
|
int i, c;
|
|
for (i = 0, c = items.size(); i < c; i++)
|
|
values.add(items.get(i).toString());
|
|
Iterator it = values.iterator();
|
|
while (it.hasNext())
|
|
super.addElement(it.next().toString());
|
|
}
|
|
public ComboBoxModel(final Object items[])
|
|
{
|
|
this(Arrays.asList(items));
|
|
}
|
|
}
|
|
|
|
/* * AutoCompleteEditor.java */
|
|
public class AutoCompleteEditor extends BasicComboBoxEditor
|
|
{
|
|
private JTextField editor = null;
|
|
public AutoCompleteEditor(JComboBox combo, boolean caseSensitive)
|
|
{
|
|
super();
|
|
editor = new AutoCompleteEditorComponent(combo, caseSensitive);
|
|
}
|
|
/**
|
|
* overrides BasicComboBox's getEditorComponent to return custom TextField
|
|
(AutoCompleteEditorComponent) */
|
|
public Component getEditorComponent()
|
|
{
|
|
return editor;
|
|
}
|
|
}
|
|
|
|
/* * AutoCompleteEditorComponent.java */
|
|
public class AutoCompleteEditorComponent extends JTextField
|
|
{
|
|
JComboBox combo = null;
|
|
boolean caseSensitive = false;
|
|
public AutoCompleteEditorComponent(JComboBox combo, boolean caseSensitive)
|
|
{
|
|
super();
|
|
this.combo = combo;
|
|
this.caseSensitive = caseSensitive;
|
|
}
|
|
/**
|
|
* overwritten to return custom PlainDocument which does the work*/
|
|
protected Document createDefaultModel()
|
|
{
|
|
return new PlainDocument()
|
|
{
|
|
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException
|
|
{
|
|
if (str == null || str.length() == 0)
|
|
return;
|
|
int size = combo.getItemCount();
|
|
String text = getText(0, getLength());
|
|
for (int i = 0; i < size; i++)
|
|
{
|
|
String item = combo.getItemAt(i).toString();
|
|
if (getLength() + str.length() > item.length())
|
|
continue;
|
|
if (!caseSensitive)
|
|
{
|
|
if ((text + str).equalsIgnoreCase(item))
|
|
{
|
|
combo.setSelectedIndex(i);
|
|
//if (!combo.isPopupVisible())
|
|
// combo.setPopupVisible(true);
|
|
super.remove(0, getLength());
|
|
super.insertString(0, item, a);
|
|
return;
|
|
}
|
|
else if (item.substring(0, getLength() + str.length()).equalsIgnoreCase(text + str))
|
|
{
|
|
combo.setSelectedIndex(i);
|
|
if (!combo.isPopupVisible())
|
|
combo.setPopupVisible(true);
|
|
super.remove(0, getLength());
|
|
super.insertString(0, item, a);
|
|
return;
|
|
}
|
|
}
|
|
else if (caseSensitive)
|
|
{
|
|
if ((text + str).equals(item))
|
|
{
|
|
combo.setSelectedIndex(i);
|
|
if (!combo.isPopupVisible())
|
|
combo.setPopupVisible(true);
|
|
super.remove(0, getLength());
|
|
super.insertString(0, item, a);
|
|
return;
|
|
}
|
|
else if (item.substring(0, getLength() + str.length()).equals(text + str))
|
|
{
|
|
combo.setSelectedIndex(i);
|
|
if (!combo.isPopupVisible())
|
|
combo.setPopupVisible(true);
|
|
super.remove(0, getLength());
|
|
super.insertString(0, item, a);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|