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

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

see #8024: After adding recent tags by shift-click, Cancel can undo all operations.
Caution: new refactoring - now Add Tags and Edit Tags are ExtendedDialog subclasses

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