// License: GPL. For details, see LICENSE file.
package CommandLine;
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 org.openstreetmap.josm.Main;
import org.openstreetmap.josm.actions.mapmode.MapMode;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.tools.ImageProvider;
public abstract class AbstractOsmAction<T extends OsmPrimitive> extends MapMode implements AWTEventListener {
private final CommandLine parentPlugin;
private final Cursor cursorNormal;
private final Cursor cursorActive;
private Cursor currentCursor;
private Point mousePos;
private T nearestPrimitive;
private boolean isCtrlDown;
protected AbstractOsmAction(CommandLine parentPlugin, String activeCursorIcon) {
super(null, "addsegment.png", null, ImageProvider.getCursor("normal", "selection"));
this.parentPlugin = parentPlugin;
cursorNormal = ImageProvider.getCursor("normal", "selection");
cursorActive = ImageProvider.getCursor("normal", activeCursorIcon);
currentCursor = cursorNormal;
nearestPrimitive = null;
}
@Override public void enterMode() {
super.enterMode();
currentCursor = cursorNormal;
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 mouseMoved(MouseEvent e) {
if (!Main.map.mapView.isActiveLayerDrawable())
return;
processMouseEvent(e);
updCursor();
Main.map.mapView.repaint();
super.mouseMoved(e);
}
@Override
public void mousePressed(MouseEvent e) {
if (!Main.map.mapView.isActiveLayerDrawable())
return;
processMouseEvent(e);
if (nearestPrimitive != null) {
DataSet ds = Main.getLayerManager().getEditDataSet();
if (isCtrlDown) {
ds.clearSelection(nearestPrimitive);
Main.map.mapView.repaint();
} else {
int maxInstances = parentPlugin.currentCommand.parameters.get(parentPlugin.currentCommand.currentParameterNum).maxInstances;
switch (maxInstances) {
case 0:
ds.addSelected(nearestPrimitive);
Main.map.mapView.repaint();
break;
case 1:
ds.addSelected(nearestPrimitive);
Main.map.mapView.repaint();
parentPlugin.loadParameter(nearestPrimitive, true);
Main.map.selectSelectTool(false);
break;
default:
if (ds.getSelected().size() < maxInstances) {
ds.addSelected(nearestPrimitive);
Main.map.mapView.repaint();
} else
parentPlugin.printHistory("Maximum instances is " + maxInstances);
}
}
}
super.mousePressed(e);
}
@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;
nearestPrimitive = getNearest(mousePos);
if (nearestPrimitive != null) {
setCursor(cursorActive);
} else {
setCursor(cursorNormal);
}
}
}
protected abstract T getNearest(Point mousePos);
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(() -> {
// Don't change cursor when mode has changed already
if (!AbstractOsmAction.this.getClass().isAssignableFrom(Main.map.mapMode.getClass()))
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();
}
}