Changeset 5633 in josm


Ignore:
Timestamp:
2012-12-26T13:13:57+01:00 (12 years ago)
Author:
akks
Message:

see #8293: Auto-select edited or added tag in Properties table, refactoring of PropertiesDialog
(TagEditHelper introduced)

Location:
trunk/src/org/openstreetmap/josm/gui/dialogs/properties
Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java

    r5590 r5633  
    55import static org.openstreetmap.josm.tools.I18n.trn;
    66
    7 import java.awt.BorderLayout;
    87import java.awt.Component;
    98import java.awt.Container;
    10 import java.awt.Cursor;
    11 import java.awt.Dialog.ModalityType;
    12 import java.awt.Dimension;
    13 import java.awt.FlowLayout;
    149import java.awt.Font;
    15 import java.awt.GridBagConstraints;
    1610import java.awt.GridBagLayout;
    1711import java.awt.Point;
    18 import java.awt.Toolkit;
    19 import java.awt.datatransfer.Clipboard;
    20 import java.awt.datatransfer.Transferable;
    2112import java.awt.event.ActionEvent;
    22 import java.awt.event.ActionListener;
    23 import java.awt.event.FocusAdapter;
    24 import java.awt.event.FocusEvent;
    2513import java.awt.event.KeyEvent;
    2614import java.awt.event.MouseAdapter;
    2715import java.awt.event.MouseEvent;
    28 import java.awt.image.BufferedImage;
    2916import java.net.HttpURLConnection;
    3017import java.net.URI;
     
    3825import java.util.HashMap;
    3926import java.util.HashSet;
    40 import java.util.Iterator;
    41 import java.util.LinkedHashMap;
    4227import java.util.LinkedList;
    4328import java.util.List;
     
    4732import java.util.TreeMap;
    4833import java.util.TreeSet;
    49 import java.util.Vector;
    5034
    5135import javax.swing.AbstractAction;
    5236import javax.swing.Action;
    53 import javax.swing.Box;
    54 import javax.swing.DefaultListCellRenderer;
    55 import javax.swing.ImageIcon;
    5637import javax.swing.JComponent;
    57 import javax.swing.JDialog;
    5838import javax.swing.JLabel;
    59 import javax.swing.JList;
    6039import javax.swing.JMenuItem;
    61 import javax.swing.JOptionPane;
    6240import javax.swing.JPanel;
    6341import javax.swing.JPopupMenu;
     
    7351import javax.swing.table.TableColumnModel;
    7452import javax.swing.table.TableModel;
    75 import javax.swing.text.JTextComponent;
    7653
    7754import org.openstreetmap.josm.Main;
    7855import org.openstreetmap.josm.actions.JosmAction;
    79 import org.openstreetmap.josm.actions.mapmode.DrawAction;
    8056import org.openstreetmap.josm.actions.search.SearchAction.SearchMode;
    8157import org.openstreetmap.josm.actions.search.SearchAction.SearchSetting;
     
    8359import org.openstreetmap.josm.command.ChangePropertyCommand;
    8460import org.openstreetmap.josm.command.Command;
    85 import org.openstreetmap.josm.command.SequenceCommand;
    8661import org.openstreetmap.josm.data.SelectionChangedListener;
    87 import org.openstreetmap.josm.data.osm.DataSet;
    8862import org.openstreetmap.josm.data.osm.IRelation;
    8963import org.openstreetmap.josm.data.osm.Node;
     
    10882import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
    10983import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    110 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
    11184import org.openstreetmap.josm.gui.tagging.TaggingPreset;
    11285import org.openstreetmap.josm.gui.tagging.TaggingPreset.PresetType;
    113 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingComboBox;
    114 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionListItem;
    115 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionManager;
    116 import org.openstreetmap.josm.gui.util.GuiHelper;
    11786import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
    11887import org.openstreetmap.josm.tools.GBC;
     
    162131                int row = propertyTable.rowAtPoint(e.getPoint());
    163132                if (row > -1) {
    164                     editProperty(row);
     133                    editHelper.editProperty(row);
    165134                } else {
    166                     addProperty();
     135                    editHelper.addProperty();
     136                    btnAdd.requestFocusInWindow();
    167137                }
    168138            } else if (e.getSource() == membershipTable) {
     
    174144            else
    175145            {
    176                 addProperty();
     146                editHelper.addProperty();
     147                btnAdd.requestFocusInWindow();
    177148            }
    178149        }
     
    184155            }
    185156        }
     157
    186158    }
    187159
     
    195167    private final Map<String, Map<String, Integer>> valueCount = new TreeMap<String, Map<String, Integer>>();
    196168
    197     Comparator<AutoCompletionListItem> defaultACItemComparator = new Comparator<AutoCompletionListItem>() {
    198         public int compare(AutoCompletionListItem o1, AutoCompletionListItem o2) {
    199             return String.CASE_INSENSITIVE_ORDER.compare(o1.getValue(), o2.getValue());
    200         }
    201     };
    202 
     169   
    203170    private final DataSetListenerAdapter dataChangedAdapter = new DataSetListenerAdapter(this);
    204171    private final HelpAction helpAction = new HelpAction();
     
    235202
    236203    /**
    237      * Edit the value in the properties table row
    238      * @param row The row of the table from which the value is edited.
    239      */
    240     private void editProperty(int row) {
    241         Collection<OsmPrimitive> sel = Main.main.getCurrentDataSet().getSelected();
    242         if (sel.isEmpty()) return;
    243 
    244         String key = propertyData.getValueAt(row, 0).toString();
    245         objKey=key;
    246 
    247         String msg = "<html>"+trn("This will change {0} object.",
    248                 "This will change up to {0} objects.", sel.size(), sel.size())
    249                 +"<br><br>("+tr("An empty value deletes the tag.", key)+")</html>";
    250 
    251         JPanel panel = new JPanel(new BorderLayout());
    252         panel.add(new JLabel(msg), BorderLayout.NORTH);
    253 
    254         JPanel p = new JPanel(new GridBagLayout());
    255         panel.add(p, BorderLayout.CENTER);
    256 
    257         AutoCompletionManager autocomplete = Main.main.getEditLayer().data.getAutoCompletionManager();
    258         List<AutoCompletionListItem> keyList = autocomplete.getKeys();
    259         Collections.sort(keyList, defaultACItemComparator);
    260 
    261         final AutoCompletingComboBox keys = new AutoCompletingComboBox(key);
    262         keys.setPossibleACItems(keyList);
    263         keys.setEditable(true);
    264         keys.setSelectedItem(key);
    265 
    266         p.add(new JLabel(tr("Key")), GBC.std());
    267         p.add(Box.createHorizontalStrut(10), GBC.std());
    268         p.add(keys, GBC.eol().fill(GBC.HORIZONTAL));
    269 
    270         @SuppressWarnings("unchecked")
    271         final Map<String, Integer> m = (Map<String, Integer>) propertyData.getValueAt(row, 1);
    272 
    273         Comparator<AutoCompletionListItem> usedValuesAwareComparator = new Comparator<AutoCompletionListItem>() {
    274 
    275             @Override
    276             public int compare(AutoCompletionListItem o1, AutoCompletionListItem o2) {
    277                 boolean c1 = m.containsKey(o1.getValue());
    278                 boolean c2 = m.containsKey(o2.getValue());
    279                 if (c1 == c2)
    280                     return String.CASE_INSENSITIVE_ORDER.compare(o1.getValue(), o2.getValue());
    281                 else if (c1)
    282                     return -1;
    283                 else
    284                     return +1;
    285             }
    286         };
    287 
    288         List<AutoCompletionListItem> valueList = autocomplete.getValues(getAutocompletionKeys(key));
    289         Collections.sort(valueList, usedValuesAwareComparator);
    290 
    291         final String selection= m.size()!=1?tr("<different>"):m.entrySet().iterator().next().getKey();
    292        
    293         final AutoCompletingComboBox values = new AutoCompletingComboBox(selection);
    294         values.setRenderer(new DefaultListCellRenderer() {
    295             @Override public Component getListCellRendererComponent(JList list,
    296                     Object value, int index, boolean isSelected,  boolean cellHasFocus){
    297                 Component c = super.getListCellRendererComponent(list, value,
    298                         index, isSelected, cellHasFocus);
    299                 if (c instanceof JLabel) {
    300                     String str = ((AutoCompletionListItem) value).getValue();
    301                     if (valueCount.containsKey(objKey)) {
    302                         Map<String, Integer> m = valueCount.get(objKey);
    303                         if (m.containsKey(str)) {
    304                             str = tr("{0} ({1})", str, m.get(str));
    305                             c.setFont(c.getFont().deriveFont(Font.ITALIC + Font.BOLD));
    306                         }
    307                     }
    308                     ((JLabel) c).setText(str);
    309                 }
    310                 return c;
    311             }
    312         });
    313        
    314         values.setEditable(true);
    315         values.setPossibleACItems(valueList);
    316         values.setSelectedItem(selection);
    317         values.getEditor().setItem(selection);
    318         p.add(new JLabel(tr("Value")), GBC.std());
    319         p.add(Box.createHorizontalStrut(10), GBC.std());
    320         p.add(values, GBC.eol().fill(GBC.HORIZONTAL));
    321         addFocusAdapter(keys, values, autocomplete, usedValuesAwareComparator);
    322 
    323         final JOptionPane optionPane = new JOptionPane(panel, JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION) {
    324             @Override public void selectInitialValue() {
    325                 // save unix system selection (middle mouse paste)
    326                 Clipboard sysSel = Toolkit.getDefaultToolkit().getSystemSelection();
    327                 if(sysSel != null) {
    328                     Transferable old = sysSel.getContents(null);
    329                     values.requestFocusInWindow();
    330                     values.getEditor().selectAll();
    331                     sysSel.setContents(old, null);
    332                 } else {
    333                     values.requestFocusInWindow();
    334                     values.getEditor().selectAll();
    335                 }
    336             }
    337         };
    338         final JDialog dlg = optionPane.createDialog(Main.parent, trn("Change value?", "Change values?", m.size()));
    339         dlg.setModalityType(ModalityType.DOCUMENT_MODAL);
    340         Dimension dlgSize = dlg.getSize();
    341         if(dlgSize.width > Main.parent.getSize().width) {
    342             dlgSize.width = Math.max(250, Main.parent.getSize().width);
    343             dlg.setSize(dlgSize);
    344         }
    345         dlg.setLocationRelativeTo(Main.parent);
    346         values.getEditor().addActionListener(new ActionListener() {
    347             public void actionPerformed(ActionEvent e) {
    348                 dlg.setVisible(false);
    349                 optionPane.setValue(JOptionPane.OK_OPTION);
    350             }
    351         });
    352 
    353         String oldValue = values.getEditor().getItem().toString();
    354         dlg.setVisible(true);
    355 
    356         Object answer = optionPane.getValue();
    357         if (answer == null || answer == JOptionPane.UNINITIALIZED_VALUE ||
    358                 (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION)) {
    359             values.getEditor().setItem(oldValue);
    360             return;
    361         }
    362 
    363         String value = values.getEditor().getItem().toString().trim();
    364         // is not Java 1.5
    365         //value = java.text.Normalizer.normalize(value, java.text.Normalizer.Form.NFC);
    366         if (value.equals("")) {
    367             value = null; // delete the key
    368         }
    369         String newkey = keys.getEditor().getItem().toString().trim();
    370         //newkey = java.text.Normalizer.normalize(newkey, java.text.Normalizer.Form.NFC);
    371         if (newkey.equals("")) {
    372             newkey = key;
    373             value = null; // delete the key instead
    374         }
    375         if (key.equals(newkey) && tr("<different>").equals(value))
    376             return;
    377         if (key.equals(newkey) || value == null) {
    378             Main.main.undoRedo.add(new ChangePropertyCommand(sel, newkey, value));
    379         } else {
    380             for (OsmPrimitive osm: sel) {
    381                 if(osm.get(newkey) != null) {
    382                     ExtendedDialog ed = new ExtendedDialog(
    383                             Main.parent,
    384                             tr("Overwrite key"),
    385                             new String[]{tr("Replace"), tr("Cancel")});
    386                     ed.setButtonIcons(new String[]{"purge", "cancel"});
    387                     ed.setContent(tr("You changed the key from ''{0}'' to ''{1}''.\n"
    388                             + "The new key is already used, overwrite values?", key, newkey));
    389                     ed.setCancelButton(2);
    390                     ed.toggleEnable("overwriteEditKey");
    391                     ed.showDialog();
    392 
    393                     if (ed.getValue() != 1)
    394                         return;
    395                     break;
    396                 }
    397             }
    398             Collection<Command> commands=new Vector<Command>();
    399             commands.add(new ChangePropertyCommand(sel, key, null));
    400             if (value.equals(tr("<different>"))) {
    401                 HashMap<String, Vector<OsmPrimitive>> map=new HashMap<String, Vector<OsmPrimitive>>();
    402                 for (OsmPrimitive osm: sel) {
    403                     String val=osm.get(key);
    404                     if(val != null)
    405                     {
    406                         if (map.containsKey(val)) {
    407                             map.get(val).add(osm);
    408                         } else {
    409                             Vector<OsmPrimitive> v = new Vector<OsmPrimitive>();
    410                             v.add(osm);
    411                             map.put(val, v);
    412                         }
    413                     }
    414                 }
    415                 for (Entry<String, Vector<OsmPrimitive>> e: map.entrySet()) {
    416                     commands.add(new ChangePropertyCommand(e.getValue(), newkey, e.getKey()));
    417                 }
    418             } else {
    419                 commands.add(new ChangePropertyCommand(sel, newkey, value));
    420             }
    421             Main.main.undoRedo.add(new SequenceCommand(
    422                     trn("Change properties of up to {0} object",
    423                             "Change properties of up to {0} objects", sel.size(), sel.size()),
    424                             commands));
    425         }
    426 
    427         if(!key.equals(newkey)) {
    428             for(int i=0; i < propertyTable.getRowCount(); i++)
    429                 if(propertyData.getValueAt(i, 0).toString().equals(newkey)) {
    430                     row=i;
    431                     break;
    432                 }
    433         }
    434         propertyTable.changeSelection(row, 0, false, false);
    435     }
    436 
    437     /**
    438      * For a given key k, return a list of keys which are used as keys for
    439      * auto-completing values to increase the search space.
    440      * @param key the key k
    441      * @return a list of keys
    442      */
    443     private static List<String> getAutocompletionKeys(String key) {
    444         if ("name".equals(key) || "addr:street".equals(key))
    445             return Arrays.asList("addr:street", "name");
    446         else
    447             return Arrays.asList(key);
    448     }
    449 
    450     /**
    451204     * This simply fires up an {@link RelationEditor} for the relation shown; everything else
    452205     * is the editor's business.
     
    463216    }
    464217
    465     private static String lastAddKey = null;
    466     private static String lastAddValue = null;
    467    
    468     public static final int DEFAULT_LRU_TAGS_NUMBER = 5;
    469     public static final int MAX_LRU_TAGS_NUMBER = 9;
    470    
    471     // LRU cache for recently added tags (http://java-planet.blogspot.com/2005/08/how-to-set-up-simple-lru-cache-using.html)
    472     private static final Map<Tag, Void> recentTags = new LinkedHashMap<Tag, Void>(MAX_LRU_TAGS_NUMBER+1, 1.1f, true) {
    473         @Override
    474         protected boolean removeEldestEntry(Entry<Tag, Void> eldest) {
    475             return size() > MAX_LRU_TAGS_NUMBER;
    476         }
    477     };
    478    
    479     /**
    480      * Open the add selection dialog and add a new key/value to the table (and
    481      * to the dataset, of course).
    482      */
    483     private void addProperty() {
    484         Collection<OsmPrimitive> sel;
    485         if (Main.map.mapMode instanceof DrawAction) {
    486             sel = ((DrawAction) Main.map.mapMode).getInProgressSelection();
    487         } else {
    488             DataSet ds = Main.main.getCurrentDataSet();
    489             if (ds == null) return;
    490             sel = ds.getSelected();
    491         }
    492         if (sel.isEmpty()) return;
    493 
    494         JPanel p = new JPanel(new GridBagLayout());
    495         p.add(new JLabel("<html>"+trn("This will change up to {0} object.",
    496                 "This will change up to {0} objects.", sel.size(),sel.size())
    497                 +"<br><br>"+tr("Please select a key")), GBC.eol().fill(GBC.HORIZONTAL));
    498         final AutoCompletingComboBox keys = new AutoCompletingComboBox();
    499         AutoCompletionManager autocomplete = Main.main.getEditLayer().data.getAutoCompletionManager();
    500         List<AutoCompletionListItem> keyList = autocomplete.getKeys();
    501 
    502         AutoCompletionListItem itemToSelect = null;
    503         // remove the object's tag keys from the list
    504         Iterator<AutoCompletionListItem> iter = keyList.iterator();
    505         while (iter.hasNext()) {
    506             AutoCompletionListItem item = iter.next();
    507             if (item.getValue().equals(lastAddKey)) {
    508                 itemToSelect = item;
    509             }
    510             for (int i = 0; i < propertyData.getRowCount(); ++i) {
    511                 if (item.getValue().equals(propertyData.getValueAt(i, 0))) {
    512                     if (itemToSelect == item) {
    513                         itemToSelect = null;
    514                     }
    515                     iter.remove();
    516                     break;
    517                 }
    518             }
    519         }
    520 
    521         Collections.sort(keyList, defaultACItemComparator);
    522         keys.setPossibleACItems(keyList);
    523         keys.setEditable(true);
    524 
    525         p.add(keys, GBC.eop().fill());
    526 
    527         p.add(new JLabel(tr("Please select a value")), GBC.eol());
    528         final AutoCompletingComboBox values = new AutoCompletingComboBox();
    529         values.setEditable(true);
    530         p.add(values, GBC.eop().fill());
    531         if (itemToSelect != null) {
    532             keys.setSelectedItem(itemToSelect);
    533             if (lastAddValue != null) {
    534                 values.setSelectedItem(lastAddValue);
    535             }
    536         }
    537 
    538         FocusAdapter focus = addFocusAdapter(keys, values, autocomplete, defaultACItemComparator);
    539         // fire focus event in advance or otherwise the popup list will be too small at first
    540         focus.focusGained(null);
    541 
    542         int recentTagsToShow = Main.pref.getInteger("properties.recently-added-tags", DEFAULT_LRU_TAGS_NUMBER);
    543         if (recentTagsToShow > MAX_LRU_TAGS_NUMBER) {
    544             recentTagsToShow = MAX_LRU_TAGS_NUMBER;
    545         }
    546         List<JosmAction> recentTagsActions = new ArrayList<JosmAction>();
    547         suggestRecentlyAddedTags(p, keys, values, recentTagsActions, recentTagsToShow, focus);
    548 
    549         JOptionPane pane = new JOptionPane(p, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION){
    550             @Override public void selectInitialValue() {
    551                 // save unix system selection (middle mouse paste)
    552                 Clipboard sysSel = Toolkit.getDefaultToolkit().getSystemSelection();
    553                 if(sysSel != null) {
    554                     Transferable old = sysSel.getContents(null);
    555                     keys.requestFocusInWindow();
    556                     keys.getEditor().selectAll();
    557                     sysSel.setContents(old, null);
    558                 } else {
    559                     keys.requestFocusInWindow();
    560                     keys.getEditor().selectAll();
    561                 }
    562             }
    563         };
    564         JDialog dialog = pane.createDialog(Main.parent, tr("Add value?"));
    565         dialog.setModalityType(ModalityType.DOCUMENT_MODAL);
    566         dialog.setVisible(true);
    567        
    568         for (JosmAction action : recentTagsActions) {
    569             action.destroy();
    570         }
    571 
    572         if (!Integer.valueOf(JOptionPane.OK_OPTION).equals(pane.getValue()))
    573             return;
    574         String key = keys.getEditor().getItem().toString().trim();
    575         String value = values.getEditor().getItem().toString().trim();
    576         if (key.isEmpty() || value.isEmpty())
    577             return;
    578         lastAddKey = key;
    579         lastAddValue = value;
    580         recentTags.put(new Tag(key, value), null);
    581         Main.main.undoRedo.add(new ChangePropertyCommand(sel, key, value));
    582         btnAdd.requestFocusInWindow();
    583     }
    584    
    585     private void suggestRecentlyAddedTags(JPanel p, final AutoCompletingComboBox keys, final AutoCompletingComboBox values, List<JosmAction> tagsActions, int tagsToShow, final FocusAdapter focus) {
    586         if (tagsToShow > 0 && !recentTags.isEmpty()) {
    587             p.add(new JLabel(tr("Recently added tags")), GBC.eol());
    588            
    589             int count = 1;
    590             // We store the maximum number (9) of recent tags to allow dynamic change of number of tags shown in the preferences.
    591             // 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.
    592             // 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.
    593             List<Tag> tags = new LinkedList<Tag>(recentTags.keySet());
    594             for (int i = tags.size()-1; i >= 0 && count <= tagsToShow; i--, count++) {
    595                 final Tag t = tags.get(i);
    596                 // Create action for reusing the tag, with keyboard shortcut Ctrl+(1-5)
    597                 String actionShortcutKey = "properties:recent:"+count;
    598                 Shortcut sc = Shortcut.registerShortcut(actionShortcutKey, null, KeyEvent.VK_0+count, Shortcut.CTRL);
    599                 final JosmAction action = new JosmAction(actionShortcutKey, null, tr("Use this tag again"), sc, false) {
    600                     @Override
    601                     public void actionPerformed(ActionEvent e) {
    602                         keys.setSelectedItem(t.getKey());
    603                         values.setSelectedItem(t.getValue());
    604                         // Update list of values (fix #7951)
    605                         focus.focusGained(null);
    606                     }
    607                 };
    608                 tagsActions.add(action);
    609                 // Disable action if its key is already set on the object (the key being absent from the keys list for this reason
    610                 // performing this action leads to autocomplete to the next key (see #7671 comments)
    611                 for (int j = 0; j < propertyData.getRowCount(); ++j) {
    612                     if (t.getKey().equals(propertyData.getValueAt(j, 0))) {
    613                         action.setEnabled(false);
    614                         break;
    615                     }
    616                 }
    617                 // Find and display icon
    618                 ImageIcon icon = MapPaintStyles.getNodeIcon(t, false); // Filters deprecated icon
    619                 if (icon == null) {
    620                     icon = new ImageIcon(new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB));
    621                 }
    622                 GridBagConstraints gbc = new GridBagConstraints();
    623                 gbc.ipadx = 5;
    624                 p.add(new JLabel(action.isEnabled() ? icon : GuiHelper.getDisabledIcon(icon)), gbc);
    625                 // Create tag label
    626                 final String color = action.isEnabled() ? "" : "; color:gray";
    627                 final JLabel tagLabel = new JLabel("<html>"
    628                     + "<style>td{border:1px solid gray; font-weight:normal"+color+"}</style>"
    629                     + "<table><tr><td>" + t.toString() + "</td></tr></table></html>");
    630                 if (action.isEnabled()) {
    631                     // Register action
    632                     p.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(sc.getKeyStroke(), actionShortcutKey);
    633                     p.getActionMap().put(actionShortcutKey, action);
    634                     // Make the tag label clickable and set tooltip to the action description (this displays also the keyboard shortcut)
    635                     tagLabel.setToolTipText((String) action.getValue(Action.SHORT_DESCRIPTION));
    636                     tagLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
    637                     tagLabel.addMouseListener(new MouseAdapter() {
    638                         @Override
    639                         public void mouseClicked(MouseEvent e) {
    640                             action.actionPerformed(null);
    641                         }
    642                     });
    643                 } else {
    644                     // Disable tag label
    645                     tagLabel.setEnabled(false);
    646                     // Explain in the tooltip why
    647                     tagLabel.setToolTipText(tr("The key ''{0}'' is already used", t.getKey()));
    648                 }
    649                 // Finally add label to the resulting panel
    650                 JPanel tagPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
    651                 tagPanel.add(tagLabel);
    652                 p.add(tagPanel, GBC.eol().fill(GBC.HORIZONTAL));
    653             }
    654         }
    655     }
    656 
    657     /**
    658      * Create a focus handling adapter and apply in to the editor component of value
    659      * autocompletion box.
    660      * @param keys Box for keys entering and autocompletion
    661      * @param values Box for values entering and autocompletion
    662      * @param autocomplete Manager handling the autocompletion
    663      * @param comparator Class to decide what values are offered on autocompletion
    664      * @return The created adapter
    665      */
    666     private FocusAdapter addFocusAdapter(final AutoCompletingComboBox keys, final AutoCompletingComboBox values,
    667             final AutoCompletionManager autocomplete, final Comparator<AutoCompletionListItem> comparator) {
    668         // get the combo box' editor component
    669         JTextComponent editor = (JTextComponent)values.getEditor()
    670                 .getEditorComponent();
    671         // Refresh the values model when focus is gained
    672         FocusAdapter focus = new FocusAdapter() {
    673             @Override public void focusGained(FocusEvent e) {
    674                 String key = keys.getEditor().getItem().toString();
    675 
    676                 List<AutoCompletionListItem> valueList = autocomplete.getValues(getAutocompletionKeys(key));
    677                 Collections.sort(valueList, comparator);
    678 
    679                 values.setPossibleACItems(valueList);
    680                 objKey=key;
    681             }
    682         };
    683         editor.addFocusListener(focus);
    684         return focus;
    685     }
    686     private String objKey;
    687 
    688218    /**
    689219     * The property data of selected objects.
     
    719249    private final JTable membershipTable = new JTable(membershipData);
    720250
     251    /**
     252     * This sub-object is responsible for all adding and editing of properties
     253     */
     254    private final TagEditHelper editHelper = new TagEditHelper(propertyData, valueCount);
     255   
    721256    /**
    722257     * The Add button (needed to be able to disable it)
     
    1062597        String selectedTag = null;
    1063598        Relation selectedRelation = null;
    1064         if (propertyTable.getSelectedRowCount() == 1) {
     599        selectedTag = editHelper.getChangedKey(); // select last added or last edited key by default
     600        if (selectedTag == null && propertyTable.getSelectedRowCount() == 1) {
    1065601            selectedTag = (String)propertyData.getValueAt(propertyTable.getSelectedRow(), 0);
    1066602        }
     
    1103639                    ? e.getValue().keySet().iterator().next() : tr("<different>"));
    1104640        }
    1105 
     641       
    1106642        membershipData.setRowCount(0);
    1107643
     
    1318854        @Override
    1319855        public void actionPerformed(ActionEvent e) {
    1320             addProperty();
     856            editHelper.addProperty();
     857            btnAdd.requestFocusInWindow();
    1321858        }
    1322859    }
     
    1339876            if (propertyTable.getSelectedRowCount() == 1) {
    1340877                int row = propertyTable.getSelectedRow();
    1341                 editProperty(row);
     878                editHelper.editProperty(row);
    1342879            } else if (membershipTable.getSelectedRowCount() == 1) {
    1343880                int row = membershipTable.getSelectedRow();
Note: See TracChangeset for help on using the changeset viewer.