Package docking.widgets.autocomplete

# Class TextFieldAutocompleter<T>

java.lang.Object
docking.widgets.autocomplete.TextFieldAutocompleter<T>

Type Parameters:
  `T` - the type of suggestions presented by this autocompleter.

public class TextFieldAutocompleter<T> extends Object
An autocompleter that may be attached to one or more `JTextField`.

Each autocompleter instance has one associated window (displaying the list of suggestions) and one associated model (generating the list of suggestions). Thus, the list can only be active on one of the attached text fields at a time. This is usually the desired behavior, and it allows for one autocompleter to be reused on many fields. Behavior is undefined when multiple autocompleters are attached to the same text field. More likely, you should implement a composite model if you wish to present completions from multiple models on a single text field.

By default, the autocompleter is activated when the user presses CTRL-SPACE, at which point, the model is queried for possible suggestions. The completer gives the model all the text preceding the current field's caret. This behavior can be changed by overriding the `getPrefix(JTextField)` method. This may be useful, e.g., to obtain a prefix for the current word, rather than the full field contents, preceding the caret. The list is displayed such that its top-left corner is placed directly under the current field's caret. As the user continues typing, the suggestions are re-computed, and the list tracks with the caret. This positioning behavior can be modified by overriding the `getCompletionWindowPosition()` method. As a convenience, the `getCaretPositionOnScreen(JTextField)` method is available to compute the default position.

Whether or not the list is currently displayed, when the user presses CTRL-SPACE, if only one completion is possible, it is automatically activated. This logic is applied again and again, until either no suggestions are given, or more than one suggestion is given (or until the autocompleter detects an infinite loop). This behavior can by modified on an item-by-item basis by overriding the `getCompletionCanDefault(T)` method. This same behavior can be activated by calling the `startCompletion(JTextField)` method, which may be useful, e.g., to bind a different key sequence to start autocompletion.

The appearance of each item in the suggestion list can be modified by overriding the various `getCompletion...` methods. Note that it's possible for an item to be displayed one way, but cause the insertion of different text. In any case, it is best to ensure any modification produces an intuitive behavior.

The simplest use case is to create a text field, create an autocompleter with a custom model, and then attach and show.

     JTextField field = new JTextField();

     AutocompletionModel model = new AutocompletionModel() {
         @Override
         public Collection computeCompletions(String text) {
             // ... Populate the completion list based on the given prefix.
         }
     }
     TextFieldAutocompleter completer = new TextFieldAutocompleter(model);
     completer.attachTo(field);
     // ... Add the field to, e.g., a dialog, and show.

