// License: GPL. For details, see LICENSE file.
package com.innovant.josm.plugin.routing.actions;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.util.List;
import org.apache.log4j.Logger;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.actions.mapmode.MapMode;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.gui.MapFrame;
import org.openstreetmap.josm.gui.layer.Layer;
import org.openstreetmap.josm.tools.ImageProvider;
import com.innovant.josm.plugin.routing.RoutingLayer;
import com.innovant.josm.plugin.routing.RoutingModel;
import com.innovant.josm.plugin.routing.RoutingPlugin;
import com.innovant.josm.plugin.routing.gui.RoutingDialog;
/**
* Accounts for the selection or unselection of the routing tool in the tool bar,
* and the mouse events when this tool is selected
* @author Juangui
* @author Jose Vidal
*
*/
public class MoveRouteNodeAction extends MapMode {
/**
* Square of the distance radius where route nodes can be selected for dragging
*/
private static final int DRAG_SQR_RADIUS = 100;
/**
* Logger.
*/
static Logger logger = Logger.getLogger(RoutingLayer.class);
/**
* Index of dragged node
*/
private int index;
/**
* Constructor
* @param mapFrame map frame
*/
public MoveRouteNodeAction(MapFrame mapFrame) {
// TODO Use constructor with shortcut
super(tr("Routing"), "move",
tr("Click and drag to move destination"),
mapFrame, ImageProvider.getCursor("normal", "move"));
}
@Override public void enterMode() {
super.enterMode();
Main.map.mapView.addMouseListener(this);
}
@Override public void exitMode() {
super.exitMode();
Main.map.mapView.removeMouseListener(this);
}
@Override public void mousePressed(MouseEvent e) {
// If left button is pressed
if (e.getButton() == MouseEvent.BUTTON1) {
if (Main.getLayerManager().getActiveLayer() instanceof RoutingLayer) {
requestFocusInMapView();
RoutingLayer layer = (RoutingLayer) Main.getLayerManager().getActiveLayer();
RoutingModel routingModel = layer.getRoutingModel();
// Search for the nearest node in the list
List<Node> nl = routingModel.getSelectedNodes();
index = -1;
double dmax = DRAG_SQR_RADIUS; // maximum distance, in pixels
for (int i = 0; i < nl.size(); i++) {
Node node = nl.get(i);
double d = Main.map.mapView.getPoint(node).distanceSq(e.getPoint());
if (d < dmax) {
dmax = d;
index = i;
}
}
if (index >= 0)
logger.debug("Moved from node " + nl.get(index));
}
}
}
@Override public void mouseReleased(MouseEvent e) {
// If left button is released and a route node is being dragged
if ((e.getButton() == MouseEvent.BUTTON1) && (index >= 0)) {
searchAndReplaceNode(e.getPoint());
}
}
@Override public void mouseDragged(MouseEvent e) {
}
private void searchAndReplaceNode(Point point) {
if (Main.getLayerManager().getActiveLayer() instanceof RoutingLayer) {
RoutingLayer layer = (RoutingLayer) Main.getLayerManager().getActiveLayer();
RoutingModel routingModel = layer.getRoutingModel();
RoutingDialog routingDialog = RoutingPlugin.getInstance().getRoutingDialog();
// Search for nearest highway node
Node node = null;
node = layer.getNearestHighwayNode(point);
if (node == null) {
logger.debug("Didn't found a close node to move to.");
return;
}
logger.debug("Moved to node " + node);
routingModel.removeNode(index);
routingDialog.removeNode(index);
routingModel.insertNode(index, node);
routingDialog.insertNode(index, node);
Main.map.repaint();
}
}
@Override public boolean layerIsSupported(Layer l) {
return l instanceof RoutingLayer;
}
}