Changeset 15565 in josm for trunk/src/org/openstreetmap/josm


Ignore:
Timestamp:
2019-12-08T14:35:57+01:00 (5 years ago)
Author:
Don-vip
Message:

fix #18302 - support national taginfo instances

Location:
trunk/src/org/openstreetmap/josm
Files:
6 edited

Legend:

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

    r15376 r15565  
    2828import java.util.TreeSet;
    2929import java.util.concurrent.atomic.AtomicBoolean;
     30import java.util.stream.Collectors;
    3031
    3132import javax.swing.AbstractAction;
    3233import javax.swing.JComponent;
    3334import javax.swing.JLabel;
     35import javax.swing.JMenuItem;
    3436import javax.swing.JPanel;
    3537import javax.swing.JPopupMenu;
     
    109111import org.openstreetmap.josm.tools.Logging;
    110112import org.openstreetmap.josm.tools.Shortcut;
     113import org.openstreetmap.josm.tools.Territories;
    111114import org.openstreetmap.josm.tools.Utils;
    112115
     
    172175    private final transient PopupMenuHandler blankSpaceMenuHandler = new PopupMenuHandler(blankSpaceMenu);
    173176
     177    private final List<JMenuItem> tagMenuTagInfoNatItems = new ArrayList<>();
     178    private final List<JMenuItem> membershipMenuTagInfoNatItems = new ArrayList<>();
     179
    174180    private final transient Map<String, Map<String, Integer>> valueCount = new TreeMap<>();
    175181    /**
     
    183189    private final TaginfoAction taginfoAction = new TaginfoAction(tagTable, editHelper::getDataKey, editHelper::getDataValues,
    184190            membershipTable, x -> (IRelation<?>) membershipData.getValueAt(x, 0));
     191    private final Collection<TaginfoAction> taginfoNationalActions = new ArrayList<>();
    185192    private final PasteValueAction pasteValueAction = new PasteValueAction();
    186193    private final CopyValueAction copyValueAction = new CopyValueAction(
     
    348355    }
    349356
     357    private void destroyTaginfoNationalActions() {
     358        membershipMenuTagInfoNatItems.forEach(membershipMenu::remove);
     359        membershipMenuTagInfoNatItems.clear();
     360        tagMenuTagInfoNatItems.forEach(tagMenu::remove);
     361        tagMenuTagInfoNatItems.clear();
     362        taginfoNationalActions.forEach(JosmAction::destroy);
     363        taginfoNationalActions.clear();
     364    }
     365
     366    private void setupTaginfoNationalActions(Collection<? extends IPrimitive> newSel) {
     367        destroyTaginfoNationalActions();
     368        if (!newSel.isEmpty()) {
     369            for (Entry<String, String> e : Territories.getNationalTaginfoUrls(
     370                    newSel.iterator().next().getBBox().getCenter()).entrySet()) {
     371                taginfoNationalActions.add(new TaginfoAction(tagTable, editHelper::getDataKey, editHelper::getDataValues,
     372                        membershipTable, x -> (IRelation<?>) membershipData.getValueAt(x, 0), e.getValue(), e.getKey()));
     373            }
     374            membershipMenuTagInfoNatItems.addAll(taginfoNationalActions.stream().map(membershipMenu::add).collect(Collectors.toList()));
     375            tagMenuTagInfoNatItems.addAll(taginfoNationalActions.stream().map(tagMenu::add).collect(Collectors.toList()));
     376        }
     377    }
     378
    350379    /**
    351380     * Creates the popup menu @field membershipMenu and its launcher on membership table.
     
    538567    public void destroy() {
    539568        taginfoAction.destroy();
     569        destroyTaginfoNationalActions();
    540570        super.destroy();
    541571        Config.getPref().removeKeyPreferenceChangeListener("display.discardable-keys", preferenceListener);
     
    558588        // Ignore parameter as we do not want to operate always on real selection here, especially in draw mode
    559589        Collection<? extends IPrimitive> newSel = OsmDataManager.getInstance().getInProgressISelection();
    560         String selectedTag;
     590        int newSelSize = newSel.size();
    561591        IRelation<?> selectedRelation = null;
    562         selectedTag = editHelper.getChangedKey(); // select last added or last edited key by default
     592        String selectedTag = editHelper.getChangedKey(); // select last added or last edited key by default
    563593        if (selectedTag == null && tagTable.getSelectedRowCount() == 1) {
    564594            selectedTag = editHelper.getDataKey(tagTable.getSelectedRow());
     
    598628                count += e1.getValue();
    599629            }
    600             if (count < newSel.size()) {
    601                 e.getValue().put("", newSel.size() - count);
     630            if (count < newSelSize) {
     631                e.getValue().put("", newSelSize - count);
    602632            }
    603633            tagData.addRow(new Object[]{e.getKey(), e.getValue()});
     
    655685        pluginHook.setVisible(hasSelection);
    656686
     687        setupTaginfoNationalActions(newSel);
    657688        autoresizeTagTable();
    658689
     
    669700
    670701        if (tagData.getRowCount() != 0 || membershipData.getRowCount() != 0) {
    671             if (newSel.size() > 1) {
     702            if (newSelSize > 1) {
    672703                setTitle(tr("Objects: {2} / Tags: {0} / Memberships: {1}",
    673                     tagData.getRowCount(), membershipData.getRowCount(), newSel.size()));
     704                    tagData.getRowCount(), membershipData.getRowCount(), newSelSize));
    674705            } else {
    675706                setTitle(tr("Tags: {0} / Memberships: {1}",
  • trunk/src/org/openstreetmap/josm/gui/dialogs/properties/TaginfoAction.java

    r13959 r15565  
    2323public class TaginfoAction extends JosmAction {
    2424
    25     final transient StringProperty TAGINFO_URL_PROP = new StringProperty("taginfo.url", "https://taginfo.openstreetmap.org/");
     25    private static final StringProperty TAGINFO_URL_PROP = new StringProperty("taginfo.url", "https://taginfo.openstreetmap.org/");
    2626
    2727    private final JTable tagTable;
     
    2929    private final IntFunction<Map<String, Integer>> tagValuesSupplier;
    3030
     31    private final String taginfoUrl;
    3132    private final JTable membershipTable;
    3233    private final IntFunction<IRelation<?>> memberValueSupplier;
     
    4344    public TaginfoAction(JTable tagTable, IntFunction<String> tagKeySupplier, IntFunction<Map<String, Integer>> tagValuesSupplier,
    4445            JTable membershipTable, IntFunction<IRelation<?>> memberValueSupplier) {
    45         super(tr("Go to Taginfo"), "dialogs/taginfo", tr("Launch browser with Taginfo statistics for selected object"), null, false);
     46        this(tagTable, tagKeySupplier, tagValuesSupplier, membershipTable, memberValueSupplier, TAGINFO_URL_PROP.get(), null);
     47    }
     48
     49    /**
     50     * Constructs a new {@code TaginfoAction} with a given URL and optional name suffix.
     51     * @param tagTable The tag table. Cannot be null
     52     * @param tagKeySupplier Finds the key from given row of tag table. Cannot be null
     53     * @param tagValuesSupplier Finds the values from given row of tag table (map of values and number of occurrences). Cannot be null
     54     * @param membershipTable The membership table. Can be null
     55     * @param memberValueSupplier Finds the parent relation from given row of membership table. Can be null
     56     * @param taginfoUrl Taginfo URL. Cannot be null
     57     * @param suffix Optional name suffix, can be null
     58     * @since 15565
     59     */
     60    public TaginfoAction(JTable tagTable, IntFunction<String> tagKeySupplier, IntFunction<Map<String, Integer>> tagValuesSupplier,
     61            JTable membershipTable, IntFunction<IRelation<?>> memberValueSupplier, String taginfoUrl, String suffix) {
     62        super(tr("Go to Taginfo") + (suffix != null ? " " + suffix : ""), "dialogs/taginfo",
     63                tr("Launch browser with Taginfo statistics for selected object"), null, false);
     64        this.taginfoUrl = taginfoUrl.endsWith("/") ? taginfoUrl : taginfoUrl + '/';
    4665        this.tagTable = Objects.requireNonNull(tagTable);
    4766        this.tagKeySupplier = Objects.requireNonNull(tagKeySupplier);
     
    5978            Map<String, Integer> values = tagValuesSupplier.apply(row);
    6079            if (values.size() == 1) {
    61                 url = TAGINFO_URL_PROP.get() + "tags/" + key
     80                url = taginfoUrl + "tags/" + key
    6281                        + '=' + Utils.encodeUrl(values.keySet().iterator().next()).replaceAll("\\+", "%20");
    6382            } else {
    64                 url = TAGINFO_URL_PROP.get() + "keys/" + key;
     83                url = taginfoUrl + "keys/" + key;
    6584            }
    6685        } else if (membershipTable != null && membershipTable.getSelectedRowCount() == 1) {
    6786            final String type = (memberValueSupplier.apply(membershipTable.getSelectedRow())).get("type");
    68             url = TAGINFO_URL_PROP.get() + "relations/" + type;
     87            url = taginfoUrl + "relations/" + type;
    6988        } else {
    7089            return;
  • trunk/src/org/openstreetmap/josm/gui/layer/AbstractOsmDataLayer.java

    r13951 r15565  
    3434        return getDataSet().isLocked();
    3535    }
     36
     37    /**
     38     * Clears the data backing this layer, unless if locked.
     39     * @since 15565
     40     */
     41    public void clear() {
     42        OsmData<?, ?, ?, ?> data = getDataSet();
     43        if (data != null && !data.isLocked()) {
     44            data.clear();
     45        }
     46    }
    3647}
  • trunk/src/org/openstreetmap/josm/gui/layer/LayerManager.java

    r14558 r15565  
    1212import java.util.function.Consumer;
    1313
    14 import org.openstreetmap.josm.data.osm.DataSet;
    1514import org.openstreetmap.josm.gui.MainApplication;
    1615import org.openstreetmap.josm.gui.util.GuiHelper;
     
    480479        }
    481480        if (layer instanceof OsmDataLayer) {
    482             DataSet data = ((OsmDataLayer) layer).data;
    483             if (data != null && !data.isLocked())
    484                 data.clear();
     481            ((OsmDataLayer) layer).clear();
    485482        }
    486483        return e.scheduleForRemoval;
  • trunk/src/org/openstreetmap/josm/gui/preferences/advanced/AdvancedPreference.java

    r14248 r15565  
    4040import org.openstreetmap.josm.data.Preferences;
    4141import org.openstreetmap.josm.data.PreferencesUtils;
     42import org.openstreetmap.josm.data.osm.DataSet;
    4243import org.openstreetmap.josm.gui.MainApplication;
    4344import org.openstreetmap.josm.gui.dialogs.LogShowDialog;
    4445import org.openstreetmap.josm.gui.help.HelpUtil;
    4546import org.openstreetmap.josm.gui.io.CustomConfigurator;
     47import org.openstreetmap.josm.gui.layer.MainLayerManager;
     48import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    4649import org.openstreetmap.josm.gui.preferences.DefaultTabPreferenceSetting;
    4750import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
     
    5659import org.openstreetmap.josm.tools.GBC;
    5760import org.openstreetmap.josm.tools.Logging;
     61import org.openstreetmap.josm.tools.Territories;
    5862import org.openstreetmap.josm.tools.Utils;
    5963
     
    7074        public PreferenceSetting createPreferenceSetting() {
    7175            return new AdvancedPreference();
     76        }
     77    }
     78
     79    private static class UnclearableOsmDataLayer extends OsmDataLayer {
     80        UnclearableOsmDataLayer(DataSet data, String name) {
     81            super(data, name, null);
     82        }
     83
     84        @Override
     85        public void clear() {
     86            // Do nothing
     87        }
     88    }
     89
     90    private final class EditBoundariesAction extends AbstractAction {
     91        EditBoundariesAction() {
     92            super(tr("Edit boundaries"));
     93        }
     94
     95        @Override
     96        public void actionPerformed(ActionEvent ae) {
     97            DataSet dataSet = Territories.getOriginalDataSet();
     98            MainLayerManager layerManager = MainApplication.getLayerManager();
     99            if (layerManager.getLayersOfType(OsmDataLayer.class).stream().noneMatch(l -> dataSet.equals(l.getDataSet()))) {
     100                layerManager.addLayer(new UnclearableOsmDataLayer(dataSet, tr("Internal JOSM boundaries")));
     101            }
     102        }
     103    }
     104
     105    private final class ResetPreferencesAction extends AbstractAction {
     106        ResetPreferencesAction() {
     107            super(tr("Reset preferences"));
     108        }
     109
     110        @Override
     111        public void actionPerformed(ActionEvent ae) {
     112            if (!GuiHelper.warnUser(tr("Reset preferences"),
     113                    "<html>"+
     114                    tr("You are about to clear all preferences to their default values<br />"+
     115                    "All your settings will be deleted: plugins, imagery, filters, toolbar buttons, keyboard, etc. <br />"+
     116                    "Are you sure you want to continue?")
     117                    +"</html>", null, "")) {
     118                Preferences.main().resetToDefault();
     119                try {
     120                    Preferences.main().save();
     121                } catch (IOException | InvalidPathException e) {
     122                    Logging.log(Logging.LEVEL_WARN, "Exception while saving preferences:", e);
     123                }
     124                readPreferences(Preferences.main());
     125                applyFilter();
     126            }
    72127        }
    73128    }
     
    333388        menu.add(getProfileMenu());
    334389        menu.addSeparator();
    335         menu.add(new AbstractAction(tr("Reset preferences")) {
    336             @Override
    337             public void actionPerformed(ActionEvent ae) {
    338                 if (!GuiHelper.warnUser(tr("Reset preferences"),
    339                         "<html>"+
    340                         tr("You are about to clear all preferences to their default values<br />"+
    341                         "All your settings will be deleted: plugins, imagery, filters, toolbar buttons, keyboard, etc. <br />"+
    342                         "Are you sure you want to continue?")
    343                         +"</html>", null, "")) {
    344                     Preferences.main().resetToDefault();
    345                     try {
    346                         Preferences.main().save();
    347                     } catch (IOException | InvalidPathException e) {
    348                         Logging.log(Logging.LEVEL_WARN, "Exception while saving preferences:", e);
    349                     }
    350                     readPreferences(Preferences.main());
    351                     applyFilter();
    352                 }
    353             }
    354         });
     390        menu.add(new EditBoundariesAction());
     391        menu.addSeparator();
     392        menu.add(new ResetPreferencesAction());
    355393        return menu;
    356394    }
  • trunk/src/org/openstreetmap/josm/tools/Territories.java

    r14484 r15565  
    1111import java.util.HashMap;
    1212import java.util.Map;
     13import java.util.Map.Entry;
    1314import java.util.Set;
     15import java.util.TreeMap;
     16import java.util.stream.Collectors;
    1417
    1518import org.openstreetmap.josm.data.coor.LatLon;
     
    3235    private static final String ISO3166_1 = "ISO3166-1:alpha2";
    3336    private static final String ISO3166_2 = "ISO3166-2";
     37    private static final String TAGINFO = "taginfo";
    3438
    3539    private static DataSet dataSet;
    3640
    3741    private static volatile Map<String, GeoPropertyIndex<Boolean>> iso3166Cache;
     42    private static volatile Map<String, String> taginfoCache;
    3843
    3944    private Territories() {
     
    7883
    7984    /**
    80      * Returns the territories dataset.
    81      * @return the territories dataset
     85     * Returns the original territories dataset. Be extra cautious when manipulating it!
     86     * @return the original territories dataset
     87     * @since 15565
     88     */
     89    public static synchronized DataSet getOriginalDataSet() {
     90        return dataSet;
     91    }
     92
     93    /**
     94     * Returns a copy of the territories dataset.
     95     * @return a copy of the territories dataset
    8296     */
    8397    public static synchronized DataSet getDataSet() {
     
    91105    public static synchronized void initialize() {
    92106        iso3166Cache = new HashMap<>();
     107        taginfoCache = new TreeMap<>();
    93108        try (CachedFile cf = new CachedFile("resource://data/" + FILENAME);
    94109                InputStream is = cf.getInputStream()) {
     
    109124                    if (iso1 != null) {
    110125                        iso3166Cache.put(iso1, gpi);
     126                        String taginfo = osm.get(TAGINFO);
     127                        if (taginfo != null) {
     128                            taginfoCache.put(iso1, taginfo);
     129                        }
    111130                    }
    112131                    if (iso2 != null) {
     
    119138        }
    120139    }
     140
     141    /**
     142     * Returns a map of national taginfo instances for the given location.
     143     * @param ll lat/lon where to look.
     144     * @return a map of national taginfo instances for the given location (code / url)
     145     * @since 15565
     146     */
     147    public static Map<String, String> getNationalTaginfoUrls(LatLon ll) {
     148        Map<String, String> result = new TreeMap<>();
     149        for (String code : iso3166Cache.entrySet().parallelStream().distinct()
     150            .filter(e -> Boolean.TRUE.equals(e.getValue().get(ll)))
     151            .map(Entry<String, GeoPropertyIndex<Boolean>>::getKey)
     152            .collect(Collectors.toSet())) {
     153            String taginfo = taginfoCache.get(code);
     154            if (taginfo != null) {
     155                result.put(code, taginfo);
     156            }
     157        }
     158        return result;
     159    }
    121160}
Note: See TracChangeset for help on using the changeset viewer.