001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.widgets;
003
004import java.util.ArrayList;
005import java.util.Iterator;
006import java.util.List;
007import java.util.NoSuchElementException;
008
009import javax.swing.DefaultComboBoxModel;
010
011import org.openstreetmap.josm.data.tagging.ac.AutoCompletionItem;
012
013/**
014 * A data model for {@link HistoryComboBox}
015 */
016class ComboBoxHistory extends DefaultComboBoxModel<AutoCompletionItem> implements Iterable<AutoCompletionItem> {
017
018    private final int maxSize;
019
020    /**
021     * Constructs a {@code ComboBoxHistory} keeping track of {@code maxSize} items
022     * @param size the history size
023     */
024    ComboBoxHistory(int size) {
025        maxSize = size;
026    }
027
028    /**
029     * Adds or moves an element to the top of the history
030     * @param s the element to add
031     */
032    public void addElement(String s) {
033        addElement(new AutoCompletionItem(s));
034    }
035
036    /**
037     * Adds or moves an element to the top of the history
038     * @param o the element to add
039     */
040    @Override
041    public void addElement(AutoCompletionItem o) {
042        String newEntry = o.getValue();
043
044        // if history contains this object already, delete it,
045        // so that it looks like a move to the top
046        for (int i = 0; i < getSize(); i++) {
047            String oldEntry = getElementAt(i).getValue();
048            if (oldEntry.equals(newEntry)) {
049                removeElementAt(i);
050            }
051        }
052
053        // insert element at the top
054        insertElementAt(o, 0);
055
056        // remove an element, if the history gets too large
057        if (getSize() > maxSize) {
058            removeElementAt(getSize()-1);
059        }
060
061        // set selected item to the one just added
062        setSelectedItem(o);
063    }
064
065    @Override
066    public Iterator<AutoCompletionItem> iterator() {
067        return new Iterator<AutoCompletionItem>() {
068
069            private int position = -1;
070
071            @Override
072            public void remove() {
073                removeElementAt(position);
074            }
075
076            @Override
077            public boolean hasNext() {
078                return position < getSize()-1 && getSize() > 0;
079            }
080
081            @Override
082            public AutoCompletionItem next() {
083                if (!hasNext())
084                    throw new NoSuchElementException();
085                position++;
086                return getElementAt(position);
087            }
088        };
089    }
090
091    /**
092     * {@link javax.swing.DefaultComboBoxModel#removeAllElements() Removes all items}
093     * and {@link ComboBoxHistory#addElement(String) adds} the given items.
094     * @param items the items to set
095     */
096    public void setItemsAsString(List<String> items) {
097        removeAllElements();
098        for (int i = items.size()-1; i >= 0; i--) {
099            addElement(items.get(i));
100        }
101    }
102
103    /**
104     * Returns the {@link AutoCompletionItem} items as strings
105     * @return a list of strings
106     */
107    public List<String> asStringList() {
108        List<String> list = new ArrayList<>(maxSize);
109        for (AutoCompletionItem item : this) {
110            list.add(item.getValue());
111        }
112        return list;
113    }
114}