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 }