Ticket #12281: 12281-v1-plugin.patch

File 12281-v1-plugin.patch, 31.8 KB (added by simon04, 8 years ago)
  • plugins/OSMRecPlugin/src/org/openstreetmap/josm/plugins/osmrec/OSMRecPluginHelper.java

    diff --git a/plugins/OSMRecPlugin/src/org/openstreetmap/josm/plugins/osmrec/OSMRecPluginHelper.java b/plugins/OSMRecPlugin/src/org/openstreetmap/josm/plugins/osmrec/OSMRecPluginHelper.java
    index 2779071..c45639f 100644
    a b import static org.openstreetmap.josm.tools.I18n.trn;  
    1616import java.awt.BorderLayout;
    1717import java.awt.Color;
    1818import java.awt.Component;
    19 import java.awt.Cursor;
    2019import java.awt.Dimension;
    2120import java.awt.FlowLayout;
    22 import java.awt.Font;
    23 import java.awt.GridBagConstraints;
    2421import java.awt.GridBagLayout;
    25 import java.awt.Toolkit;
    26 import java.awt.datatransfer.Clipboard;
    27 import java.awt.datatransfer.Transferable;
    2822import java.awt.event.ActionEvent;
    29 import java.awt.event.FocusAdapter;
    30 import java.awt.event.FocusEvent;
    31 import java.awt.event.KeyEvent;
    32 import java.awt.event.MouseAdapter;
    33 import java.awt.event.MouseEvent;
    3423import java.awt.event.WindowAdapter;
    3524import java.awt.event.WindowEvent;
    36 import java.awt.image.BufferedImage;
    3725import java.beans.PropertyChangeEvent;
    3826import java.beans.PropertyChangeListener;
    3927import java.io.File;
    import java.util.ArrayList;  
    4937import java.util.Arrays;
    5038import java.util.Collection;
    5139import java.util.Collections;
    52 import java.util.Comparator;
    5340import java.util.HashMap;
    5441import java.util.Iterator;
    5542import java.util.LinkedHashMap;
    56 import java.util.LinkedList;
    5743import java.util.List;
    5844import java.util.Map;
    5945import java.util.Map.Entry;
    import java.util.logging.Level;  
    6349import java.util.logging.Logger;
    6450
    6551import javax.swing.AbstractAction;
    66 import javax.swing.Action;
    6752import javax.swing.BorderFactory;
    6853import javax.swing.BoxLayout;
    6954import javax.swing.ButtonGroup;
    70 import javax.swing.DefaultListCellRenderer;
    7155import javax.swing.DefaultListModel;
    7256import javax.swing.GroupLayout;
    7357import javax.swing.GroupLayout.Alignment;
    74 import javax.swing.ImageIcon;
    7558import javax.swing.JButton;
    7659import javax.swing.JCheckBox;
    7760import javax.swing.JCheckBoxMenuItem;
    78 import javax.swing.JComponent;
    7961import javax.swing.JDialog;
    8062import javax.swing.JFileChooser;
    8163import javax.swing.JLabel;
    8264import javax.swing.JList;
    8365import javax.swing.JOptionPane;
    8466import javax.swing.JPanel;
    85 import javax.swing.JPopupMenu;
    8667import javax.swing.JProgressBar;
    8768import javax.swing.JRadioButton;
    8869import javax.swing.JScrollPane;
     70import javax.swing.JTable;
    8971import javax.swing.JTextField;
    90 import javax.swing.ListCellRenderer;
    9172import javax.swing.SwingConstants;
    9273import javax.swing.border.EtchedBorder;
    9374import javax.swing.border.TitledBorder;
    9475import javax.swing.event.ListSelectionEvent;
    9576import javax.swing.event.ListSelectionListener;
    9677import javax.swing.table.DefaultTableModel;
    97 import javax.swing.text.JTextComponent;
    9878import org.geotools.geometry.jts.JTS;
    9979import org.geotools.referencing.CRS;
    10080import org.geotools.referencing.crs.DefaultGeocentricCRS;
    import org.opengis.referencing.operation.MathTransform;  
    10686import org.opengis.referencing.operation.TransformException;
    10787
    10888import org.openstreetmap.josm.Main;
    109 import org.openstreetmap.josm.actions.JosmAction;
    110 import org.openstreetmap.josm.command.ChangePropertyCommand;
    11189import org.openstreetmap.josm.data.osm.Node;
    11290import org.openstreetmap.josm.data.osm.OsmPrimitive;
    11391import org.openstreetmap.josm.data.osm.Tag;
    11492import org.openstreetmap.josm.data.osm.Way;
    115 import org.openstreetmap.josm.data.preferences.BooleanProperty;
    116 import org.openstreetmap.josm.data.preferences.IntegerProperty;
    117 import org.openstreetmap.josm.gui.ExtendedDialog;
    118 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
    119 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingComboBox;
     93import org.openstreetmap.josm.gui.dialogs.properties.TagEditHelper;
    12094import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionListItem;
    12195import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionManager;
    122 //import org.openstreetmap.josm.gui.tagging.presets.TaggingPreset;
    123 import org.openstreetmap.josm.gui.util.GuiHelper;
    124 import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
    125 import org.openstreetmap.josm.io.XmlWriter;
    12696import org.openstreetmap.josm.plugins.container.OSMWay;
    12797import org.openstreetmap.josm.plugins.core.TrainWorker;
    12898import org.openstreetmap.josm.plugins.extractor.LanguageDetector;
    import org.openstreetmap.josm.plugins.parsers.OSMParser;  
    137107import org.openstreetmap.josm.plugins.parsers.Ontology;
    138108import org.openstreetmap.josm.plugins.parsers.TextualStatistics;
    139109import org.openstreetmap.josm.tools.GBC;
    140 import org.openstreetmap.josm.tools.Shortcut;
    141 import org.openstreetmap.josm.tools.WindowGeometry;
    142110
    143111/**
    144112 * Modified PropertiesDialog(since 5633) to serve the plugin functionality.
    import org.openstreetmap.josm.tools.WindowGeometry;  
    146114 * @author imis-nkarag
    147115 */
    148116
    149 class OSMRecPluginHelper {
     117class OSMRecPluginHelper extends TagEditHelper {
    150118   
    151     private final DefaultTableModel tagData;
    152     private final Map<String, Map<String, Integer>> valueCount;
    153119    private static Collection<String> fileHistory;
    154120    private Map<File, Double> filesAndWeights = new HashMap<>();
    155121    private boolean useCombinedModel = false;
    class OSMRecPluginHelper {  
    170136    private String customSVMModelPath;
    171137    private final String combinedModelClasses;
    172138    private final String combinedModel;
    173        
    174     // Selection that we are editing by using both dialogs
    175     Collection<OsmPrimitive> sel;
    176 
    177     private String changedKey;
    178     private String objKey;
    179 
    180     Comparator<AutoCompletionListItem> defaultACItemComparator = new Comparator<AutoCompletionListItem>() {
    181         @Override
    182         public int compare(AutoCompletionListItem o1, AutoCompletionListItem o2) {
    183             return String.CASE_INSENSITIVE_ORDER.compare(o1.getValue(), o2.getValue());
    184         }
    185     };
    186139
    187140    private String lastAddKey = null;
    188141    private String lastAddValue = null;
    class OSMRecPluginHelper {  
    197150            return size() > MAX_LRU_TAGS_NUMBER;
    198151        }
    199152    };
    200 
    201153   
    202     OSMRecPluginHelper(DefaultTableModel propertyData, Map<String, Map<String, Integer>> valueCount) {
    203         this.tagData = propertyData;
    204         this.valueCount = valueCount;
     154    OSMRecPluginHelper(JTable tagTable, DefaultTableModel propertyData, Map<String, Map<String, Integer>> valueCount) {
     155        super(tagTable, propertyData, valueCount);
    205156        fileHistory = Main.pref.getCollection("file-open.history");
    206157        if(!fileHistory.isEmpty()){           
    207158            MAIN_PATH = (String) fileHistory.toArray()[0];
    class OSMRecPluginHelper {  
    225176       
    226177    }
    227178
    228     /**
    229      * Open the add selection dialog and add a new key/value to the table (and
    230      * to the dataset, of course).
    231      */
    232     public void addTag() {
    233         changedKey = null;
    234         sel = Main.main.getInProgressSelection();
    235         if (sel == null || sel.isEmpty()) return;
    236 
    237         final AddTagsDialog addDialog = new AddTagsDialog();
    238        
    239         addDialog.showDialog();
    240 
    241         addDialog.destroyActions();
    242         if (addDialog.getValue() == 1)
    243             addDialog.performTagAdding();
    244         else
    245             addDialog.undoAllTagsAdding();
    246     }
    247 
    248     /**
    249     * Edit the value in the tags table row.
    250     * @param row The row of the table from which the value is edited.
    251     * @param focusOnKey Determines if the initial focus should be set on key instead of value
    252     * @since 5653
    253     */
    254     public void editTag(final int row, boolean focusOnKey) {
    255         changedKey = null;
    256         sel = Main.main.getInProgressSelection();
    257         //if (sel == null || sel.isEmpty()) return;
    258 //        String key = tagData.getValueAt(row, 0).toString();
    259         String key = "";
    260 //        objKey=key;
    261 
    262         @SuppressWarnings("unchecked")
     179    @Override
     180    protected IEditTagDialog getEditTagDialog(int row, boolean focusOnKey, String key) {
    263181        Map<String, Integer> dumPar = new HashMap<>();
    264182        dumPar.put(" ", -1);
    265         final TrainingDialog editDialog = new TrainingDialog(key, row,
    266                 dumPar, focusOnKey);               
    267         editDialog.showDialog();
    268         //if (editDialog.getValue() !=1 ) return;
    269         //editDialog.performTagEdit();
     183        return new TrainingDialog(key, row, dumPar, focusOnKey);
    270184    }
    271185
    272     /**
    273      * If during last editProperty call user changed the key name, this key will be returned
    274      * Elsewhere, returns null.
    275      * @return The modified key, or {@code null}
    276      */
    277     public String getChangedKey() {
    278         return changedKey;
    279     }
    280 
    281     public void resetChangedKey() {
    282         changedKey = null;
    283     }
    284 
    285     /**
    286      * For a given key k, return a list of keys which are used as keys for
    287      * auto-completing values to increase the search space.
    288      * @param key the key k
    289      * @return a list of keys
    290      */
    291     private static List<String> getAutocompletionKeys(String key) {
    292         if ("name".equals(key) || "addr:street".equals(key))
    293             return Arrays.asList("addr:street", "name");
    294         else
    295             return Arrays.asList(key);
    296     }
    297 
    298     /**
    299      * Load recently used tags from preferences if needed.
    300      */
    301     public void loadTagsIfNeeded() {
    302         if (PROPERTY_REMEMBER_TAGS.get() && recentTags.isEmpty()) {
    303             recentTags.clear();
    304             Collection<String> c = Main.pref.getCollection("properties.recent-tags");
    305             Iterator<String> it = c.iterator();
    306             String key, value;
    307             while (it.hasNext()) {
    308                 key = it.next();
    309                 value = it.next();
    310                 recentTags.put(new Tag(key, value), null);
    311             }
    312         }
    313     }
    314 
    315     /**
    316      * Store recently used tags in preferences if needed.
    317      */
    318     public void saveTagsIfNeeded() {
    319         if (PROPERTY_REMEMBER_TAGS.get() && !recentTags.isEmpty()) {
    320             List<String> c = new ArrayList<>( recentTags.size()*2 );
    321             for (Tag t: recentTags.keySet()) {
    322                 c.add(t.getKey());
    323                 c.add(t.getValue());
    324             }
    325             Main.pref.putCollection("properties.recent-tags", c);
    326         }
    327     }
    328 
    329     /**
    330      * Warns user about a key being overwritten.
    331      * @param action The action done by the user. Must state what key is changed
    332      * @param togglePref  The preference to save the checkbox state to
    333      * @return {@code true} if the user accepts to overwrite key, {@code false} otherwise
    334      */
    335     private boolean warnOverwriteKey(String action, String togglePref) {
    336         ExtendedDialog ed = new ExtendedDialog(
    337                 Main.parent,
    338                 tr("Overwrite key"),
    339                 new String[]{tr("Replace"), tr("Cancel")});
    340         ed.setButtonIcons(new String[]{"purge", "cancel"});
    341         ed.setContent(action+"\n"+ tr("The new key is already used, overwrite values?"));
    342         ed.setCancelButton(2);
    343         ed.toggleEnable(togglePref);
    344         ed.showDialog();
    345 
    346         return ed.getValue() == 1;
    347     }
    348 
    349     public final class TrainingDialog extends AbstractTagsDialog {
     186    public final class TrainingDialog extends AbstractTagsDialog implements IEditTagDialog {
    350187
    351         ListCellRenderer<AutoCompletionListItem> cellRenderer = new ListCellRenderer<AutoCompletionListItem>() {
    352             final DefaultListCellRenderer def = new DefaultListCellRenderer();
    353             @Override
    354             public Component getListCellRendererComponent(JList<? extends AutoCompletionListItem> list,
    355                     AutoCompletionListItem value, int index, boolean isSelected,  boolean cellHasFocus){
    356                 Component c = def.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
    357                 if (c instanceof JLabel) {
    358                     String str = value.getValue();
    359                     if (valueCount.containsKey(objKey)) {
    360                         Map<String, Integer> m = valueCount.get(objKey);
    361                         if (m.containsKey(str)) {
    362                             str = tr("{0} ({1})", str, m.get(str));
    363                             c.setFont(c.getFont().deriveFont(Font.ITALIC + Font.BOLD));
    364                         }
    365                     }
    366                     ((JLabel) c).setText(str);
    367                 }
    368                 return c;
    369             }
    370         };
    371188        private static final int FIELD_COLUMNS = 4;
    372189        private final JTextField inputFileField;
    373190        private final JLabel inputFileLabel;
    class OSMRecPluginHelper {  
    975792                });
    976793            }
    977794        }
    978     }
    979 
    980     public static final BooleanProperty PROPERTY_FIX_TAG_LOCALE = new BooleanProperty("properties.fix-tag-combobox-locale", false);
    981     public static final BooleanProperty PROPERTY_REMEMBER_TAGS = new BooleanProperty("properties.remember-recently-added-tags", true);
    982     public static final IntegerProperty PROPERTY_RECENT_TAGS_NUMBER = new IntegerProperty("properties.recently-added-tags", DEFAULT_LRU_TAGS_NUMBER);
    983 
    984     abstract class AbstractTagsDialog extends ExtendedDialog {
    985         AutoCompletingComboBox keys;
    986         AutoCompletingComboBox values;
    987         Component componentUnderMouse;
    988 
    989         public AbstractTagsDialog(Component parent, String title, String[] buttonTexts) {
    990             super(parent, title, buttonTexts);
    991             addMouseListener(new PopupMenuLauncher(popupMenu));
    992         }
    993795
    994796        @Override
    995         public void setupDialog() {
    996             super.setupDialog();
    997             final Dimension size = getSize();
    998             // Set resizable only in width
    999             setMinimumSize(size);
    1000             setPreferredSize(size);
    1001             // setMaximumSize does not work, and never worked, but still it seems not to bother Oracle to fix this 10-year-old bug
    1002             // https://bugs.openjdk.java.net/browse/JDK-6200438
    1003             // https://bugs.openjdk.java.net/browse/JDK-6464548
    1004 
    1005             setRememberWindowGeometry(getClass().getName() + ".geometry",
    1006                 WindowGeometry.centerInWindow(Main.parent, size));
     797        public void performTagEdit() {
     798            // do nothing
    1007799        }
    1008800
    1009801        @Override
    1010         public void setVisible(boolean visible) {
    1011             // Do not want dialog to be resizable in height, as its size may increase each time because of the recently added tags
    1012             // So need to modify the stored geometry (size part only) in order to use the automatic positioning mechanism
    1013             if (visible) {
    1014                 WindowGeometry geometry = initWindowGeometry();
    1015                 Dimension storedSize = geometry.getSize();
    1016                 Dimension size = getSize();
    1017                 if (!storedSize.equals(size)) {
    1018                     if (storedSize.width < size.width) {
    1019                         storedSize.width = size.width;
    1020                     }
    1021                     if (storedSize.height != size.height) {
    1022                         storedSize.height = size.height;
    1023                     }
    1024                     rememberWindowGeometry(geometry);
    1025                 }
    1026                 if(keys != null){
    1027                    keys.setFixedLocale(PROPERTY_FIX_TAG_LOCALE.get());
    1028                 }               
    1029             }
    1030             super.setVisible(visible);
    1031         }
    1032 
    1033         private void selectACComboBoxSavingUnixBuffer(AutoCompletingComboBox cb) {
    1034             // select combobox with saving unix system selection (middle mouse paste)
    1035             Clipboard sysSel = Toolkit.getDefaultToolkit().getSystemSelection();
    1036             if(sysSel != null) {
    1037                 Transferable old = sysSel.getContents(null);
    1038                 cb.requestFocusInWindow();
    1039                 cb.getEditor().selectAll();
    1040                 sysSel.setContents(old, null);
    1041             } else {
    1042                 cb.requestFocusInWindow();
    1043                 cb.getEditor().selectAll();
    1044             }
    1045         }
    1046 
    1047802        public void selectKeysComboBox() {
    1048             //selectACComboBoxSavingUnixBuffer(keys);
     803            // do nothing
    1049804        }
    1050805
    1051         public void selectValuesCombobox()   {
    1052             //selectACComboBoxSavingUnixBuffer(values);
     806        @Override
     807        public void selectValuesCombobox() {
     808            // do nothing
    1053809        }
    1054 
    1055         /**
    1056         * Create a focus handling adapter and apply in to the editor component of value
    1057         * autocompletion box.
    1058         * @param autocomplete Manager handling the autocompletion
    1059         * @param comparator Class to decide what values are offered on autocompletion
    1060         * @return The created adapter
    1061         */
    1062         protected FocusAdapter addFocusAdapter(final AutoCompletionManager autocomplete, final Comparator<AutoCompletionListItem> comparator) {
    1063            // get the combo box' editor component
    1064            JTextComponent editor = (JTextComponent)values.getEditor().getEditorComponent();
    1065            // Refresh the values model when focus is gained
    1066            FocusAdapter focus = new FocusAdapter() {
    1067                @Override
    1068                public void focusGained(FocusEvent e) {
    1069                    String key = keys.getEditor().getItem().toString();
    1070 
    1071                    List<AutoCompletionListItem> valueList = autocomplete.getValues(getAutocompletionKeys(key));
    1072                    Collections.sort(valueList, comparator);
    1073 
    1074                    values.setPossibleACItems(valueList);
    1075                    values.getEditor().selectAll();
    1076                    objKey=key;
    1077                }
    1078            };
    1079            editor.addFocusListener(focus);
    1080            return focus;
    1081         }
    1082 
    1083         protected JPopupMenu popupMenu = new JPopupMenu() {
    1084             JCheckBoxMenuItem fixTagLanguageCb = new JCheckBoxMenuItem(
    1085                 new AbstractAction(tr("Use English language for tag by default")){
    1086                 @Override
    1087                 public void actionPerformed(ActionEvent e) {
    1088                     boolean sel=((JCheckBoxMenuItem) e.getSource()).getState();
    1089                     PROPERTY_FIX_TAG_LOCALE.put(sel);
    1090                 }
    1091             });
    1092             {
    1093                 add(fixTagLanguageCb);
    1094                 fixTagLanguageCb.setState(PROPERTY_FIX_TAG_LOCALE.get());
    1095             }
    1096         };
    1097810    }
    1098811
    1099812    class ModelSettingsDialog extends JPanel{
    class OSMRecPluginHelper {  
    15361249        }
    15371250    }
    15381251   
    1539     class AddTagsDialog extends  AbstractTagsDialog {
    1540         List<JosmAction> recentTagsActions = new ArrayList<>();
    1541 
    1542         // Counter of added commands for possible undo
    1543         private int commandCount;
     1252    class AddTagsDialog extends TagEditHelper.AddTagsDialog {
    15441253        private final JLabel recommendedClassesLabel;
    15451254        private final JButton modelSettingsButton;
    15461255        private final JButton addAndContinueButton;
    class OSMRecPluginHelper {  
    15591268        private static final int RECOMMENDATIONS_SIZE = 10;
    15601269
    15611270        public AddTagsDialog() {
    1562             super(Main.parent, tr("Add value?"), new String[] {tr("OK"),tr("Cancel")});
    1563             setButtonIcons(new String[] {"ok","cancel"});
    1564             setCancelButton(2);
    1565             configureContextsensitiveHelp("/Dialog/AddValue", true /* show help button */);
     1271            super();
    15661272            final AddTagsDialog addTagsDialog = this;
    15671273           
    15681274            loadOntology();
    class OSMRecPluginHelper {  
    16821388                    }                   
    16831389                }
    16841390            });
    1685            
    1686             keys = new AutoCompletingComboBox();
    1687             values = new AutoCompletingComboBox();
    16881391
    16891392            mainPanel.add(new JLabel("<html>"+trn("This will change up to {0} object.",
    16901393                "This will change up to {0} objects.", sel.size(),sel.size())
    16911394                +"<br><br>"+tr("Please select a key")), GBC.eol().fill(GBC.HORIZONTAL));
    16921395
    1693             AutoCompletionManager autocomplete = Main.main.getEditLayer().data.getAutoCompletionManager();
    1694             List<AutoCompletionListItem> keyList = autocomplete.getKeys();
    1695 
    1696             AutoCompletionListItem itemToSelect = null;
    1697             // remove the object's tag keys from the list
    1698             Iterator<AutoCompletionListItem> iter = keyList.iterator();
    1699             while (iter.hasNext()) {
    1700                 AutoCompletionListItem item = iter.next();
    1701                 if (item.getValue().equals(lastAddKey)) {
    1702                     itemToSelect = item;
    1703                 }
    1704                 for (int i = 0; i < tagData.getRowCount(); ++i) {
    1705                     if (item.getValue().equals(tagData.getValueAt(i, 0))) {
    1706                         if (itemToSelect == item) {
    1707                             itemToSelect = null;
    1708                         }
    1709                         iter.remove();
    1710                         break;
    1711                     }
    1712                 }
    1713             }
    1714 
    1715             Collections.sort(keyList, defaultACItemComparator);
    1716             keys.setPossibleACItems(keyList);
    1717             keys.setEditable(true);
    1718 
    17191396            mainPanel.add(keys, GBC.eop().fill());
    17201397            mainPanel.add(new JLabel(tr("Please select a value")), GBC.eol());           
    17211398 
    class OSMRecPluginHelper {  
    17791456            categoryList.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
    17801457            categoryList.setModel(model);
    17811458
    1782             values.setEditable(true);
    17831459            mainPanel.add(values, GBC.eop().fill());
    1784             if (itemToSelect != null) {
    1785                 keys.setSelectedItem(itemToSelect);
    1786                 if (lastAddValue != null) {
    1787                     values.setSelectedItem(lastAddValue);
    1788                 }
    1789             }
    17901460
    1791             FocusAdapter focus = addFocusAdapter(autocomplete, defaultACItemComparator);
    1792             // fire focus event in advance or otherwise the popup list will be too small at first
    1793             focus.focusGained(null);
    1794 
    1795             int recentTagsToShow = PROPERTY_RECENT_TAGS_NUMBER.get();
    1796             if (recentTagsToShow > MAX_LRU_TAGS_NUMBER) {
    1797                 recentTagsToShow = MAX_LRU_TAGS_NUMBER;
    1798             }
    1799 
    1800             // Add tag on Shift-Enter
    1801 //            mainPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
    1802 //                        KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_MASK), "addAndContinue");
    1803 //                mainPanel.getActionMap().put("addAndContinue", new AbstractAction() {
    1804 //                    @Override
    1805 //                    public void actionPerformed(ActionEvent e) {
    1806 //                        performTagAdding();
    1807 //                        selectKeysComboBox();
    1808 //                    }
    1809 //                });
    1810 
    1811             suggestRecentlyAddedTags(mainPanel, recentTagsToShow, focus);
     1461            suggestRecentlyAddedTags(mainPanel, focus);
    18121462
    18131463            mainPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
    18141464            listPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
    class OSMRecPluginHelper {  
    18541504            performTagAdding();
    18551505            selectKeysComboBox();
    18561506        }
    1857        
    1858         private void selectNumberOfTags() {
    1859             String s = JOptionPane.showInputDialog(this, tr("Please enter the number of recently added tags to display"));
    1860             if (s!=null) try {
    1861                 int v = Integer.parseInt(s);
    1862                 if (v>=0 && v<=MAX_LRU_TAGS_NUMBER) {
    1863                     PROPERTY_RECENT_TAGS_NUMBER.put(v);
    1864                     return;
    1865                 }
    1866             } catch (NumberFormatException ex) {
    1867                 Main.warn(ex);
    1868             }
    1869             JOptionPane.showMessageDialog(this, tr("Please enter integer number between 0 and {0}", MAX_LRU_TAGS_NUMBER));
    1870         }
    18711507
    1872         private void suggestRecentlyAddedTags(JPanel mainPanel, int tagsToShow, final FocusAdapter focus) {
    1873             if (!(tagsToShow > 0 && !recentTags.isEmpty()))
    1874                 return;
    1875 
    1876             mainPanel.add(new JLabel(tr("Recently added tags")), GBC.eol());
    1877 
    1878             int count = 1;
    1879             // We store the maximum number (9) of recent tags to allow dynamic change of number of tags shown in the preferences.
    1880             // 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.
    1881             // 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.
    1882             List<Tag> tags = new LinkedList<>(recentTags.keySet());
    1883             for (int i = tags.size()-1; i >= 0 && count <= tagsToShow; i--, count++) {
    1884                 final Tag t = tags.get(i);
    1885                 // Create action for reusing the tag, with keyboard shortcut Ctrl+(1-5)
    1886                 String actionShortcutKey = "properties:recent:"+count;
    1887                 String actionShortcutShiftKey = "properties:recent:shift:"+count;
    1888                 Shortcut sc = Shortcut.registerShortcut(actionShortcutKey, tr("Choose recent tag {0}", count), KeyEvent.VK_0+count, Shortcut.CTRL);
    1889                 final JosmAction action = new JosmAction(actionShortcutKey, null, tr("Use this tag again"), sc, false) {
    1890                     @Override
    1891                     public void actionPerformed(ActionEvent e) {
    1892                         keys.setSelectedItem(t.getKey());
    1893                         // fix #7951, #8298 - update list of values before setting value (?)
    1894                         focus.focusGained(null);
    1895                         values.setSelectedItem(t.getValue());
    1896                         selectValuesCombobox();
    1897                     }
    1898                 };
    1899                 Shortcut scShift = Shortcut.registerShortcut(actionShortcutShiftKey, tr("Apply recent tag {0}", count), KeyEvent.VK_0+count, Shortcut.CTRL_SHIFT);
    1900                 final JosmAction actionShift = new JosmAction(actionShortcutShiftKey, null, tr("Use this tag again"), scShift, false) {
    1901                     @Override
    1902                     public void actionPerformed(ActionEvent e) {
    1903                         action.actionPerformed(null);
    1904                         performTagAdding();
    1905                         selectKeysComboBox();
    1906                     }
    1907                 };
    1908                 recentTagsActions.add(action);
    1909                 recentTagsActions.add(actionShift);
    1910                 disableTagIfNeeded(t, action);
    1911                 // Find and display icon
    1912                 ImageIcon icon = MapPaintStyles.getNodeIcon(t, false); // Filters deprecated icon
    1913                 if (icon == null) {
    1914                     // If no icon found in map style look at presets
    1915                     Map<String, String> map = new HashMap<>();
    1916                     map.put(t.getKey(), t.getValue());
    1917 //                    for (TaggingPreset tp : TaggingPreset.getMatchingPresets(null, map, false)) {
    1918 //                        icon = tp.getIcon();
    1919 //                        if (icon != null) {
    1920 //                            break;
    1921 //                        }
    1922 //                    }
    1923                     // If still nothing display an empty icon
    1924                     if (icon == null) {
    1925                         icon = new ImageIcon(new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB));
    1926                     }
    1927                 }
    1928                 GridBagConstraints gbc = new GridBagConstraints();
    1929                 gbc.ipadx = 5;
    1930                 mainPanel.add(new JLabel(action.isEnabled() ? icon : GuiHelper.getDisabledIcon(icon)), gbc);
    1931                 // Create tag label
    1932                 final String color = action.isEnabled() ? "" : "; color:gray";
    1933                 final JLabel tagLabel = new JLabel("<html>"
    1934                     + "<style>td{border:1px solid gray; font-weight:normal"+color+"}</style>"
    1935                     + "<table><tr><td>" + XmlWriter.encode(t.toString(), true) + "</td></tr></table></html>");
    1936                 if (action.isEnabled()) {
    1937                     // Register action
    1938                     mainPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(sc.getKeyStroke(), actionShortcutKey);
    1939                     mainPanel.getActionMap().put(actionShortcutKey, action);
    1940                     mainPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(scShift.getKeyStroke(), actionShortcutShiftKey);
    1941                     mainPanel.getActionMap().put(actionShortcutShiftKey, actionShift);
    1942                     // Make the tag label clickable and set tooltip to the action description (this displays also the keyboard shortcut)
    1943                     tagLabel.setToolTipText((String) action.getValue(Action.SHORT_DESCRIPTION));
    1944                     tagLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
    1945                     tagLabel.addMouseListener(new MouseAdapter() {
    1946                         @Override
    1947                         public void mouseClicked(MouseEvent e) {
    1948                             action.actionPerformed(null);
    1949                             // add tags and close window on double-click
    1950                            
    1951                             if (e.getClickCount()>1) {
    1952                                 buttonAction(0, null); // emulate OK click and close the dialog
    1953                             }
    1954                             // add tags on Shift-Click
    1955                             if (e.isShiftDown()) {
    1956                                 performTagAdding();
    1957                                 selectKeysComboBox();
    1958                             }
    1959                         }
    1960                     });
    1961                 } else {
    1962                     // Disable tag label
    1963                     tagLabel.setEnabled(false);
    1964                     // Explain in the tooltip why
    1965                     tagLabel.setToolTipText(tr("The key ''{0}'' is already used", t.getKey()));
    1966                 }
    1967                 // Finally add label to the resulting panel
    1968                 JPanel tagPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
    1969                 tagPanel.add(tagLabel);
    1970                 mainPanel.add(tagPanel, GBC.eol().fill(GBC.HORIZONTAL));
    1971             }
    1972         }
    1973 
    1974         public void destroyActions() {
    1975             for (JosmAction action : recentTagsActions) {
    1976                 action.destroy();
    1977             }
    1978         }
    1979 
    1980         /**
    1981          * Read tags from comboboxes and add it to all selected objects
    1982          */
    1983         public final void performTagAdding() {
    1984             String key = Tag.removeWhiteSpaces(keys.getEditor().getItem().toString());
    1985             String value = Tag.removeWhiteSpaces(values.getEditor().getItem().toString());
    1986             if (key.isEmpty() || value.isEmpty()) return;
    1987             for (OsmPrimitive osm: sel) {
    1988                 String val = osm.get(key);
    1989                 if (val != null && !val.equals(value)) {
    1990                     if (!warnOverwriteKey(tr("You changed the value of ''{0}'' from ''{1}'' to ''{2}''.", key, val, value),
    1991                             "overwriteAddKey"))
    1992                         return;
    1993                     break;
    1994                 }
    1995             }
    1996             lastAddKey = key;
    1997             lastAddValue = value;
    1998             recentTags.put(new Tag(key, value), null);
    1999             AutoCompletionManager.rememberUserInput(key, value, false);
    2000             commandCount++;
    2001             Main.main.undoRedo.add(new ChangePropertyCommand(sel, key, value));
    2002             changedKey = key;
    2003         }
    2004 
    2005         public void undoAllTagsAdding() {
    2006             Main.main.undoRedo.undo(commandCount);
    2007         }
    2008 
    2009         private void disableTagIfNeeded(final Tag t, final JosmAction action) {
    2010             // Disable action if its key is already set on the object (the key being absent from the keys list for this reason
    2011             // performing this action leads to autocomplete to the next key (see #7671 comments)
    2012             for (int j = 0; j < tagData.getRowCount(); ++j) {
    2013                 if (t.getKey().equals(tagData.getValueAt(j, 0))) {
    2014                     action.setEnabled(false);
    2015                     break;
    2016                 }
    2017             }
     1508        @Override
     1509        protected void clearEntries() {
     1510            // do nothing
    20181511        }
    20191512
    20201513        private void loadSVMmodel() {