001//License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.actions; 003 004import static org.openstreetmap.josm.gui.help.HelpUtil.ht; 005import static org.openstreetmap.josm.tools.I18n.tr; 006 007import java.awt.event.ActionEvent; 008import java.awt.event.KeyEvent; 009import java.util.Collection; 010 011import javax.swing.JOptionPane; 012 013import org.openstreetmap.josm.Main; 014import org.openstreetmap.josm.command.Command; 015import org.openstreetmap.josm.command.MoveCommand; 016import org.openstreetmap.josm.data.coor.EastNorth; 017import org.openstreetmap.josm.data.osm.Node; 018import org.openstreetmap.josm.data.osm.OsmPrimitive; 019import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor; 020import org.openstreetmap.josm.tools.Shortcut; 021 022/** 023 * Moves the selection 024 * 025 * @author Frederik Ramm 026 */ 027public 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 { 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 @Override 082 public void actionPerformed(ActionEvent event) { 083 084 if (!Main.isDisplayingMapView()) 085 return; 086 087 // find out how many "real" units the objects have to be moved in order to 088 // achive an 1-pixel movement 089 090 EastNorth en1 = Main.map.mapView.getEastNorth(100, 100); 091 EastNorth en2 = Main.map.mapView.getEastNorth(101, 101); 092 093 double distx = en2.east() - en1.east(); 094 double disty = en2.north() - en1.north(); 095 096 switch (myDirection) { 097 case UP: 098 distx = 0; 099 disty = -disty; 100 break; 101 case DOWN: 102 distx = 0; 103 break; 104 case LEFT: 105 disty = 0; 106 distx = -distx; 107 break; 108 default: 109 disty = 0; 110 } 111 112 Collection<OsmPrimitive> selection = getCurrentDataSet().getSelected(); 113 Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(selection); 114 115 Command c = !Main.main.undoRedo.commands.isEmpty() 116 ? Main.main.undoRedo.commands.getLast() : null; 117 118 getCurrentDataSet().beginUpdate(); 119 if (c instanceof MoveCommand && affectedNodes.equals(((MoveCommand)c).getParticipatingPrimitives())) { 120 ((MoveCommand)c).moveAgain(distx, disty); 121 } else { 122 Main.main.undoRedo.add( 123 c = new MoveCommand(selection, distx, disty)); 124 } 125 getCurrentDataSet().endUpdate(); 126 127 for (Node n : affectedNodes) { 128 if (n.getCoor().isOutSideWorld()) { 129 // Revert move 130 ((MoveCommand) c).moveAgain(-distx, -disty); 131 JOptionPane.showMessageDialog( 132 Main.parent, 133 tr("Cannot move objects outside of the world."), 134 tr("Warning"), 135 JOptionPane.WARNING_MESSAGE 136 ); 137 return; 138 } 139 } 140 141 Main.map.mapView.repaint(); 142 } 143 144 @Override 145 protected void updateEnabledState() { 146 if (getCurrentDataSet() == null) { 147 setEnabled(false); 148 } else { 149 updateEnabledState(getCurrentDataSet().getSelected()); 150 } 151 } 152 153 @Override 154 protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) { 155 setEnabled(selection != null && !selection.isEmpty()); 156 } 157}