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