001 //License: GPL. Copyright 2007 by Immanuel Scholz and others
002 package org.openstreetmap.josm.actions;
003
004 import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
005 import static org.openstreetmap.josm.tools.I18n.tr;
006
007 import java.awt.event.ActionEvent;
008 import java.awt.event.KeyEvent;
009 import java.util.Collection;
010
011 import javax.swing.JOptionPane;
012
013 import org.openstreetmap.josm.Main;
014 import org.openstreetmap.josm.command.Command;
015 import org.openstreetmap.josm.command.MoveCommand;
016 import org.openstreetmap.josm.data.coor.EastNorth;
017 import org.openstreetmap.josm.data.osm.Node;
018 import org.openstreetmap.josm.data.osm.OsmPrimitive;
019 import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
020 import org.openstreetmap.josm.tools.Shortcut;
021
022 /**
023 * Moves the selection
024 *
025 * @author Frederik Ramm
026 */
027 public class MoveAction extends JosmAction {
028
029 public enum Direction { UP, LEFT, RIGHT, DOWN }
030
031 private Direction myDirection;
032
033 // any better idea?
034 private static String calltosupermustbefirststatementinconstructor_text(Direction dir) {
035 String directiontext;
036 if (dir == Direction.UP) {
037 directiontext = tr("up");
038 } else if (dir == Direction.DOWN) {
039 directiontext = tr("down");
040 } else if (dir == Direction.LEFT) {
041 directiontext = tr("left");
042 } else { //dir == Direction.RIGHT) {
043 directiontext = tr("right");
044 }
045 return directiontext;
046 }
047
048 // any better idea?
049 private static Shortcut calltosupermustbefirststatementinconstructor(Direction dir) {
050 Shortcut sc;
051 if (dir == Direction.UP) {
052 sc = Shortcut.registerShortcut("core:moveup", tr("Move objects {0}", tr("up")), KeyEvent.VK_UP, Shortcut.SHIFT);
053 } else if (dir == Direction.DOWN) {
054 sc = Shortcut.registerShortcut("core:movedown", tr("Move objects {0}", tr("down")), KeyEvent.VK_DOWN, Shortcut.SHIFT);
055 } else if (dir == Direction.LEFT) {
056 sc = Shortcut.registerShortcut("core:moveleft", tr("Move objects {0}", tr("left")), KeyEvent.VK_LEFT, Shortcut.SHIFT);
057 } else { //dir == Direction.RIGHT) {
058 sc = Shortcut.registerShortcut("core:moveright", tr("Move objects {0}", tr("right")), KeyEvent.VK_RIGHT, Shortcut.SHIFT);
059 }
060 return sc;
061 }
062
063 public MoveAction(Direction dir) {
064 super(tr("Move {0}", calltosupermustbefirststatementinconstructor_text(dir)), null,
065 tr("Moves Objects {0}", calltosupermustbefirststatementinconstructor_text(dir)),
066 calltosupermustbefirststatementinconstructor(dir), false);
067 myDirection = dir;
068 putValue("help", ht("/Action/Move"));
069 if (dir == Direction.UP) {
070 putValue("toolbar", "action/move/up");
071 } else if (dir == Direction.DOWN) {
072 putValue("toolbar", "action/move/down");
073 } else if (dir == Direction.LEFT) {
074 putValue("toolbar", "action/move/left");
075 } else { //dir == Direction.RIGHT) {
076 putValue("toolbar", "action/move/right");
077 }
078 Main.toolbar.register(this);
079 }
080
081 public void actionPerformed(ActionEvent event) {
082
083 if (!Main.isDisplayingMapView())
084 return;
085
086 // find out how many "real" units the objects have to be moved in order to
087 // achive an 1-pixel movement
088
089 EastNorth en1 = Main.map.mapView.getEastNorth(100, 100);
090 EastNorth en2 = Main.map.mapView.getEastNorth(101, 101);
091
092 double distx = en2.east() - en1.east();
093 double disty = en2.north() - en1.north();
094
095 switch (myDirection) {
096 case UP:
097 distx = 0;
098 disty = -disty;
099 break;
100 case DOWN:
101 distx = 0;
102 break;
103 case LEFT:
104 disty = 0;
105 distx = -distx;
106 break;
107 default:
108 disty = 0;
109 }
110
111 Collection<OsmPrimitive> selection = getCurrentDataSet().getSelected();
112 Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(selection);
113
114 Command c = !Main.main.undoRedo.commands.isEmpty()
115 ? Main.main.undoRedo.commands.getLast() : null;
116
117 getCurrentDataSet().beginUpdate();
118 if (c instanceof MoveCommand && affectedNodes.equals(((MoveCommand)c).getParticipatingPrimitives())) {
119 ((MoveCommand)c).moveAgain(distx, disty);
120 } else {
121 Main.main.undoRedo.add(
122 c = new MoveCommand(selection, distx, disty));
123 }
124 getCurrentDataSet().endUpdate();
125
126 for (Node n : affectedNodes) {
127 if (n.getCoor().isOutSideWorld()) {
128 // Revert move
129 ((MoveCommand) c).moveAgain(-distx, -disty);
130 JOptionPane.showMessageDialog(
131 Main.parent,
132 tr("Cannot move objects outside of the world."),
133 tr("Warning"),
134 JOptionPane.WARNING_MESSAGE
135 );
136 return;
137 }
138 }
139
140 Main.map.mapView.repaint();
141 }
142
143 @Override
144 protected void updateEnabledState() {
145 if (getCurrentDataSet() == null) {
146 setEnabled(false);
147 } else {
148 updateEnabledState(getCurrentDataSet().getSelected());
149 }
150 }
151
152 @Override
153 protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
154 setEnabled(selection != null && !selection.isEmpty());
155 }
156 }