// License: GPL. For details, see LICENSE file.
package CommandLine;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.AWTEvent;
import java.awt.Cursor;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JOptionPane;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.actions.mapmode.MapMode;
import org.openstreetmap.josm.data.coor.LatLon;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.tools.ImageProvider;
public class PointAction extends MapMode implements AWTEventListener {
private final CommandLine parentPlugin;
private final Cursor cursorCrosshair;
private final Cursor cursorJoinNode;
private Cursor currentCursor;
private Point mousePos;
private Node nearestNode;
private final ArrayList<String> pointList;
private boolean isCtrlDown;
public PointAction(CommandLine parentPlugin) {
super(null, "addsegment.png", null, ImageProvider.getCursor("crosshair", null));
this.parentPlugin = parentPlugin;
cursorCrosshair = ImageProvider.getCursor("crosshair", null);
cursorJoinNode = ImageProvider.getCursor("crosshair", "joinnode");
currentCursor = cursorCrosshair;
nearestNode = null;
pointList = new ArrayList<>();
}
@Override public void enterMode() {
super.enterMode();
if (getLayerManager().getEditDataSet() == null) {
Main.map.selectSelectTool(false);
return;
}
currentCursor = cursorCrosshair;
Main.map.mapView.addMouseListener(this);
Main.map.mapView.addMouseMotionListener(this);
try {
Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
} catch (SecurityException ex) {
Main.warn(ex);
}
}
@Override public void exitMode() {
super.exitMode();
Main.map.mapView.removeMouseListener(this);
Main.map.mapView.removeMouseMotionListener(this);
try {
Toolkit.getDefaultToolkit().removeAWTEventListener(this);
} catch (SecurityException ex) {
Main.warn(ex);
}
}
@Override public void mousePressed(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
if (isCtrlDown) {
if (pointList.size() > 0) {
pointList.remove(pointList.size() - 1);
updateTextEdit();
}
} else {
LatLon coor;
if (nearestNode == null)
coor = Main.map.mapView.getLatLon(e.getX(), e.getY());
else
coor = nearestNode.getCoor();
if (coor.isOutSideWorld()) {
JOptionPane.showMessageDialog(Main.parent, tr("Can not draw outside of the world."));
return;
}
String point = String.valueOf(coor.getX()) + "," + String.valueOf(coor.getY());
int maxInstances = parentPlugin.currentCommand.parameters.get(parentPlugin.currentCommand.currentParameterNum).maxInstances;
if (maxInstances == 1) {
parentPlugin.loadParameter(point, true);
exitMode();
} else {
if (pointList.size() < maxInstances || maxInstances == 0) {
pointList.add(point);
updateTextEdit();
} else
Main.info("Maximum instances!");
}
}
}
}
@Override
public void mouseMoved(MouseEvent e) {
if (!Main.map.mapView.isActiveLayerDrawable())
return;
processMouseEvent(e);
updCursor();
Main.map.mapView.repaint();
}
@Override
public void eventDispatched(AWTEvent arg0) {
if (!(arg0 instanceof KeyEvent))
return;
KeyEvent ev = (KeyEvent) arg0;
isCtrlDown = (ev.getModifiersEx() & KeyEvent.CTRL_DOWN_MASK) != 0;
if (ev.getKeyCode() == KeyEvent.VK_ESCAPE && ev.getID() == KeyEvent.KEY_PRESSED) {
ev.consume();
cancelDrawing();
}
}
private void updCursor() {
if (mousePos != null) {
if (!Main.isDisplayingMapView())
return;
nearestNode = Main.map.mapView.getNearestNode(mousePos, OsmPrimitive::isUsable);
if (nearestNode != null) {
setCursor(cursorJoinNode);
} else {
setCursor(cursorCrosshair);
}
}
}
private void processMouseEvent(MouseEvent e) {
if (e != null) {
mousePos = e.getPoint();
}
}
private void setCursor(final Cursor c) {
if (currentCursor.equals(c))
return;
try {
// We invoke this to prevent strange things from happening
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
// Don't change cursor when mode has changed already
if (!(Main.map.mapMode instanceof PointAction))
return;
Main.map.mapView.setCursor(c);
}
});
currentCursor = c;
} catch (Exception e) {
Main.warn(e);
}
}
public void cancelDrawing() {
if (Main.map == null || Main.map.mapView == null)
return;
Main.map.statusLine.setHeading(-1);
Main.map.statusLine.setAngle(-1);
Main.map.mapView.repaint();
updateStatusLine();
parentPlugin.abortInput();
}
public String currentValue() {
String out = "";
boolean first = true;
for (String point : pointList) {
if (!first)
out += ";";
out += point;
first = false;
}
return out;
}
private void updateTextEdit() {
Parameter currentParameter = parentPlugin.currentCommand.parameters.get(parentPlugin.currentCommand.currentParameterNum);
String prefix = tr(currentParameter.description);
prefix += parentPlugin.commandSymbol;
String value = currentValue();
parentPlugin.textField.setText(prefix + value);
}
}