001    /*
002     * $Id: ComboBoxAdaptor.java 3100 2008-10-14 22:33:10Z rah003 $
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.autocomplete;
022    
023    import java.awt.Rectangle;
024    import java.awt.event.ActionEvent;
025    import java.awt.event.ActionListener;
026    
027    import javax.accessibility.Accessible;
028    import javax.swing.JComboBox;
029    import javax.swing.JList;
030    import javax.swing.plaf.basic.ComboPopup;
031    import javax.swing.text.JTextComponent;
032    
033    /**
034     * An implementation of the AbstractAutoCompleteAdaptor that is suitable for JComboBox.
035     * 
036     * @author Thomas Bierhance
037     * @author Karl Schaefer
038     */
039    public class ComboBoxAdaptor extends AbstractAutoCompleteAdaptor implements ActionListener {
040        
041        /** the combobox being adapted */
042        private JComboBox comboBox;
043        
044        /**
045         * Creates a new ComobBoxAdaptor for the given combobox.
046         * @param comboBox the combobox that should be adapted
047         */
048        public ComboBoxAdaptor(JComboBox comboBox) {
049            this.comboBox = comboBox;
050            // mark the entire text when a new item is selected
051            comboBox.addActionListener(this);
052        }
053        
054        /**
055         * Implementation side effect - do not invoke.
056         * @param actionEvent -
057         */
058        // ActionListener (listening to comboBox)
059        public void actionPerformed(ActionEvent actionEvent) {
060            markEntireText();
061        }
062        
063        public int getItemCount() {
064            return comboBox.getItemCount();
065        }
066        
067        public Object getItem(int index) {
068            return comboBox.getItemAt(index);
069        }
070        
071        public void setSelectedItem(Object item) {
072            //SwingX 834: avoid moving when already selected
073            if (item == getSelectedItem()) {
074                return;
075            }
076            
077            // kgs - back door our way to finding the JList that displays the data.
078            // then we ask the list to scroll until the last cell is visible. this
079            // will cause the selected item to appear closest to the top.
080            //
081            // it is unknown whether this functionality will work outside of Sun's
082            // implementation, but the code is safe and will "fail gracefully" on
083            // other systems
084            Accessible a = comboBox.getUI().getAccessibleChild(comboBox, 0);
085            
086            if (getItemCount() > 0 && a instanceof ComboPopup) {
087                JList list = ((ComboPopup) a).getList();
088                int lastIndex = list.getModel().getSize() - 1;
089                
090                Rectangle rect = list.getCellBounds(lastIndex, lastIndex);
091                
092                if (rect == null) {
093                    throw new IllegalStateException(
094                            "attempting to access index " + lastIndex + " for " + comboBox);
095                }
096                
097                list.scrollRectToVisible(rect);
098            }
099            
100            //setting the selected item should scroll it into the visible region
101            comboBox.setSelectedItem(item);
102        }
103        
104        public Object getSelectedItem() {
105            return comboBox.getModel().getSelectedItem();
106        }
107        
108        public JTextComponent getTextComponent() {
109            // returning the component of the combobox's editor
110            return (JTextComponent) comboBox.getEditor().getEditorComponent();
111        }
112    }