001    /* Copyright (c) 2008, Henrik Niehaus
002     * All rights reserved.
003     *
004     * Redistribution and use in source and binary forms, with or without
005     * modification, are permitted provided that the following conditions are met:
006     *
007     * 1. Redistributions of source code must retain the above copyright notice,
008     *    this list of conditions and the following disclaimer.
009     * 2. Redistributions in binary form must reproduce the above copyright notice,
010     *    this list of conditions and the following disclaimer in the documentation
011     *    and/or other materials provided with the distribution.
012     * 3. Neither the name of the project nor the names of its
013     *    contributors may be used to endorse or promote products derived from this
014     *    software without specific prior written permission.
015     *
016     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
017     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
018     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
019     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
020     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
021     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
022     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
023     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
024     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
025     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
026     * POSSIBILITY OF SUCH DAMAGE.
027     */
028    package org.openstreetmap.josm.gui.widgets;
029    
030    import java.util.ArrayList;
031    import java.util.Iterator;
032    import java.util.List;
033    
034    import javax.swing.DefaultComboBoxModel;
035    
036    import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionListItem;
037    
038    public class ComboBoxHistory extends DefaultComboBoxModel implements Iterable<AutoCompletionListItem> {
039    
040        private int maxSize = 10;
041    
042        private List<HistoryChangedListener> listeners = new ArrayList<HistoryChangedListener>();
043    
044        public ComboBoxHistory(int size) {
045            maxSize = size;
046        }
047    
048        /**
049         * Adds or moves an element to the top of the history
050         */
051        @Override
052        public void addElement(Object o) {
053            if (o instanceof String) {
054                o = new AutoCompletionListItem((String) o);
055            }
056    
057            String newEntry = ((AutoCompletionListItem)o).getValue();
058    
059            // if history contains this object already, delete it,
060            // so that it looks like a move to the top
061            for (int i = 0; i < getSize(); i++) {
062                String oldEntry = ((AutoCompletionListItem) getElementAt(i)).getValue();
063                if(oldEntry.equals(newEntry)) {
064                    removeElementAt(i);
065                }
066            }
067    
068            // insert element at the top
069            insertElementAt(o, 0);
070    
071            // remove an element, if the history gets too large
072            if(getSize()> maxSize) {
073                removeElementAt(getSize()-1);
074            }
075    
076            // set selected item to the one just added
077            setSelectedItem(o);
078    
079            fireHistoryChanged();
080        }
081    
082        public Iterator<AutoCompletionListItem> iterator() {
083            return new Iterator<AutoCompletionListItem>() {
084    
085                private int position = -1;
086    
087                public void remove() {
088                    removeElementAt(position);
089                }
090    
091                public boolean hasNext() {
092                    if(position < getSize()-1 && getSize()>0)
093                        return true;
094                    return false;
095                }
096    
097                public AutoCompletionListItem next() {
098                    position++;
099                    return (AutoCompletionListItem)getElementAt(position);
100                }
101    
102            };
103        }
104    
105        public void setItemsAsString(List<String> items) {
106            removeAllElements();
107            for (int i = items.size()-1; i>=0; i--) {
108                addElement(new AutoCompletionListItem(items.get(i)));
109            }
110        }
111    
112        public List<String> asStringList() {
113            List<String> list = new ArrayList<String>(maxSize);
114            for (AutoCompletionListItem item : this) {
115                list.add(item.getValue());
116            }
117            return list;
118        }
119    
120        public void addHistoryChangedListener(HistoryChangedListener l) {
121            listeners.add(l);
122        }
123    
124        public void removeHistoryChangedListener(HistoryChangedListener l) {
125            listeners.remove(l);
126        }
127    
128        private void fireHistoryChanged() {
129            for (HistoryChangedListener l : listeners) {
130                l.historyChanged(asStringList());
131            }
132        }
133    }