This class
AutoCompleteSupport
s support for filtering and autocompletion into
a standard
JComboBox
. It also acts as a factory class for
creating autocompleting table cell editors
.
All autocompletion behaviour provided is meant to mimic the functionality
of the Firefox address field. To be explicit, the following is a list of
expected behaviours which are installed:
Typing into the ComboBox Editor
- typing any value into the editor when the popup is invisible causes
the popup to appear and its contents to be filtered according to the
editor's text. It also autocompletes to the first item that is
prefixed with the editor's text and selects that item within the popup.
- typing any value into the editor when the popup is visible causes
the popup to be refiltered according to the editor's text and
reselects an appropriate autocompletion item
- typing the down or up arrow keys in the editor when the popup is
invisible causes the popup to appear and its contents to be filtered
according to the editor's text. It also autocompletes to the first
item that is prefixed with the editor's text and selects that item
within the popup.
- typing the up arrow key when the popup is visible and the selected
element is the first element causes the autocompletion to be cleared
and the popup's selection to be removed
- typing the up arrow key when no selection exists causes the last
element of the popup to become selected and used for autocompletion
- typing the down arrow key when the popup is visible and the selected
element is the last element causes the autocompletion to be cleared
and the popup's selection to be removed
- typing the down arrow key when no selection exists causes the first
element of the popup to become selected and used for autocompletion
Clicking on the Arrow Button
- clicking the arrow button when the popup is invisible causes the
popup to appear and its contents to be shown unfiltered
- clicking the arrow button when the popup is visible causes the popup
to be hidden
Sizing the ComboBox Popup
- the popup is always at least as wide as the
autocompleting
JComboBox
, but may be wider to accomodate a
prototype display value
if a non-null prototype display value exists
- as items are filtered in the ComboBoxModel, the popup height is
adjusted to display between 0 and
JComboBox.getMaximumRowCount()
rows before scrolling the popup
JComboBox ActionEvents
A single
ActionEvent
is fired from the JComboBox in these situations:
- the user hits the enter key
- the selected item within the popup is changed (which can happen due
to a mouse click, a change in the autocompletion term, or using the
arrow keys)
- the JComboBox loses focus and contains a value that does not appear
in the ComboBoxModel
Null Values in the ComboBoxModel
null
values located in the ComboBoxModel are considered
identical to empty Strings ("") for the purposes of locating autocompletion
terms.
ComboBoxEditor Focus
When the ComboBoxEditor gains focus it selects the text it contains if
getSelectsTextOnFocusGain()
returns
true; otherwise it
does nothing.
Extracting String Values
Each value in the ComboBoxModel must be converted to a String for many
reasons: filtering, setting into the ComboBoxEditor, displaying in the
renderer, etc. By default, JComboBox relies on
Object.toString()
to map elements to their String equivalents. Sometimes, however, toString()
is not a reliable or desirable mechanism to use. To deal with this problem,
AutoCompleteSupport provides an install method that takes a
Format
object which is used to do all converting back and forth between Strings and
ComboBoxModel objects.
In order to achieve all of the autocompletion and filtering behaviour,
the following occurs when
AutoCompleteSupport
is called:
- the JComboBox will be made editable
- the JComboBox will have a custom ComboBoxModel installed on it
containing the given items
- the ComboBoxEditor will be wrapped with functionality and set back
into the JComboBox as the editor
- the JTextField which is the editor component for the JComboBox
will have a DocumentFilter installed on its backing Document
The strategy of this support class is to alter all of the objects which
influence the behaviour of the JComboBox in one single context. With that
achieved, it greatly reduces the cross-functional communication required to
customize the behaviour of JComboBox for filtering and autocompletion.
Warning: This class must be
mutated from the Swing Event Dispatch Thread. Failure to do so will result in
an
IllegalStateException
thrown from any one of:
AutoCompleteSupport install
public static AutoCompleteSupport install(JComboBox comboBox,
EventList items)
Installs support for autocompletion into the
comboBox
and
returns the support object that is actually providing those facilities.
The support object is returned so that the caller may invoke
uninstall()
at some later time to remove the autocompletion
features.
This method assumes that the
items
can be converted into
reasonable String representations via
Object.toString()
.
The following must be true in order to successfully install support
for autocompletion on a
JComboBox
:
- The JComboBox must use a
JTextField
as its editor component
- The JTextField must use an
AbstractDocument
as its model
comboBox
- the JComboBox
to decorate with autocompletionitems
- the objects to display in the comboBox
- an instance of the support class providing autocomplete features
AutoCompleteSupport install
public static AutoCompleteSupport install(JComboBox comboBox,
EventList items,
TextFilterator filterator)
Installs support for autocompletion into the
comboBox
and
returns the support object that is actually providing those facilities.
The support object is returned so that the caller may invoke
uninstall()
at some later time to remove the autocompletion
features.
This method assumes that the
items
can be converted into
reasonable String representations via
Object.toString()
.
The
filterator
will be used to extract searchable text
strings from each of the
items
. A
null
filterator implies the item's toString() method should be used when
filtering it.
The following must be true in order to successfully install support
for autocompletion on a
JComboBox
:
- The JComboBox must use a
JTextField
as its editor component
- The JTextField must use an
AbstractDocument
as its model
comboBox
- the JComboBox
to decorate with autocompletionitems
- the objects to display in the comboBox
filterator
- extracts searchable text strings from each item;
null
implies the item's toString() method should be
used when filtering it
- an instance of the support class providing autocomplete features
AutoCompleteSupport install
public static AutoCompleteSupport install(JComboBox comboBox,
EventList items,
TextFilterator filterator,
Format format)
Installs support for autocompletion into the
comboBox
and
returns the support object that is actually providing those facilities.
The support object is returned so that the caller may invoke
uninstall()
at some later time to remove the autocompletion
features.
This method uses the given
format
to convert the
given
items
into Strings and back again. In other words,
this method does
NOT rely on
Object.toString()
to produce a reasonable String representation of each item. Likewise,
it does not rely on the existence of a valueOf(String) method for
creating items out of Strings as is the default behaviour of JComboBox.
It can be assumed that the only methods called on the given
format
are:
Format.format(Object)
Format.parseObject(String, ParsePosition)
As a convenience, this method will install a custom
ListCellRenderer
on the
comboBox
that displays the
String value returned by the
format
. Though this is only
done if the given
format
is not
null
and if
the
comboBox
does not already use a custom renderer.
The
filterator
will be used to extract searchable text
strings from each of the
items
. A
null
filterator implies one of two default strategies will be used. If the
format
is not null then the String value returned from the
format
object will be used when filtering a given item.
Otherwise, the item's toString() method will be used when it is filtered.
The following must be true in order to successfully install support
for autocompletion on a
JComboBox
:
- The JComboBox must use a
JTextField
as its editor component
- The JTextField must use an
AbstractDocument
as its model
comboBox
- the JComboBox
to decorate with autocompletionitems
- the objects to display in the comboBox
filterator
- extracts searchable text strings from each item. If the
format
is not null then the String value returned from
the format
object will be used when filtering a given
item. Otherwise, the item's toString() method will be used when it
is filtered.format
- a Format object capable of converting items
into Strings and back. null
indicates the standard
JComboBox methods of converting are acceptable.
- an instance of the support class providing autocomplete features
DefaultCellEditor createTableCellEditor
public static DefaultCellEditor createTableCellEditor(Comparator uniqueComparator,
TableFormat tableFormat,
EventList tableData,
int columnIndex)
This factory method creates and returns a
DefaultCellEditor
which adapts an autocompleting
JComboBox
for use as a Table
Cell Editor. The values within the table column are used as
autocompletion terms within the
ComboBoxModel
.
This version of
createTableCellEditor
makes no
assumption about the values stored in the TableModel at the given
columnIndex
. Instead, it uses the given
uniqueComparator
to determine which values are duplicates
(and thus can safely be removed) and which are unique (and thus must
remain in the
ComboBoxModel
).
Note that this factory method is only appropriate for use when the
values in the
ComboBoxModel
should be the unique set of values
in a table column. If some other list of values will be used, do not use
this factory method and create the
DefaultCellEditor
directly
with code similar to this:
EventList comboBoxModelValues = ...
JComboBox comboBox = new JComboBox();
DefaultCellEditor cellEditor = new DefaultCellEditor(comboBox);
AutoCompleteSupport.install(comboBox, comboBoxModelValues);
If the appearance or function of the autocompleting
JComboBox
is to be customized, it can be retrieved using
DefaultCellEditor.getComponent()
.
uniqueComparator
- the Comparator
that strips away
duplicate elements from the ComboBoxModel
tableFormat
- specifies how each row object within a table is
broken apart into column valuestableData
- the EventList
backing the TableModelcolumnIndex
- the index of the column for which to return a
DefaultCellEditor
- a
DefaultCellEditor
which contains an autocompleting
combobox whose contents remain consistent with the data in the
table column at the given columnIndex
DefaultCellEditor createTableCellEditor
public static DefaultCellEditor createTableCellEditor(TableFormat tableFormat,
EventList tableData,
int columnIndex)
This factory method creates and returns a
DefaultCellEditor
which adapts an autocompleting
JComboBox
for use as a Table
Cell Editor. The values within the table column are used as
autocompletion terms within the
ComboBoxModel
.
This version of
createTableCellEditor
assumes that the
values stored in the TableModel at the given
columnIndex
are all
Comparable
, and that the natural ordering defined by
those
Comparable
values also determines which are duplicates
(and thus can safely be removed) and which are unique (and thus must
remain in the
ComboBoxModel
).
Note that this factory method is only appropriate for use when the
values in the
ComboBoxModel
should be the unique set of values
in a table column. If some other list of values will be used, do not use
this factory method and create the
DefaultCellEditor
directly
with code similar to this:
EventList comboBoxModelValues = ...
JComboBox comboBox = new JComboBox();
DefaultCellEditor cellEditor = new DefaultCellEditor(comboBox);
AutoCompleteSupport.install(comboBox, comboBoxModelValues);
If the appearance or function of the autocompleting
JComboBox
is to be customized, it can be retrieved using
DefaultCellEditor.getComponent()
.
tableFormat
- specifies how each row object within a table is
broken apart into column valuestableData
- the EventList
backing the TableModelcolumnIndex
- the index of the column for which to return a
DefaultCellEditor
- a
DefaultCellEditor
which contains an autocompleting
combobox whose contents remain consistent with the data in the
table column at the given columnIndex
getComboBox
public JComboBox getComboBox()
getCorrectsCase
public boolean getCorrectsCase()
Returns true if user specified strings are converted to the
case of the autocompletion term they match; false otherwise.
getFilterMode
public int getFilterMode()
Returns the manner in which the contents of the
ComboBoxModel
are filtered. This method will return one of
TextMatcherEditor.CONTAINS
or
TextMatcherEditor.STARTS_WITH
.
TextMatcherEditor.CONTAINS
indicates elements of the
ComboBoxModel
are matched when they contain the text entered by
the user.
TextMatcherEditor.STARTS_WITH
indicates elements of the
ComboBoxModel
are matched when they start with the text entered
by the user.
In both modes, autocompletion only occurs when a given item starts
with user-specified text. The filter mode only affects the filtering
aspect of autocomplete support.
getItemList
public EventList getItemList()
Returns the filtered
EventList
of items which backs the
ComboBoxModel
of the autocompleting
JComboBox
.
getSelectsTextOnFocusGain
public boolean getSelectsTextOnFocusGain()
Returns true if the combo box editor text is selected when it
gains focus; false otherwise.
getTextFilterator
public TextFilterator getTextFilterator()
Returns the
TextFilterator
that extracts searchable strings from
each item in the
ComboBoxModel
.
isStrict
public boolean isStrict()
Returns true if the user is able to specify values which do not
appear in the popup list of suggestions; false otherwise.
setCorrectsCase
public void setCorrectsCase(boolean correctCase)
If
correctCase
is
true, user specified strings
will be converted to the case of the element they match. Otherwise
they will be left unaltered.
Note: this flag only has meeting when strict mode is turned off.
When strict mode is on, case is corrected regardless of this setting.
setFilterMode
public void setFilterMode(int mode)
setSelectsTextOnFocusGain
public void setSelectsTextOnFocusGain(boolean selectsTextOnFocusGain)
If selectsTextOnFocusGain
is true, all text in the
editor is selected when the combo box editor gains focus. If it is
false the selection state of the editor is not effected by
focus changes.
setStrict
public void setStrict(boolean strict)
If
strict
is
true, the user can specify values not
appearing within the ComboBoxModel. If it is
false each
keystroke must continue to match some value in the ComboBoxModel or it
will be discarded.
Note: When strict mode is enabled, all user input is corrected to the
case of the autocompletion term, regardless of the correctsCase setting.
uninstall
public void uninstall()
This method removes autocompletion support from the
JComboBox
it was installed on. This method is useful when the
EventList
of
items that backs the combo box must outlive the combo box itself.
Calling this method will return the combo box to its original state
before autocompletion was installed, and it will be available for
garbage collection independently of the
EventList
of items.