001 // License: GPL. Copyright 2007 by Immanuel Scholz and others
002 package org.openstreetmap.josm.actions;
003
004 import static org.openstreetmap.josm.tools.I18n.tr;
005 import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
006
007 import java.awt.event.ActionEvent;
008 import java.awt.event.KeyEvent;
009 import java.util.Collection;
010 import java.util.HashSet;
011 import java.util.LinkedList;
012
013 import javax.swing.JOptionPane;
014
015 import org.openstreetmap.josm.Main;
016 import org.openstreetmap.josm.command.Command;
017 import org.openstreetmap.josm.command.MoveCommand;
018 import org.openstreetmap.josm.command.SequenceCommand;
019 import org.openstreetmap.josm.data.osm.Node;
020 import org.openstreetmap.josm.data.osm.OsmPrimitive;
021 import org.openstreetmap.josm.data.osm.Way;
022 import org.openstreetmap.josm.tools.Shortcut;
023
024 /**
025 * Mirror the selected nodes or ways along the vertical axis
026 *
027 * Note: If a ways are selected, their nodes are mirrored
028 *
029 * @author Teemu Koskinen, based on much copy&Paste from other Actions.
030 */
031 public final class MirrorAction extends JosmAction {
032
033 public MirrorAction() {
034 super(tr("Mirror"), "mirror", tr("Mirror selected nodes and ways."),
035 Shortcut.registerShortcut("tools:mirror", tr("Tool: {0}", tr("Mirror")),
036 KeyEvent.VK_M, Shortcut.SHIFT), true);
037 putValue("help", ht("/Action/Mirror"));
038 }
039
040 public void actionPerformed(ActionEvent e) {
041 Collection<OsmPrimitive> sel = getCurrentDataSet().getSelected();
042 HashSet<Node> nodes = new HashSet<Node>();
043
044 for (OsmPrimitive osm : sel) {
045 if (osm instanceof Node) {
046 nodes.add((Node)osm);
047 } else if (osm instanceof Way) {
048 nodes.addAll(((Way)osm).getNodes());
049 }
050 }
051
052 if (nodes.size() == 0) {
053 JOptionPane.showMessageDialog(
054 Main.parent,
055 tr("Please select at least one node or way."),
056 tr("Information"),
057 JOptionPane.INFORMATION_MESSAGE
058 );
059 return;
060 }
061
062 double minEast = 20000000000.0;
063 double maxEast = -20000000000.0;
064 for (Node n : nodes) {
065 double east = n.getEastNorth().east();
066 minEast = Math.min(minEast, east);
067 maxEast = Math.max(maxEast, east);
068 }
069 double middle = (minEast + maxEast) / 2;
070
071 Collection<Command> cmds = new LinkedList<Command>();
072
073 for (Node n : nodes) {
074 cmds.add(new MoveCommand(n, 2 * (middle - n.getEastNorth().east()), 0.0));
075 }
076
077 Main.main.undoRedo.add(new SequenceCommand(tr("Mirror"), cmds));
078 Main.map.repaint();
079 }
080
081 @Override
082 protected void updateEnabledState() {
083 if (getCurrentDataSet() == null) {
084 setEnabled(false);
085 } else {
086 updateEnabledState(getCurrentDataSet().getSelected());
087 }
088 }
089
090 @Override
091 protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
092 setEnabled(selection != null && !selection.isEmpty());
093 }
094 }