Ticket #2411: patch_v2_not_cleaned_up.patch
| File patch_v2_not_cleaned_up.patch, 74.9 KB (added by , 15 years ago) |
|---|
-
src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java
5 5 6 6 import java.awt.AWTEvent; 7 7 import java.awt.Cursor; 8 import java.awt.EventQueue;9 8 import java.awt.Toolkit; 10 9 import java.awt.event.AWTEventListener; 11 10 import java.awt.event.ActionEvent; … … 13 12 import java.awt.event.KeyEvent; 14 13 import java.awt.event.MouseEvent; 15 14 import java.util.Collections; 15 import java.util.HashSet; 16 import java.util.Set; 16 17 17 18 import org.openstreetmap.josm.Main; 18 19 import org.openstreetmap.josm.command.Command; 19 20 import org.openstreetmap.josm.command.DeleteCommand; 21 import org.openstreetmap.josm.data.osm.DataSet; 20 22 import org.openstreetmap.josm.data.osm.Node; 21 23 import org.openstreetmap.josm.data.osm.OsmPrimitive; 22 24 import org.openstreetmap.josm.data.osm.Relation; … … 44 46 * 45 47 * @author imi 46 48 */ 47 48 /**49 * This class contains stubs for highlighting affected primitives when affected.50 * However, way segments can be deleted as well, but cannot be highlighted51 * alone. If the highlight feature for this delete action is to be implemented52 * properly, highlighting way segments must be possible first. --xeen, 2009-09-0253 */54 49 public class DeleteAction extends MapMode implements AWTEventListener { 55 50 // Cache previous mouse event (needed when only the modifier keys are 56 51 // pressed but the mouse isn't moved) 57 52 private MouseEvent oldEvent = null; 58 53 54 /** 55 * elements that have been highlighted in the previous iteration. Used 56 * to remove the highlight from them again as otherwise the whole data 57 * set would have to be checked. 58 */ 59 private Set<OsmPrimitive> oldHighlights = new HashSet<OsmPrimitive>(); 60 61 private boolean drawTargetHighlight; 62 59 63 private enum DeleteMode { 60 64 none("delete"), 61 65 segment("delete_segment"), … … 100 104 if (!isEnabled()) 101 105 return; 102 106 107 drawTargetHighlight = Main.pref.getBoolean("draw.target-highlight", true); 108 103 109 Main.map.mapView.addMouseListener(this); 104 110 Main.map.mapView.addMouseMotionListener(this); 105 111 // This is required to update the cursors when ctrl/shift/alt is pressed … … 119 125 } catch (SecurityException ex) { 120 126 System.out.println(ex); 121 127 } 128 removeHighlighting(); 122 129 } 123 130 124 131 @Override public void actionPerformed(ActionEvent e) { … … 156 163 */ 157 164 @Override public void mouseMoved(MouseEvent e) { 158 165 oldEvent = e; 159 updateCursor(e, e.getModifiers());166 giveUserFeedback(e); 160 167 } 161 168 162 169 /** 170 * removes any highlighting that may have been set beforehand. 171 */ 172 private void removeHighlighting() { 173 for(OsmPrimitive prim : oldHighlights) { 174 prim.setHighlighted(false); 175 } 176 oldHighlights = new HashSet<OsmPrimitive>(); 177 DataSet ds = getCurrentDataSet(); 178 if(ds != null) { 179 ds.clearHighlightedWaySegments(); 180 } 181 } 182 183 /** 184 * handles everything related to highlighting primitives and way 185 * segments for the given pointer position (via MouseEvent) and 186 * modifiers. 187 * @param e 188 * @param modifiers 189 */ 190 private void addHighlighting(MouseEvent e, int modifiers) { 191 if(!drawTargetHighlight) 192 return; 193 removeHighlighting(); 194 195 Command delCmd = buildDeleteCommands(e, modifiers, true); 196 if(delCmd == null) { 197 Main.map.mapView.repaint(); 198 return; 199 } 200 201 DeleteParameters parameters = getDeleteParameters(e, modifiers); 202 203 if(parameters.mode == DeleteMode.segment) { 204 // deleting segments is the only action not working on OsmPrimitives 205 // so we have to handle them separately. 206 DataSet ds = getCurrentDataSet(); 207 if(ds != null) { 208 ds.setHighlightedWaySegments(Collections.singleton(parameters.nearestSegment)); 209 } 210 } else { 211 // all other cases delete OsmPrimitives directly, so we can 212 // safely do the following 213 for(OsmPrimitive osm : delCmd.getParticipatingPrimitives()) { 214 osm.setHighlighted(true); 215 oldHighlights.add(osm); 216 } 217 } 218 Main.map.mapView.repaint(); 219 } 220 221 /** 163 222 * This function handles all work related to updating the cursor and 164 * highlights. For now, only the cursor is enabled because highlighting 165 * requires WaySegment to be highlightable. 223 * highlights 166 224 * 167 * Normally the mouse event also contains the modifiers. However, when the168 * mouse is not moved and only modifier keys are pressed, no mouse event169 * occurs. We can use AWTEvent to catch those but still lack a proper170 * mouseevent. Instead we copy the previous event and only update the171 * modifiers.172 *173 225 * @param MouseEvent 174 226 * @param int modifiers 175 227 */ … … 182 234 DeleteParameters parameters = getDeleteParameters(e, modifiers); 183 235 Main.map.mapView.setNewCursor(parameters.mode.cursor(), this); 184 236 } 237 /** 238 * Gives the user feedback for the action he/she is about to do. Currently 239 * calls the cursor and target highlighting routines. Allows for modifiers 240 * not taken from the given mouse event. 241 * 242 * Normally the mouse event also contains the modifiers. However, when the 243 * mouse is not moved and only modifier keys are pressed, no mouse event 244 * occurs. We can use AWTEvent to catch those but still lack a proper 245 * mouseevent. Instead we copy the previous event and only update the 246 * modifiers. 247 */ 248 private void giveUserFeedback(MouseEvent e, int modifiers) { 249 updateCursor(e, modifiers); 250 addHighlighting(e, modifiers); 251 } 185 252 186 253 /** 254 * Gives the user feedback for the action he/she is about to do. Currently 255 * calls the cursor and target highlighting routines. Extracts modifiers 256 * from mouse event. 257 */ 258 private void giveUserFeedback(MouseEvent e) { 259 giveUserFeedback(e, e.getModifiers()); 260 } 261 262 /** 187 263 * If user clicked with the left button, delete the nearest object. 188 264 * position. 189 265 */ … … 203 279 } 204 280 205 281 getCurrentDataSet().setSelected(); 282 giveUserFeedback(e); 206 283 Main.map.mapView.repaint(); 207 284 } 208 285 … … 241 318 } 242 319 243 320 private DeleteParameters getDeleteParameters(MouseEvent e, int modifiers) { 244 // Note: CTRL is the only modifier that is checked in MouseMove, don't 245 // forget updating it there 246 boolean ctrl = (modifiers & ActionEvent.CTRL_MASK) != 0; 247 boolean shift = (modifiers & ActionEvent.SHIFT_MASK) != 0; 248 boolean alt = (modifiers & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0; 321 updateKeyModifiers(modifiers); 249 322 250 323 DeleteParameters result = new DeleteParameters(); 251 324 … … 287 360 case node: 288 361 return DeleteCommand.delete(getEditLayer(),Collections.singleton(parameters.nearestNode), false, silent); 289 362 case node_with_references: 290 return DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton(parameters.nearestNode) );363 return DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton(parameters.nearestNode), silent); 291 364 case segment: 292 365 return DeleteCommand.deleteWaySegment(getEditLayer(), parameters.nearestSegment); 293 366 case way: … … 295 368 case way_with_nodes: 296 369 return DeleteCommand.delete(getEditLayer(), Collections.singleton(parameters.nearestSegment.way), true, silent); 297 370 case way_with_references: 298 return DeleteCommand.deleteWithReferences(getEditLayer(), Collections.singleton(parameters.nearestSegment.way),true);371 return DeleteCommand.deleteWithReferences(getEditLayer(), Collections.singleton(parameters.nearestSegment.way), true); 299 372 default: 300 373 return null; 301 374 } … … 305 378 * This is required to update the cursors when ctrl/shift/alt is pressed 306 379 */ 307 380 public void eventDispatched(AWTEvent e) { 381 if(e == null) 382 return; 308 383 // We don't have a mouse event, so we pass the old mouse event but the 309 384 // new modifiers. 310 updateCursor(oldEvent, ((InputEvent)e).getModifiers());385 giveUserFeedback(oldEvent, ((InputEvent) e).getModifiers()); 311 386 } 312 387 } -
src/org/openstreetmap/josm/actions/mapmode/MapMode.java
3 3 4 4 import java.awt.Cursor; 5 5 import java.awt.event.ActionEvent; 6 import java.awt.event.InputEvent; 6 7 import java.awt.event.MouseEvent; 7 8 import java.awt.event.MouseListener; 8 9 import java.awt.event.MouseMotionListener; … … 24 25 */ 25 26 abstract public class MapMode extends JosmAction implements MouseListener, MouseMotionListener { 26 27 protected final Cursor cursor; 28 protected boolean ctrl; 29 protected boolean alt; 30 protected boolean shift; 27 31 28 32 /** 29 33 * Constructor for mapmodes without an menu … … 76 80 return true; 77 81 } 78 82 83 protected void updateKeyModifiers(InputEvent e) { 84 updateKeyModifiers(e.getModifiers()); 85 } 86 87 protected void updateKeyModifiers(MouseEvent e) { 88 updateKeyModifiers(e.getModifiers()); 89 } 90 91 protected void updateKeyModifiers(int modifiers) { 92 ctrl = (modifiers & ActionEvent.CTRL_MASK) != 0; 93 alt = (modifiers & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0; 94 shift = (modifiers & ActionEvent.SHIFT_MASK) != 0; 95 } 96 79 97 public void mouseReleased(MouseEvent e) {} 80 98 public void mouseExited(MouseEvent e) {} 81 99 public void mousePressed(MouseEvent e) {} -
src/org/openstreetmap/josm/actions/mapmode/PlayHeadDragMode.java
5 5 6 6 import java.awt.Cursor; 7 7 import java.awt.Point; 8 import java.awt.event.ActionEvent;9 8 import java.awt.event.MouseEvent; 10 9 11 10 import org.openstreetmap.josm.Main; … … 27 26 28 27 public PlayHeadDragMode(PlayHeadMarker m) { 29 28 super(tr("Drag play head"), "playheaddrag", tr("Drag play head"), null, 30 Main.map, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));29 Main.map, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); 31 30 playHeadMarker = m; 32 31 } 33 32 … … 67 66 mouseStart = null; 68 67 if (ev.getButton() != MouseEvent.BUTTON1 || p == null || ! dragging) 69 68 return; 70 boolean shift = (ev.getModifiers() & ActionEvent.SHIFT_MASK) != 0; 69 70 updateKeyModifiers(ev); 71 71 72 EastNorth en = Main.map.mapView.getEastNorth(ev.getX(), ev.getY()); 72 73 if (! shift) { 73 74 playHeadMarker.reposition(en); -
src/org/openstreetmap/josm/actions/mapmode/DrawAction.java
8 8 import java.awt.BasicStroke; 9 9 import java.awt.Color; 10 10 import java.awt.Cursor; 11 import java.awt.EventQueue;12 11 import java.awt.Graphics2D; 13 12 import java.awt.Point; 14 13 import java.awt.Toolkit; 15 14 import java.awt.event.AWTEventListener; 16 import java.awt.event.ActionEvent;17 15 import java.awt.event.InputEvent; 18 16 import java.awt.event.KeyEvent; 19 17 import java.awt.event.MouseEvent; … … 65 63 private Node lastUsedNode = null; 66 64 private double PHI=Math.toRadians(90); 67 65 68 private boolean ctrl;69 private boolean alt;70 private boolean shift;71 66 private Node mouseOnExistingNode; 72 67 private Set<Way> mouseOnExistingWays = new HashSet<Way>(); 73 68 private Set<OsmPrimitive> oldHighlights = new HashSet<OsmPrimitive>(); … … 512 507 513 508 getCurrentDataSet().setSelected(newSelection); 514 509 515 // "viewport following" mode for tracing long features 516 // from aerial imagery or GPS tracks. 510 // "viewport following" mode for tracing long features 511 // from aerial imagery or GPS tracks. 517 512 if (n != null && Main.map.mapView.viewportFollowing) { 518 513 Main.map.mapView.smoothScrollTo(n.getEastNorth()); 519 514 }; … … 601 596 redrawIfRequired(); 602 597 } 603 598 604 private void updateKeyModifiers(InputEvent e) {605 ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;606 alt = (e.getModifiers() & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0;607 shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;608 }609 610 private void updateKeyModifiers(MouseEvent e) {611 ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;612 alt = (e.getModifiers() & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0;613 shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;614 }615 616 599 /** 617 600 * This method prepares data required for painting the "helper line" from 618 601 * the last used position to the mouse cursor. It duplicates some code from -
src/org/openstreetmap/josm/actions/mapmode/ParallelWayAction.java
13 13 import java.awt.Stroke; 14 14 import java.awt.Toolkit; 15 15 import java.awt.event.AWTEventListener; 16 import java.awt.event.ActionEvent;17 16 import java.awt.event.InputEvent; 18 17 import java.awt.event.KeyEvent; 19 18 import java.awt.event.MouseEvent; … … 108 107 109 108 private final MapView mv; 110 109 111 private boolean ctrl;112 private boolean alt;113 private boolean shift;114 115 110 // Mouse tracking state 116 111 private Point mousePressedPos; 117 112 private boolean mouseIsDown; … … 232 227 233 228 private boolean updateModifiersState(InputEvent e) { 234 229 boolean oldAlt = alt, oldShift = shift, oldCtrl = ctrl; 235 alt = (e.getModifiers() & (ActionEvent.ALT_MASK | InputEvent.ALT_GRAPH_MASK)) != 0; 236 ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0; 237 shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0; 230 updateKeyModifiers(e); 238 231 boolean changed = (oldAlt != alt || oldShift != shift || oldCtrl != ctrl); 239 232 return changed; 240 233 } … … 393 386 // event can come quite late 394 387 if (!isModifiersValidForDragMode()) 395 388 return; 396 if (!initParallelWays(mousePressedPos, copyTags)) {389 if (!initParallelWays(mousePressedPos, copyTags)) 397 390 return; 398 }399 391 setMode(Mode.dragging); 400 392 } 401 393 … … 408 400 double d = enp.distance(nearestPointOnRefLine); 409 401 double realD = mv.getProjection().eastNorth2latlon(enp).greatCircleDistance(mv.getProjection().eastNorth2latlon(nearestPointOnRefLine)); 410 402 double snappedRealD = realD; 411 403 412 404 // TODO: abuse of isToTheRightSideOfLine function. 413 405 boolean toTheRight = Geometry.isToTheRightSideOfLine(referenceSegment.getFirstNode(), 414 406 referenceSegment.getFirstNode(), referenceSegment.getSecondNode(), new Node(enp)); … … 430 422 d = -d; 431 423 } 432 424 pWays.changeOffset(d); 433 425 434 426 Main.map.statusLine.setDist(Math.abs(snappedRealD)); 435 427 Main.map.statusLine.repaint(); 436 428 mv.repaint(); -
src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
5 5 import static org.openstreetmap.josm.tools.I18n.tr; 6 6 import static org.openstreetmap.josm.tools.I18n.trn; 7 7 8 import java.awt.AWTEvent; 8 9 import java.awt.Cursor; 9 10 import java.awt.Point; 10 11 import java.awt.Rectangle; 12 import java.awt.Toolkit; 13 import java.awt.event.AWTEventListener; 11 14 import java.awt.event.ActionEvent; 12 15 import java.awt.event.InputEvent; 13 16 import java.awt.event.KeyEvent; … … 15 18 import java.awt.geom.Point2D; 16 19 import java.util.Collection; 17 20 import java.util.Collections; 21 import java.util.HashSet; 18 22 import java.util.Iterator; 19 23 import java.util.LinkedList; 24 import java.util.Set; 20 25 21 26 import javax.swing.JOptionPane; 22 27 … … 59 64 * 60 65 * @author imi 61 66 */ 62 public class SelectAction extends MapMode implements SelectionEnded { 67 public class SelectAction extends MapMode implements AWTEventListener, SelectionEnded { 68 // "select" means the selection rectangle and "move" means either dragging 69 // or select if no mouse movement occurs (i.e. just clicking) 63 70 enum Mode { move, rotate, scale, select } 64 71 72 // contains all possible cases the cursor can be in the SelectAction except the 73 // the move pointer (latter is a system one and not an image) 74 private enum SelectActionCursor { 75 rect("normal", "selection"), 76 rect_add("normal", "select_add"), 77 rect_rm("normal", "select_remove"), 78 way("normal", "select_way"), 79 way_add("normal", "select_way_add"), 80 way_rm("normal", "select_way_remove"), 81 node("normal", "select_node"), 82 node_add("normal", "select_node_add"), 83 node_rm("normal", "select_node_remove"), 84 virtual_node("normal", "addnode"), 85 scale("scale", null), 86 rotate("rotate", null); 87 88 private final Cursor c; 89 private SelectActionCursor(String main, String sub) { 90 c = ImageProvider.getCursor(main, sub); 91 } 92 public Cursor cursor() { 93 return c; 94 } 95 } 96 97 // Cache previous mouse event (needed when only the modifier keys are 98 // pressed but the mouse isn't moved) 99 private MouseEvent oldEvent = null; 100 65 101 private Mode mode = null; 66 102 private SelectionManager selectionManager; 67 103 private boolean cancelDrawMode = false; 104 private boolean drawTargetHighlight; 68 105 private boolean didMouseDrag = false; 69 106 /** 70 107 * The component this SelectAction is associated with. … … 95 132 private boolean initialMoveThresholdExceeded = false; 96 133 97 134 /** 135 * elements that have been highlighted in the previous iteration. Used 136 * to remove the highlight from them again as otherwise the whole data 137 * set would have to be checked. 138 */ 139 private Set<OsmPrimitive> oldHighlights = new HashSet<OsmPrimitive>(); 140 141 /** 98 142 * Create a new SelectAction 99 143 * @param mapFrame The MapFrame this action belongs to. 100 144 */ … … 108 152 selectionManager = new SelectionManager(this, false, mv); 109 153 initialMoveDelay = Main.pref.getInteger("edit.initial-move-delay", 200); 110 154 initialMoveThreshold = Main.pref.getInteger("edit.initial-move-threshold", 5); 155 drawTargetHighlight = Main.pref.getBoolean("draw.target-highlight", true); 156 // This is required to update the cursors when ctrl/shift/alt is pressed 157 try { 158 Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK); 159 } catch (SecurityException ex) { 160 System.out.println(ex); 161 } 111 162 } 112 163 113 164 @Override … … 126 177 mv.removeMouseListener(this); 127 178 mv.removeMouseMotionListener(this); 128 179 mv.setVirtualNodesEnabled(false); 180 removeHighlighting(); 129 181 } 130 182 131 183 /** 184 * works out which cursor should be displayed for most of SelectAction's 185 * features. The only exception is the "move" cursor when actually dragging 186 * primitives. 187 * @param nearbyStuff primitives near the cursor 188 * @return the cursor that should be displayed 189 */ 190 private Cursor getCursor(Collection<OsmPrimitive> nearbyStuff) { 191 String c = "rect"; 192 switch(mode) { 193 case move: 194 if(virtualNode != null) { 195 c = "virtual_node"; 196 break; 197 } 198 199 // nearbyStuff cannot be empty as otherwise we would be in 200 // Move.select and not Move.move 201 OsmPrimitive osm = nearbyStuff.iterator().next(); 202 203 c = (osm instanceof Node) ? "node" : c; 204 c = (osm instanceof Way) ? "way" : c; 205 206 if(shift) { 207 c += "_add"; 208 } else if(ctrl) { 209 c += osm.isSelected() ? "_rm" : "_add"; 210 } 211 break; 212 case rotate: 213 c = "rotate"; 214 break; 215 case scale: 216 c = "scale"; 217 break; 218 case select: 219 c = "rect" + (shift ? "_add" : (ctrl ? "_rm" : "")); 220 break; 221 } 222 return SelectActionCursor.valueOf(c).cursor(); 223 } 224 225 /** 226 * Removes all existing highlights. 227 * @return true if a repaint is required 228 */ 229 private boolean removeHighlighting() { 230 boolean needsRepaint = false; 231 DataSet ds = getCurrentDataSet(); 232 if(ds != null && !ds.getHighlightedVirtualNodes().isEmpty()) { 233 needsRepaint = true; 234 ds.clearHighlightedVirtualNodes(); 235 } 236 if(oldHighlights.isEmpty()) 237 return needsRepaint; 238 239 for(OsmPrimitive prim : oldHighlights) { 240 prim.setHighlighted(false); 241 } 242 oldHighlights = new HashSet<OsmPrimitive>(); 243 return true; 244 } 245 246 /** 247 * handles adding highlights and updating the cursor for the given mouse event. 248 * @param MouseEvent which should be used as base for the feedback 249 * @return true if repaint is required 250 */ 251 private boolean giveUserFeedback(MouseEvent e) { 252 return giveUserFeedback(e, e.getModifiers()); 253 } 254 255 /** 256 * handles adding highlights and updating the cursor for the given mouse event. 257 * @param MouseEvent which should be used as base for the feedback 258 * @param define custom keyboard modifiers if the ones from MouseEvent are outdated or similar 259 * @return true if repaint is required 260 */ 261 private boolean giveUserFeedback(MouseEvent e, int modifiers) { 262 boolean needsRepaints = false; 263 264 Collection<OsmPrimitive> c = MapView.asColl( 265 mv.getNearestNodeOrWay(e.getPoint(), OsmPrimitive.isSelectablePredicate, true)); 266 267 updateKeyModifiers(modifiers); 268 determineMapMode(!c.isEmpty()); 269 270 if(drawTargetHighlight) { 271 needsRepaints = removeHighlighting(); 272 } 273 274 virtualWays.clear(); 275 virtualNode = null; 276 if(mode == Mode.move && setupVirtual(e)) { 277 DataSet ds = getCurrentDataSet(); 278 if (ds != null) { 279 ds.setHighlightedVirtualNodes(virtualWays); 280 } 281 mv.setNewCursor(SelectActionCursor.virtual_node.cursor(), this); 282 // don't highlight anything else if a virtual node will be 283 return true; 284 } 285 286 mv.setNewCursor(getCursor(c), this); 287 288 // return early if there can't be any highlights 289 if(!drawTargetHighlight || mode != Mode.move || c.isEmpty()) 290 return needsRepaints; 291 292 oldHighlights = (Set<OsmPrimitive>) c; 293 for(OsmPrimitive x : c) { 294 // only highlight primitives that will change the selection 295 // when clicked. I.e. don't highlight selected elements unless 296 // we are in toggle mode. 297 if(ctrl || !x.isSelected()) { 298 x.setHighlighted(true); 299 } 300 } 301 return true; 302 } 303 304 /** 305 * This is called whenever the keyboard modifier status changes 306 */ 307 public void eventDispatched(AWTEvent e) { 308 if(e == null) 309 return; 310 // We don't have a mouse event, so we pass the old mouse event but the 311 // new modifiers. 312 giveUserFeedback(oldEvent, ((InputEvent) e).getModifiers()); 313 } 314 315 /** 132 316 * If the left mouse button is pressed, move all currently selected 133 317 * objects (if one of them is under the mouse) or the current one under the 134 318 * mouse (which will become selected). … … 210 394 return; 211 395 212 396 Command c = !Main.main.undoRedo.commands.isEmpty() 213 ? Main.main.undoRedo.commands.getLast() : null;397 ? Main.main.undoRedo.commands.getLast() : null; 214 398 if (c instanceof SequenceCommand) { 215 399 c = ((SequenceCommand) c).getLastCommand(); 216 400 } … … 263 447 @Override 264 448 public void mouseMoved(MouseEvent e) { 265 449 // Mac OSX simulates with ctrl + mouse 1 the second mouse button hence no dragging events get fired. 266 //267 450 if ((Main.platform instanceof PlatformHookOsx) && (mode == Mode.rotate || mode == Mode.scale)) { 268 451 mouseDragged(e); 452 return; 269 453 } 454 oldEvent = e; 455 if(giveUserFeedback(e)) { 456 mv.repaint(); 457 } 270 458 } 459 460 @Override 461 public void mouseExited(MouseEvent e) { 462 if(removeHighlighting()) { 463 mv.repaint(); 464 } 465 } 466 271 467 private Node virtualNode = null; 272 468 private Collection<WaySegment> virtualWays = new LinkedList<WaySegment>(); 273 469 … … 338 534 339 535 Point p = e.getPoint(); 340 536 boolean waitForMouseUp = Main.pref.getBoolean("mappaint.select.waits-for-mouse-up", false); 341 boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;342 boolean alt = ((e.getModifiers() & (ActionEvent.ALT_MASK | InputEvent.ALT_GRAPH_MASK)) != 0 || Main.pref.getBoolean("selectaction.cycles.multiple.matches", false));537 updateKeyModifiers(e); 538 alt = alt || Main.pref.getBoolean("selectaction.cycles.multiple.matches", false); 343 539 344 540 if (!alt) { 345 541 cycleList = MapView.asColl(osm); … … 388 584 } 389 585 390 586 /** 587 * sets the mapmode according to key modifiers and if there are any 588 * selectables nearby. Everything has to be pre-determined for this 589 * function; its main purpose is to centralize what the modifiers do. 590 * @param nearSelectables 591 */ 592 private void determineMapMode(boolean hasSelectionNearby) { 593 if (shift && ctrl) { 594 mode = Mode.rotate; 595 } else if (alt && ctrl) { 596 mode = Mode.scale; 597 } else if (hasSelectionNearby) { 598 mode = Mode.move; 599 } else { 600 mode = Mode.select; 601 } 602 } 603 604 /** 391 605 * Look, whether any object is selected. If not, select the nearest node. 392 606 * If there are no nodes in the dataset, do nothing. 393 607 * … … 399 613 @Override 400 614 public void mousePressed(MouseEvent e) { 401 615 // return early 402 if (!mv.isActiveLayerVisible() || !(Boolean) this.getValue("active") || e.getButton() != MouseEvent.BUTTON1) {616 if (!mv.isActiveLayerVisible() || !(Boolean) this.getValue("active") || e.getButton() != MouseEvent.BUTTON1) 403 617 return; 404 }405 618 406 619 // request focus in order to enable the expected keyboard shortcuts 407 620 mv.requestFocus(); 408 621 409 boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0; 410 boolean shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0; 411 boolean alt = (e.getModifiers() & ActionEvent.ALT_MASK) != 0; 622 // update which modifiers are pressed (shift, alt, ctrl) 623 updateKeyModifiers(e); 412 624 413 625 // We don't want to change to draw tool if the user tries to (de)select 414 626 // stuff but accidentally clicks in an empty area when selection is empty … … 421 633 Collection<OsmPrimitive> c = MapView.asColl( 422 634 mv.getNearestNodeOrWay(e.getPoint(), OsmPrimitive.isSelectablePredicate, true)); 423 635 424 if (shift && ctrl) { 425 mode = Mode.rotate; 426 636 determineMapMode(!c.isEmpty()); 637 switch(mode) { 638 case rotate: 639 case scale: 427 640 if (getCurrentDataSet().getSelected().isEmpty()) { 428 641 getCurrentDataSet().setSelected(c); 429 642 } … … 431 644 // Mode.select redraws when selectPrims is called 432 645 // Mode.move redraws when mouseDragged is called 433 646 // Mode.rotate redraws here 434 mv.setNewCursor(ImageProvider.getCursor("rotate", null), this);435 mv.repaint();436 } else if (alt && ctrl) {437 mode = Mode.scale;438 439 if (getCurrentDataSet().getSelected().isEmpty()) {440 getCurrentDataSet().setSelected(c);441 }442 443 // Mode.select redraws when selectPrims is called444 // Mode.move redraws when mouseDragged is called445 647 // Mode.scale redraws here 446 mv.setNewCursor(ImageProvider.getCursor("scale", null), this); 447 mv.repaint(); 448 } else if (!c.isEmpty()) { 449 mode = Mode.move; 450 648 break; 649 case move: 451 650 if (!cancelDrawMode && c.iterator().next() instanceof Way) { 452 651 setupVirtual(e); 453 652 } 454 653 455 654 selectPrims(cycleSetup(c, e), e, false, false); 456 } else {457 mode = Mode.select;458 655 break; 656 case select: 657 default: 459 658 selectionManager.register(mv); 460 659 selectionManager.mousePressed(e); 660 break; 461 661 } 462 662 // this doesn't require repainting since the mouse was only pressed 663 // but not moved, therefore the highlighted elements will still be 664 // the same 665 giveUserFeedback(e); 666 mv.repaint(); 463 667 updateStatusLine(); 464 668 } 465 669 466 670 @Override 467 671 public void mouseReleased(MouseEvent e) { 468 if (!mv.isActiveLayerVisible()) {672 if (!mv.isActiveLayerVisible()) 469 673 return; 470 }471 674 472 675 startingDraggingPos = null; 473 676 474 mv.setNewCursor(cursor, this);475 677 if (mode == Mode.select) { 476 678 selectionManager.unregister(mv); 477 679 … … 488 690 virtualWays.clear(); 489 691 virtualNode = null; 490 692 491 // do nothing if the click was to short to be recognized as a drag,693 // do nothing if the click was to short too be recognized as a drag, 492 694 // but the release position is farther than 10px away from the press position 493 695 if (lastMousePos.distanceSq(e.getPoint()) < 100) { 494 696 selectPrims(cyclePrims(cycleList, e), e, true, false); … … 499 701 // We need to do it like this as otherwise drawAction will see a double 500 702 // click and switch back to SelectMode 501 703 Main.worker.execute(new Runnable() { 502 503 704 public void run() { 504 705 Main.map.selectDrawTool(true); 505 706 } … … 538 739 } 539 740 } 540 741 541 // I don't see why we need this.542 //updateStatusLine();543 742 mode = null; 743 giveUserFeedback(e); 544 744 updateStatusLine(); 545 745 } 546 746 547 747 public void selectionEnded(Rectangle r, MouseEvent e) { 548 boolean alt = (e.getModifiersEx() & (MouseEvent.ALT_DOWN_MASK | MouseEvent.ALT_GRAPH_DOWN_MASK)) != 0;748 updateKeyModifiers(e); 549 749 selectPrims(selectionManager.getObjectsInRectangle(r, alt), e, true, true); 550 750 } 551 751 … … 553 753 * Modifies current selection state and returns the next element in a 554 754 * selection cycle given by <code>prims</code>. 555 755 * @param prims the primitives that form the selection cycle 556 * @param shift whether shift is pressed 557 * @param ctrl whether ctrl is pressed 756 * @param mouse event 558 757 * @return the next element of cycle list <code>prims</code>. 559 758 */ 560 759 private Collection<OsmPrimitive> cyclePrims(Collection<OsmPrimitive> prims, MouseEvent e) { 561 760 OsmPrimitive nxt = null; 562 761 563 762 if (prims.size() > 1) { 564 boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0; 565 boolean shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0; 763 updateKeyModifiers(e); 566 764 567 765 DataSet ds = getCurrentDataSet(); 568 766 OsmPrimitive first = prims.iterator().next(), foundInDS = null; … … 629 827 } 630 828 631 829 private void selectPrims(Collection<OsmPrimitive> prims, MouseEvent e, boolean released, boolean area) { 632 boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0; 633 boolean shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0; 830 updateKeyModifiers(e); 634 831 DataSet ds = getCurrentDataSet(); 635 832 636 833 // not allowed together: do not change dataset selection, return early 637 if ((shift && ctrl) || (ctrl && !released) || (!virtualWays.isEmpty())) {834 if ((shift && ctrl) || (ctrl && !released) || (!virtualWays.isEmpty())) 638 835 return; 639 }640 836 641 837 if (!released) { 642 838 // Don't replace the selection if the user clicked on a … … 665 861 666 862 @Override 667 863 public String getModeHelpText() { 668 if (mode == Mode.select) {864 if (mode == Mode.select) 669 865 return tr("Release the mouse button to select the objects in the rectangle."); 670 } else if (mode == Mode.move) {866 else if (mode == Mode.move) 671 867 return tr("Release the mouse button to stop moving. Ctrl to merge with nearest node."); 672 } else if (mode == Mode.rotate) {868 else if (mode == Mode.rotate) 673 869 return tr("Release the mouse button to stop rotating."); 674 } else if (mode == Mode.scale) {870 else if (mode == Mode.scale) 675 871 return tr("Release the mouse button to stop scaling."); 676 } else {872 else 677 873 return tr("Move objects by dragging; Shift to add to selection (Ctrl to toggle); Shift-Ctrl to rotate selected; Alt-Ctrl to scale selected; or change selection"); 678 }679 874 } 680 875 681 876 @Override -
src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java
184 184 if (e.getButton() != MouseEvent.BUTTON1) 185 185 return; 186 186 187 updateKeyModifiers(e); 188 187 189 selectedSegment = Main.map.mapView.getNearestWaySegment(e.getPoint(), OsmPrimitive.isSelectablePredicate); 188 190 189 191 if (selectedSegment == null) { … … 191 193 } else { 192 194 // Otherwise switch to another mode 193 195 194 if ( (e.getModifiers() & ActionEvent.CTRL_MASK) != 0) {196 if (ctrl) { 195 197 mode = Mode.translate; 196 } else if ( (e.getModifiers() & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0) {198 } else if (alt) { 197 199 mode = Mode.create_new; 198 200 // create a new segment and then select and extrude the new segment 199 201 getCurrentDataSet().setSelected(selectedSegment.way); … … 201 203 } else { 202 204 mode = Mode.extrude; 203 205 getCurrentDataSet().setSelected(selectedSegment.way); 204 alwaysCreateNodes = ((e.getModifiers() & ActionEvent.SHIFT_MASK) != 0);206 alwaysCreateNodes = shift; 205 207 } 206 208 207 209 // remember initial positions for segment nodes. -
src/org/openstreetmap/josm/gui/OsmPrimitivRenderer.java
66 66 */ 67 67 private Component renderer(Component def, OsmPrimitive value) { 68 68 if (def != null && value != null && def instanceof JLabel) { 69 System.out.println(); 70 System.out.println(value); 71 System.out.println(getComponentText(value)); 69 72 ((JLabel)def).setText(getComponentText(value)); 70 73 ((JLabel)def).setIcon(ImageProvider.get(value.getDisplayType())); 71 74 ((JLabel)def).setToolTipText(getComponentToolTipText(value)); -
src/org/openstreetmap/josm/gui/DefaultNameFormatter.java
56 56 } 57 57 return instance; 58 58 } 59 59 60 60 /** 61 61 * Registers a format hook. Adds the hook at the first position of the format hooks. 62 62 * (for plugins) … … 165 165 if (name == null) { 166 166 name = node.isNew() ? tr("node") : ""+ node.getId(); 167 167 } 168 name += " (" + node.getCoor().latToString(CoordinateFormat.getDefaultFormat()) + ", " + node.getCoor().lonToString(CoordinateFormat.getDefaultFormat()) + ")";168 name += " \u200E(" + node.getCoor().latToString(CoordinateFormat.getDefaultFormat()) + ", " + node.getCoor().lonToString(CoordinateFormat.getDefaultFormat()) + ")"; 169 169 } 170 170 name = decorateNameWithId(name, node); 171 171 … … 252 252 name += (name.length() > 0) ? " ("+nodes+")" : nodes; 253 253 } 254 254 name = decorateNameWithId(name, way); 255 255 256 256 for (NameFormatterHook hook: formatHooks) { 257 257 String hookResult = hook.checkFormat(way, name); 258 if (hookResult != null) {258 if (hookResult != null) 259 259 return hookResult; 260 }261 260 } 262 261 263 262 return name; … … 310 309 311 310 for (NameFormatterHook hook: formatHooks) { 312 311 String hookResult = hook.checkFormat(relation, name); 313 if (hookResult != null) {312 if (hookResult != null) 314 313 return hookResult; 315 }316 314 } 317 315 318 316 return name; … … 407 405 if (admin_level != null) { 408 406 name += "["+admin_level+"]"; 409 407 } 410 408 411 409 for (NameFormatterHook hook: formatHooks) { 412 410 String hookResult = hook.checkRelationTypeName(relation, name); 413 if (hookResult != null) {411 if (hookResult != null) 414 412 return hookResult; 415 }416 413 } 417 414 418 415 return name; -
src/org/openstreetmap/josm/gui/layer/GpxLayer.java
29 29 import java.util.Comparator; 30 30 import java.util.LinkedList; 31 31 import java.util.List; 32 import java.util.concurrent.Callable; 33 import java.util.concurrent.ExecutionException; 32 34 import java.util.concurrent.Future; 33 35 34 36 import javax.swing.AbstractAction; … … 466 468 } 467 469 if (oldWp != null && trkPnt.time > oldWp.time) { 468 470 double vel = c.greatCircleDistance(oldWp.getCoor()) 469 / (trkPnt.time - oldWp.time);471 / (trkPnt.time - oldWp.time); 470 472 if(vel > maxval) { 471 473 maxval = vel; 472 474 } … … 657 659 // skip points that are on the same screenposition 658 660 if (old != null 659 661 && (oldA == null || screen.x < oldA.x - delta || screen.x > oldA.x + delta 660 || screen.y < oldA.y - delta || screen.y > oldA.y + delta)) {662 || screen.y < oldA.y - delta || screen.y > oldA.y + delta)) { 661 663 g.setColor(trkPnt.customColoring); 662 664 double t = Math.atan2(screen.y - old.y, screen.x - old.x) + Math.PI; 663 665 g.drawLine(screen.x, screen.y, (int) (screen.x + 10 * Math.cos(t - PHI)), … … 687 689 // skip points that are on the same screenposition 688 690 if (old != null 689 691 && (oldA == null || screen.x < oldA.x - delta || screen.x > oldA.x + delta 690 || screen.y < oldA.y - delta || screen.y > oldA.y + delta)) {692 || screen.y < oldA.y - delta || screen.y > oldA.y + delta)) { 691 693 g.setColor(trkPnt.customColoring); 692 694 g.drawLine(screen.x, screen.y, screen.x + dir[trkPnt.dir][0], screen.y 693 695 + dir[trkPnt.dir][1]); … … 857 859 858 860 msg.add(new JLabel(tr("Download near:")), GBC.eol()); 859 861 JList downloadNear = new JList(new String[] { tr("track only"), tr("waypoints only"), tr("track and waypoints") }); 860 int NEAR_TRACK=0;861 int NEAR_WAYPOINTS=1;862 int NEAR_BOTH=2;862 final int NEAR_TRACK=0; 863 final int NEAR_WAYPOINTS=1; 864 final int NEAR_BOTH=2; 863 865 864 866 downloadNear.setSelectedIndex(Main.pref.getInteger(PREF_DOWNLOAD_ALONG_TRACK_NEAR, 0)); 865 867 msg.add(downloadNear, GBC.eol()); … … 870 872 tr("Download from OSM along this track"), 871 873 JOptionPane.OK_CANCEL_OPTION, 872 874 JOptionPane.QUESTION_MESSAGE 873 );875 ); 874 876 switch(ret) { 875 877 case JOptionPane.CANCEL_OPTION: 876 878 case JOptionPane.CLOSED_OPTION: … … 881 883 882 884 Main.pref.putInteger(PREF_DOWNLOAD_ALONG_TRACK_DISTANCE, buffer.getSelectedIndex()); 883 885 Main.pref.putInteger(PREF_DOWNLOAD_ALONG_TRACK_AREA, maxRect.getSelectedIndex()); 884 int near = downloadNear.getSelectedIndex();886 final int near = downloadNear.getSelectedIndex(); 885 887 Main.pref.putInteger(PREF_DOWNLOAD_ALONG_TRACK_NEAR, near); 886 888 887 889 /* … … 890 892 */ 891 893 double latsum = 0; 892 894 int latcnt = 0; 895 // one "tick" takes about 1 ms to compute later on, so use this to guess if a 896 // please wait dialog should be shown. 897 int ticks = 0; 893 898 894 899 if (near == NEAR_TRACK || near == NEAR_BOTH) { 895 900 for (GpxTrack trk : data.tracks) { 896 901 for (GpxTrackSegment segment : trk.getSegments()) { 897 902 for (WayPoint p : segment.getWayPoints()) { 903 ticks++; 898 904 latsum += p.getCoor().lat(); 899 905 latcnt++; 900 906 } … … 912 918 double avglat = latsum / latcnt; 913 919 double scale = Math.cos(Math.toRadians(avglat)); 914 920 921 922 923 Integer i = buffer.getSelectedIndex(); 924 final int buffer_dist = dist[i < 0 ? 0 : i]; 925 i = maxRect.getSelectedIndex(); 926 double max_area = area[i < 0 ? 0 : i] / 10000.0 / scale; 927 final double buffer_y = buffer_dist / 100000.0; 928 final double buffer_x = buffer_y / scale; 929 915 930 /* 916 931 * Compute buffer zone extents and maximum bounding box size. Note that the maximum we 917 932 * ever offer is a bbox area of 0.002, while the API theoretically supports 0.25, but as 918 933 * soon as you touch any built-up area, that kind of bounding box will download forever 919 934 * and then stop because it has more than 50k nodes. 920 935 */ 921 Integer i = buffer.getSelectedIndex(); 922 int buffer_dist = dist[i < 0 ? 0 : i]; 923 double buffer_y = buffer_dist / 100000.0; 924 double buffer_x = buffer_y / scale; 925 i = maxRect.getSelectedIndex(); 926 double max_area = area[i < 0 ? 0 : i] / 10000.0 / scale; 927 Area a = new Area(); 928 Rectangle2D r = new Rectangle2D.Double(); 936 Callable<Area> calc = new Callable<Area>() { 937 public Area call() { 938 try { 939 Thread.sleep(2000); 940 } catch (InterruptedException e) { 941 // TODO Auto-generated catch block 942 e.printStackTrace(); 943 } 944 Area a = new Area(); 945 Rectangle2D r = new Rectangle2D.Double(); 929 946 930 /* 931 * Collect the combined area of all gpx points plus buffer zones around them. We ignore 932 * points that lie closer to the previous point than the given buffer size because 933 * otherwise this operation takes ages. 934 */ 935 LatLon previous = null; 936 if (near == NEAR_TRACK || near == NEAR_BOTH) { 937 for (GpxTrack trk : data.tracks) { 938 for (GpxTrackSegment segment : trk.getSegments()) { 939 for (WayPoint p : segment.getWayPoints()) { 947 /* 948 * Collect the combined area of all gpx points plus buffer zones around them. We ignore 949 * points that lie closer to the previous point than the given buffer size because 950 * otherwise this operation takes ages. 951 */ 952 LatLon previous = null; 953 if (near == NEAR_TRACK || near == NEAR_BOTH) { 954 for (GpxTrack trk : data.tracks) { 955 for (GpxTrackSegment segment : trk.getSegments()) { 956 for (WayPoint p : segment.getWayPoints()) { 957 LatLon c = p.getCoor(); 958 if (previous == null || c.greatCircleDistance(previous) > buffer_dist) { 959 // we add a buffer around the point. 960 r.setRect(c.lon() - buffer_x, c.lat() - buffer_y, 2 * buffer_x, 2 * buffer_y); 961 a.add(new Area(r)); 962 previous = c; 963 } 964 } 965 } 966 } 967 } 968 if (near == NEAR_WAYPOINTS || near == NEAR_BOTH) { 969 for (WayPoint p : data.waypoints) { 940 970 LatLon c = p.getCoor(); 941 971 if (previous == null || c.greatCircleDistance(previous) > buffer_dist) { 942 972 // we add a buffer around the point. … … 946 976 } 947 977 } 948 978 } 979 return a; 949 980 } 981 }; 982 983 Area a; 984 final PleaseWaitProgressMonitor monitor1 = new PleaseWaitProgressMonitor(tr("Calculating download areas")); 985 try { 986 monitor1.beginTask("I have no idea", ticks); 987 a = Main.worker.submit(calc).get(); 988 } catch (InterruptedException e1) { 989 e1.printStackTrace(); 990 return; 991 } catch (ExecutionException e1) { 992 e1.printStackTrace(); 993 return; 994 } finally { 995 //monitor1.close(); 950 996 } 951 if (near == NEAR_WAYPOINTS || near == NEAR_BOTH) {952 for (WayPoint p : data.waypoints) {953 LatLon c = p.getCoor();954 if (previous == null || c.greatCircleDistance(previous) > buffer_dist) {955 // we add a buffer around the point.956 r.setRect(c.lon() - buffer_x, c.lat() - buffer_y, 2 * buffer_x, 2 * buffer_y);957 a.add(new Area(r));958 previous = c;959 }960 }961 }962 997 963 998 /* 964 999 * Area "a" now contains the hull that we would like to download data for. however we … … 993 1028 tr("Download from OSM along this track"), 994 1029 JOptionPane.OK_CANCEL_OPTION, 995 1030 JOptionPane.PLAIN_MESSAGE 996 );1031 ); 997 1032 switch(ret) { 998 1033 case JOptionPane.CANCEL_OPTION: 999 1034 case JOptionPane.CLOSED_OPTION: … … 1002 1037 // continue 1003 1038 } 1004 1039 } 1005 final PleaseWaitProgressMonitor monitor = new PleaseWaitProgressMonitor(tr("Download data"));1006 final Future<?> future = new DownloadOsmTaskList().download(false, toDownload, monitor );1040 final PleaseWaitProgressMonitor monitor2 = new PleaseWaitProgressMonitor(tr("Download data")); 1041 final Future<?> future = new DownloadOsmTaskList().download(false, toDownload, monitor2); 1007 1042 Main.worker.submit( 1008 1043 new Runnable() { 1009 1044 @Override … … 1014 1049 e.printStackTrace(); 1015 1050 return; 1016 1051 } 1017 monitor .close();1052 monitor2.close(); 1018 1053 } 1019 1054 } 1020 );1055 ); 1021 1056 } 1022 1057 } 1023 1058 … … 1100 1135 tr("No GPX track available in layer to associate audio with."), 1101 1136 tr("Error"), 1102 1137 JOptionPane.ERROR_MESSAGE 1103 );1138 ); 1104 1139 return; 1105 1140 } 1106 1141 … … 1159 1194 double duration = AudioUtil.getCalibratedDuration(wavFile); 1160 1195 double startTime = lastModified - duration; 1161 1196 startTime = firstStartTime + (startTime - firstStartTime) 1162 / Main.pref.getDouble("audio.calibration", "1.0" /* default, ratio */);1197 / Main.pref.getDouble("audio.calibration", "1.0" /* default, ratio */); 1163 1198 WayPoint w1 = null; 1164 1199 WayPoint w2 = null; 1165 1200 … … 1481 1516 String msg = tr("<html>The data in the GPX layer ''{0}'' has been downloaded from the server.<br>" 1482 1517 + "Because its way points do not include a timestamp we cannot correlate them with audio data.</html>", 1483 1518 layer.getName() 1484 );1519 ); 1485 1520 HelpAwareOptionPane.showOptionDialog( 1486 1521 Main.parent, 1487 1522 msg, 1488 1523 tr("Import not possible"), 1489 1524 JOptionPane.WARNING_MESSAGE, 1490 1525 ht("/Action/ImportAudio#CantImportIntoGpxLayerFromServer") 1491 );1526 ); 1492 1527 } 1493 1528 1494 1529 @Override … … 1547 1582 MarkerLayer ml = new MarkerLayer(new GpxData(), tr("Audio markers from {0}", getName()) + names, 1548 1583 getAssociatedFile(), GpxLayer.this); 1549 1584 double firstStartTime = sel[0].lastModified() / 1000.0 /* ms -> seconds */ 1550 - AudioUtil.getCalibratedDuration(sel[0]);1585 - AudioUtil.getCalibratedDuration(sel[0]); 1551 1586 1552 1587 Markers m = new Markers(); 1553 1588 for (int i = 0; i < sel.length; i++) { … … 1571 1606 String msg = tr("<html>The data in the GPX layer ''{0}'' has been downloaded from the server.<br>" 1572 1607 + "Because its way points do not include a timestamp we cannot correlate them with images.</html>", 1573 1608 layer.getName() 1574 );1609 ); 1575 1610 HelpAwareOptionPane.showOptionDialog( 1576 1611 Main.parent, 1577 1612 msg, 1578 1613 tr("Import not possible"), 1579 1614 JOptionPane.WARNING_MESSAGE, 1580 1615 ht("/Action/ImportImages#CantImportIntoGpxLayerFromServer") 1581 );1616 ); 1582 1617 } 1583 1618 1584 1619 private void addRecursiveFiles(LinkedList<File> files, File[] sel) { -
src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java
18 18 import java.util.Collection; 19 19 import java.util.Collections; 20 20 import java.util.Comparator; 21 import java.util.HashMap;22 21 import java.util.HashSet; 23 22 import java.util.LinkedList; 24 23 import java.util.List; … … 58 57 import org.openstreetmap.josm.data.osm.event.DataChangedEvent; 59 58 import org.openstreetmap.josm.data.osm.event.DataSetListener; 60 59 import org.openstreetmap.josm.data.osm.event.DatasetEventManager; 61 import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode;62 60 import org.openstreetmap.josm.data.osm.event.NodeMovedEvent; 63 61 import org.openstreetmap.josm.data.osm.event.PrimitivesAddedEvent; 64 62 import org.openstreetmap.josm.data.osm.event.PrimitivesRemovedEvent; … … 66 64 import org.openstreetmap.josm.data.osm.event.SelectionEventManager; 67 65 import org.openstreetmap.josm.data.osm.event.TagsChangedEvent; 68 66 import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent; 67 import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode; 69 68 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor; 70 69 import org.openstreetmap.josm.gui.DefaultNameFormatter; 71 70 import org.openstreetmap.josm.gui.MapView; 72 import org.openstreetmap.josm.gui.MapView.EditLayerChangeListener;73 71 import org.openstreetmap.josm.gui.OsmPrimitivRenderer; 74 72 import org.openstreetmap.josm.gui.SideButton; 73 import org.openstreetmap.josm.gui.MapView.EditLayerChangeListener; 75 74 import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask; 76 75 import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor; 77 76 import org.openstreetmap.josm.gui.layer.OsmDataLayer; … … 622 621 double dist = -1; 623 622 if(this.selection.size() == 1) { 624 623 OsmPrimitive o = this.selection.get(0); 625 if(o instanceof Way) 626 dist = ((Way)o).getLength(); 624 if(o instanceof Way) { 625 dist = ((Way)o).getLength(); 626 } 627 627 } 628 628 Main.map.statusLine.setDist(dist); 629 629 } -
src/org/openstreetmap/josm/data/osm/WaySegment.java
29 29 return way.getNode(lowerIndex + 1); 30 30 } 31 31 32 /** 33 * returns this way segment as complete way. 34 * @return 35 */ 36 public Way toWay() { 37 Way w = new Way(); 38 w.addNode(getFirstNode()); 39 w.addNode(getSecondNode()); 40 return w; 41 } 42 32 43 @Override public boolean equals(Object o) { 33 44 return o != null && o instanceof WaySegment 34 45 && ((WaySegment) o).way == way -
src/org/openstreetmap/josm/data/osm/DataSet.java
114 114 private Map<PrimitiveId, OsmPrimitive> primitivesMap = allPrimitives.foreignKey(new IdHash()); 115 115 private CopyOnWriteArrayList<DataSetListener> listeners = new CopyOnWriteArrayList<DataSetListener>(); 116 116 117 // provide means to highlight map elements that are not osm primitives 118 private Collection<WaySegment> highlightedVirtualNodes = new LinkedList<WaySegment>(); 119 private Collection<WaySegment> highlightedWaySegments = new LinkedList<WaySegment>(); 120 117 121 // Number of open calls to beginUpdate 118 122 private int updateCount; 119 123 // Events that occurred while dataset was locked but should be fired after write lock is released … … 430 434 } 431 435 432 436 /** 437 * returns an unmodifiable collection of *WaySegments* whose virtual 438 * nodes should be highlighted. WaySegements are used to avoid having 439 * to create a VirtualNode class that wouldn't have much purpose otherwise. 440 * 441 * @return unmodifiable collection of WaySegements 442 */ 443 public Collection<WaySegment> getHighlightedVirtualNodes() { 444 return Collections.unmodifiableCollection(highlightedVirtualNodes); 445 } 446 447 /** 448 * returns an unmodifiable collection of WaySegments that should be 449 * highlighted. 450 * 451 * @return unmodifiable collection of WaySegements 452 */ 453 public Collection<WaySegment> getHighlightedWaySegments() { 454 return Collections.unmodifiableCollection(highlightedWaySegments); 455 } 456 457 /** 433 458 * Replies an unmodifiable collection of primitives currently selected 434 459 * in this dataset. May be empty, but not null. 435 460 * … … 507 532 } 508 533 509 534 /** 535 * set what virtual nodes should be highlighted. Requires a Collection of 536 * *WaySegements* to avoid a VirtualNode class that wouldn't have much use 537 * otherwise. 538 * @param Collection of waySegments 539 */ 540 public void setHighlightedVirtualNodes(Collection<WaySegment> waySegments) { 541 if(highlightedVirtualNodes.isEmpty() && waySegments.isEmpty()) 542 return; 543 544 highlightedVirtualNodes = waySegments; 545 // can't use fireHighlightingChanged because it requires an OsmPrimitive 546 highlightUpdateCount++; 547 } 548 549 /** 550 * set what virtual ways should be highlighted. 551 * @param Collection of waySegments 552 */ 553 public void setHighlightedWaySegments(Collection<WaySegment> waySegments) { 554 if(highlightedWaySegments.isEmpty() && waySegments.isEmpty()) 555 return; 556 557 highlightedWaySegments = waySegments; 558 // can't use fireHighlightingChanged because it requires an OsmPrimitive 559 highlightUpdateCount++; 560 } 561 562 /** 510 563 * Sets the current selection to the primitives in <code>selection</code>. 511 564 * Notifies all {@see SelectionChangedListener} if <code>fireSelectionChangeEvent</code> is true. 512 565 * … … 592 645 } 593 646 594 647 /** 648 * clear all highlights of virtual nodes 649 */ 650 public void clearHighlightedVirtualNodes() { 651 setHighlightedVirtualNodes(new ArrayList<WaySegment>()); 652 } 653 654 /** 655 * clear all highlights of way segments 656 */ 657 public void clearHighlightedWaySegments() { 658 setHighlightedWaySegments(new ArrayList<WaySegment>()); 659 } 660 661 /** 595 662 * Remove the selection from every value in the collection. 596 663 * @param list The collection to remove the selection from. 597 664 */ -
src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java
20 20 import java.awt.geom.GeneralPath; 21 21 import java.awt.geom.Rectangle2D; 22 22 import java.awt.image.BufferedImage; 23 import java.util.ArrayList; 23 24 import java.util.Arrays; 24 25 import java.util.Collection; 25 26 import java.util.Iterator; … … 34 35 import org.openstreetmap.josm.data.osm.Relation; 35 36 import org.openstreetmap.josm.data.osm.RelationMember; 36 37 import org.openstreetmap.josm.data.osm.Way; 38 import org.openstreetmap.josm.data.osm.WaySegment; 37 39 import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon; 38 40 import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon.PolyData; 39 41 import org.openstreetmap.josm.gui.NavigatableComponent; … … 41 43 import org.openstreetmap.josm.gui.mappaint.BoxTextElemStyle.HorizontalTextAlignment; 42 44 import org.openstreetmap.josm.gui.mappaint.BoxTextElemStyle.VerticalTextAlignment; 43 45 import org.openstreetmap.josm.gui.mappaint.NodeElemStyle; 46 import org.openstreetmap.josm.gui.mappaint.TextElement; 44 47 import org.openstreetmap.josm.gui.mappaint.NodeElemStyle.Symbol; 45 import org.openstreetmap.josm.gui.mappaint.TextElement;46 48 import org.openstreetmap.josm.tools.ImageProvider; 47 49 import org.openstreetmap.josm.tools.Pair; 48 50 … … 52 54 private final NavigatableComponent nc; 53 55 private final boolean inactive; 54 56 private final MapPaintSettings settings; 57 private final Collection<WaySegment> highlightWaySegments; 55 58 56 59 private final boolean useStrokes; 57 60 private final boolean showNames; … … 63 66 private final Color selectedColor; 64 67 private final Color relationSelectedColor; 65 68 private final Color nodeColor; 69 private final Color highlightColor; 66 70 private final Color backgroundColor; 67 71 68 72 private final Font orderFont; … … 80 84 81 85 public MapPainter(MapPaintSettings settings, Graphics2D g, 82 86 boolean inactive, NavigatableComponent nc, boolean virtual, 83 double circum, boolean leftHandTraffic){ 87 double circum, boolean leftHandTraffic, 88 Collection<WaySegment> highlightWaySegments){ 84 89 this.settings = settings; 85 90 this.g = g; 86 91 this.inactive = inactive; 87 92 this.nc = nc; 93 this.highlightWaySegments = highlightWaySegments; 88 94 this.useStrokes = settings.getUseStrokesDistance() > circum; 89 95 this.showNames = settings.getShowNamesDistance() > circum; 90 96 this.showIcons = settings.getShowIconsDistance() > circum; … … 95 101 this.selectedColor = PaintColors.SELECTED.get(); 96 102 this.relationSelectedColor = PaintColors.RELATIONSELECTED.get(); 97 103 this.nodeColor = PaintColors.NODE.get(); 104 this.highlightColor = PaintColors.HIGHLIGHT.get(); 98 105 this.backgroundColor = PaintColors.getBackgroundColor(); 99 106 100 107 this.orderFont = new Font(Main.pref.get("mappaint.font", "Helvetica"), Font.PLAIN, Main.pref.getInteger("mappaint.fontsize", 8)); … … 130 137 boolean initialMoveToNeeded = true; 131 138 List<Node> wayNodes = way.getNodes(); 132 139 if (wayNodes.size() < 2) return; 133 134 Iterator<Point> it = new OffsetIterator(way.getNodes(), offset); 140 141 Collection<Integer> segmentsToHighlight = new ArrayList<Integer>(); 142 // only highlight the segment if the way itself is not highlighted 143 if(!way.isHighlighted()) { 144 for(WaySegment ws : highlightWaySegments) { 145 if(ws.way != way || ws.lowerIndex < offset) { 146 continue; 147 } 148 segmentsToHighlight.add(ws.lowerIndex+1); 149 } 150 } 151 GeneralPath highlightSegs = segmentsToHighlight.isEmpty() ? null : new GeneralPath(); 152 153 Iterator<Point> it = new OffsetIterator(wayNodes, offset); 135 154 while (it.hasNext()) { 136 155 Point p = it.next(); 137 156 if (lastPoint != null) { … … 153 172 path.moveTo(p1.x, p1.y); 154 173 } 155 174 p2 = clip.getP2(); 156 path.lineTo(p2.x, p2.y); 175 if(segmentsToHighlight.contains(offset)) { 176 path.moveTo(p2.x, p2.y); 177 // it is assumed that highlighted segments are not 178 // next to each other. 179 highlightSegs.moveTo(p1.x, p1.y); 180 highlightSegs.lineTo(p2.x, p2.y); 181 } else { 182 path.lineTo(p2.x, p2.y); 183 } 157 184 158 185 /* draw arrow */ 159 186 if (showHeadArrowOnly ? !it.hasNext() : showOrientation) { … … 207 234 } 208 235 } 209 236 lastPoint = p; 237 // have the offset variable point to the current segment 238 offset++; 210 239 } 211 displaySegments(path, orientationArrows, onewayArrows, onewayArrowsCasing, color, line, dashes, dashedColor);240 displaySegments(path, orientationArrows, onewayArrows, onewayArrowsCasing, highlightSegs, color, line, dashes, dashedColor); 212 241 } 213 242 214 243 /** … … 220 249 * perfect way, but it is should not throw an exception. 221 250 */ 222 251 public class OffsetIterator implements Iterator<Point> { 223 252 224 253 private List<Node> nodes; 225 254 private int offset; 226 255 private int idx; 227 256 228 257 private Point prev = null; 229 258 /* 'prev0' is a point that has distance 'offset' from 'prev' and the 230 259 * line from 'prev' to 'prev0' is perpendicular to the way segment from … … 237 266 this.offset = offset; 238 267 idx = 0; 239 268 } 240 269 241 270 @Override 242 271 public boolean hasNext() { 243 272 return idx < nodes.size(); … … 246 275 @Override 247 276 public Point next() { 248 277 if (offset == 0) return nc.getPoint(nodes.get(idx++)); 249 278 250 279 Point current = nc.getPoint(nodes.get(idx)); 251 280 252 281 if (idx == nodes.size() - 1) { 253 282 ++idx; 254 283 return new Point(x_prev0 + current.x - prev.x, y_prev0 + current.y - prev.y); … … 276 305 } else { 277 306 int dx_prev = current.x - prev.x; 278 307 int dy_prev = current.y - prev.y; 279 308 280 309 // determine intersection of the lines parallel to the two 281 310 // segments 282 311 int det = dx_next*dy_prev - dx_prev*dy_next; 283 312 284 313 if (det == 0) { 285 314 ++idx; 286 315 prev = current; … … 306 335 throw new UnsupportedOperationException(); 307 336 } 308 337 } 309 310 private void displaySegments(GeneralPath path, GeneralPath orientationArrows, GeneralPath onewayArrows, GeneralPath onewayArrowsCasing, 311 Color color, BasicStroke line, BasicStroke dashes, Color dashedColor) { 338 339 private void displaySegments(GeneralPath path, GeneralPath orientationArrows, GeneralPath onewayArrows, 340 GeneralPath onewayArrowsCasing, GeneralPath highlightedSegments, Color color, BasicStroke line, 341 BasicStroke dashes, Color dashedColor) { 312 342 g.setColor(inactive ? inactiveColor : color); 313 343 if (useStrokes) { 314 344 g.setStroke(line); 315 345 } 316 346 g.draw(path); 317 347 348 if(highlightedSegments != null) { 349 g.setColor(highlightColor); 350 g.draw(highlightedSegments); 351 } 352 318 353 if(!inactive && useStrokes && dashes != null) { 319 354 g.setColor(dashedColor); 320 355 g.setStroke(dashes); 321 356 g.draw(path); 357 if(highlightedSegments != null) { 358 g.draw(highlightedSegments); 359 } 322 360 } 323 361 324 362 if (orientationArrows != null) { … … 997 1035 pVia, vx, vx2, vy, vy2, iconAngle, r.isSelected()); 998 1036 } 999 1037 1000 public void drawVirtualNodes(Collection<Way> ways ) {1001 1002 if (virtualNodeSize != 0) {1003 GeneralPath path = new GeneralPath();1004 for (Way osm: ways){1005 if (osm.isUsable() && !osm.isDisabled()){1006 visitVirtual(path, osm);1007 }1038 public void drawVirtualNodes(Collection<Way> ways, Collection<WaySegment> highlightVirtualNodes) { 1039 if (virtualNodeSize == 0) 1040 return; 1041 // print normal virtual nodes 1042 GeneralPath path = new GeneralPath(); 1043 for (Way osm: ways){ 1044 if (osm.isUsable() && !osm.isDisabled()) { 1045 visitVirtual(path, osm); 1008 1046 } 1009 g.setColor(nodeColor);1010 g.draw(path);1011 1047 } 1048 g.setColor(nodeColor); 1049 g.draw(path); 1050 // print highlighted virtual nodes. Since only the color changes, simply 1051 // drawing them over the existing ones works fine (at least in their current 1052 // simple style) 1053 path = new GeneralPath(); 1054 for (WaySegment wseg: highlightVirtualNodes){ 1055 if (wseg.way.isUsable() && !wseg.way.isDisabled()) { 1056 visitVirtual(path, wseg.toWay()); 1057 } 1058 } 1059 g.setColor(highlightColor); 1060 g.draw(path); 1012 1061 } 1013 1062 1014 1063 public void visitVirtual(GeneralPath path, Way w) { -
src/org/openstreetmap/josm/data/osm/visitor/paint/WireframeMapRenderer.java
24 24 import org.openstreetmap.josm.data.osm.Relation; 25 25 import org.openstreetmap.josm.data.osm.RelationMember; 26 26 import org.openstreetmap.josm.data.osm.Way; 27 import org.openstreetmap.josm.data.osm.WaySegment; 27 28 import org.openstreetmap.josm.data.osm.visitor.Visitor; 28 29 import org.openstreetmap.josm.gui.NavigatableComponent; 29 30 … … 127 128 } 128 129 129 130 DataSet ds; 131 130 132 public void render(DataSet data, boolean virtual, Bounds bounds) { 131 133 BBox bbox = new BBox(bounds); 132 134 this.ds = data; … … 167 169 osm.visit(this); 168 170 } 169 171 } 170 drawVirtualNodes(data.searchWays(bbox)); 172 drawVirtualNodes(data.searchWays(bbox), data.getHighlightedVirtualNodes()); 173 174 // draw highlighted way segments over the already drawn ways. Otherwise each 175 // way would have to be checked if it contains a way segment to highlight when 176 // in most of the cases there won't be more than one segment. Since the wireframe 177 // renderer does not feature any transparency there should be no visual difference. 178 for(final WaySegment wseg : data.getHighlightedWaySegments()) { 179 drawSegment(nc.getPoint(wseg.getFirstNode()), nc.getPoint(wseg.getSecondNode()), highlightColor, false); 180 } 181 displaySegments(); 171 182 } 172 183 173 184 private static final int max(int a, int b, int c, int d) { … … 227 238 return (xd+yd > space); 228 239 } 229 240 230 public void drawVirtualNodes(Collection<Way> ways ) {231 232 if (virtualNodeSize != 0) {233 GeneralPath path = new GeneralPath();234 for (Way osm: ways){235 if (osm.isUsable() && !osm.isDisabledAndHidden() && !osm.isDisabled()) {236 visitVirtual(path, osm);237 }241 public void drawVirtualNodes(Collection<Way> ways, Collection<WaySegment> highlightVirtualNodes) { 242 if (virtualNodeSize == 0) 243 return; 244 // print normal virtual nodes 245 GeneralPath path = new GeneralPath(); 246 for (Way osm : ways) { 247 if (osm.isUsable() && !osm.isDisabledAndHidden() && !osm.isDisabled()) { 248 visitVirtual(path, osm); 238 249 } 239 g.setColor(nodeColor);240 g.draw(path);241 250 } 251 g.setColor(nodeColor); 252 g.draw(path); 253 // print highlighted virtual nodes. Since only the color changes, simply 254 // drawing them over the existing ones works fine (at least in their current 255 // simple style) 256 path = new GeneralPath(); 257 for (WaySegment wseg: highlightVirtualNodes){ 258 if (wseg.way.isUsable() && !wseg.way.isDisabled()) { 259 visitVirtual(path, wseg.toWay()); 260 } 261 } 262 g.setColor(highlightColor); 263 g.draw(path); 242 264 } 243 265 244 266 public void visitVirtual(GeneralPath path, Way w) { … … 308 330 309 331 private Stroke relatedWayStroke = new BasicStroke( 310 332 4, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL); 333 311 334 public void visit(Relation r) { 312 335 if (r.isIncomplete()) return; 313 336 … … 428 451 final double sy = l * (p1.y - p2.y); 429 452 430 453 path.lineTo (p2.x + (int) Math.round(cosPHI * sx - sinPHI * sy), p2.y + (int) Math.round(sinPHI * sx + cosPHI * sy)); 431 path.moveTo (p2.x + (int) Math.round(cosPHI * sx + sinPHI * sy), p2.y + (int) Math.round(- sinPHI * sx + cosPHI * sy));454 path.moveTo (p2.x + (int) Math.round(cosPHI * sx + sinPHI * sy), p2.y + (int) Math.round(-sinPHI * sx + cosPHI * sy)); 432 455 path.lineTo(p2.x, p2.y); 433 456 } 434 457 } -
src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java
4 4 import java.awt.Graphics2D; 5 5 import java.awt.RenderingHints; 6 6 import java.util.ArrayList; 7 import java.util.Collection; 7 8 import java.util.Collections; 8 9 import java.util.List; 9 10 … … 15 16 import org.openstreetmap.josm.data.osm.OsmPrimitive; 16 17 import org.openstreetmap.josm.data.osm.Relation; 17 18 import org.openstreetmap.josm.data.osm.Way; 19 import org.openstreetmap.josm.data.osm.WaySegment; 18 20 import org.openstreetmap.josm.gui.NavigatableComponent; 19 21 import org.openstreetmap.josm.gui.mappaint.AreaElemStyle; 20 22 import org.openstreetmap.josm.gui.mappaint.ElemStyle; … … 219 221 Main.pref.getBoolean("mappaint.use-antialiasing", true) ? 220 222 RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF); 221 223 222 this.painter = new MapPainter(paintSettings, g, isInactiveMode, nc, renderVirtualNodes, circum, leftHandTraffic);224 Collection<WaySegment> hws = data.getHighlightedWaySegments(); 223 225 226 this.painter = new MapPainter(paintSettings, g, isInactiveMode, nc, renderVirtualNodes, circum, leftHandTraffic, hws); 227 224 228 StyleCollector sc = new StyleCollector(drawArea, drawMultipolygon, drawRestriction); 225 229 collectNodeStyles(data, sc, bbox); 226 230 collectWayStyles(data, sc, bbox); … … 228 232 //long phase1 = System.currentTimeMillis(); 229 233 sc.drawAll(); 230 234 sc = null; 231 painter.drawVirtualNodes(data.searchWays(bbox) );235 painter.drawVirtualNodes(data.searchWays(bbox), data.getHighlightedVirtualNodes()); 232 236 233 237 //long now = System.currentTimeMillis(); 234 238 //System.err.println(String.format("PAINTING TOOK %d [PHASE1 took %d] (at scale %s)", now - start, phase1 - start, circum)); -
src/org/openstreetmap/josm/command/DeleteCommand.java
233 233 234 234 if (parents.isEmpty()) 235 235 return null; 236 if (! checkAndConfirmOutlyingDeletes(layer,parents) && !silent)236 if (!silent && !checkAndConfirmOutlyingDeletes(layer,parents)) 237 237 return null; 238 238 return new DeleteCommand(layer,parents); 239 239 } … … 387 387 } 388 388 389 389 public static Command deleteWaySegment(OsmDataLayer layer, WaySegment ws) { 390 if (ws.way.getNodesCount() < 3) 391 return delete(layer, Collections.singleton(ws.way), false); 392 390 393 if (ws.way.firstNode() == ws.way.lastNode()) { 391 394 // If the way is circular (first and last nodes are the same), 392 395 // the way shouldn't be splitted
