// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.gui.tagging.ac; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Set; import javax.swing.JTable; import javax.swing.table.AbstractTableModel; import org.openstreetmap.josm.data.tagging.ac.AutoCompletionItem; import org.openstreetmap.josm.data.tagging.ac.AutoCompletionPriority; import org.openstreetmap.josm.data.tagging.ac.AutoCompletionSet; import org.openstreetmap.josm.tools.CheckParameterUtil; /** * AutoCompletionList manages a graphical list of {@link AutoCompletionItem}s. * * The list is sorted, items with higher priority first, then according to lexicographic order * on the value of the {@link AutoCompletionItem}. * * AutoCompletionList maintains two views on the list of {@link AutoCompletionItem}s. *
    *
  1. the bare, unfiltered view which includes all items
  2. *
  3. a filtered view, which includes only items which match a current filter expression
  4. *
* * AutoCompletionList is an {@link AbstractTableModel} which serves the list of filtered * items to a {@link JTable}. * @since 1762 */ public class AutoCompletionList extends AbstractTableModel { /** the bare list of AutoCompletionItems */ private final transient AutoCompletionSet list; /** the filtered list of AutoCompletionItems */ private final transient ArrayList filtered; /** the filter expression */ private String filter; /** * constructor */ public AutoCompletionList() { list = new AutoCompletionSet(); filtered = new ArrayList<>(); } /** * applies a filter expression to the list of {@link AutoCompletionItem}s. * * The matching criterion is a case insensitive substring match. * * @param filter the filter expression; must not be null * * @throws IllegalArgumentException if filter is null */ public void applyFilter(String filter) { CheckParameterUtil.ensureParameterNotNull(filter, "filter"); this.filter = filter; filter(); } /** * clears the current filter */ public void clearFilter() { filter = null; filter(); } /** * @return the current filter expression; null, if no filter expression is set */ public String getFilter() { return filter; } /** * adds an {@link AutoCompletionItem} to the list. Only adds the item if it * is not null and if not in the list yet. * * @param item the item * @since 12859 */ public void add(AutoCompletionItem item) { if (item != null && list.add(item)) { filter(); } } /** * adds another {@link AutoCompletionList} to this list. An item is only * added it is not null and if it does not exist in the list yet. * * @param other another auto completion list; must not be null * @throws IllegalArgumentException if other is null */ public void add(AutoCompletionList other) { CheckParameterUtil.ensureParameterNotNull(other, "other"); add(other.list); } /** * adds a colleciton of {@link AutoCompletionItem} to this list. An item is only * added it is not null and if it does not exist in the list yet. * * @param collection auto completion collection; must not be null * @throws IllegalArgumentException if other is null * @since 12859 */ public void add(Collection collection) { CheckParameterUtil.ensureParameterNotNull(collection, "collection"); if (list.addAll(collection)) { filter(); } } /** * adds a list of strings to this list. Only strings which * are not null and which do not exist yet in the list are added. * * @param values a list of strings to add * @param priority the priority to use * @since 12859 */ public void add(Collection values, AutoCompletionPriority priority) { if (values != null && list.addAll(values, priority)) { filter(); } } /** * Adds values that have been entered by the user. * @param values values that have been entered by the user */ public void addUserInput(Collection values) { if (values != null && list.addUserInput(values)) { filter(); } } /** * checks whether a specific item is already in the list. Matches for the * the value and the priority of the item * * @param item the item to check * @return true, if item is in the list; false, otherwise * @since 12859 */ public boolean contains(AutoCompletionItem item) { return list.contains(item); } /** * checks whether an item with the given value is already in the list. Ignores * priority of the items. * * @param value the value of an auto completion item * @return true, if value is in the list; false, otherwise */ public boolean contains(String value) { return list.contains(value); } /** * removes the auto completion item with key key * @param key the key */ public void remove(String key) { if (key != null) { list.remove(key); } } protected void filter() { filtered.clear(); if (filter == null) { // Collections.copy throws an exception "Source does not fit in dest" filtered.ensureCapacity(list.size()); filtered.addAll(list); return; } // apply the pattern to list of possible values. If it matches, add the // value to the list of filtered values // list.stream().filter(e -> e.getValue().startsWith(filter)).forEach(filtered::add); fireTableDataChanged(); } /** * replies the number of filtered items * * @return the number of filtered items */ public int getFilteredSize() { return filtered.size(); } /** * replies the idx-th item from the list of filtered items * @param idx the index; must be in the range 0 <= idx < {@link #getFilteredSize()} * @return the item * * @throws IndexOutOfBoundsException if idx is out of bounds * @since 12859 */ public AutoCompletionItem getFilteredItemAt(int idx) { return filtered.get(idx); } AutoCompletionSet getSet() { return list; } Set getUnmodifiableSet() { return Collections.unmodifiableSet(list); } /** * removes all elements from the auto completion list */ public void clear() { list.clear(); fireTableDataChanged(); } @Override public int getColumnCount() { return 1; } @Override public int getRowCount() { return list == null ? 0 : getFilteredSize(); } @Override public Object getValueAt(int rowIndex, int columnIndex) { return list == null ? null : getFilteredItemAt(rowIndex); } }