001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.io.remotecontrol.handler; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.Point; 007import java.util.Collections; 008import java.util.Map; 009 010import org.openstreetmap.josm.actions.AutoScaleAction; 011import org.openstreetmap.josm.actions.AutoScaleAction.AutoScaleMode; 012import org.openstreetmap.josm.command.AddCommand; 013import org.openstreetmap.josm.data.UndoRedoHandler; 014import org.openstreetmap.josm.data.coor.LatLon; 015import org.openstreetmap.josm.data.osm.DataSet; 016import org.openstreetmap.josm.data.osm.Node; 017import org.openstreetmap.josm.data.osm.OsmPrimitive; 018import org.openstreetmap.josm.gui.MainApplication; 019import org.openstreetmap.josm.gui.MapView; 020import org.openstreetmap.josm.gui.util.GuiHelper; 021import org.openstreetmap.josm.io.remotecontrol.AddTagsDialog; 022import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault; 023import org.openstreetmap.josm.spi.preferences.Config; 024import org.openstreetmap.josm.tools.Logging; 025 026/** 027 * Handler for add_node request. 028 */ 029public class AddNodeHandler extends RequestHandler { 030 031 /** 032 * The remote control command name used to add a node. 033 */ 034 public static final String command = "add_node"; 035 036 private double lat; 037 private double lon; 038 039 @Override 040 protected void handleRequest() { 041 GuiHelper.runInEDTAndWait(() -> addNode(args)); 042 } 043 044 @Override 045 public String[] getMandatoryParams() { 046 return new String[] {"lat", "lon"}; 047 } 048 049 @Override 050 public String[] getOptionalParams() { 051 return new String[] {"addtags"}; 052 } 053 054 @Override 055 public String getUsage() { 056 return "adds a node (given by its latitude and longitude) to the current dataset"; 057 } 058 059 @Override 060 public String[] getUsageExamples() { 061 return new String[] { 062 "/add_node?lat=11&lon=22", 063 "/add_node?lon=13.3&lat=53.2&addtags=natural=tree|name=%20%20%20==Great%20Oak==" 064 }; 065 } 066 067 @Override 068 public String getPermissionMessage() { 069 return tr("Remote Control has been asked to create a new node.") + 070 "<br>" + tr("Coordinates: ") + args.get("lat") + ", " + args.get("lon"); 071 } 072 073 @Override 074 public PermissionPrefWithDefault getPermissionPref() { 075 return PermissionPrefWithDefault.CREATE_OBJECTS; 076 } 077 078 /** 079 * Adds a node, implements the GET /add_node?lon=...&lat=... request. 080 * @param args request arguments 081 */ 082 private void addNode(Map<String, String> args) { 083 084 // Parse the arguments 085 Logging.info("Adding node at (" + lat + ", " + lon + ')'); 086 087 // Create a new node 088 LatLon ll = new LatLon(lat, lon); 089 090 Node node = null; 091 092 if (MainApplication.isDisplayingMapView()) { 093 MapView mapView = MainApplication.getMap().mapView; 094 Point p = mapView.getPoint(ll); 095 node = mapView.getNearestNode(p, OsmPrimitive::isUsable); 096 if (node != null && node.getCoor().greatCircleDistance(ll) > Config.getPref().getDouble("remotecontrol.tolerance", 0.1)) { 097 node = null; // node is too far 098 } 099 } 100 101 DataSet ds = MainApplication.getLayerManager().getEditDataSet(); 102 if (node == null) { 103 node = new Node(ll); 104 // Now execute the commands to add this node. 105 UndoRedoHandler.getInstance().add(new AddCommand(ds, node)); 106 } 107 108 ds.setSelected(node); 109 if (PermissionPrefWithDefault.CHANGE_VIEWPORT.isAllowed()) { 110 AutoScaleAction.autoScale(AutoScaleMode.SELECTION); 111 } else { 112 MainApplication.getMap().mapView.repaint(); 113 } 114 // parse parameter addtags=tag1=value1|tag2=vlaue2 115 AddTagsDialog.addTags(args, sender, Collections.singleton(node)); 116 } 117 118 @Override 119 protected void validateRequest() throws RequestHandlerBadRequestException { 120 try { 121 lat = Double.parseDouble(args != null ? args.get("lat") : ""); 122 lon = Double.parseDouble(args != null ? args.get("lon") : ""); 123 } catch (NumberFormatException e) { 124 throw new RequestHandlerBadRequestException("NumberFormatException ("+e.getMessage()+')', e); 125 } 126 if (MainApplication.getLayerManager().getEditLayer() == null) { 127 throw new RequestHandlerBadRequestException(tr("There is no layer opened to add node")); 128 } 129 } 130}