001    /*
002     * $Id: ListComboBoxModel.java 3374 2009-07-01 14:36:43Z kschaefe $
003     *
004     * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005     * Santa Clara, California 95054, U.S.A. All rights reserved.
006     *
007     * This library is free software; you can redistribute it and/or
008     * modify it under the terms of the GNU Lesser General Public
009     * License as published by the Free Software Foundation; either
010     * version 2.1 of the License, or (at your option) any later version.
011     * 
012     * This library is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015     * Lesser General Public License for more details.
016     * 
017     * You should have received a copy of the GNU Lesser General Public
018     * License along with this library; if not, write to the Free Software
019     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020     */
021    package org.jdesktop.swingx.combobox;
022    
023    import java.awt.event.ActionEvent;
024    import java.awt.event.ActionListener;
025    import java.util.List;
026    
027    import javax.swing.AbstractListModel;
028    import javax.swing.ComboBoxModel;
029    
030    /**
031     * A {@code ComboBoxModel} for {@code List}s.
032     *
033     * @param <E> the type of elements maintained by the list backing this model
034     * 
035     * @author jm158417
036     * @author Karl George Schaefer
037     */
038    public class ListComboBoxModel<E> extends AbstractListModel implements ComboBoxModel, ActionListener {
039        /**
040         * A key used to notify the model that the backing {@code List} has changed.
041         */
042        public static final String UPDATE = "update";
043        
044        /**
045         * A reference to the list backing this model.
046         * <p>
047         * This model does <b>not</b> make a copy of the list, so any changes in
048         * the list without synchronizing the model may have drastic effects.
049         */
050        protected final List<E> data;
051        
052        /**
053         * The currently selected item.
054         */
055        protected E selected;
056        
057        /**
058         * Creates a {@code ListComboBoxModel} backed by the supplied {@code list}.
059         * 
060         * @param list
061         *                the list backing this model
062         * @throws NullPointerException
063         *                 if {@code list} is {@code null}
064         */
065        public ListComboBoxModel(List<E> list) {
066            this.data = list;
067            
068            if(list.size() > 0) {
069                selected = list.get(0);
070            }
071        }
072        
073        /**
074         * Set the selected item. The implementation of this method should notify
075         * all registered {@code ListDataListener}s that the contents have changed.
076         * 
077         * @param item
078         *                the list object to select or {@code null} to clear the
079         *                selection
080         * @throws ClassCastException
081         *                 if {@code item} is not of type {@code E}
082         */
083        @SuppressWarnings("unchecked")
084        public void setSelectedItem(Object item) {
085            if ((selected != null && !selected.equals(item))
086                    || selected == null && item != null) {
087                selected = (E) item;
088                fireContentsChanged(this, -1, -1);
089            }
090        }
091        
092        /**
093         * {@inheritDoc}
094         */
095        public E getSelectedItem() {
096            return this.selected;
097        }
098        
099        /**
100         * {@inheritDoc}
101         */
102        public E getElementAt(int index) {
103            return data.get(index);
104        }
105        
106        /**
107         * {@inheritDoc}
108         */
109        public int getSize() {
110            return data.size();
111        }
112        
113        /**
114         * {@inheritDoc}
115         */
116        public void actionPerformed(ActionEvent evt) {
117            if(evt.getActionCommand().equals(UPDATE)) {
118                this.fireContentsChanged(this, 0, getSize() - 1);
119            }
120        }
121    }