Ignore:
Timestamp:
2021-09-13T00:41:53+02:00 (3 years ago)
Author:
Don-vip
Message:

fix #21319 - Refactoring of class hierarchy around JosmComboBox / AutoCompComboBox (patch by marcello):

  • Code reuse: JosmComboBox now uses a JosmTextField as editor
  • Code reuse: AutoCompComboBox now uses AutoCompTextField as editor
  • JosmComboBox uses more of the original L&F
  • JosmComboBox lists now expand all the way to the bottom or the top of the screen
  • Variable height items in combobox lists now work, see #19321
  • Autocomplete uses different algorithm, fix #21290
  • editable="false" comboboxes in Presets now work, fix #6157 see #11024 see #18714
  • The user may toggle LTR-RTL script in JosmTextField (menu and ctrl+space)
  • LTR-RTL automatically toggles according to key in AddTag and EditTag dialogs, fix #16163
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/tagging/presets/items/Combo.java

    r17651 r18221  
    66import java.awt.Color;
    77import java.awt.Cursor;
     8import java.awt.Insets;
    89import java.awt.event.ActionEvent;
    910import java.awt.event.ActionListener;
     11import java.awt.event.ComponentAdapter;
     12import java.awt.event.ComponentEvent;
     13import java.util.Arrays;
     14import java.util.Comparator;
    1015
    1116import javax.swing.AbstractAction;
    1217import javax.swing.JButton;
    1318import javax.swing.JColorChooser;
     19import javax.swing.JComponent;
    1420import javax.swing.JPanel;
    1521
     22import org.openstreetmap.josm.data.tagging.ac.AutoCompletionItem;
    1623import org.openstreetmap.josm.data.tagging.ac.AutoCompletionPriority;
    1724import org.openstreetmap.josm.gui.MainApplication;
    1825import org.openstreetmap.josm.gui.mappaint.mapcss.CSSColors;
    19 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
    20 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
     26import org.openstreetmap.josm.gui.tagging.ac.AutoCompComboBoxEditor;
     27import org.openstreetmap.josm.gui.tagging.ac.AutoCompComboBoxModel;
     28import org.openstreetmap.josm.gui.tagging.ac.AutoCompTextField;
    2129import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItem;
    2230import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItemGuiSupport;
     
    3644    public boolean editable = true; // NOSONAR
    3745    /** The length of the combo box (number of characters allowed). */
    38     public short length; // NOSONAR
     46    public int length; // NOSONAR
    3947
    4048    protected JosmComboBox<PresetListEntry> combobox;
     49    protected AutoCompComboBoxModel<PresetListEntry> dropDownModel;
     50    protected AutoCompComboBoxModel<AutoCompletionItem> autoCompModel;
     51
     52    class ComponentListener extends ComponentAdapter {
     53        @Override
     54        public void componentResized(ComponentEvent e) {
     55            // Make multi-line JLabels the correct size
     56            // Only needed if there is any short_description
     57            JComponent component = (JComponent) e.getSource();
     58            int width = component.getWidth();
     59            if (width == 0)
     60                width = 200;
     61            Insets insets = component.getInsets();
     62            width -= insets.left + insets.right + 10;
     63            ComboMultiSelectListCellRenderer renderer = (ComboMultiSelectListCellRenderer) combobox.getRenderer();
     64            renderer.setWidth(width);
     65            combobox.setRenderer(null); // needed to make prop change fire
     66            combobox.setRenderer(renderer);
     67        }
     68    }
    4169
    4270    /**
     
    4876
    4977    @Override
    50     protected void addToPanelAnchor(JPanel p, String def, TaggingPresetItemGuiSupport support) {
     78    protected JComponent addToPanelAnchor(JPanel p, String def, TaggingPresetItemGuiSupport support) {
    5179        if (!usage.unused()) {
    5280            for (String s : usage.values) {
     
    5987        presetListEntries.add(new PresetListEntry(""));
    6088
    61         combobox = new JosmComboBox<>(presetListEntries.toArray(new PresetListEntry[0]));
    62         component = combobox;
    63         combobox.setRenderer(getListCellRenderer());
    64         combobox.setEditable(true); // fix incorrect height, see #6157
    65         combobox.reinitialize(presetListEntries);
    66         combobox.setEditable(editable); // see #6157
    67         AutoCompletingTextField tf = new AutoCompletingTextField();
    68         initAutoCompletionField(tf, key);
     89        dropDownModel = new AutoCompComboBoxModel<PresetListEntry>(Comparator.naturalOrder());
     90        autoCompModel = new AutoCompComboBoxModel<AutoCompletionItem>(Comparator.naturalOrder());
     91        presetListEntries.forEach(dropDownModel::addElement);
     92
     93        combobox = new JosmComboBox<>(dropDownModel);
     94        AutoCompComboBoxEditor<AutoCompletionItem> editor = new AutoCompComboBoxEditor<>();
     95        combobox.setEditor(editor);
     96
     97        // The default behaviour of JComboBox is to size the editor according to the tallest item in
     98        // the dropdown list.  We don't want that to happen because we want to show taller items in
     99        // the list than in the editor.  We can't use
     100        // {@code combobox.setPrototypeDisplayValue(new PresetListEntry(" "));} because that would
     101        // set a fixed cell height in JList.
     102        combobox.setPreferredHeight(combobox.getPreferredSize().height);
     103
     104        // a custom cell renderer capable of displaying a short description text along with the
     105        // value
     106        combobox.setRenderer(new ComboMultiSelectListCellRenderer(combobox, combobox.getRenderer(), 200, key));
     107        combobox.setEditable(editable);
     108
     109        getAllForKeys(Arrays.asList(key)).forEach(autoCompModel::addElement);
     110        getDisplayValues().forEach(s -> autoCompModel.addElement(new AutoCompletionItem(s, AutoCompletionPriority.IS_IN_STANDARD)));
     111
     112        AutoCompTextField<AutoCompletionItem> tf = editor.getEditorComponent();
     113        tf.setModel(autoCompModel);
     114
    69115        if (TaggingPresetItem.DISPLAY_KEYS_AS_HINT.get()) {
    70             tf.setHint(key);
     116            combobox.setHint(key);
    71117        }
    72118        if (length > 0) {
    73             tf.setMaxChars((int) length);
     119            tf.setMaxTextLength(length);
    74120        }
    75         AutoCompletionList acList = tf.getAutoCompletionList();
    76         if (acList != null) {
    77             acList.add(getDisplayValues(), AutoCompletionPriority.IS_IN_STANDARD);
    78         }
    79         combobox.setEditor(tf);
    80         combobox.setSelectedItem(getItemToSelect(def, support, false));
    81121
    82122        if (key != null && ("colour".equals(key) || key.startsWith("colour:") || key.endsWith(":colour"))) {
     
    93133            p.add(combobox, GBC.eol().fill(GBC.HORIZONTAL));
    94134        }
     135
     136        Object itemToSelect = getItemToSelect(default_, support, false);
     137        combobox.setSelectedItemText(itemToSelect == null ? null : itemToSelect.toString());
    95138        combobox.addActionListener(l -> support.fireItemValueModified(this, key, getSelectedValue()));
     139        combobox.addComponentListener(new ComponentListener());
     140        return combobox;
    96141    }
    97142
Note: See TracChangeset for help on using the changeset viewer.