001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.dialogs.properties;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.event.ActionEvent;
007import java.awt.event.KeyEvent;
008import java.io.IOException;
009import java.util.ArrayList;
010import java.util.Arrays;
011import java.util.List;
012
013import javax.swing.AbstractAction;
014import javax.swing.KeyStroke;
015import javax.xml.parsers.ParserConfigurationException;
016import javax.xml.xpath.XPathExpressionException;
017
018import org.openstreetmap.josm.data.osm.IRelation;
019import org.openstreetmap.josm.gui.MainApplication;
020import org.openstreetmap.josm.spi.preferences.Config;
021import org.openstreetmap.josm.tools.ImageProvider;
022import org.openstreetmap.josm.tools.LanguageInfo;
023import org.openstreetmap.josm.tools.Logging;
024import org.openstreetmap.josm.tools.Mediawiki;
025import org.openstreetmap.josm.tools.OpenBrowser;
026import org.openstreetmap.josm.tools.Utils;
027import org.xml.sax.SAXException;
028
029/**
030 * Launch browser with wiki help for selected object.
031 * @since 13521
032 */
033public abstract class HelpAction extends AbstractAction {
034
035    /**
036     * Constructs a new {@code HelpAction}.
037     */
038    public HelpAction() {
039        putValue(SHORT_DESCRIPTION, tr("Launch browser with wiki help for selected object"));
040        new ImageProvider("dialogs", "search").getResource().attachImageIcon(this, true);
041        putValue(ACCELERATOR_KEY, getKeyStroke());
042    }
043
044    /**
045     * Returns the keystroke launching this action (F1).
046     * @return the keystroke launching this action
047     */
048    public static KeyStroke getKeyStroke() {
049        return KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0);
050    }
051
052    @Override
053    public void actionPerformed(ActionEvent e) {
054        // give the generic help page, if more than one element is selected
055        MainApplication.worker.execute(HelpAction::displayGenericHelp);
056    }
057
058    /**
059     * Displays the most specific wiki page for the given key/value.
060     * @param key Key
061     * @param val Value
062     * @since 14208
063     */
064    public static void displayTagHelp(String key, String val) {
065        final String lang = LanguageInfo.getWikiLanguagePrefix(LanguageInfo.LocaleType.OSM_WIKI);
066        final List<String> pages = Arrays.asList(
067                String.format("%sTag:%s=%s", lang, key, val),
068                String.format("Tag:%s=%s", key, val),
069                String.format("%sKey:%s", lang, key),
070                String.format("Key:%s", key),
071                String.format("%sMap_Features", lang),
072                "Map_Features"
073        );
074        displayHelp(pages);
075    }
076
077    /**
078     * Displays the most specific wiki page for the given relation.
079     * @param rel Relation
080     * @since 14208
081     */
082    public static void displayRelationHelp(IRelation<?> rel) {
083        final String lang = LanguageInfo.getWikiLanguagePrefix(LanguageInfo.LocaleType.OSM_WIKI);
084        final List<String> pages = new ArrayList<>();
085        String type = rel.get("type");
086        if (type != null) {
087            type = Utils.encodeUrl(type);
088        }
089
090        if (type != null && !type.isEmpty()) {
091            pages.add(String.format("%sRelation:%s", lang, type));
092            pages.add(String.format("Relation:%s", type));
093        }
094
095        pages.add(String.format("%sRelations", lang));
096        pages.add("Relations");
097        displayHelp(pages);
098    }
099
100    /**
101     * Displays the localized Map Features.
102     * @since 14208
103     */
104    public static void displayGenericHelp() {
105        final String lang = LanguageInfo.getWikiLanguagePrefix(LanguageInfo.LocaleType.OSM_WIKI);
106        final List<String> pages = Arrays.asList(
107                String.format("%sMap_Features", lang),
108                "Map_Features"
109        );
110        displayHelp(pages);
111    }
112
113    /**
114     * Display help by opening the first existing wiki page in the given list.
115     * @param pages list of wiki page names to test
116     * @since 14208
117     */
118    public static void displayHelp(final List<String> pages) {
119        try {
120            new Mediawiki(Config.getUrls().getOSMWiki())
121                    .findExistingPage(pages)
122                    .ifPresent(page -> OpenBrowser.displayUrl(Config.getUrls().getOSMWiki() + "/wiki/" + page));
123        } catch (IOException | ParserConfigurationException | XPathExpressionException | SAXException e1) {
124            Logging.error(e1);
125        }
126    }
127}