- ## Nested Class Summary

  Nested Classes
  Modifier and Type
  Class
  Description
  `static class`
  `TextFieldAutocompleter.DualTextAutocompleterDemo`
  A demonstration of the autocompleter on two linked text fields.
  `protected class`
  `TextFieldAutocompleter.MyListener`
  A listener to handle all the callbacks
  `static class`
  `TextFieldAutocompleter.TextFieldAutocompleterDemo`
  A demonstration of the autocompleter on a single text field.

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `protected TextFieldAutocompleter<T>.MyListener`
  `listener`

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `TextFieldAutocompleter(AutocompletionModel<T> model)`
  Create a new autocompleter associated with the given model.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `protected void`
  `activateCurrentCompletion()`
  Cause the currently-selected suggestion to be activated.
  `void`
  `addAutocompletionListener(AutocompletionListener<T> l)`
  Register the given auto-completion listener
  `protected void`
  `addContent(JPanel contentPanel)`
  `boolean`
  `attachTo(JTextField field)`
  Attach the autocompleter to the given text field.
  `protected void`
  `buildCompletionWindow()`
  Build the completion window, parented to the attached field that last had focus.
  `protected ListCellRenderer<? super T>`
  `buildListCellRenderer()`
  Builds the list cell renderer for the autocompletion list.
  `protected void`
  `destroyCompletionWindow()`
  Dispose of the completion window resources.
  `boolean`
  `detachFrom(JTextField field)`
  Deprive the given field of this autocompleter.
  `void`
  `dispose()`
  `protected boolean`
  `fireAutocompletionListeners(AutocompletionEvent<T> ev)`
  Fire the registered autocompletion listeners on the given event.
  `void`
  `flushUpdates()`
  If a completion list update is pending, run it immediately
  `AutocompletionListener<T>[]`
  `getAutocompletionListeners()`
  Get all the registered auto-completion listeners
  `protected Point`
  `getCaretPositionOnScreen(JTextField field)`
  A convenience function that returns the bottom on-screen position of the given field's caret.
  `protected Color`
  `getCompletionBackground(T sel, boolean isSelected, boolean cellHasFocus)`
  Get the background color to display for the given suggestion in the list
  `protected boolean`
  `getCompletionCanDefault(T sel)`
  Decide whether the given suggestion can be automatically activated.
  `protected String`
  `getCompletionDisplay(T sel)`
  Get the (possibly HTML) text to display for the given suggestion in the list
  `protected Font`
  `getCompletionFont(T sel, boolean isSelected, boolean cellHasFocus)`
  Get the font for the given suggestion in the list
  `protected Color`
  `getCompletionForeground(T sel, boolean isSelected, boolean cellHasFocus)`
  Get the foreground color to display for the given suggestion in the list
  `protected Icon`
  `getCompletionIcon(T sel, boolean isSelected, boolean cellHasFocus)`
  Get the icon to display with the given suggestion in the list
  `protected String`
  `getCompletionText(T sel)`
  Get the text to insert when the given suggestion is activated
  `protected Point`
  `getCompletionWindowPosition()`
  Get the preferred location (on screen) of the completion list window.
  `protected Dimension`
  `getDefaultCompletionWindowDimension()`
  Get the preferred dimensions of the completion list window.
  `<T> T[]`
  `getListeners(Class<T> listenerType)`
  Get all registered listeners of the given type
  `protected String`
  `getPrefix(JTextField field)`
  Gets the prefix from the given text field, used to query the model.
  `List<T>`
  `getSuggestions()`
  Get the list of suggestions as ordered on screen
  `boolean`
  `isCompletionListVisible()`
  Check if the completion list window is visible.
  `void`
  `removeAutocompletionListener(AutocompletionListener<T> l)`
  Unregister the given auto-completion listener
  `void`
  `select(int index)`
  Cause the suggestion at the given index to be selected
  `void`
  `selectFirst()`
  Select the first suggestion
  `void`
  `selectLast()`
  Select the last suggestion
  `void`
  `selectNext()`
  Cause the next suggestion to be selected, wrapping if applicable
  `protected void`
  `selectNextPage()`
  Advance the selection down a page
  `void`
  `selectPrev()`
  Cause the previous suggestion to be selected, wrapping if applicable
  `protected void`
  `selectPrevPage()`
  Advance the selection up a page
  `void`
  `setCompletionListVisible(boolean visible)`
  Show or hide the completion list window
  `void`
  `startCompletion(JTextField field)`
  Starts the autocompleter on the given text field.
  `protected void`
  `updateDisplayContents()`
  Update the contents of the suggestion list.
  `void`
  `updateDisplayLocation()`
  Recompute the display location and move with list window.
  `void`
  `updateNow()`
  Update the completion list immediately

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Field Details

  - ### listener

    protected TextFieldAutocompleter<T>.MyListener listener

- ## Constructor Details

  - ### TextFieldAutocompleter

    public TextFieldAutocompleter(AutocompletionModel<T> model)
    Create a new autocompleter associated with the given model.
    Parameters:
      `model` - the model giving the suggestions.

