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