source: josm/trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java@ 383

Last change on this file since 383 was 383, checked in by gebner, 17 years ago

Fix warnings reported by -Xlint.

File size: 7.8 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.actions.mapmode;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Cursor;
7import java.awt.Point;
8import java.awt.Rectangle;
9import java.awt.event.KeyEvent;
10import java.awt.event.MouseEvent;
11import java.awt.event.ActionEvent;
12import java.util.Collection;
13import java.util.Collections;
14import java.util.LinkedList;
15
16import javax.swing.JOptionPane;
17
18import org.openstreetmap.josm.Main;
19import org.openstreetmap.josm.actions.GroupAction;
20import org.openstreetmap.josm.command.Command;
21import org.openstreetmap.josm.command.MoveCommand;
22import org.openstreetmap.josm.command.RotateCommand;
23import org.openstreetmap.josm.data.coor.EastNorth;
24import org.openstreetmap.josm.data.osm.Node;
25import org.openstreetmap.josm.data.osm.OsmPrimitive;
26import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
27import org.openstreetmap.josm.gui.MapFrame;
28import org.openstreetmap.josm.gui.SelectionManager;
29import org.openstreetmap.josm.gui.SelectionManager.SelectionEnded;
30import org.openstreetmap.josm.tools.ImageProvider;
31/**
32 * Move is an action that can move all kind of OsmPrimitives (except Keys for now).
33 *
34 * If an selected object is under the mouse when dragging, move all selected objects.
35 * If an unselected object is under the mouse when dragging, it becomes selected
36 * and will be moved.
37 * If no object is under the mouse, move all selected objects (if any)
38 *
39 * @author imi
40 */
41public class SelectAction extends MapMode implements SelectionEnded {
42
43 enum Mode { move, rotate, select }
44 private Mode mode = null;
45
46 /**
47 * The old cursor before the user pressed the mouse button.
48 */
49 private Cursor oldCursor;
50 /**
51 * The position of the mouse before the user moves a node.
52 */
53 private Point mousePos;
54 private SelectionManager selectionManager;
55
56 /**
57 * Create a new MoveAction
58 * @param mapFrame The MapFrame, this action belongs to.
59 */
60 public SelectAction(MapFrame mapFrame) {
61 super(tr("Select"), "move/move", tr("Select, move and rotate objects"),
62 KeyEvent.VK_S, mapFrame,
63 getCursor("normal", "selection", Cursor.DEFAULT_CURSOR));
64 putValue("help", "Action/Move/Move");
65 selectionManager = new SelectionManager(this, false, mapFrame.mapView);
66 }
67
68 private static Cursor getCursor(String name, String mod, int def) {
69 try {
70 return ImageProvider.getCursor(name, mod);
71 } catch (Exception e) {
72 }
73 return Cursor.getPredefinedCursor(def);
74 }
75
76 private static Cursor getCursor(String name, int def) {
77 return getCursor(name, null, def);
78 }
79
80 private void setCursor(Cursor c) {
81 if (oldCursor == null) {
82 oldCursor = Main.map.mapView.getCursor();
83 Main.map.mapView.setCursor(c);
84 }
85 }
86
87 private void restoreCursor() {
88 if (oldCursor != null) {
89 Main.map.mapView.setCursor(oldCursor);
90 oldCursor = null;
91 }
92 }
93
94 @Override public void enterMode() {
95 super.enterMode();
96 Main.map.mapView.addMouseListener(this);
97 Main.map.mapView.addMouseMotionListener(this);
98 }
99
100 @Override public void exitMode() {
101 super.exitMode();
102 Main.map.mapView.removeMouseListener(this);
103 Main.map.mapView.removeMouseMotionListener(this);
104 }
105
106 /**
107 * If the left mouse button is pressed, move all currently selected
108 * objects (if one of them is under the mouse) or the current one under the
109 * mouse (which will become selected).
110 */
111 @Override public void mouseDragged(MouseEvent e) {
112 if (mode == Mode.select) return;
113
114 if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == 0)
115 return;
116
117 if (mode == Mode.move) {
118 setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
119 }
120
121 if (mousePos == null) {
122 mousePos = e.getPoint();
123 }
124
125 EastNorth mouseEN = Main.map.mapView.getEastNorth(e.getX(), e.getY());
126 EastNorth mouseStartEN = Main.map.mapView.getEastNorth(mousePos.x, mousePos.y);
127 double dx = mouseEN.east() - mouseStartEN.east();
128 double dy = mouseEN.north() - mouseStartEN.north();
129 if (dx == 0 && dy == 0)
130 return;
131
132 Collection<OsmPrimitive> selection = Main.ds.getSelected();
133 Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(selection);
134
135 // when rotating, having only one node makes no sense - quit silently
136 if (mode == Mode.rotate && affectedNodes.size() < 2)
137 return;
138
139
140 // check if any coordinate would be outside the world
141 for (OsmPrimitive osm : affectedNodes) {
142 if (osm instanceof Node && ((Node)osm).coor.isOutSideWorld()) {
143 JOptionPane.showMessageDialog(Main.parent,
144 tr("Cannot move objects outside of the world."));
145 return;
146 }
147 }
148 Command c = !Main.main.undoRedo.commands.isEmpty()
149 ? Main.main.undoRedo.commands.getLast() : null;
150
151 if (mode == Mode.move) {
152 if (c instanceof MoveCommand && affectedNodes.equals(((MoveCommand)c).objects))
153 ((MoveCommand)c).moveAgain(dx,dy);
154 else
155 Main.main.undoRedo.add(new MoveCommand(selection, dx, dy));
156 } else if (mode == Mode.rotate) {
157 if (c instanceof RotateCommand && affectedNodes.equals(((RotateCommand)c).objects))
158 ((RotateCommand)c).rotateAgain(mouseStartEN, mouseEN);
159 else
160 Main.main.undoRedo.add(new RotateCommand(selection, mouseStartEN, mouseEN));
161 }
162
163 Main.map.mapView.repaint();
164 mousePos = e.getPoint();
165 }
166
167 /**
168 * Look, whether any object is selected. If not, select the nearest node.
169 * If there are no nodes in the dataset, do nothing.
170 *
171 * If the user did not press the left mouse button, do nothing.
172 *
173 * Also remember the starting position of the movement and change the mouse
174 * cursor to movement.
175 */
176 @Override public void mousePressed(MouseEvent e) {
177 if (e.getButton() != MouseEvent.BUTTON1)
178 return;
179 boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
180 boolean alt = (e.getModifiers() & ActionEvent.ALT_MASK) != 0;
181 boolean shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
182
183 Collection<OsmPrimitive> sel = Main.ds.getSelected();
184 OsmPrimitive osm = Main.map.mapView.getNearest(e.getPoint());
185 Collection<OsmPrimitive> osmColl;
186 if (osm == null) {
187 osmColl = Collections.emptySet();
188 } else {
189 osmColl = Collections.singleton(osm);
190 }
191
192 if (ctrl && shift) {
193 selectPrims(osmColl, true, false);
194 mode = Mode.rotate;
195 setCursor(ImageProvider.getCursor("rotate", null));
196 } else if (osm != null) {
197 selectPrims(osmColl, shift, ctrl);
198 mode = Mode.move;
199 } else {
200 mode = Mode.select;
201 oldCursor = Main.map.mapView.getCursor();
202 selectionManager.register(Main.map.mapView);
203 selectionManager.mousePressed(e);
204 }
205
206 updateStatusLine();
207 Main.map.mapView.repaint();
208
209 mousePos = e.getPoint();
210 }
211
212 /**
213 * Restore the old mouse cursor.
214 */
215 @Override public void mouseReleased(MouseEvent e) {
216 if (mode == Mode.select) {
217 selectionManager.unregister(Main.map.mapView);
218 }
219 restoreCursor();
220 updateStatusLine();
221 mode = null;
222 updateStatusLine();
223 }
224
225 public void selectionEnded(Rectangle r, boolean alt, boolean shift, boolean ctrl) {
226 selectPrims(selectionManager.getObjectsInRectangle(r, alt), shift, ctrl);
227 }
228
229 public void selectPrims(Collection<OsmPrimitive> selectionList, boolean shift, boolean ctrl) {
230 if (shift && ctrl)
231 return; // not allowed together
232
233 Collection<OsmPrimitive> curSel;
234 if (!ctrl && !shift)
235 curSel = new LinkedList<OsmPrimitive>(); // new selection will replace the old.
236 else
237 curSel = Main.ds.getSelected();
238
239 for (OsmPrimitive osm : selectionList)
240 if (ctrl)
241 curSel.remove(osm);
242 else
243 curSel.add(osm);
244 Main.ds.setSelected(curSel);
245 Main.map.mapView.repaint();
246 }
247
248 @Override public String getModeHelpText() {
249 if (mode == Mode.select) {
250 return "Release the mouse button to select the objects in the rectangle.";
251 } else if (mode == Mode.move) {
252 return "Release the mouse button to stop moving.";
253 } else if (mode == Mode.rotate) {
254 return "Release the mouse button to stop rotating.";
255 } else {
256 return "Move objects by dragging; Shift to add to selection; Shift-Ctrl to rotate selected; or change selection";
257 }
258 }
259}
Note: See TracBrowser for help on using the repository browser.