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