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

Last change on this file since 390 was 390, checked in by framm, 17 years ago
  • do not count anything as a move if it lasts less than 100 milliseconds.
File size: 8.0 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 private long mouseDownTime = 0;
46
47 /**
48 * The old cursor before the user pressed the mouse button.
49 */
50 private Cursor oldCursor;
51 /**
52 * The position of the mouse before the user moves a node.
53 */
54 private Point mousePos;
55 private SelectionManager selectionManager;
56
57 /**
58 * Create a new MoveAction
59 * @param mapFrame The MapFrame, this action belongs to.
60 */
61 public SelectAction(MapFrame mapFrame) {
62 super(tr("Select"), "move/move", tr("Select, move and rotate objects"),
63 KeyEvent.VK_S, mapFrame,
64 getCursor("normal", "selection", Cursor.DEFAULT_CURSOR));
65 putValue("help", "Action/Move/Move");
66 selectionManager = new SelectionManager(this, false, mapFrame.mapView);
67 }
68
69 private static Cursor getCursor(String name, String mod, int def) {
70 try {
71 return ImageProvider.getCursor(name, mod);
72 } catch (Exception e) {
73 }
74 return Cursor.getPredefinedCursor(def);
75 }
76
77 private static Cursor getCursor(String name, int def) {
78 return getCursor(name, null, def);
79 }
80
81 private void setCursor(Cursor c) {
82 if (oldCursor == null) {
83 oldCursor = Main.map.mapView.getCursor();
84 Main.map.mapView.setCursor(c);
85 }
86 }
87
88 private void restoreCursor() {
89 if (oldCursor != null) {
90 Main.map.mapView.setCursor(oldCursor);
91 oldCursor = null;
92 }
93 }
94
95 @Override public void enterMode() {
96 super.enterMode();
97 Main.map.mapView.addMouseListener(this);
98 Main.map.mapView.addMouseMotionListener(this);
99 }
100
101 @Override public void exitMode() {
102 super.exitMode();
103 Main.map.mapView.removeMouseListener(this);
104 Main.map.mapView.removeMouseMotionListener(this);
105 }
106
107 /**
108 * If the left mouse button is pressed, move all currently selected
109 * objects (if one of them is under the mouse) or the current one under the
110 * mouse (which will become selected).
111 */
112 @Override public void mouseDragged(MouseEvent e) {
113 if (mode == Mode.select) return;
114
115 // do not count anything as a move if it lasts less than 100 milliseconds.
116 if ((mode == Mode.move) && (System.currentTimeMillis() - mouseDownTime < 100)) return;
117
118 if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == 0)
119 return;
120
121 if (mode == Mode.move) {
122 setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
123 }
124
125 if (mousePos == null) {
126 mousePos = e.getPoint();
127 }
128
129 EastNorth mouseEN = Main.map.mapView.getEastNorth(e.getX(), e.getY());
130 EastNorth mouseStartEN = Main.map.mapView.getEastNorth(mousePos.x, mousePos.y);
131 double dx = mouseEN.east() - mouseStartEN.east();
132 double dy = mouseEN.north() - mouseStartEN.north();
133 if (dx == 0 && dy == 0)
134 return;
135
136 Collection<OsmPrimitive> selection = Main.ds.getSelected();
137 Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(selection);
138
139 // when rotating, having only one node makes no sense - quit silently
140 if (mode == Mode.rotate && affectedNodes.size() < 2)
141 return;
142
143
144 // check if any coordinate would be outside the world
145 for (OsmPrimitive osm : affectedNodes) {
146 if (osm instanceof Node && ((Node)osm).coor.isOutSideWorld()) {
147 JOptionPane.showMessageDialog(Main.parent,
148 tr("Cannot move objects outside of the world."));
149 return;
150 }
151 }
152 Command c = !Main.main.undoRedo.commands.isEmpty()
153 ? Main.main.undoRedo.commands.getLast() : null;
154
155 if (mode == Mode.move) {
156 if (c instanceof MoveCommand && affectedNodes.equals(((MoveCommand)c).objects))
157 ((MoveCommand)c).moveAgain(dx,dy);
158 else
159 Main.main.undoRedo.add(new MoveCommand(selection, dx, dy));
160 } else if (mode == Mode.rotate) {
161 if (c instanceof RotateCommand && affectedNodes.equals(((RotateCommand)c).objects))
162 ((RotateCommand)c).rotateAgain(mouseStartEN, mouseEN);
163 else
164 Main.main.undoRedo.add(new RotateCommand(selection, mouseStartEN, mouseEN));
165 }
166
167 Main.map.mapView.repaint();
168 mousePos = e.getPoint();
169 }
170
171 /**
172 * Look, whether any object is selected. If not, select the nearest node.
173 * If there are no nodes in the dataset, do nothing.
174 *
175 * If the user did not press the left mouse button, do nothing.
176 *
177 * Also remember the starting position of the movement and change the mouse
178 * cursor to movement.
179 */
180 @Override public void mousePressed(MouseEvent e) {
181 if (e.getButton() != MouseEvent.BUTTON1)
182 return;
183 boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
184 boolean alt = (e.getModifiers() & ActionEvent.ALT_MASK) != 0;
185 boolean shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
186
187 mouseDownTime = System.currentTimeMillis();
188
189 OsmPrimitive osm = Main.map.mapView.getNearest(e.getPoint());
190 Collection<OsmPrimitive> osmColl;
191 if (osm == null) {
192 osmColl = Collections.emptySet();
193 } else {
194 osmColl = Collections.singleton(osm);
195 }
196
197 if (ctrl && shift) {
198 selectPrims(osmColl, true, false);
199 mode = Mode.rotate;
200 setCursor(ImageProvider.getCursor("rotate", null));
201 } else if (osm != null) {
202 selectPrims(osmColl, shift, ctrl);
203 mode = Mode.move;
204 } else {
205 mode = Mode.select;
206 oldCursor = Main.map.mapView.getCursor();
207 selectionManager.register(Main.map.mapView);
208 selectionManager.mousePressed(e);
209 }
210
211 updateStatusLine();
212 Main.map.mapView.repaint();
213
214 mousePos = e.getPoint();
215 }
216
217 /**
218 * Restore the old mouse cursor.
219 */
220 @Override public void mouseReleased(MouseEvent e) {
221 if (mode == Mode.select) {
222 selectionManager.unregister(Main.map.mapView);
223 }
224 restoreCursor();
225 updateStatusLine();
226 mode = null;
227 updateStatusLine();
228 }
229
230 public void selectionEnded(Rectangle r, boolean alt, boolean shift, boolean ctrl) {
231 selectPrims(selectionManager.getObjectsInRectangle(r, alt), shift, ctrl);
232 }
233
234 public void selectPrims(Collection<OsmPrimitive> selectionList, boolean shift, boolean ctrl) {
235 if (shift && ctrl)
236 return; // not allowed together
237
238 Collection<OsmPrimitive> curSel;
239 if (!ctrl && !shift)
240 curSel = new LinkedList<OsmPrimitive>(); // new selection will replace the old.
241 else
242 curSel = Main.ds.getSelected();
243
244 for (OsmPrimitive osm : selectionList)
245 if (ctrl)
246 curSel.remove(osm);
247 else
248 curSel.add(osm);
249 Main.ds.setSelected(curSel);
250 Main.map.mapView.repaint();
251 }
252
253 @Override public String getModeHelpText() {
254 if (mode == Mode.select) {
255 return "Release the mouse button to select the objects in the rectangle.";
256 } else if (mode == Mode.move) {
257 return "Release the mouse button to stop moving.";
258 } else if (mode == Mode.rotate) {
259 return "Release the mouse button to stop rotating.";
260 } else {
261 return "Move objects by dragging; Shift to add to selection; Shift-Ctrl to rotate selected; or change selection";
262 }
263 }
264}
Note: See TracBrowser for help on using the repository browser.