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 }