001 /*
002 * $Id: ComboBoxCellEditor.java,v 1.3 2005/10/10 18:01:33 rbair Exp $
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.event.ActionEvent;
024 import java.awt.event.KeyAdapter;
025 import java.awt.event.KeyEvent;
026 import java.beans.PropertyChangeEvent;
027 import java.beans.PropertyChangeListener;
028 import java.io.Serializable;
029
030 import javax.swing.AbstractCellEditor;
031 import javax.swing.ComboBoxEditor;
032 import javax.swing.JComboBox;
033 import javax.swing.JComponent;
034 import javax.swing.table.TableCellEditor;
035
036 /**
037 * <p>This is a cell editor that can be used when a combo box (that has been set
038 * up for automatic completion) is to be used in a JTable. The
039 * {@link javax.swing.DefaultCellEditor DefaultCellEditor} won't work in this
040 * case, because each time an item gets selected it stops cell editing and hides
041 * the combo box.
042 * </p>
043 * <p>
044 * Usage example:
045 * </p>
046 * <code>
047 * JTable table = ...;</br>
048 * JComboBox comboBox = ...;</br>
049 * ...</br>
050 * TableColumn column = table.getColumnModel().getColumn(0);</br>
051 * column.setCellEditor(new ComboBoxCellEditor(comboBox));
052 * </code>
053 */
054 public class ComboBoxCellEditor extends AbstractCellEditor implements TableCellEditor, Serializable {
055
056 private JComboBox comboBox;
057 // a Listener listening for key events (handling enter-key)
058 // and changes of the combo box' editor component.
059 private Handler handler;
060
061 /**
062 * Creates a new ComboBoxCellEditor.
063 * @param comboBox the comboBox that should be used as the cell editor.
064 */
065 public ComboBoxCellEditor(final JComboBox comboBox) {
066 this.comboBox = comboBox;
067
068 handler = new Handler();
069
070 // Don't do this:
071 // this.comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
072 // it probably breaks various things
073
074 // hitting enter in the combo box should stop cellediting
075 JComponent editorComponent = (JComponent) comboBox.getEditor().getEditorComponent();
076 editorComponent.addKeyListener(handler);
077 // remove the editor's border - the cell itself already has one
078 editorComponent.setBorder(null);
079
080 // editor component might change (e.g. a look&feel change)
081 // the new editor component needs to be modified then (keyListener, border)
082 comboBox.addPropertyChangeListener(handler);
083 }
084
085 // ------ Implementing CellEditor ------
086 /**
087 * Returns the value contained in the combo box
088 * @return the value contained in the combo box
089 */
090 public Object getCellEditorValue() {
091 return comboBox.getSelectedItem();
092 }
093
094 /**
095 * Tells the combo box to stop editing and accept any partially edited value as the value of the combo box.
096 * Always returns true.
097 * @return true
098 */
099 public boolean stopCellEditing() {
100 if (comboBox.isEditable()) {
101 // Notify the combo box that editing has stopped (e.g. User pressed F2)
102 comboBox.actionPerformed(new ActionEvent(this, 0, ""));
103 }
104 fireEditingStopped();
105 return true;
106 }
107
108 // ------ Implementing TableCellEditor ------
109 /**
110 * Sets an initial value for the combo box.
111 * Returns the combo box that should be added to the client's Component hierarchy.
112 * Once installed in the client's hierarchy this combo box will then be able to draw and receive user input.
113 * @param table the JTable that is asking the editor to edit; can be null
114 * @param value the value of the cell to be edited; null is a valid value
115 * @param isSelected will be ignored
116 * @param row the row of the cell being edited
117 * @param column the column of the cell being edited
118 * @return the combo box for editing
119 */
120 public java.awt.Component getTableCellEditorComponent(javax.swing.JTable table, Object value, boolean isSelected, int row, int column) {
121 comboBox.setSelectedItem(value);
122 return comboBox;
123 }
124
125 // ------ Implementing TreeCellEditor ------
126 // public java.awt.Component getTreeCellEditorComponent(javax.swing.JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) {
127 // String stringValue = tree.convertValueToText(value, isSelected, expanded, leaf, row, false);
128 // comboBox.setSelectedItem(stringValue);
129 // return comboBox;
130 // }
131
132 class Handler extends KeyAdapter implements PropertyChangeListener {
133 public void keyPressed(KeyEvent keyEvent) {
134 int keyCode = keyEvent.getKeyCode();
135 if (keyCode==keyEvent.VK_ENTER) stopCellEditing();
136 }
137 public void propertyChange(PropertyChangeEvent e) {
138 if (e.getPropertyName().equals("editor")) {
139 ComboBoxEditor editor = comboBox.getEditor();
140 if (editor!=null && editor.getEditorComponent()!=null) {
141 JComponent editorComponent = (JComponent) comboBox.getEditor().getEditorComponent();
142 editorComponent.addKeyListener(this);
143 editorComponent.setBorder(null);
144 }
145 }
146 }
147 }
148 }