001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.tagging.presets.items;
003
004import javax.swing.JPanel;
005
006import org.openstreetmap.josm.Main;
007import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
008import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionItemPriority;
009import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
010import org.openstreetmap.josm.gui.widgets.JosmComboBox;
011import org.openstreetmap.josm.tools.GBC;
012
013/**
014 * Combobox type.
015 */
016public class Combo extends ComboMultiSelect {
017
018    /**
019     * Whether the combo box is editable, which means that the user can add other values as text.
020     * Default is {@code true}. If {@code false} it is readonly, which means that the user can only select an item in the list.
021     */
022    public boolean editable = true; // NOSONAR
023    /** The length of the combo box (number of characters allowed). */
024    public String length; // NOSONAR
025
026    protected JosmComboBox<PresetListEntry> combobox;
027
028    /**
029     * Constructs a new {@code Combo}.
030     */
031    public Combo() {
032        delimiter = ",";
033    }
034
035    @Override
036    protected void addToPanelAnchor(JPanel p, String def, boolean presetInitiallyMatches) {
037        if (!usage.unused()) {
038            for (String s : usage.values) {
039                if (!lhm.containsKey(s)) {
040                    lhm.put(s, new PresetListEntry(s));
041                }
042            }
043        }
044        if (def != null && !lhm.containsKey(def)) {
045            lhm.put(def, new PresetListEntry(def));
046        }
047        if (!lhm.containsKey("")) {
048            lhm.put("", new PresetListEntry(""));
049        }
050
051        combobox = new JosmComboBox<>(lhm.values().toArray(new PresetListEntry[0]));
052        component = combobox;
053        combobox.setRenderer(getListCellRenderer());
054        combobox.setEditable(editable);
055        combobox.reinitialize(lhm.values());
056        AutoCompletingTextField tf = new AutoCompletingTextField();
057        initAutoCompletionField(tf, key);
058        if (Main.pref.getBoolean("taggingpreset.display-keys-as-hint", true)) {
059            tf.setHint(key);
060        }
061        if (length != null && !length.isEmpty()) {
062            tf.setMaxChars(Integer.valueOf(length));
063        }
064        AutoCompletionList acList = tf.getAutoCompletionList();
065        if (acList != null) {
066            acList.add(getDisplayValues(), AutoCompletionItemPriority.IS_IN_STANDARD);
067        }
068        combobox.setEditor(tf);
069
070        if (usage.hasUniqueValue()) {
071            // all items have the same value (and there were no unset items)
072            originalValue = lhm.get(usage.getFirst());
073            combobox.setSelectedItem(originalValue);
074        } else if (def != null && usage.unused()) {
075            // default is set and all items were unset
076            if (!usage.hadKeys() || PROP_FILL_DEFAULT.get() || "force".equals(use_last_as_default)) {
077                // selected osm primitives are untagged or filling default feature is enabled
078                combobox.setSelectedItem(lhm.get(def).getDisplayValue(true));
079            } else {
080                // selected osm primitives are tagged and filling default feature is disabled
081                combobox.setSelectedItem("");
082            }
083            originalValue = lhm.get(DIFFERENT);
084        } else if (usage.unused()) {
085            // all items were unset (and so is default)
086            originalValue = lhm.get("");
087            if ("force".equals(use_last_as_default) && LAST_VALUES.containsKey(key) && !presetInitiallyMatches) {
088                combobox.setSelectedItem(lhm.get(LAST_VALUES.get(key)));
089            } else {
090                combobox.setSelectedItem(originalValue);
091            }
092        } else {
093            originalValue = lhm.get(DIFFERENT);
094            combobox.setSelectedItem(originalValue);
095        }
096        p.add(combobox, GBC.eol().fill(GBC.HORIZONTAL));
097    }
098
099    @Override
100    protected Object getSelectedItem() {
101        return combobox.getSelectedItem();
102    }
103
104    @Override
105    protected String getDisplayIfNull() {
106        if (combobox.isEditable())
107            return combobox.getEditor().getItem().toString();
108        else
109            return null;
110    }
111}