001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.actions;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.Component;
007import java.awt.Point;
008import java.awt.event.ActionEvent;
009import java.awt.event.KeyEvent;
010import java.util.Optional;
011
012import javax.swing.MenuElement;
013import javax.swing.MenuSelectionManager;
014import javax.swing.SwingUtilities;
015
016import org.openstreetmap.josm.gui.MainApplication;
017import org.openstreetmap.josm.gui.help.HelpBrowser;
018import org.openstreetmap.josm.gui.help.HelpUtil;
019import org.openstreetmap.josm.io.NetworkManager;
020import org.openstreetmap.josm.io.OnlineResource;
021import org.openstreetmap.josm.tools.Shortcut;
022
023/**
024 * Open a help browser and displays lightweight online help.
025 * @since 155
026 */
027public class HelpAction extends JosmAction {
028
029    /**
030     * Constructs a new {@code HelpAction}.
031     */
032    public HelpAction() {
033        this(true);
034    }
035
036    private HelpAction(boolean shortcut) {
037        super(tr("Help"), "help", null,
038                shortcut ? Shortcut.registerShortcut("system:help", tr("Help: {0}", tr("Help")), KeyEvent.VK_F1, Shortcut.DIRECT) : null,
039                true, false);
040        setEnabled(!NetworkManager.isOffline(OnlineResource.JOSM_WEBSITE));
041    }
042
043    /**
044     * Constructs a new {@code HelpAction} without assigning a shortcut.
045     * @return a new {@code HelpAction}
046     */
047    public static HelpAction createWithoutShortcut() {
048        return new HelpAction(false);
049    }
050
051    @Override
052    public void actionPerformed(ActionEvent e) {
053        if (e.getActionCommand() == null) {
054            String topic;
055            MenuElement[] menuPath = MenuSelectionManager.defaultManager().getSelectedPath();
056            if (menuPath.length > 0) {
057                // Get help topic from last element in selected menu path (usually a JMenuItem).
058                // If a JMenu is selected, which shows a JPopupMenu, then the last path element
059                // is a JPopupMenu and it is necessary to look also into previous path elements.
060                topic = null;
061                for (int i = menuPath.length - 1; i >= 0; i--) {
062                    Component c = menuPath[i].getComponent();
063                    topic = HelpUtil.getContextSpecificHelpTopic(c);
064                    if (topic != null) {
065                        break;
066                    }
067                }
068            } else if (e.getSource() instanceof Component) {
069                Component c = SwingUtilities.getRoot((Component) e.getSource());
070                Point mouse = c.getMousePosition();
071                if (mouse != null) {
072                    c = SwingUtilities.getDeepestComponentAt(c, mouse.x, mouse.y);
073                    topic = HelpUtil.getContextSpecificHelpTopic(c);
074                } else {
075                    topic = null;
076                }
077            } else {
078                Point mouse = MainApplication.getMainFrame().getMousePosition();
079                topic = HelpUtil.getContextSpecificHelpTopic(
080                        SwingUtilities.getDeepestComponentAt(MainApplication.getMainFrame(), mouse.x, mouse.y));
081            }
082            HelpBrowser.setUrlForHelpTopic(Optional.ofNullable(topic).orElse("/"));
083        } else {
084            HelpBrowser.setUrlForHelpTopic("/");
085        }
086    }
087}