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