Ticket #21408: 21408.patch
| File 21408.patch, 58.2 KB (added by , 5 years ago) |
|---|
-
src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetItemGuiSupport.java
24 24 public final class TaggingPresetItemGuiSupport implements TemplateEngineDataProvider { 25 25 26 26 private final Collection<OsmPrimitive> selected; 27 /** True if all selected primitives matched this preset at the moment it was openend. */ 27 28 private final boolean presetInitiallyMatches; 28 29 private final Supplier<Collection<Tag>> changedTagsSupplier; 29 30 private final ListenerList<ChangeListener> listeners = ListenerList.create(); … … 83 84 } 84 85 85 86 /** 86 * Returns whether the preset initially matched(before opening the dialog)87 * Returns true if all selected primitives matched this preset (before opening the dialog) 87 88 * 88 * @return whetherthe preset initially matched89 * @return true if the preset initially matched 89 90 */ 90 91 public boolean isPresetInitiallyMatches() { 91 92 return presetInitiallyMatches; -
src/org/openstreetmap/josm/gui/tagging/presets/items/Check.java
39 39 40 40 // find out if our key is already used in the selection. 41 41 final Usage usage = determineBooleanUsage(support.getSelected(), key); 42 final String oneValue = usage. values.isEmpty() ? null : usage.values.last();42 final String oneValue = usage.map.isEmpty() ? null : usage.map.lastKey(); 43 43 def = "on".equals(default_) ? Boolean.TRUE : "off".equals(default_) ? Boolean.FALSE : null; 44 44 45 45 initializeLocaleText(null); 46 46 47 if (usage. values.size() < 2 && (oneValue == null || value_on.equals(oneValue) || value_off.equals(oneValue))) {47 if (usage.map.size() < 2 && (oneValue == null || value_on.equals(oneValue) || value_off.equals(oneValue))) { 48 48 if (def != null && !PROP_FILL_DEFAULT.get()) { 49 49 // default is set and filling default values feature is disabled - check if all primitives are untagged 50 50 for (OsmPrimitive s : support.getSelected()) { -
src/org/openstreetmap/josm/gui/tagging/presets/items/Combo.java
12 12 import java.awt.event.ComponentEvent; 13 13 import java.util.Arrays; 14 14 import java.util.Comparator; 15 import java.util.TreeMap; 15 16 16 17 import javax.swing.AbstractAction; 17 18 import javax.swing.JButton; 18 19 import javax.swing.JColorChooser; 19 20 import javax.swing.JComponent; 21 import javax.swing.JLabel; 20 22 import javax.swing.JPanel; 21 23 22 24 import org.openstreetmap.josm.data.tagging.ac.AutoCompletionItem; … … 29 31 import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItem; 30 32 import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItemGuiSupport; 31 33 import org.openstreetmap.josm.gui.widgets.JosmComboBox; 34 import org.openstreetmap.josm.gui.widgets.OrientationAction; 32 35 import org.openstreetmap.josm.tools.ColorHelper; 33 36 import org.openstreetmap.josm.tools.GBC; 34 37 … … 74 77 delimiter = ','; 75 78 } 76 79 80 private void addEntry(PresetListEntry entry) { 81 if (!seenValues.containsKey(entry.value)) { 82 dropDownModel.addElement(entry); 83 seenValues.put(entry.value, entry); 84 } 85 } 86 77 87 @Override 78 protected JComponent addToPanelAnchor(JPanel p, String def, TaggingPresetItemGuiSupport support) { 79 if (!usage.unused()) { 80 for (String s : usage.values) { 81 presetListEntries.add(new PresetListEntry(s)); 82 } 88 protected boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support) { 89 initializeLocaleText(null); 90 usage = determineTextUsage(support.getSelected(), key); 91 seenValues = new TreeMap<>(); 92 // get the standard values from the preset definition 93 initListEntries(); 94 95 // init the model 96 dropDownModel = new AutoCompComboBoxModel<PresetListEntry>(Comparator.naturalOrder()); 97 98 if (!usage.hasUniqueValue() && !usage.unused()) { 99 addEntry(PresetListEntry.ENTRY_DIFFERENT); 83 100 } 84 if (def != null) { 85 presetListEntries.add(new PresetListEntry(def)); 101 presetListEntries.forEach(this::addEntry); 102 if (default_ != null) { 103 addEntry(new PresetListEntry(default_, this)); 86 104 } 87 presetListEntries.add(new PresetListEntry(""));105 addEntry(PresetListEntry.ENTRY_EMPTY); 88 106 89 dropDownModel = new AutoCompComboBoxModel<PresetListEntry>(Comparator.naturalOrder());90 autoCompModel = new AutoCompComboBoxModel<AutoCompletionItem>(Comparator.naturalOrder());91 presetListEntries.forEach(dropDownModel::addElement);107 usage.map.forEach((value, count) -> { 108 addEntry(new PresetListEntry(value, this)); 109 }); 92 110 93 111 combobox = new JosmComboBox<>(dropDownModel); 94 112 AutoCompComboBoxEditor<AutoCompletionItem> editor = new AutoCompComboBoxEditor<>(); … … 97 115 // The default behaviour of JComboBox is to size the editor according to the tallest item in 98 116 // the dropdown list. We don't want that to happen because we want to show taller items in 99 117 // the list than in the editor. We can't use 100 // {@code combobox.setPrototypeDisplayValue( new PresetListEntry(" "));} because that would118 // {@code combobox.setPrototypeDisplayValue(PresetListEntry.ENTRY_EMPTY);} because that would 101 119 // set a fixed cell height in JList. 102 120 combobox.setPreferredHeight(combobox.getPreferredSize().height); 103 121 … … 106 124 combobox.setRenderer(new ComboMultiSelectListCellRenderer(combobox, combobox.getRenderer(), 200, key)); 107 125 combobox.setEditable(editable); 108 126 127 autoCompModel = new AutoCompComboBoxModel<AutoCompletionItem>(Comparator.naturalOrder()); 109 128 getAllForKeys(Arrays.asList(key)).forEach(autoCompModel::addElement); 110 129 getDisplayValues().forEach(s -> autoCompModel.addElement(new AutoCompletionItem(s, AutoCompletionPriority.IS_IN_STANDARD))); 111 130 … … 119 138 tf.setMaxTextLength(length); 120 139 } 121 140 141 JLabel label = addLabel(p); 142 122 143 if (key != null && ("colour".equals(key) || key.startsWith("colour:") || key.endsWith(":colour"))) { 123 p.add(combobox, GBC.std().fill(GBC.HORIZONTAL)); 144 p.add(combobox, GBC.std().fill(GBC.HORIZONTAL)); // NOSONAR 124 145 JButton button = new JButton(new ChooseColorAction()); 125 146 button.setOpaque(true); 126 147 button.setBorderPainted(false); 127 148 button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); 128 p.add(button, GBC.eol().fill(GBC.VERTICAL)); 149 p.add(button, GBC.eol().fill(GBC.VERTICAL)); // NOSONAR 129 150 ActionListener updateColor = ignore -> button.setBackground(getColor()); 130 151 updateColor.actionPerformed(null); 131 152 combobox.addActionListener(updateColor); 132 153 } else { 133 p.add(combobox, GBC.eol().fill(GBC.HORIZONTAL)); 154 p.add(combobox, GBC.eol().fill(GBC.HORIZONTAL)); // NOSONAR 134 155 } 135 156 136 Object itemToSelect = getItemToSelect(default_, support, false); 137 combobox.setSelectedItemText(itemToSelect == null ? null : itemToSelect.toString()); 138 combobox.addActionListener(l -> support.fireItemValueModified(this, key, getSelectedValue())); 157 String valueToSelect = getInitialValue(default_); 158 if (valueToSelect != null) { 159 PresetListEntry selItem = find(valueToSelect); 160 if (selItem != null) { 161 combobox.setSelectedItem(selItem); 162 } else { 163 combobox.setText(valueToSelect); 164 } 165 } 166 combobox.addActionListener(l -> support.fireItemValueModified(this, key, getSelectedItem().value)); 139 167 combobox.addComponentListener(new ComponentListener()); 140 return combobox; 168 169 label.setLabelFor(combobox); 170 combobox.setToolTipText(getKeyTooltipText()); 171 combobox.applyComponentOrientation(OrientationAction.getValueOrientation(key)); 172 173 return true; 141 174 } 142 175 176 /** 177 * Finds the PresetListEntry that matches value. 178 * <p> 179 * Looks in the model for an element whose {@code value} matches {@code value}. 180 * 181 * @param value The value to match. 182 * @return The entry or null 183 */ 184 private PresetListEntry find(String value) { 185 return dropDownModel.asCollection().stream().filter(o -> o.value.equals(value)).findAny().orElse(null); 186 } 187 143 188 class ChooseColorAction extends AbstractAction { 144 189 ChooseColorAction() { 145 190 putValue(SHORT_DESCRIPTION, tr("Choose a color")); … … 160 205 } 161 206 162 207 protected Color getColor() { 163 String colorString = String.valueOf(getSelectedValue());208 String colorString = getSelectedItem().value; 164 209 return colorString.startsWith("#") 165 210 ? ColorHelper.html2color(colorString) 166 211 : CSSColors.get(colorString); … … 167 212 } 168 213 169 214 @Override 170 protected Object getSelectedItem() { 171 return combobox.getSelectedItem(); 215 protected PresetListEntry getSelectedItem() { 216 Object sel = combobox.getSelectedItem(); 217 if (sel instanceof PresetListEntry) 218 // selected from the dropdown 219 return (PresetListEntry) sel; 220 if (sel instanceof String) { 221 // free edit. If the free edit corresponds to a known entry, use that entry. This is 222 // to avoid that we write a display_value to the tag's value, eg. if the user did an 223 // undo. 224 PresetListEntry selItem = dropDownModel.find((String) sel); 225 if (selItem != null) 226 return selItem; 227 return new PresetListEntry((String) sel, this); 228 } 229 return PresetListEntry.ENTRY_EMPTY; 172 230 } 173 174 @Override175 protected String getDisplayIfNull() {176 if (combobox.isEditable())177 return combobox.getEditor().getItem().toString();178 else179 return null;180 }181 231 } -
src/org/openstreetmap/josm/gui/tagging/presets/items/ComboMultiSelect.java
2 2 package org.openstreetmap.josm.gui.tagging.presets.items; 3 3 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 import static org.openstreetmap.josm.tools.I18n.trc;6 5 7 6 import java.awt.Component; 8 7 import java.lang.reflect.Method; … … 12 11 import java.util.Collection; 13 12 import java.util.Collections; 14 13 import java.util.List; 15 import java.util.Objects; 16 import java.util.Set; 17 import java.util.concurrent.CopyOnWriteArraySet; 14 import java.util.Map; 15 import java.util.TreeMap; 18 16 import java.util.stream.Collectors; 19 17 20 import javax.swing.JComponent;21 18 import javax.swing.JLabel; 22 19 import javax.swing.JList; 23 20 import javax.swing.JPanel; … … 24 21 import javax.swing.ListCellRenderer; 25 22 26 23 import org.openstreetmap.josm.data.osm.Tag; 27 import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItemGuiSupport;28 24 import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetSelector; 29 25 import org.openstreetmap.josm.gui.tagging.presets.TaggingPresets; 30 26 import org.openstreetmap.josm.gui.widgets.JosmListCellRenderer; 31 27 import org.openstreetmap.josm.gui.widgets.OrientationAction; 28 import org.openstreetmap.josm.tools.AlphanumComparator; 32 29 import org.openstreetmap.josm.tools.GBC; 33 30 import org.openstreetmap.josm.tools.Logging; 34 import org.openstreetmap.josm.tools.Utils;35 31 36 32 /** 37 33 * Abstract superclass for combo box and multi-select list types. … … 88 84 /** whether to use values for search via {@link TaggingPresetSelector} */ 89 85 public boolean values_searchable; // NOSONAR 90 86 91 protected final Set<PresetListEntry> presetListEntries = new CopyOnWriteArraySet<>(); 92 private boolean initialized; 87 /** 88 * The standard entries in the combobox dropdown or multiselect list. These entries are defined 89 * in {@code defaultpresets.xml} (or in other custom preset files). 90 */ 91 protected final List<PresetListEntry> presetListEntries = new ArrayList<>(); 92 /** Helps avoid duplicate list entries */ 93 protected Map<String, PresetListEntry> seenValues = new TreeMap<>(); 93 94 protected Usage usage; 94 protected Object originalValue; 95 /** Used to see if the user edited the value. May be null. */ 96 protected String originalValue; 95 97 96 98 /** 97 99 * A list cell renderer that paints a short text in the current value pane and and a longer text … … 133 135 // editor-ersatz of a readonly combobox. fixes #6157 134 136 l.setText(value.getListDisplay(width)); 135 137 } 136 String tt = value.value; 137 if (tt != null && !tt.isEmpty()) { 138 l.setToolTipText(tr("Sets the key ''{0}'' to the value ''{1}''.", key, tt)); 139 } else { 140 l.setToolTipText(tr("Clears the key ''{0}''.", key)); 141 } 138 l.setToolTipText(value.getToolTipText(key)); 142 139 l.setIcon(value.getIcon()); 143 140 return l; 144 141 } … … 152 149 * @param s the string 153 150 * @return splitted items 154 151 */ 155 public static String[]splitEscaped(char delimiter, String s) {152 public static List<String> splitEscaped(char delimiter, String s) { 156 153 if (s == null) 157 return new String[0]; 154 return null; // NOSONAR 155 158 156 List<String> result = new ArrayList<>(); 159 157 boolean backslash = false; 160 158 StringBuilder item = new StringBuilder(); … … 175 173 if (item.length() > 0) { 176 174 result.add(item.toString()); 177 175 } 178 return result .toArray(new String[0]);176 return result; 179 177 } 180 178 181 protected abstract Object getSelectedItem(); 179 /** 180 * Returns the value selected in the combobox or a synthetic value if a multiselect. 181 * 182 * @return the value 183 */ 184 protected abstract PresetListEntry getSelectedItem(); 182 185 183 protected abstract JComponent addToPanelAnchor(JPanel p, String def, TaggingPresetItemGuiSupport support);184 185 186 @Override 186 187 public Collection<String> getValues() { 187 initListEntries( false);188 initListEntries(); 188 189 return presetListEntries.stream().map(x -> x.value).collect(Collectors.toSet()); 189 190 } 190 191 … … 193 194 * @return the values to display 194 195 */ 195 196 public Collection<String> getDisplayValues() { 196 initListEntries( false);197 initListEntries(); 197 198 return presetListEntries.stream().map(PresetListEntry::getDisplayValue).collect(Collectors.toList()); 198 199 } 199 200 200 @Override 201 public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support) { 202 initListEntries(true); 203 204 // find out if our key is already used in the selection. 205 usage = determineTextUsage(support.getSelected(), key); 206 if (!usage.hasUniqueValue() && !usage.unused()) { 207 presetListEntries.add(new PresetListEntry(DIFFERENT)); 208 } 209 201 /** 202 * Adds the label to the panel 203 * 204 * @param p the panel 205 * @return the label 206 */ 207 protected JLabel addLabel(JPanel p) { 210 208 final JLabel label = new JLabel(tr("{0}:", locale_text)); 211 209 addIcon(label); 212 210 label.setToolTipText(getKeyTooltipText()); … … 213 211 label.setComponentPopupMenu(getPopupMenu()); 214 212 label.applyComponentOrientation(OrientationAction.getDefaultComponentOrientation()); 215 213 p.add(label, GBC.std().insets(0, 0, 10, 0)); 216 JComponent component = addToPanelAnchor(p, default_, support); 217 label.setLabelFor(component); 218 component.setToolTipText(getKeyTooltipText()); 219 component.applyComponentOrientation(OrientationAction.getValueOrientation(key)); 214 return label; 215 } 220 216 221 return true; 217 protected void initListEntries() { 218 if (presetListEntries.isEmpty()) { 219 initListEntriesFromAttributes(); 220 } 222 221 } 223 222 224 private void initListEntries(boolean cleanup) { 225 if (initialized) { 226 if (cleanup) { // do not cleanup for #getDisplayValues used in Combo#addToPanelAnchor 227 presetListEntries.remove(new PresetListEntry(DIFFERENT)); // possibly added in #addToPanel 228 } 229 return; 230 } else if (presetListEntries.isEmpty()) { 231 initListEntriesFromAttributes(); 232 } else { 233 if (values != null) { 234 Logging.warn(tr("Warning in tagging preset \"{0}-{1}\": " 235 + "Ignoring ''{2}'' attribute as ''{3}'' elements are given.", 236 key, text, "values", "list_entry")); 237 } 238 if (display_values != null || locale_display_values != null) { 239 Logging.warn(tr("Warning in tagging preset \"{0}-{1}\": " 240 + "Ignoring ''{2}'' attribute as ''{3}'' elements are given.", 241 key, text, "display_values", "list_entry")); 242 } 243 if (short_descriptions != null || locale_short_descriptions != null) { 244 Logging.warn(tr("Warning in tagging preset \"{0}-{1}\": " 245 + "Ignoring ''{2}'' attribute as ''{3}'' elements are given.", 246 key, text, "short_descriptions", "list_entry")); 247 } 248 for (PresetListEntry e : presetListEntries) { 249 if (e.value_context == null) { 250 e.value_context = values_context; 223 private List<String> getValuesFromCode(String values_from) { 224 // get the values from a Java function 225 String[] classMethod = values_from.split("#", -1); 226 if (classMethod.length == 2) { 227 try { 228 Method method = Class.forName(classMethod[0]).getMethod(classMethod[1]); 229 // Check method is public static String[] methodName() 230 int mod = method.getModifiers(); 231 if (Modifier.isPublic(mod) && Modifier.isStatic(mod) 232 && method.getReturnType().equals(String[].class) && method.getParameterTypes().length == 0) { 233 return Arrays.asList((String[]) method.invoke(null)); 234 } else { 235 Logging.error(tr("Broken tagging preset \"{0}-{1}\" - Java method given in ''values_from'' is not \"{2}\"", key, text, 236 "public static String[] methodName()")); 251 237 } 238 } catch (ReflectiveOperationException e) { 239 Logging.error(tr("Broken tagging preset \"{0}-{1}\" - Java method given in ''values_from'' threw {2} ({3})", key, text, 240 e.getClass().getName(), e.getMessage())); 241 Logging.debug(e); 252 242 } 253 243 } 254 initializeLocaleText(null); 255 initialized = true; 244 return null; // NOSONAR 256 245 } 257 246 258 private void initListEntriesFromAttributes() { 247 /** 248 * Checks if list {@code a} is either null or the same length as list {@code b}. 249 * 250 * @param a The list to check 251 * @param b The other list 252 * @param name The name of the list for error reporting 253 * @return {@code a} if both lists have the same length or {@code null} 254 */ 255 private List<String> checkListsSameLength(List<String> a, List<String> b, String name) { 256 if (a != null && a.size() != b.size()) { 257 Logging.error(tr("Broken tagging preset \"{0}-{1}\" - number of items in ''{2}List'' must be the same as in ''values''", 258 key, text, name)); 259 Logging.error(tr("Detailed information: {0} <> {1}", a, b)); 260 return null; // NOSONAR 261 } 262 return a; 263 } 259 264 260 String[] valueArray = null; 265 protected void initListEntriesFromAttributes() { 266 List<String> valueList = null; 267 List<String> displayList = null; 268 List<String> localeDisplayList = null; 261 269 262 270 if (values_from != null) { 263 String[] classMethod = values_from.split("#", -1); 264 if (classMethod.length == 2) { 265 try { 266 Method method = Class.forName(classMethod[0]).getMethod(classMethod[1]); 267 // Check method is public static String[] methodName() 268 int mod = method.getModifiers(); 269 if (Modifier.isPublic(mod) && Modifier.isStatic(mod) 270 && method.getReturnType().equals(String[].class) && method.getParameterTypes().length == 0) { 271 valueArray = (String[]) method.invoke(null); 272 } else { 273 Logging.error(tr("Broken tagging preset \"{0}-{1}\" - Java method given in ''values_from'' is not \"{2}\"", key, text, 274 "public static String[] methodName()")); 275 } 276 } catch (ReflectiveOperationException e) { 277 Logging.error(tr("Broken tagging preset \"{0}-{1}\" - Java method given in ''values_from'' threw {2} ({3})", key, text, 278 e.getClass().getName(), e.getMessage())); 279 Logging.debug(e); 280 } 281 } 271 valueList = getValuesFromCode(values_from); 282 272 } 283 273 284 if (value Array== null) {285 valueArray = splitEscaped(delimiter, values);286 value s = null;274 if (valueList == null) { 275 // get from {@code values} attribute 276 valueList = splitEscaped(delimiter, values); 287 277 } 278 if (valueList == null) { 279 return; 280 } 288 281 289 String[] displayArray = valueArray;290 282 if (!values_no_i18n) { 291 final String displ = Utils.firstNonNull(locale_display_values,display_values);292 display Array = displ == null ? valueArray : splitEscaped(delimiter, displ);283 localeDisplayList = splitEscaped(delimiter, locale_display_values); 284 displayList = splitEscaped(delimiter, display_values); 293 285 } 286 List<String> localeShortDescriptionsList = splitEscaped(delimiter, locale_short_descriptions); 287 List<String> shortDescriptionsList = splitEscaped(delimiter, short_descriptions); 294 288 295 final String descr = Utils.firstNonNull(locale_short_descriptions, short_descriptions); 296 String[] shortDescriptionsArray = descr == null ? null : splitEscaped(delimiter, descr); 289 displayList = checkListsSameLength(displayList, valueList, "display"); 290 localeDisplayList = checkListsSameLength(localeDisplayList, valueList, "localeDisplay"); 291 shortDescriptionsList = checkListsSameLength(shortDescriptionsList, valueList, "shortDescriptions"); 292 localeShortDescriptionsList = checkListsSameLength(localeShortDescriptionsList, valueList, "localeShortDescriptions"); 297 293 298 if (displayArray.length != valueArray.length) { 299 Logging.error(tr("Broken tagging preset \"{0}-{1}\" - number of items in ''display_values'' must be the same as in ''values''", 300 key, text)); 301 Logging.error(tr("Detailed information: {0} <> {1}", Arrays.toString(displayArray), Arrays.toString(valueArray))); 302 displayArray = valueArray; 294 for (int i = 0; i < valueList.size(); i++) { 295 final PresetListEntry e = new PresetListEntry(valueList.get(i), this); 296 if (displayList != null) 297 e.display_value = displayList.get(i); 298 if (localeDisplayList != null) 299 e.locale_display_value = localeDisplayList.get(i); 300 if (shortDescriptionsList != null) 301 e.short_description = shortDescriptionsList.get(i); 302 if (localeShortDescriptionsList != null) 303 e.locale_short_description = localeShortDescriptionsList.get(i); 304 addListEntry(e); 303 305 } 304 306 305 if (shortDescriptionsArray != null && shortDescriptionsArray.length != valueArray.length) {306 Logging.error(tr("Broken tagging preset \"{0}-{1}\" - number of items in ''short_descriptions'' must be the same as in ''values''",307 key, text));308 Logging.error(tr("Detailed information: {0} <> {1}", Arrays.toString(shortDescriptionsArray), Arrays.toString(valueArray)));309 shortDescriptionsArray = null;310 }311 312 final List<PresetListEntry> entries = new ArrayList<>(valueArray.length);313 for (int i = 0; i < valueArray.length; i++) {314 final PresetListEntry e = new PresetListEntry(valueArray[i]);315 final String value = locale_display_values != null || values_no_i18n316 ? displayArray[i]317 : trc(values_context, fixPresetString(displayArray[i]));318 e.locale_display_value = value == null ? null : value.intern();319 if (shortDescriptionsArray != null) {320 final String description = locale_short_descriptions != null321 ? shortDescriptionsArray[i]322 : tr(fixPresetString(shortDescriptionsArray[i]));323 e.locale_short_description = description == null ? null : description.intern();324 }325 326 entries.add(e);327 }328 329 307 if (values_sort && TaggingPresets.SORT_MENU.get()) { 330 Collections.sort( entries);308 Collections.sort(presetListEntries, (a, b) -> AlphanumComparator.getInstance().compare(a.getDisplayValue(), b.getDisplayValue())); 331 309 } 332 333 addListEntries(entries);334 310 } 335 311 336 protected String getDisplayIfNull() { 337 return null; 338 } 312 /** 313 * Returns the initial value to use for this preset. 314 * <p> 315 * The initial value is the value shown in the control when the preset dialogs opens. 316 * 317 * @param def The default value 318 * @return The initial value to use. 319 */ 320 protected String getInitialValue(String def) { 321 String initialValue = null; 339 322 340 protected Object getItemToSelect(String def, TaggingPresetItemGuiSupport support, boolean multi) {341 final Object itemToSelect;342 323 if (usage.hasUniqueValue()) { 343 // all items have the same value (and there were no unset items) 344 originalValue = multi ? usage.getFirst() : getListEntry(usage.getFirst()); 345 itemToSelect = originalValue; 346 } else if (def != null && usage.unused()) { 347 // default is set and all items were unset 348 if (!usage.hadKeys() || PROP_FILL_DEFAULT.get() || isForceUseLastAsDefault()) { 349 // selected osm primitives are untagged or filling default feature is enabled 350 if (multi) { 351 itemToSelect = def; 352 } else { 353 PresetListEntry entry = getListEntry(def); 354 itemToSelect = entry == null ? "" : entry.getDisplayValue(); 355 } 356 } else { 357 // selected osm primitives are tagged and filling default feature is disabled 358 itemToSelect = ""; 359 } 360 originalValue = multi ? DIFFERENT : getListEntry(DIFFERENT); 361 } else if (usage.unused()) { 362 // all items were unset (and so is default) 363 originalValue = multi ? null : getListEntry(""); 364 if (LAST_VALUES.containsKey(key) && isUseLastAsDefault() && (!support.isPresetInitiallyMatches() || isForceUseLastAsDefault())) { 365 itemToSelect = getListEntry(LAST_VALUES.get(key)); 366 } else { 367 itemToSelect = originalValue; 368 } 369 } else { 370 originalValue = multi ? DIFFERENT : getListEntry(DIFFERENT); 371 itemToSelect = originalValue; 324 // all selected primitives have the same not empty value for this key 325 initialValue = usage.getFirst(); 326 } else if (!usage.unused()) { 327 // at least one primitive has a value for this key (but not all have the same one) 328 initialValue = DIFFERENT; 329 } else if (PROP_FILL_DEFAULT.get() || isForceUseLastAsDefault()) { 330 // at this point no primitive had any value for this key 331 // use the last value no matter what 332 initialValue = LAST_VALUES.get(key); 333 } else if (!usage.hadKeys() && isUseLastAsDefault()) { 334 // use the last value only on objects with no keys at all 335 initialValue = LAST_VALUES.get(key); 336 } else if (!usage.hadKeys()) { 337 // use the default only on objects with no keys at all 338 initialValue = def; 372 339 } 373 return itemToSelect; 340 originalValue = initialValue; 341 return initialValue; 374 342 } 375 343 376 protected String getSelectedValue() {377 Object obj = getSelectedItem();378 String display = obj == null ? getDisplayIfNull() : obj.toString();379 380 if (display == null) {381 return "";382 }383 return presetListEntries.stream()384 .filter(entry -> Objects.equals(entry.toString(), display))385 .findFirst()386 .map(entry -> entry.value)387 .map(Utils::removeWhiteSpaces)388 .orElse(display);389 }390 391 344 @Override 392 345 public void addCommands(List<Tag> changedTags) { 393 String value = getSelected Value();346 String value = getSelectedItem().value; 394 347 395 348 // no change if same as before 396 if (originalValue == null) { 397 if (value.isEmpty()) 398 return; 399 } else if (value.equals(originalValue.toString())) 349 if (value.isEmpty() && originalValue == null) 400 350 return; 351 if (value.equals(originalValue)) 352 return; 353 changedTags.add(new Tag(key, value)); 401 354 402 355 if (isUseLastAsDefault()) { 403 356 LAST_VALUES.put(key, value); 404 357 } 405 changedTags.add(new Tag(key, value));406 358 } 407 359 408 360 /** … … 419 371 } 420 372 } 421 373 374 /** 375 * Returns true if the last entered value should be used as default. 376 * <p> 377 * Note: never used in {@code defaultpresets.xml}. 378 * 379 * @return true if the last entered value should be used as default. 380 */ 422 381 protected boolean isUseLastAsDefault() { 423 382 return use_last_as_default > 0; 424 383 } 425 384 385 /** 386 * Returns true if the last entered value should be used as default also on primitives that 387 * already have tags. 388 * <p> 389 * Note: used for {@code addr:*} tags in {@code defaultpresets.xml}. 390 * 391 * @return true if see above 392 */ 426 393 protected boolean isForceUseLastAsDefault() { 427 394 return use_last_as_default == 2; 428 395 } … … 433 400 */ 434 401 public void addListEntry(PresetListEntry e) { 435 402 presetListEntries.add(e); 403 // we need to fix the entries because the XML Parser 404 // {@link org.openstreetmap.josm.tools.XmlObjectParser.Parser#startElement} has used the 405 // default standard constructor for {@link PresetListEntry} if the list entry was defined 406 // using XML {@code <list_entry>}. 407 e.cms = this; 436 408 } 437 409 438 410 /** … … 445 417 } 446 418 } 447 419 448 protected PresetListEntry getListEntry(String value) {449 return presetListEntries.stream().filter(e -> Objects.equals(e.value, value)).findFirst().orElse(null);450 }451 452 420 @Override 453 421 public MatchType getDefaultMatch() { 454 422 return MatchType.NONE; -
src/org/openstreetmap/josm/gui/tagging/presets/items/KeyedItem.java
7 7 import java.util.EnumSet; 8 8 import java.util.HashMap; 9 9 import java.util.Map; 10 import java.util.SortedMap; 10 11 import java.util.NoSuchElementException; 11 import java.util.SortedSet; 12 import java.util.TreeSet; 12 import java.util.TreeMap; 13 13 14 14 import javax.swing.JPopupMenu; 15 15 … … 26 26 */ 27 27 public abstract class KeyedItem extends TextItem { 28 28 29 /** Translation of "<different>". Use in combo boxes to display an entry matching several different values. */ 30 protected static final String DIFFERENT = tr("<different>"); 29 /** The constant value {@code "<different>"}. */ 30 protected static final String DIFFERENT = "<different>"; 31 /** Translation of {@code "<different>"}. */ 32 protected static final String DIFFERENT_I18N = tr(DIFFERENT); 31 33 34 /** True if the default value should also be set on primitives that already have tags. */ 32 35 protected static final BooleanProperty PROP_FILL_DEFAULT = new BooleanProperty("taggingpreset.fill-default-for-tagged-primitives", false); 33 36 34 37 /** Last value of each key used in presets, used for prefilling corresponding fields */ … … 99 102 * TODO merge with {@link org.openstreetmap.josm.data.osm.TagCollection} 100 103 */ 101 104 public static class Usage { 102 /** 103 * A set of values that were used for this key. 104 */ 105 public final SortedSet<String> values = new TreeSet<>(); // NOSONAR 105 /** Usage count for all values used for this key */ 106 public final SortedMap<String, Integer> map = new TreeMap<>(); 106 107 private boolean hadKeys; 107 108 private boolean hadEmpty; 108 109 … … 111 112 * @return <code>true</code> if there was exactly one value. 112 113 */ 113 114 public boolean hasUniqueValue() { 114 return values.size() == 1 && !hadEmpty;115 return map.size() == 1 && !hadEmpty; 115 116 } 116 117 117 118 /** … … 119 120 * @return <code>true</code> if it was unused. 120 121 */ 121 122 public boolean unused() { 122 return values.isEmpty();123 return map.isEmpty(); 123 124 } 124 125 125 126 /** … … 128 129 * @throws NoSuchElementException if there is no such value. 129 130 */ 130 131 public String getFirst() { 131 return values.first();132 return map.firstKey(); 132 133 } 133 134 134 135 /** … … 151 152 for (OsmPrimitive s : sel) { 152 153 String v = s.get(key); 153 154 if (v != null) { 154 returnValue. values.add(v);155 returnValue.map.merge(v, 1, Integer::sum); 155 156 } else { 156 157 returnValue.hadEmpty = true; 157 158 } … … 167 168 for (OsmPrimitive s : sel) { 168 169 String booleanValue = OsmUtils.getNamedOsmBoolean(s.get(key)); 169 170 if (booleanValue != null) { 170 returnValue. values.add(booleanValue);171 returnValue.map.merge(booleanValue, 1, Integer::sum); 171 172 } 172 173 } 173 174 return returnValue; … … 202 203 public Boolean matches(Map<String, String> tags) { 203 204 switch (MatchType.ofString(match)) { 204 205 case NONE: 205 return null; 206 return null; // NOSONAR 206 207 case KEY: 207 208 return tags.containsKey(key) ? Boolean.TRUE : null; 208 209 case KEY_REQUIRED: -
src/org/openstreetmap/josm/gui/tagging/presets/items/MultiSelect.java
1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.gui.tagging.presets.items; 3 3 4 import java.awt.Dimension; 5 import java.util.Arrays; 6 import java.util.List; 7 import java.util.Set; 8 import java.util.TreeSet; 4 import java.util.TreeMap; 5 import java.util.stream.Collectors; 9 6 10 import javax.swing.JComponent; 7 import javax.swing.DefaultListModel; 8 import javax.swing.JLabel; 11 9 import javax.swing.JList; 12 10 import javax.swing.JPanel; 13 11 import javax.swing.JScrollPane; 14 import javax.swing.ListModel;15 12 16 import org.openstreetmap.josm.data.osm.Tag;17 13 import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItemGuiSupport; 14 import org.openstreetmap.josm.gui.widgets.OrientationAction; 18 15 import org.openstreetmap.josm.tools.GBC; 19 16 20 17 /** … … 27 24 */ 28 25 public short rows; // NOSONAR 29 26 30 protected ConcatenatingJList list; 27 /** The model for the JList */ 28 protected final DefaultListModel<PresetListEntry> model = new DefaultListModel<>(); 29 /** The swing component */ 30 protected final JList<PresetListEntry> list = new JList<>(model); 31 31 32 @Override 33 protected JComponent addToPanelAnchor(JPanel p, String def, TaggingPresetItemGuiSupport support) { 34 list = new ConcatenatingJList(delimiter, presetListEntries.toArray(new PresetListEntry[0])); 35 ComboMultiSelectListCellRenderer renderer = new ComboMultiSelectListCellRenderer(list, list.getCellRenderer(), 200, key); 36 list.setCellRenderer(renderer); 37 Object itemToSelect = getItemToSelect(def, support, true); 38 list.setSelectedItem(itemToSelect == null ? null : new PresetListEntry(itemToSelect.toString())); 39 JScrollPane sp = new JScrollPane(list); 40 // if a number of rows has been specified in the preset, 41 // modify preferred height of scroll pane to match that row count. 42 if (rows > 0) { 43 double height = renderer.getListCellRendererComponent(list, 44 new PresetListEntry("x"), 0, false, false).getPreferredSize().getHeight() * rows; 45 sp.setPreferredSize(new Dimension((int) sp.getPreferredSize().getWidth(), (int) height)); 32 private void addEntry(PresetListEntry entry) { 33 if (!seenValues.containsKey(entry.value)) { 34 model.addElement(entry); 35 seenValues.put(entry.value, entry); 46 36 } 47 list.addListSelectionListener(l -> support.fireItemValueModified(this, key, getSelectedValue()));48 p.add(sp, GBC.eol().fill(GBC.HORIZONTAL));49 return list;50 37 } 51 38 52 39 @Override 53 protected Object getSelectedItem() { 54 return list.getSelectedItem(); 55 } 40 protected boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support) { 41 initializeLocaleText(null); 42 usage = determineTextUsage(support.getSelected(), key); 43 seenValues = new TreeMap<>(); 44 initListEntries(); 56 45 57 @Override 58 public void addCommands(List<Tag> changedTags) { 59 // Do not create any commands if list has been disabled because of an unknown value (fix #8605) 60 if (list.isEnabled()) { 61 super.addCommands(changedTags); 46 model.clear(); 47 if (!usage.hasUniqueValue() && !usage.unused()) { 48 addEntry(PresetListEntry.ENTRY_DIFFERENT); 62 49 } 63 }64 50 65 /**66 * Class that allows list values to be assigned and retrieved as a comma-delimited67 * string (extracted from TaggingPreset)68 */69 private static class ConcatenatingJList extends JList<PresetListEntry>{70 private final char delimiter;71 72 protected ConcatenatingJList(char del, PresetListEntry... o) {73 super(o);74 delimiter = del;51 String initialValue = getInitialValue(default_); 52 if (initialValue != null) { 53 // add all values already present to the list, otherwise we would remove all 54 // custom entries unknown to the preset 55 for (String value : initialValue.split(String.valueOf(delimiter), -1)) { 56 PresetListEntry e = new PresetListEntry(value, this); 57 addEntry(e); 58 int i = model.indexOf(e); 59 list.addSelectionInterval(i, i); 60 } 75 61 } 76 62 77 public void setSelectedItem(Object o) { 78 if (o == null) { 79 clearSelection(); 80 } else { 81 String s = o.toString(); 82 Set<String> parts = new TreeSet<>(Arrays.asList(s.split(String.valueOf(delimiter), -1))); 83 ListModel<PresetListEntry> lm = getModel(); 84 int[] intParts = new int[lm.getSize()]; 85 int j = 0; 86 for (int i = 0; i < lm.getSize(); i++) { 87 final String value = lm.getElementAt(i).value; 88 if (parts.contains(value)) { 89 intParts[j++] = i; 90 parts.remove(value); 91 } 92 } 93 setSelectedIndices(Arrays.copyOf(intParts, j)); 94 // check if we have actually managed to represent the full 95 // value with our presets. if not, cop out; we will not offer 96 // a selection list that threatens to ruin the value. 97 setEnabled(parts.isEmpty()); 98 } 63 presetListEntries.forEach(this::addEntry); 64 65 ComboMultiSelectListCellRenderer renderer = new ComboMultiSelectListCellRenderer(list, list.getCellRenderer(), 200, key); 66 list.setCellRenderer(renderer); 67 68 if (rows > 0) { 69 list.setVisibleRowCount(rows); 99 70 } 71 JLabel label = addLabel(p); 72 p.add(new JScrollPane(list), GBC.eol().fill(GBC.HORIZONTAL)); // NOSONAR 73 label.setLabelFor(list); 100 74 101 public String getSelectedItem() { 102 ListModel<PresetListEntry> lm = getModel(); 103 int[] si = getSelectedIndices(); 104 StringBuilder builder = new StringBuilder(); 105 for (int i = 0; i < si.length; i++) { 106 if (i > 0) { 107 builder.append(delimiter); 108 } 109 builder.append(lm.getElementAt(si[i]).value); 110 } 111 return builder.toString(); 112 } 75 list.addListSelectionListener(l -> support.fireItemValueModified(this, key, getSelectedItem().value)); 76 list.setToolTipText(getKeyTooltipText()); 77 list.applyComponentOrientation(OrientationAction.getValueOrientation(key)); 78 79 return true; 113 80 } 81 82 @Override 83 protected PresetListEntry getSelectedItem() { 84 return new PresetListEntry(list.getSelectedValuesList() 85 .stream().map(e -> e.value).collect(Collectors.joining(String.valueOf(delimiter))), this); 86 } 114 87 } -
src/org/openstreetmap/josm/gui/tagging/presets/items/PresetListEntry.java
16 16 17 17 /** 18 18 * Preset list entry. 19 * <p> 20 * Used for controls that offer a list of items to choose from like {@link Combo} and 21 * {@link MultiSelect}. 19 22 */ 20 23 public class PresetListEntry implements Comparable<PresetListEntry> { 21 /** Entry value */ 24 /** Used to display an entry matching several different values. */ 25 protected static final PresetListEntry ENTRY_DIFFERENT = new PresetListEntry(KeyedItem.DIFFERENT, null); 26 /** Used to display an empty entry used to clear values. */ 27 protected static final PresetListEntry ENTRY_EMPTY = new PresetListEntry("", null); 28 29 /** 30 * This is the value that is going to be written to the tag on the selected primitive(s). Except 31 * when the value is {@code "<different>"}, which is never written, or the value is empty, which 32 * deletes the tag. {@code value} is never translated. 33 */ 22 34 public String value; // NOSONAR 23 /** The context used for translating {@link #value}*/24 public String value_context; // NOSONAR25 /** Value displayed to the user*/35 /** The ComboMultiSelect that displays the list */ 36 public ComboMultiSelect cms; // NOSONAR 37 /** Text displayed to the user instead of {@link #value}. */ 26 38 public String display_value; // NOSONAR 27 /** Text to be displayed below {@ code display_value}. */39 /** Text to be displayed below {@link #display_value} in the combobox list. */ 28 40 public String short_description; // NOSONAR 29 41 /** The location of icon file to display */ 30 42 public String icon; // NOSONAR … … 35 47 /** The localized version of {@link #short_description}. */ 36 48 public String locale_short_description; // NOSONAR 37 49 50 private String cachedDisplayValue = null; 51 private String cachedShortDescription = null; 52 private ImageIcon cachedIcon = null; 53 38 54 /** 39 55 * Constructs a new {@code PresetListEntry}, uninitialized. 56 * 57 * Public default constructor is needed by {@link org.openstreetmap.josm.tools.XmlObjectParser.Parser#startElement} 40 58 */ 41 59 public PresetListEntry() { 42 // Public default constructor is needed43 60 } 44 61 45 62 /** 46 * Constructs a new {@code PresetListEntry}, initialized with a value. 63 * Constructs a new {@code PresetListEntry}, initialized with a value and 64 * {@link ComboMultiSelect} context. 65 * 47 66 * @param value value 67 * @param cms the ComboMultiSelect 48 68 */ 49 public PresetListEntry(String value ) {69 public PresetListEntry(String value, ComboMultiSelect cms) { 50 70 this.value = value; 71 this.cms = cms; 51 72 } 52 73 53 74 /** … … 60 81 * @return HTML formatted contents 61 82 */ 62 83 public String getListDisplay(int width) { 63 if (value.equals(KeyedItem.DIFFERENT)) { 64 return "<b>" + KeyedItem.DIFFERENT + "</b>"; 84 String displayValue = getDisplayValue(); 85 Integer count = cms == null ? null : cms.usage.map.get(value); 86 87 if (count != null) { 88 displayValue = String.format("%s (%d)", displayValue, count); 65 89 } 66 90 67 String shortDescription = getShortDescription(true); 68 String displayValue = getDisplayValue(); 91 if (this.equals(ENTRY_DIFFERENT)) { 92 return "<html><b>" + Utils.escapeReservedCharactersHTML(displayValue) + "</b></html>"; 93 } 69 94 95 String shortDescription = getShortDescription(); 96 70 97 if (shortDescription.isEmpty()) { 98 // avoids a collapsed list entry if value == "" 71 99 if (displayValue.isEmpty()) { 72 100 return " "; 73 101 } … … 86 114 * @return the entry icon, or {@code null} 87 115 */ 88 116 public ImageIcon getIcon() { 89 return icon == null ? null : TaggingPresetItem.loadImageIcon(icon, TaggingPresetReader.getZipIcons(), (int) icon_size); 117 if (icon != null && cachedIcon == null) { 118 cachedIcon = TaggingPresetItem.loadImageIcon(icon, TaggingPresetReader.getZipIcons(), (int) icon_size); 119 } 120 return cachedIcon; 90 121 } 91 122 92 123 /** 93 * Returns the contents ofthe current item view.124 * Returns the contents displayed in the current item view. 94 125 * @return the value to display 95 126 */ 96 127 public String getDisplayValue() { 97 return Utils.firstNonNull(locale_display_value, tr(display_value), trc(value_context, value)); 128 if (cachedDisplayValue == null) { 129 if (cms != null && cms.values_no_i18n) { 130 cachedDisplayValue = Utils.firstNonNull(value, " "); 131 } else { 132 cachedDisplayValue = Utils.firstNonNull( 133 locale_display_value, tr(display_value), trc(cms == null ? null : cms.values_context, value), " "); 134 } 135 } 136 return cachedDisplayValue; 98 137 } 99 138 100 139 /** 101 140 * Returns the short description to display. 102 * @param translated whether the text must be translated103 141 * @return the short description to display 104 142 */ 105 public String getShortDescription( boolean translated) {106 String shortDesc = translated107 ? Utils.firstNonNull(locale_short_description, tr(short_description))108 : short_description;109 return shortDesc == null ? "" : shortDesc;143 public String getShortDescription() { 144 if (cachedShortDescription == null) { 145 cachedShortDescription = Utils.firstNonNull(locale_short_description, tr(short_description), ""); 146 } 147 return cachedShortDescription; 110 148 } 111 149 150 /** 151 * Returns the tooltip for this entry. 152 * @param key the tag key 153 * @return the tooltip 154 */ 155 public String getToolTipText(String key) { 156 if (this.equals(ENTRY_DIFFERENT)) { 157 return tr("Keeps the original values of the selected objects unchanged."); 158 } 159 if (value != null && !value.isEmpty()) { 160 return tr("Sets the key ''{0}'' to the value ''{1}''.", key, value); 161 } 162 return tr("Clears the key ''{0}''.", key); 163 } 164 112 165 // toString is mainly used to initialize the Editor 113 166 @Override 114 167 public String toString() { 115 if (KeyedItem.DIFFERENT.equals(value)) 116 return KeyedItem.DIFFERENT; 117 String displayValue = getDisplayValue(); 118 return displayValue != null ? displayValue.replaceAll("\\s*<.*>\\s*", " ") : ""; // remove additional markup, e.g. <br> 168 if (this.equals(ENTRY_DIFFERENT)) 169 return getDisplayValue(); 170 return getDisplayValue().replaceAll("\\s*<.*>\\s*", " "); // remove additional markup, e.g. <br> 119 171 } 120 172 121 173 @Override … … 133 185 134 186 @Override 135 187 public int compareTo(PresetListEntry o) { 136 return AlphanumComparator.getInstance().compare(this. getDisplayValue(), o.getDisplayValue());188 return AlphanumComparator.getInstance().compare(this.value, o.value); 137 189 } 138 190 } -
src/org/openstreetmap/josm/gui/tagging/presets/items/Text.java
137 137 // The selected primitives have different values for this key. <b>Note:</b> this 138 138 // cannot be an AutoCompComboBox because the values in the dropdown are different from 139 139 // those we autocomplete on. 140 JosmComboBox<String> comboBox = new JosmComboBox<>(usage.values.toArray(new String[0])); 140 JosmComboBox<String> comboBox = new JosmComboBox<>(); 141 comboBox.getModel().addAllElements(usage.map.keySet()); 141 142 comboBox.setEditable(true); 142 143 comboBox.setEditor(editor); 143 comboBox.getEditor().setItem(DIFFERENT );144 comboBox.getEditor().setItem(DIFFERENT_I18N); 144 145 value = comboBox; 145 originalValue = DIFFERENT ;146 originalValue = DIFFERENT_I18N; 146 147 } 147 148 initializeLocaleText(null); 148 149 -
test/unit/org/openstreetmap/josm/gui/tagging/presets/items/ComboTest.java
41 41 } 42 42 43 43 /** 44 * Unit test for {@link ComboMultiSelect#use_last_as_default} and {@link ComboMultiSelect#getI temToSelect}44 * Unit test for {@link ComboMultiSelect#use_last_as_default} and {@link ComboMultiSelect#getInitialValue} 45 45 */ 46 46 @Test 47 47 void testUseLastAsDefault() { 48 48 Combo combo = new Combo(); 49 49 combo.key = "addr:country"; 50 combo.use_last_as_default = 1;51 50 combo.values_from = "java.util.Locale#getISOCountries"; 52 51 OsmPrimitive way = OsmUtils.createPrimitive("way"); 52 OsmPrimitive wayTagged = OsmUtils.createPrimitive("way highway=residential"); 53 53 OsmPrimitive wayAT = OsmUtils.createPrimitive("way addr:country=AT"); 54 54 OsmPrimitive waySI = OsmUtils.createPrimitive("way addr:country=SI"); 55 KeyedItem.LAST_VALUES.clear(); 56 KeyedItem.LAST_VALUES.put("addr:country", "AT"); 55 57 58 combo.use_last_as_default = 0; 56 59 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, way)); 57 assertEquals("", combo.getSelectedValue()); 60 assertEquals("", combo.getSelectedItem().value); 61 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayTagged)); 62 assertEquals("", combo.getSelectedItem().value); 63 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT)); 64 assertEquals("AT", combo.getSelectedItem().value); 65 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, waySI)); 66 assertEquals("SI", combo.getSelectedItem().value); 67 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT, waySI)); 68 assertEquals(Combo.DIFFERENT, combo.getSelectedItem().value); 58 69 59 combo.default_ = " SI";70 combo.default_ = "AT"; 60 71 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, way)); 61 assertEquals("SI", combo.getSelectedValue()); 72 assertEquals("AT", combo.getSelectedItem().value); 73 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayTagged)); 74 assertEquals("", combo.getSelectedItem().value); 62 75 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT)); 63 assertEquals("AT", combo.getSelectedValue()); 76 assertEquals("AT", combo.getSelectedItem().value); 77 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, waySI)); 78 assertEquals("SI", combo.getSelectedItem().value); 79 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT, waySI)); 80 assertEquals(Combo.DIFFERENT, combo.getSelectedItem().value); 64 81 combo.default_ = null; 65 82 66 KeyedItem.LAST_VALUES.clear(); 67 KeyedItem.LAST_VALUES.put("addr:country", "AT"); 83 combo.use_last_as_default = 1; // untagged objects only 68 84 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, way)); 69 assertEquals("AT", combo.getSelectedValue()); 70 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(true, wayAT)); 71 assertEquals("AT", combo.getSelectedValue()); 72 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(true)); 73 assertEquals("", combo.getSelectedValue()); 74 combo.use_last_as_default = 2; // "force" 75 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(true)); 76 assertEquals("AT", combo.getSelectedValue()); 85 assertEquals("AT", combo.getSelectedItem().value); 86 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayTagged)); 87 assertEquals("", combo.getSelectedItem().value); 88 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT)); 89 assertEquals("AT", combo.getSelectedItem().value); 90 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, waySI)); 91 assertEquals("SI", combo.getSelectedItem().value); 92 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT, waySI)); 93 assertEquals(Combo.DIFFERENT, combo.getSelectedItem().value); 94 95 combo.use_last_as_default = 2; // "force" on tagged objects too 96 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, way)); 97 assertEquals("AT", combo.getSelectedItem().value); 98 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayTagged)); 99 assertEquals("AT", combo.getSelectedItem().value); 100 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT)); 101 assertEquals("AT", combo.getSelectedItem().value); 102 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, waySI)); 103 assertEquals("SI", combo.getSelectedItem().value); 104 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT, waySI)); 105 assertEquals(Combo.DIFFERENT, combo.getSelectedItem().value); 106 77 107 KeyedItem.LAST_VALUES.clear(); 78 79 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(true, wayAT, waySI));80 assertEquals(Combo.DIFFERENT, combo.getSelectedValue());81 108 } 82 109 83 110 @Test … … 90 117 combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false)); 91 118 assertEquals(5, combo.combobox.getItemCount()); 92 119 combo.presetListEntries.stream().filter(e -> "red".equals(e.value)).findFirst().ifPresent(combo.combobox::setSelectedItem); 93 assertEquals("red", combo.getSelected Value());120 assertEquals("red", combo.getSelectedItem().value); 94 121 assertEquals("Rot", combo.getSelectedItem().toString()); 95 122 assertEquals(new Color(0xFF0000), combo.getColor()); 96 123 combo.presetListEntries.stream().filter(e -> "green".equals(e.value)).findFirst().ifPresent(combo.combobox::setSelectedItem); 97 assertEquals("green", combo.getSelected Value());124 assertEquals("green", combo.getSelectedItem().value); 98 125 assertEquals("Grün", combo.getSelectedItem().toString()); 99 126 assertEquals(new Color(0x008000), combo.getColor()); 100 127 combo.combobox.setSelectedItem("#135"); 101 assertEquals("#135", combo.getSelected Value());128 assertEquals("#135", combo.getSelectedItem().value); 102 129 assertEquals(new Color(0x113355), combo.getColor()); 103 130 combo.combobox.setSelectedItem("#123456"); 104 assertEquals("#123456", combo.getSelected Value());131 assertEquals("#123456", combo.getSelectedItem().value); 105 132 assertEquals(new Color(0x123456), combo.getColor()); 106 133 combo.setColor(new Color(0x448822)); 107 assertEquals("#448822", combo.getSelected Value());134 assertEquals("#448822", combo.getSelectedItem().value); 108 135 } 109 136 } -
test/unit/org/openstreetmap/josm/gui/tagging/presets/items/PresetListEntryTest.java
25 25 */ 26 26 @Test 27 27 void testTicket12416() { 28 assertTrue(new PresetListEntry("" ).getListDisplay(200).contains(" "));28 assertTrue(new PresetListEntry("", null).getListDisplay(200).contains(" ")); 29 29 } 30 30 }
