source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/properties/TagEditHelper.java@ 5645

Last change on this file since 5645 was 5645, checked in by akks, 11 years ago

fix #8301 (Exception while editing key value); Shift-Enter in Add Tag dialog adds tag without closing, see #8300

File size: 27.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.properties;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5import static org.openstreetmap.josm.tools.I18n.trn;
6
7import java.awt.BorderLayout;
8import java.awt.Component;
9import java.awt.Cursor;
10import java.awt.FlowLayout;
11import java.awt.Font;
12import java.awt.GridBagConstraints;
13import java.awt.GridBagLayout;
14import java.awt.Toolkit;
15import java.awt.datatransfer.Clipboard;
16import java.awt.datatransfer.Transferable;
17import java.awt.event.ActionEvent;
18import java.awt.event.ActionListener;
19import java.awt.event.FocusAdapter;
20import java.awt.event.FocusEvent;
21import java.awt.event.InputEvent;
22import java.awt.event.KeyEvent;
23import java.awt.event.MouseAdapter;
24import java.awt.event.MouseEvent;
25import java.awt.image.BufferedImage;
26import java.security.KeyStore;
27import java.util.ArrayList;
28import java.util.Arrays;
29import java.util.Collection;
30import java.util.Collections;
31import java.util.Comparator;
32import java.util.HashMap;
33import java.util.Iterator;
34import java.util.LinkedHashMap;
35import java.util.LinkedList;
36import java.util.List;
37import java.util.Map;
38import java.util.Vector;
39import javax.swing.AbstractAction;
40import javax.swing.Action;
41import javax.swing.Box;
42import javax.swing.DefaultListCellRenderer;
43import javax.swing.ImageIcon;
44import javax.swing.JComponent;
45import javax.swing.JLabel;
46import javax.swing.JList;
47import javax.swing.JOptionPane;
48import javax.swing.JPanel;
49import javax.swing.KeyStroke;
50import javax.swing.table.DefaultTableModel;
51import javax.swing.text.JTextComponent;
52import org.openstreetmap.josm.Main;
53import org.openstreetmap.josm.actions.JosmAction;
54import org.openstreetmap.josm.actions.mapmode.DrawAction;
55import org.openstreetmap.josm.command.ChangePropertyCommand;
56import org.openstreetmap.josm.command.Command;
57import org.openstreetmap.josm.command.SequenceCommand;
58import org.openstreetmap.josm.data.osm.DataSet;
59import org.openstreetmap.josm.data.osm.OsmPrimitive;
60import org.openstreetmap.josm.data.osm.Tag;
61import org.openstreetmap.josm.gui.ExtendedDialog;
62import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
63import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingComboBox;
64import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionListItem;
65import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionManager;
66import org.openstreetmap.josm.gui.util.GuiHelper;
67import org.openstreetmap.josm.tools.GBC;
68import org.openstreetmap.josm.tools.Shortcut;
69
70/**
71 * Class that helps PropertiesDialog add and edit tag values
72 */
73 class TagEditHelper {
74 private final DefaultTableModel propertyData;
75 private final Map<String, Map<String, Integer>> valueCount;
76
77 // Selection that we are editing by using both dialogs
78 Collection<OsmPrimitive> sel;
79
80 private String changedKey;
81 private String objKey;
82
83 Comparator<AutoCompletionListItem> defaultACItemComparator = new Comparator<AutoCompletionListItem>() {
84 public int compare(AutoCompletionListItem o1, AutoCompletionListItem o2) {
85 return String.CASE_INSENSITIVE_ORDER.compare(o1.getValue(), o2.getValue());
86 }
87 };
88
89 private String lastAddKey = null;
90 private String lastAddValue = null;
91
92 public static final int DEFAULT_LRU_TAGS_NUMBER = 5;
93 public static final int MAX_LRU_TAGS_NUMBER = 9;
94
95 // LRU cache for recently added tags (http://java-planet.blogspot.com/2005/08/how-to-set-up-simple-lru-cache-using.html)
96 private final Map<Tag, Void> recentTags = new LinkedHashMap<Tag, Void>(MAX_LRU_TAGS_NUMBER+1, 1.1f, true) {
97 @Override
98 protected boolean removeEldestEntry(Map.Entry<Tag, Void> eldest) {
99 return size() > MAX_LRU_TAGS_NUMBER;
100 }
101 };
102
103 TagEditHelper(DefaultTableModel propertyData, Map<String, Map<String, Integer>> valueCount) {
104 this.propertyData = propertyData;
105 this.valueCount = valueCount;
106 }
107
108 /**
109 * Open the add selection dialog and add a new key/value to the table (and
110 * to the dataset, of course).
111 */
112 public void addProperty() {
113 changedKey = null;
114 if (Main.map.mapMode instanceof DrawAction) {
115 sel = ((DrawAction) Main.map.mapMode).getInProgressSelection();
116 } else {
117 DataSet ds = Main.main.getCurrentDataSet();
118 if (ds == null) return;
119 sel = ds.getSelected();
120 }
121 if (sel.isEmpty()) return;
122
123 final AddTagsDialog addDialog = new AddTagsDialog();
124
125 addDialog.showDialog();
126
127 addDialog.destroyActions();
128 if (addDialog.getValue() == 1)
129 addDialog.performTagAdding();
130 else
131 addDialog.undoAllTagsAdding();
132 }
133
134 /**
135 * Edit the value in the properties table row
136 * @param row The row of the table from which the value is edited.
137 */
138 public void editProperty(final int row) {
139 changedKey = null;
140 sel = Main.main.getCurrentDataSet().getSelected();
141 if (sel.isEmpty()) return;
142
143 String key = propertyData.getValueAt(row, 0).toString();
144 objKey=key;
145
146 final EditTagDialog editDialog = new EditTagDialog(key, row,
147 (Map<String, Integer>) propertyData.getValueAt(row, 1));
148 editDialog.showDialog();
149 if (editDialog.getValue() !=1 ) return;
150 editDialog.performTagEdit();
151 }
152 /**
153 * If during last editProperty call user changed the key name, this key will be returned
154 * Elsewhere, returns null.
155 */
156 public String getChangedKey() {
157 return changedKey;
158 }
159
160 public void resetChangedKey() {
161 changedKey = null;
162 }
163
164 /**
165 * For a given key k, return a list of keys which are used as keys for
166 * auto-completing values to increase the search space.
167 * @param key the key k
168 * @return a list of keys
169 */
170 private static List<String> getAutocompletionKeys(String key) {
171 if ("name".equals(key) || "addr:street".equals(key))
172 return Arrays.asList("addr:street", "name");
173 else
174 return Arrays.asList(key);
175 }
176
177 /**
178 * Create a focus handling adapter and apply in to the editor component of value
179 * autocompletion box.
180 * @param keys Box for keys entering and autocompletion
181 * @param values Box for values entering and autocompletion
182 * @param autocomplete Manager handling the autocompletion
183 * @param comparator Class to decide what values are offered on autocompletion
184 * @return The created adapter
185 */
186 private FocusAdapter addFocusAdapter(final AutoCompletingComboBox keys, final AutoCompletingComboBox values,
187 final AutoCompletionManager autocomplete, final Comparator<AutoCompletionListItem> comparator) {
188 // get the combo box' editor component
189 JTextComponent editor = (JTextComponent)values.getEditor()
190 .getEditorComponent();
191 // Refresh the values model when focus is gained
192 FocusAdapter focus = new FocusAdapter() {
193 @Override public void focusGained(FocusEvent e) {
194 String key = keys.getEditor().getItem().toString();
195
196 List<AutoCompletionListItem> valueList = autocomplete.getValues(getAutocompletionKeys(key));
197 Collections.sort(valueList, comparator);
198
199 values.setPossibleACItems(valueList);
200 objKey=key;
201 }
202 };
203 editor.addFocusListener(focus);
204 return focus;
205 }
206
207
208 public class EditTagDialog extends ExtendedDialog {
209 AutoCompletingComboBox keys;
210 AutoCompletingComboBox values;
211 String oldValue;
212 String key;
213 Map<String, Integer> m;
214 int row;
215
216 Comparator<AutoCompletionListItem> usedValuesAwareComparator = new Comparator<AutoCompletionListItem>() {
217 @Override
218 public int compare(AutoCompletionListItem o1, AutoCompletionListItem o2) {
219 boolean c1 = m.containsKey(o1.getValue());
220 boolean c2 = m.containsKey(o2.getValue());
221 if (c1 == c2)
222 return String.CASE_INSENSITIVE_ORDER.compare(o1.getValue(), o2.getValue());
223 else if (c1)
224 return -1;
225 else
226 return +1;
227 }
228 };
229
230 DefaultListCellRenderer cellRenderer = new DefaultListCellRenderer() {
231 @Override public Component getListCellRendererComponent(JList list,
232 Object value, int index, boolean isSelected, boolean cellHasFocus){
233 Component c = super.getListCellRendererComponent(list, value,
234 index, isSelected, cellHasFocus);
235 if (c instanceof JLabel) {
236 String str = ((AutoCompletionListItem) value).getValue();
237 if (valueCount.containsKey(objKey)) {
238 Map<String, Integer> m = valueCount.get(objKey);
239 if (m.containsKey(str)) {
240 str = tr("{0} ({1})", str, m.get(str));
241 c.setFont(c.getFont().deriveFont(Font.ITALIC + Font.BOLD));
242 }
243 }
244 ((JLabel) c).setText(str);
245 }
246 return c;
247 }
248 };
249
250 private EditTagDialog(String key, int row, Map<String, Integer> map) {
251 super(Main.parent, trn("Change value?", "Change values?", map.size()), new String[] {tr("OK"),tr("Cancel")});
252 setButtonIcons(new String[] {"ok","cancel"});
253 setCancelButton(2);
254 setIcon(JOptionPane.QUESTION_MESSAGE);
255 this.key = key;
256 this.row = row;
257 this.m = map;
258
259 // TODO : How to remember position, allowing autosizing?
260 // setRememberWindowGeometry(getClass().getName() + ".geometry",
261 // WindowGeometry.centerInWindow(Main.parent, new Dimension(270, 180)));
262 //setRememberWindowGeometry(getClass().getName() + ".geometry",
263 // WindowGeometry.centerInWindow(Main.parent, new Dimension(270, 180)));
264
265 JPanel mainPanel = new JPanel(new BorderLayout());
266
267 String msg = "<html>"+trn("This will change {0} object.",
268 "This will change up to {0} objects.", sel.size(), sel.size())
269 +"<br><br>("+tr("An empty value deletes the tag.", key)+")</html>";
270
271 mainPanel.add(new JLabel(msg), BorderLayout.NORTH);
272
273 JPanel p = new JPanel(new GridBagLayout());
274 mainPanel.add(p, BorderLayout.CENTER);
275
276 AutoCompletionManager autocomplete = Main.main.getEditLayer().data.getAutoCompletionManager();
277 List<AutoCompletionListItem> keyList = autocomplete.getKeys();
278 Collections.sort(keyList, defaultACItemComparator);
279
280 keys = new AutoCompletingComboBox(key);
281 keys.setPossibleACItems(keyList);
282 keys.setEditable(true);
283 keys.setSelectedItem(key);
284
285 p.add(new JLabel(tr("Key")), GBC.std());
286 p.add(Box.createHorizontalStrut(10), GBC.std());
287 p.add(keys, GBC.eol().fill(GBC.HORIZONTAL));
288
289 List<AutoCompletionListItem> valueList = autocomplete.getValues(getAutocompletionKeys(key));
290 Collections.sort(valueList, usedValuesAwareComparator);
291
292 final String selection= m.size()!=1?tr("<different>"):m.entrySet().iterator().next().getKey();
293
294 values = new AutoCompletingComboBox(selection);
295 values.setRenderer(cellRenderer);
296
297 values.setEditable(true);
298 values.setPossibleACItems(valueList);
299 values.setSelectedItem(selection);
300 values.getEditor().setItem(selection);
301 p.add(new JLabel(tr("Value")), GBC.std());
302 p.add(Box.createHorizontalStrut(10), GBC.std());
303 p.add(values, GBC.eol().fill(GBC.HORIZONTAL));
304 values.getEditor().addActionListener(new ActionListener() {
305 public void actionPerformed(ActionEvent e) {
306 buttonAction(0, null); // emulate OK button click
307 }
308 });
309 addFocusAdapter(keys, values, autocomplete, usedValuesAwareComparator);
310
311 setContent(mainPanel, false);
312
313 // TODO: Is it correct place for thois code - was in
314 // new JOptionPane(p, JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION) {
315 // @Override public void selectInitialValue() {
316 Clipboard sysSel = Toolkit.getDefaultToolkit().getSystemSelection();
317 if(sysSel != null) {
318 Transferable old = sysSel.getContents(null);
319 values.requestFocusInWindow();
320 values.getEditor().selectAll();
321 sysSel.setContents(old, null);
322 } else {
323 values.requestFocusInWindow();
324 values.getEditor().selectAll();
325 }
326 }
327
328 /**
329 * Edit tags of multiple selected objects according to selected ComboBox values
330 * If value == "", tag will be deleted
331 * Confirmations may be needed.
332 */
333 private void performTagEdit() {
334 String value = values.getEditor().getItem().toString().trim();
335 // is not Java 1.5
336 //value = java.text.Normalizer.normalize(value, java.text.Normalizer.Form.NFC);
337 if (value.equals("")) {
338 value = null; // delete the key
339 }
340 String newkey = keys.getEditor().getItem().toString().trim();
341 //newkey = java.text.Normalizer.normalize(newkey, java.text.Normalizer.Form.NFC);
342 if (newkey.equals("")) {
343 newkey = key;
344 value = null; // delete the key instead
345 }
346 if (key.equals(newkey) && tr("<different>").equals(value))
347 return;
348 if (key.equals(newkey) || value == null) {
349 Main.main.undoRedo.add(new ChangePropertyCommand(sel, newkey, value));
350 } else {
351 for (OsmPrimitive osm: sel) {
352 if(osm.get(newkey) != null) {
353 ExtendedDialog ed = new ExtendedDialog(
354 Main.parent,
355 tr("Overwrite key"),
356 new String[]{tr("Replace"), tr("Cancel")});
357 ed.setButtonIcons(new String[]{"purge", "cancel"});
358 ed.setContent(tr("You changed the key from ''{0}'' to ''{1}''.\n"
359 + "The new key is already used, overwrite values?", key, newkey));
360 ed.setCancelButton(2);
361 ed.toggleEnable("overwriteEditKey");
362 ed.showDialog();
363
364 if (ed.getValue() != 1)
365 return;
366 break;
367 }
368 }
369 Collection<Command> commands=new Vector<Command>();
370 commands.add(new ChangePropertyCommand(sel, key, null));
371 if (value.equals(tr("<different>"))) {
372 HashMap<String, Vector<OsmPrimitive>> map=new HashMap<String, Vector<OsmPrimitive>>();
373 for (OsmPrimitive osm: sel) {
374 String val=osm.get(key);
375 if(val != null)
376 {
377 if (map.containsKey(val)) {
378 map.get(val).add(osm);
379 } else {
380 Vector<OsmPrimitive> v = new Vector<OsmPrimitive>();
381 v.add(osm);
382 map.put(val, v);
383 }
384 }
385 }
386 for (Map.Entry<String, Vector<OsmPrimitive>> e: map.entrySet()) {
387 commands.add(new ChangePropertyCommand(e.getValue(), newkey, e.getKey()));
388 }
389 } else {
390 commands.add(new ChangePropertyCommand(sel, newkey, value));
391 }
392 Main.main.undoRedo.add(new SequenceCommand(
393 trn("Change properties of up to {0} object",
394 "Change properties of up to {0} objects", sel.size(), sel.size()),
395 commands));
396 }
397
398 changedKey = newkey;
399 }
400 }
401
402 class AddTagsDialog extends ExtendedDialog {
403 AutoCompletingComboBox keys;
404 AutoCompletingComboBox values;
405 List<JosmAction> recentTagsActions = new ArrayList<JosmAction>();
406
407 // Counter of added commands for possible undo
408 private int commandCount;
409
410 public AddTagsDialog() {
411 super(Main.parent, tr("Add value?"), new String[] {tr("OK"),tr("Cancel")});
412 setButtonIcons(new String[] {"ok","cancel"});
413 setCancelButton(2);
414
415 // TODO : How to remember position, allowing autosizing?
416 // setRememberWindowGeometry(getClass().getName() + ".geometry",
417 // WindowGeometry.centerInWindow(Main.parent, new Dimension(270, 180)));
418
419 JPanel mainPanel = new JPanel(new GridBagLayout());
420 keys = new AutoCompletingComboBox();
421 values = new AutoCompletingComboBox();
422
423 mainPanel.add(new JLabel("<html>"+trn("This will change up to {0} object.",
424 "This will change up to {0} objects.", sel.size(),sel.size())
425 +"<br><br>"+tr("Please select a key")), GBC.eol().fill(GBC.HORIZONTAL));
426
427 AutoCompletionManager autocomplete = Main.main.getEditLayer().data.getAutoCompletionManager();
428 List<AutoCompletionListItem> keyList = autocomplete.getKeys();
429
430 AutoCompletionListItem itemToSelect = null;
431 // remove the object's tag keys from the list
432 Iterator<AutoCompletionListItem> iter = keyList.iterator();
433 while (iter.hasNext()) {
434 AutoCompletionListItem item = iter.next();
435 if (item.getValue().equals(lastAddKey)) {
436 itemToSelect = item;
437 }
438 for (int i = 0; i < propertyData.getRowCount(); ++i) {
439 if (item.getValue().equals(propertyData.getValueAt(i, 0))) {
440 if (itemToSelect == item) {
441 itemToSelect = null;
442 }
443 iter.remove();
444 break;
445 }
446 }
447 }
448
449 Collections.sort(keyList, defaultACItemComparator);
450 keys.setPossibleACItems(keyList);
451 keys.setEditable(true);
452
453 mainPanel.add(keys, GBC.eop().fill());
454
455 mainPanel.add(new JLabel(tr("Please select a value")), GBC.eol());
456 values.setEditable(true);
457 mainPanel.add(values, GBC.eop().fill());
458 if (itemToSelect != null) {
459 keys.setSelectedItem(itemToSelect);
460 if (lastAddValue != null) {
461 values.setSelectedItem(lastAddValue);
462 }
463 }
464
465 FocusAdapter focus = addFocusAdapter(keys, values, autocomplete, defaultACItemComparator);
466 // fire focus event in advance or otherwise the popup list will be too small at first
467 focus.focusGained(null);
468
469 int recentTagsToShow = Main.pref.getInteger("properties.recently-added-tags", DEFAULT_LRU_TAGS_NUMBER);
470 if (recentTagsToShow > MAX_LRU_TAGS_NUMBER) {
471 recentTagsToShow = MAX_LRU_TAGS_NUMBER;
472 }
473
474 // Add tag on Shift-Enter
475 mainPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
476 KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_MASK), "addAndContinue");
477 mainPanel.getActionMap().put("addAndContinue", new AbstractAction() {
478 @Override
479 public void actionPerformed(ActionEvent e) {
480 performTagAdding();
481 }
482 });
483
484 suggestRecentlyAddedTags(mainPanel, recentTagsToShow, focus);
485
486 setContent(mainPanel, false);
487
488 // TODO: Is it correct place for thois code - was in
489 // new JOptionPane(p, JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION) {
490 // @Override public void selectInitialValue() {
491 Clipboard sysSel = Toolkit.getDefaultToolkit().getSystemSelection();
492 if(sysSel != null) {
493 Transferable old = sysSel.getContents(null);
494 values.requestFocusInWindow();
495 values.getEditor().selectAll();
496 sysSel.setContents(old, null);
497 } else {
498 values.requestFocusInWindow();
499 values.getEditor().selectAll();
500 }
501
502
503 }
504
505 private void suggestRecentlyAddedTags(JPanel mainPanel, int tagsToShow, final FocusAdapter focus) {
506 if (!(tagsToShow > 0 && !recentTags.isEmpty()))
507 return;
508
509 mainPanel.add(new JLabel(tr("Recently added tags")), GBC.eol());
510
511 int count = 1;
512 // We store the maximum number (9) of recent tags to allow dynamic change of number of tags shown in the preferences.
513 // This implies to iterate in descending order, as the oldest elements will only be removed after we reach the maximum numbern and not the number of tags to show.
514 // However, as Set does not allow to iterate in descending order, we need to copy its elements into a List we can access in reverse order.
515 List<Tag> tags = new LinkedList<Tag>(recentTags.keySet());
516 for (int i = tags.size()-1; i >= 0 && count <= tagsToShow; i--, count++) {
517 final Tag t = tags.get(i);
518 // Create action for reusing the tag, with keyboard shortcut Ctrl+(1-5)
519 String actionShortcutKey = "properties:recent:"+count;
520 Shortcut sc = Shortcut.registerShortcut(actionShortcutKey, null, KeyEvent.VK_0+count, Shortcut.CTRL);
521 final JosmAction action = new JosmAction(actionShortcutKey, null, tr("Use this tag again"), sc, false) {
522 @Override
523 public void actionPerformed(ActionEvent e) {
524 keys.setSelectedItem(t.getKey());
525 // Update list of values (fix #7951)
526 // fix #8298 - update list of values before setting value (?)
527 focus.focusGained(null);
528 values.setSelectedItem(t.getValue());
529 }
530 };
531 recentTagsActions.add(action);
532 disableTagIfNeeded(t, action);
533 // Find and display icon
534 ImageIcon icon = MapPaintStyles.getNodeIcon(t, false); // Filters deprecated icon
535 if (icon == null) {
536 icon = new ImageIcon(new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB));
537 }
538 GridBagConstraints gbc = new GridBagConstraints();
539 gbc.ipadx = 5;
540 mainPanel.add(new JLabel(action.isEnabled() ? icon : GuiHelper.getDisabledIcon(icon)), gbc);
541 // Create tag label
542 final String color = action.isEnabled() ? "" : "; color:gray";
543 final JLabel tagLabel = new JLabel("<html>"
544 + "<style>td{border:1px solid gray; font-weight:normal"+color+"}</style>"
545 + "<table><tr><td>" + t.toString() + "</td></tr></table></html>");
546 if (action.isEnabled()) {
547 // Register action
548 mainPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(sc.getKeyStroke(), actionShortcutKey);
549 mainPanel.getActionMap().put(actionShortcutKey, action);
550 // Make the tag label clickable and set tooltip to the action description (this displays also the keyboard shortcut)
551 tagLabel.setToolTipText((String) action.getValue(Action.SHORT_DESCRIPTION));
552 tagLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
553 tagLabel.addMouseListener(new MouseAdapter() {
554 @Override
555 public void mouseClicked(MouseEvent e) {
556 action.actionPerformed(null);
557 // add tags and close window on double-click
558 if (e.getClickCount()>1) {
559 performTagAdding();
560 buttonAction(0, null); // emulate OK click and close the dialog
561 }
562 // add tags on Shift-Click
563 if (e.isShiftDown()) {
564 performTagAdding();
565 }
566 }
567 });
568 } else {
569 // Disable tag label
570 tagLabel.setEnabled(false);
571 // Explain in the tooltip why
572 tagLabel.setToolTipText(tr("The key ''{0}'' is already used", t.getKey()));
573 }
574 // Finally add label to the resulting panel
575 JPanel tagPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
576 tagPanel.add(tagLabel);
577 mainPanel.add(tagPanel, GBC.eol().fill(GBC.HORIZONTAL));
578 }
579 }
580
581 public void destroyActions() {
582 for (JosmAction action : recentTagsActions) {
583 action.destroy();
584 }
585 }
586
587
588 /**
589 * Read tags from comboboxes and add it to all selected objects
590 */
591 public void performTagAdding() {
592 String key = keys.getEditor().getItem().toString().trim();
593 String value = values.getEditor().getItem().toString().trim();
594 if (key.isEmpty() || value.isEmpty()) return;
595 lastAddKey = key;
596 lastAddValue = value;
597 recentTags.put(new Tag(key, value), null);
598 commandCount++;
599 Main.main.undoRedo.add(new ChangePropertyCommand(sel, key, value));
600 changedKey = key;
601 }
602
603
604 public void undoAllTagsAdding() {
605 Main.main.undoRedo.undo(commandCount);
606 }
607
608
609 private void disableTagIfNeeded(final Tag t, final JosmAction action) {
610 // Disable action if its key is already set on the object (the key being absent from the keys list for this reason
611 // performing this action leads to autocomplete to the next key (see #7671 comments)
612 for (int j = 0; j < propertyData.getRowCount(); ++j) {
613 if (t.getKey().equals(propertyData.getValueAt(j, 0))) {
614 action.setEnabled(false);
615 break;
616 }
617 }
618 }
619
620 }
621 }
Note: See TracBrowser for help on using the repository browser.