001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.actions;
003
004import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
005import static org.openstreetmap.josm.tools.I18n.tr;
006
007import java.awt.event.ActionEvent;
008import java.awt.event.KeyEvent;
009import java.util.Collections;
010
011import javax.swing.SwingUtilities;
012
013import org.openstreetmap.josm.command.AddCommand;
014import org.openstreetmap.josm.data.UndoRedoHandler;
015import org.openstreetmap.josm.data.coor.LatLon;
016import org.openstreetmap.josm.data.osm.DataSet;
017import org.openstreetmap.josm.data.osm.Node;
018import org.openstreetmap.josm.data.osm.OsmPrimitive;
019import org.openstreetmap.josm.gui.MainApplication;
020import org.openstreetmap.josm.gui.MapView;
021import org.openstreetmap.josm.gui.dialogs.LatLonDialog;
022import org.openstreetmap.josm.tools.Shortcut;
023
024/**
025 * This action displays a dialog where the user can enter a latitude and longitude,
026 * and when ok is pressed, a new node is created at the specified position.
027 */
028public final class AddNodeAction extends JosmAction {
029    // remember input from last time
030    private String textLatLon, textEastNorth;
031
032    /**
033     * Constructs a new {@code AddNodeAction}.
034     */
035    public AddNodeAction() {
036        super(tr("Add Node..."), "addnode", tr("Add a node by entering latitude / longitude or easting / northing."),
037                Shortcut.registerShortcut("addnode", tr("Tools: {0}", tr("Add Node...")),
038                        KeyEvent.VK_D, Shortcut.SHIFT), true);
039        setHelpId(ht("/Action/AddNode"));
040    }
041
042    @Override
043    public void actionPerformed(ActionEvent e) {
044        if (!isEnabled())
045            return;
046
047        // #17682 - Run the action later in EDT to make sure the KeyEvent triggering it is consumed before the dialog is shown
048        SwingUtilities.invokeLater(() -> {
049            LatLonDialog dialog = new LatLonDialog(MainApplication.getMainFrame(), tr("Add Node..."), ht("/Action/AddNode"));
050
051            if (textLatLon != null) {
052                dialog.setLatLonText(textLatLon);
053            }
054            if (textEastNorth != null) {
055                dialog.setEastNorthText(textEastNorth);
056            }
057
058            dialog.showDialog();
059
060            if (dialog.getValue() != 1)
061                return;
062
063            LatLon coordinates = dialog.getCoordinates();
064            if (coordinates == null)
065                return;
066
067            textLatLon = dialog.getLatLonText();
068            textEastNorth = dialog.getEastNorthText();
069
070            Node nnew = new Node(coordinates);
071
072            // add the node
073            DataSet ds = getLayerManager().getEditDataSet();
074            UndoRedoHandler.getInstance().add(new AddCommand(ds, nnew));
075            ds.setSelected(nnew);
076            MapView mapView = MainApplication.getMap().mapView;
077            if (mapView != null && !mapView.getRealBounds().contains(nnew.getCoor())) {
078                AutoScaleAction.zoomTo(Collections.<OsmPrimitive>singleton(nnew));
079            }
080        });
081    }
082
083    @Override
084    protected boolean listenToSelectionChange() {
085        return false;
086    }
087
088    @Override
089    protected void updateEnabledState() {
090        setEnabled(getLayerManager().getEditLayer() != null);
091    }
092}