- ## Method Details

  - ### dispose

    public void dispose()

  - ### addContent

    protected void addContent(JPanel contentPanel)

  - ### updateDisplayLocation

    public void updateDisplayLocation()
    Recompute the display location and move with list window.

    This is useful, e.g., when the window containing the associated text field(s) moves.

  - ### updateDisplayContents

    protected void updateDisplayContents()
    Update the contents of the suggestion list.

    This entails taking the prefix, querying the model, and rendering the list.

  - ### destroyCompletionWindow

    protected void destroyCompletionWindow()
    Dispose of the completion window resources.

  - ### buildCompletionWindow

    protected void buildCompletionWindow()
    Build the completion window, parented to the attached field that last had focus.

  - ### setCompletionListVisible

    public void setCompletionListVisible(boolean visible)
    Show or hide the completion list window
    Parameters:
      `visible` - true to show, false to hide

  - ### isCompletionListVisible

    public boolean isCompletionListVisible()
    Check if the completion list window is visible.

    If it is visible, this implies that the user is actively using the autocompleter.

    Returns:
      true if shown, false if hidden.

  - ### getPrefix

    protected String getPrefix(JTextField field)
    Gets the prefix from the given text field, used to query the model.
    Parameters:
      `field` - an attached field, usually the one with focus.
    Returns:
      the prefix to use as the query.

  - ### getCompletionWindowPosition

    protected Point getCompletionWindowPosition()
    Get the preferred location (on screen) of the completion list window.

    Typically, this is a location near the focused field. Ideally, it is positioned such that the displayed suggestions coincide with the applicable text in the focused field. For example, if the suggestions display some portion of the prefix, the window could be positioned such that the portion in the suggestion appears directly below the same portion in the field.

    Returns:
      the point giving the top-left corner of the completion window

  - ### getDefaultCompletionWindowDimension

    protected Dimension getDefaultCompletionWindowDimension()
    Get the preferred dimensions of the completion list window.

    Typically, this is the width of the focused field.

    Returns:
      the dimension giving the preferred height and width. A value can be -1 to indicate no preference.

  - ### getCaretPositionOnScreen

    protected Point getCaretPositionOnScreen(JTextField field)
    A convenience function that returns the bottom on-screen position of the given field's caret.
    Parameters:
      `field` - the field, typically the one having focus
    Returns:
      the on-screen position of the caret's bottom; null if the given field is null

  - ### buildListCellRenderer

    protected ListCellRenderer<? super T> buildListCellRenderer()
    Builds the list cell renderer for the autocompletion list.

    A programmer may override this if the various `getCompletion...` methods prove insufficient for customizing the display of the suggestions. Please remember that `JLabel`s can render HTML, so `getCompletionDisplay(T)` is quite powerful with the default `AutocompletionCellRenderer`.

    Returns:
      a list cell renderer for the completion list.

  - ### attachTo

    public boolean attachTo(JTextField field)
    Attach the autocompleter to the given text field.

    If this method is never called, then the autocompleter can never appear.

    Parameters:
      `field` - the field that will gain this autocompletion feature
    Returns:
      true, if this field is not already attached

  - ### detachFrom

    public boolean detachFrom(JTextField field)
    Deprive the given field of this autocompleter.
    Parameters:
      `field` - the field that will lose this autocompletion feature
    Returns:
      true, if this field was actually attached

  - ### activateCurrentCompletion

    protected void activateCurrentCompletion()
    Cause the currently-selected suggestion to be activated.

    By default, this is called when the user presses ENTER or clicks a suggestion.

  - ### fireAutocompletionListeners

    protected boolean fireAutocompletionListeners(AutocompletionEvent<T> ev)
    Fire the registered autocompletion listeners on the given event.

    Each registered listener is invoked in order of registration. If any listener consumes the event, then later-registered listeners will not be notified of the event. If any listener cancels the event, then the suggested text will not be inserted.

    Parameters:
      `ev` - the event
    Returns:
      true, if no listener cancelled the event

  - ### addAutocompletionListener

    public void addAutocompletionListener(AutocompletionListener<T> l)
    Register the given auto-completion listener
    Parameters:
      `l` - the listener to register

  - ### removeAutocompletionListener

    public void removeAutocompletionListener(AutocompletionListener<T> l)
    Unregister the given auto-completion listener
    Parameters:
      `l` - the listener to unregister

  - ### getAutocompletionListeners

    public AutocompletionListener<T>[] getAutocompletionListeners()
    Get all the registered auto-completion listeners
    Returns:
      an array of registered listeners

  - ### getListeners

    public <T> T[] getListeners(Class<T> listenerType)
    Get all registered listeners of the given type
    Parameters:
      `listenerType` - the type of listeners to get
    Returns:
      an array of registered listeners

  - ### getCompletionText

    protected String getCompletionText(T sel)
    Get the text to insert when the given suggestion is activated
    Parameters:
      `sel` - the activated suggestion
    Returns:
      the text to insert

  - ### getCompletionDisplay

    protected String getCompletionDisplay(T sel)
    Get the (possibly HTML) text to display for the given suggestion in the list
    Parameters:
      `sel` - the suggestion to display
    Returns:
      the text or HTML representing the suggestion

  - ### getCompletionForeground

    protected Color getCompletionForeground(T sel, boolean isSelected, boolean cellHasFocus)
    Get the foreground color to display for the given suggestion in the list
    Parameters:
      `sel` - the suggestion to display
      `isSelected` - true if the suggestion is currently selected
      `cellHasFocus` - true if the suggestion currently has focus
    Returns:
      the foreground color for the suggestion

  - ### getCompletionBackground

    protected Color getCompletionBackground(T sel, boolean isSelected, boolean cellHasFocus)
    Get the background color to display for the given suggestion in the list
    Parameters:
      `sel` - the suggestion to display
      `isSelected` - true if the suggestion is currently selected
      `cellHasFocus` - true if the suggestion currently has focus
    Returns:
      the background color for the suggestion

  - ### getCompletionIcon

    protected Icon getCompletionIcon(T sel, boolean isSelected, boolean cellHasFocus)
    Get the icon to display with the given suggestion in the list
    Parameters:
      `sel` - the suggestion to display
      `isSelected` - true if the suggestion is currently selected
      `cellHasFocus` - true if the suggestion currently has focus
    Returns:
      the icon to display with the suggestion

  - ### getCompletionFont

    protected Font getCompletionFont(T sel, boolean isSelected, boolean cellHasFocus)
    Get the font for the given suggestion in the list
    Parameters:
      `sel` - the suggestion to display
      `isSelected` - true if the suggestion is currently selected
      `cellHasFocus` - true if the suggestion currently has focus
    Returns:
      the font to use

  - ### getCompletionCanDefault

    protected boolean getCompletionCanDefault(T sel)
    Decide whether the given suggestion can be automatically activated.

    When autocompletion is started (via `startCompletion(JTextField)`) or when the user presses CTRL-SPACE, if there is only a single suggestion, it is taken automatically, and the process repeats until there is not a sole suggestion. Before the suggestion is taken, though, it calls this method. If it returns false, the single suggestion is displayed in a 1-long list instead. This is useful to prevent consequential actions from being automatically activated by the autocompleter.

    Parameters:
      `sel` - the potentially auto-activated suggestion.
    Returns:
      true to permit auto-activation, false to prevent it.

  - ### startCompletion

    public void startCompletion(JTextField field)
    Starts the autocompleter on the given text field.

    First, this repeatedly attempts auto-activation. When there are many suggestions, or when auto-activation is prevented (see `getCompletionCanDefault(T)`), a list is displayed (usually below the caret) containing the suggestions given the fields current contents. The list remains open until either the user cancels it (usually via ESC) or the user activates a suggestion.

    NOTE: The text field must already be attached.

    Parameters:
      `field` - the field on which to start autocompletion.

  - ### flushUpdates

    public void flushUpdates()
    If a completion list update is pending, run it immediately

  - ### updateNow

    public void updateNow()
    Update the completion list immediately

  - ### select

    public void select(int index)
    Cause the suggestion at the given index to be selected
    Parameters:
      `index` - the index of the selection

  - ### selectNext

    public void selectNext()
    Cause the next suggestion to be selected, wrapping if applicable

  - ### selectPrev

    public void selectPrev()
    Cause the previous suggestion to be selected, wrapping if applicable

  - ### selectNextPage

    protected void selectNextPage()
    Advance the selection down a page

  - ### selectPrevPage

    protected void selectPrevPage()
    Advance the selection up a page

  - ### selectFirst

    public void selectFirst()
    Select the first suggestion

  - ### selectLast

    public void selectLast()
    Select the last suggestion

  - ### getSuggestions

    public List<T> getSuggestions()
    Get the list of suggestions as ordered on screen
    Returns:
      an immutable copy of the list