001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.tagging;
003
004import java.awt.Component;
005
006import javax.swing.AbstractCellEditor;
007import javax.swing.BorderFactory;
008import javax.swing.JTable;
009import javax.swing.table.TableCellEditor;
010
011import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
012import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
013import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionManager;
014
015/**
016 * This is the table cell editor for the tag editor dialog.
017 *
018 */
019@SuppressWarnings("serial")
020public class TagCellEditor extends AbstractCellEditor implements TableCellEditor{
021
022    protected AutoCompletingTextField editor = null;
023    protected TagModel currentTag = null;
024
025    /** the cache of auto completion items derived from the current JOSM data set */
026    protected AutoCompletionManager autocomplete = null;
027
028    /** user input is matched against this list of auto completion items */
029    protected AutoCompletionList autoCompletionList = null;
030
031    /**
032     * constructor
033     */
034    public TagCellEditor() {
035        editor = new AutoCompletingTextField();
036        editor.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
037    }
038
039    /**
040     * initializes  the auto completion list when the table cell editor starts
041     * to edit the key of a tag. In this case the auto completion list is
042     * initialized with the set of standard key values and the set of current key
043     * values from the current JOSM data set. Keys already present in the
044     * current tag model are removed from the auto completion list.
045     *
046     * @param model  the tag editor model
047     * @param currentTag  the current tag
048     */
049    protected void initAutoCompletionListForKeys(TagEditorModel model, TagModel currentTag) {
050
051        if (autoCompletionList == null)
052            return;
053        autoCompletionList.clear();
054
055        // add the list of keys in the current data set
056        //
057        autocomplete.populateWithKeys(autoCompletionList);
058
059        // remove the keys already present in the current tag model
060        //
061        for (String key : model.getKeys()) {
062            if (! key.equals(currentTag.getName())) {
063                autoCompletionList.remove(key);
064            }
065        }
066        autoCompletionList.fireTableDataChanged();
067    }
068
069    /**
070     * initializes the auto completion list when the cell editor starts to edit
071     * a tag value. In this case the auto completion list is initialized with the
072     * set of standard values for a given key and the set of values present in the
073     * current data set for the given key.
074     *
075     * @param forKey the key
076     */
077    protected void initAutoCompletionListForValues(String forKey) {
078        if (autoCompletionList == null) {
079            return;
080        }
081        autoCompletionList.clear();
082        autocomplete.populateWithTagValues(autoCompletionList, forKey);
083    }
084
085    /**
086     * replies the table cell editor
087     */
088    @Override
089    public Component getTableCellEditorComponent(JTable table,
090            Object value, boolean isSelected, int row, int column) {
091        currentTag = (TagModel) value;
092
093        // no autocompletion for initial editor#setText()
094        if(autoCompletionList != null) {
095            autoCompletionList.clear();
096        }
097        if (column == 0) {
098            editor.setText(currentTag.getName());
099            TagEditorModel model = (TagEditorModel)table.getModel();
100            initAutoCompletionListForKeys(model, currentTag);
101            return editor;
102        } else if (column == 1) {
103
104            if (currentTag.getValueCount() == 0) {
105                editor.setText("");
106            } else if (currentTag.getValueCount() == 1) {
107                editor.setText(currentTag.getValues().get(0));
108            } else {
109                editor.setText("");
110            }
111            initAutoCompletionListForValues(currentTag.getName());
112            return editor;
113        } else {
114            return null;
115        }
116    }
117
118    @Override
119    public Object getCellEditorValue() {
120        return editor.getText();
121    }
122
123    /**
124     * replies the {@link AutoCompletionList} this table cell editor synchronizes with
125     *
126     * @return the auto completion list
127     */
128    public AutoCompletionList getAutoCompletionList() {
129        return autoCompletionList;
130    }
131
132    /**
133     * sets the {@link AutoCompletionList} this table cell editor synchronizes with
134     * @param autoCompletionList the auto completion list
135     */
136    public void setAutoCompletionList(AutoCompletionList autoCompletionList) {
137        this.autoCompletionList = autoCompletionList;
138        editor.setAutoCompletionList(autoCompletionList);
139    }
140
141    public void setAutoCompletionManager(AutoCompletionManager autocomplete) {
142        this.autocomplete = autocomplete;
143    }
144
145    public void autoCompletionItemSelected(String item) {
146        editor.setText(item);
147        editor.selectAll();
148        editor.requestFocus();
149    }
150
151    public AutoCompletingTextField getEditor() {
152        return editor;
153    }
154}