package org.jabref.gui.autocompleter; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.List; import java.util.Vector; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; import javax.swing.JList; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; import javax.swing.ScrollPaneConstants; /** * Renders possible autocomplete items in form of a simple list. * * @param <E> the type of the items */ public class ListAutoCompleteRenderer<E> extends AutoCompleteRenderer<E> { private final DefaultListModel<E> model = new DefaultListModel<>(); private final JList<E> list = new JList<>(model); /** * Every selection change by the user is interpreted as accepting the new item as autocompletion. Thus we need this * helper variable to prevent that also programmatically trigger an autocompletion. */ private Boolean interpretSelectionChangeAsAccept = true; @Override public void update(List<E> autoCompletions) { if (autoCompletions == null) { model.removeAllElements(); } else { list.setListData(new Vector<>(autoCompletions)); list.clearSelection(); } } @Override public Component init(ActionListener newAcceptAction) { // Init list list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); list.setFocusable(false); list.setRequestFocusEnabled(false); list.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5)); list.addListSelectionListener(e -> { if (interpretSelectionChangeAsAccept && (newAcceptAction != null)) { newAcceptAction.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null)); } }); // Init pane containing the list JScrollPane scrollPane = new JScrollPane(list); scrollPane.setFocusable(false); scrollPane.setRequestFocusEnabled(false); scrollPane.setBorder(BorderFactory.createEmptyBorder()); scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); return scrollPane; } @Override public E getSelectedItem() { return list.getSelectedValue(); } @Override public void selectItem(int index) { interpretSelectionChangeAsAccept = false; // Set new index if valid otherwise clean selection if ((index >= 0) && (index < list.getModel().getSize())) { list.setSelectedIndex(index); list.ensureIndexIsVisible(index); } else { list.clearSelection(); } interpretSelectionChangeAsAccept = true; } @Override public int getSelectedIndex() { return list.getSelectedIndex(); } }