// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.actions;
import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.Collection;
import javax.swing.JOptionPane;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.command.Command;
import org.openstreetmap.josm.command.MoveCommand;
import org.openstreetmap.josm.data.coor.EastNorth;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
import org.openstreetmap.josm.tools.Shortcut;
/**
* Moves the selection
*
* @author Frederik Ramm
*/
public class MoveAction extends JosmAction {
public enum Direction { UP, LEFT, RIGHT, DOWN }
private final Direction myDirection;
// any better idea?
private static String calltosupermustbefirststatementinconstructortext(Direction dir) {
String directiontext;
if (dir == Direction.UP) {
directiontext = tr("up");
} else if (dir == Direction.DOWN) {
directiontext = tr("down");
} else if (dir == Direction.LEFT) {
directiontext = tr("left");
} else {
directiontext = tr("right");
}
return directiontext;
}
// any better idea?
private static Shortcut calltosupermustbefirststatementinconstructor(Direction dir) {
Shortcut sc;
// CHECKSTYLE.OFF: SingleSpaceSeparator
if (dir == Direction.UP) {
sc = Shortcut.registerShortcut("core:moveup", tr("Move objects {0}", tr("up")), KeyEvent.VK_UP, Shortcut.SHIFT);
} else if (dir == Direction.DOWN) {
sc = Shortcut.registerShortcut("core:movedown", tr("Move objects {0}", tr("down")), KeyEvent.VK_DOWN, Shortcut.SHIFT);
} else if (dir == Direction.LEFT) {
sc = Shortcut.registerShortcut("core:moveleft", tr("Move objects {0}", tr("left")), KeyEvent.VK_LEFT, Shortcut.SHIFT);
} else { //dir == Direction.RIGHT
sc = Shortcut.registerShortcut("core:moveright", tr("Move objects {0}", tr("right")), KeyEvent.VK_RIGHT, Shortcut.SHIFT);
}
// CHECKSTYLE.ON: SingleSpaceSeparator
return sc;
}
/**
* Constructs a new {@code MoveAction}.
* @param dir direction
*/
public MoveAction(Direction dir) {
super(tr("Move {0}", calltosupermustbefirststatementinconstructortext(dir)), null,
tr("Moves Objects {0}", calltosupermustbefirststatementinconstructortext(dir)),
calltosupermustbefirststatementinconstructor(dir), false);
myDirection = dir;
putValue("help", ht("/Action/Move"));
if (dir == Direction.UP) {
putValue("toolbar", "action/move/up");
} else if (dir == Direction.DOWN) {
putValue("toolbar", "action/move/down");
} else if (dir == Direction.LEFT) {
putValue("toolbar", "action/move/left");
} else { //dir == Direction.RIGHT
putValue("toolbar", "action/move/right");
}
Main.toolbar.register(this);
}
@Override
public void actionPerformed(ActionEvent event) {
if (!Main.isDisplayingMapView())
return;
// find out how many "real" units the objects have to be moved in order to
// achive an 1-pixel movement
EastNorth en1 = Main.map.mapView.getEastNorth(100, 100);
EastNorth en2 = Main.map.mapView.getEastNorth(101, 101);
double distx = en2.east() - en1.east();
double disty = en2.north() - en1.north();
switch (myDirection) {
case UP:
distx = 0;
disty = -disty;
break;
case DOWN:
distx = 0;
break;
case LEFT:
disty = 0;
distx = -distx;
break;
default:
disty = 0;
}
DataSet ds = getLayerManager().getEditDataSet();
Collection<OsmPrimitive> selection = ds.getSelected();
Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(selection);
Command c = !Main.main.undoRedo.commands.isEmpty()
? Main.main.undoRedo.commands.getLast() : null;
ds.beginUpdate();
if (c instanceof MoveCommand && affectedNodes.equals(((MoveCommand) c).getParticipatingPrimitives())) {
((MoveCommand) c).moveAgain(distx, disty);
} else {
c = new MoveCommand(selection, distx, disty);
Main.main.undoRedo.add(c);
}
ds.endUpdate();
for (Node n : affectedNodes) {
if (n.getCoor().isOutSideWorld()) {
// Revert move
((MoveCommand) c).moveAgain(-distx, -disty);
JOptionPane.showMessageDialog(
Main.parent,
tr("Cannot move objects outside of the world."),
tr("Warning"),
JOptionPane.WARNING_MESSAGE
);
return;
}
}
Main.map.mapView.repaint();
}
@Override
protected void updateEnabledState() {
updateEnabledStateOnCurrentSelection();
}
@Override
protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
setEnabled(selection != null && !selection.isEmpty());
}
}