Changeset 1438 in josm for trunk/src/org/openstreetmap/josm/actions/mapmode
- Timestamp:
- 2009-02-24T17:58:50+01:00 (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java
r1430 r1438 132 132 */ 133 133 private void addHighlighting() { 134 removeHighlighting(); 134 135 // if ctrl key is held ("no join"), don't highlight anything 135 136 if (ctrl) { 136 removeHighlighting();137 137 resetCursor(); 138 138 return; 139 139 } 140 141 // This happens when nothing is selected 142 if(mouseOnExistingNode == null && Main.ds.getSelected().size() == 0 && mousePos != null) 143 mouseOnExistingNode = Main.map.mapView.getNearestNode(mousePos); 140 144 141 145 if (mouseOnExistingNode != null) { 142 146 setJoinCursor(false); 143 // Clean old highlights 144 removeHighlighting(); 145 if(drawTargetHighlight) { 146 oldHighlights.add(mouseOnExistingNode); 147 // We also need this list for the statusbar help text 148 oldHighlights.add(mouseOnExistingNode); 149 if(drawTargetHighlight) 147 150 mouseOnExistingNode.highlighted = true; 148 }149 151 return; 150 152 } … … 152 154 // Insert the node into all the nearby way segments 153 155 if(mouseOnExistingWays.size() == 0) { 154 removeHighlighting();155 156 resetCursor(); 156 157 return; … … 158 159 159 160 setJoinCursor(true); 160 // Clean old highlights 161 removeHighlighting();162 161 162 // We also need this list for the statusbar help text 163 oldHighlights.addAll(mouseOnExistingWays); 163 164 if(!drawTargetHighlight) return; 164 oldHighlights.addAll(mouseOnExistingWays);165 165 for(Way w : mouseOnExistingWays) { 166 166 w.highlighted = true; … … 175 175 prim.highlighted = false; 176 176 } 177 oldHighlights = new HashSet<OsmPrimitive>(); 177 178 } 178 179 … … 215 216 */ 216 217 public void eventDispatched(AWTEvent event) { 217 if(Main.map == null ||Main.map.mapView == null || !Main.map.mapView.isDrawableLayer()) 218 return; 219 InputEvent e = (InputEvent) event; 220 ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0; 221 alt = (e.getModifiers() & ActionEvent.ALT_MASK) != 0; 222 shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0; 218 if(Main.map == null || Main.map.mapView == null || !Main.map.mapView.isDrawableLayer()) 219 return; 220 updateKeyModifiers((InputEvent) event); 221 addHighlighting(); 223 222 computeHelperLine(); 224 223 } … … 235 234 Main.ds.setSelected(); 236 235 mouseClicked(e); 236 } 237 238 /** 239 * This function should be called when the user wishes to finish his current draw action. 240 * If Potlatch Style is enabled, it will switch to select tool, otherwise simply disable 241 * the helper line until the user chooses to draw something else. 242 */ 243 private void finishDrawing() { 244 lastUsedNode = null; 245 wayIsFinished = true; 246 Main.map.selectSelectTool(true); 247 248 // Redraw to remove the helper line stub 249 removeHighlighting(); 250 computeHelperLine(); 251 Main.map.mapView.repaint(); 237 252 } 238 253 … … 248 263 if(!Main.map.mapView.isDrawableLayer()) 249 264 return; 250 265 251 266 if(e.getClickCount() > 1 && mousePos != null && mousePos.equals(oldMousePos)) { 252 267 // A double click equals "user clicked last node again, finish way" 253 268 // Change draw tool only if mouse position is nearly the same, as 254 269 // otherwise fast clicks will count as a double click 255 lastUsedNode = null; 256 wayIsFinished = true; 257 258 Main.map.selectSelectTool(true); 270 finishDrawing(); 259 271 return; 260 272 } 261 273 oldMousePos = mousePos; 262 274 263 275 // we copy ctrl/alt/shift from the event just in case our global 264 276 // AWTEvent didn't make it through the security manager. Unclear 265 277 // if that can ever happen but better be safe. 266 ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0; 267 alt = (e.getModifiers() & ActionEvent.ALT_MASK) != 0; 268 shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0; 278 updateKeyModifiers(e); 269 279 mousePos = e.getPoint(); 270 280 … … 277 287 Node n = null; 278 288 279 if (!ctrl )289 if (!ctrl && !shift) 280 290 n = Main.map.mapView.getNearestNode(mousePos); 281 291 282 292 if (n != null) { 283 293 // user clicked on node 284 if (s hift || selection.isEmpty()) {294 if (selection.isEmpty()) { 285 295 // select the clicked node and do nothing else 286 296 // (this is just a convenience option so that people don't … … 330 340 for (int i : is) wnew.addNode(i + 1, n); 331 341 342 // If ALT is pressed, a new way should be created and that new way should get 343 // selected. This works everytime unless the ways the nodes get inserted into 344 // are already selected. This is the case when creating a self-overlapping way 345 // but pressing ALT prevents this. Therefore we must de-select the way manually 346 // here so /only/ the new way will be selected after this method finishes. 347 if(alt) wnew.selected = false; 348 332 349 cmds.add(new ChangeCommand(insertPoint.getKey(), wnew)); 333 350 replacedWays.add(insertPoint.getKey()); … … 351 368 boolean wayIsFinishedTemp = wayIsFinished; 352 369 wayIsFinished = false; 353 if ( !shift &&selection.size() > 0 && !wayIsFinishedTemp) {370 if (selection.size() > 0 && !wayIsFinishedTemp) { 354 371 Node selectedNode = null; 355 372 Way selectedWay = null; … … 373 390 } 374 391 375 // No nodes or ways have been selected, try again with no selection 376 // This occurs when a relation has been selected 377 if(selectedNode == null && selectedWay == null) { 392 // the node from which we make a connection 393 Node n0 = findNodeToContinueFrom(selectedNode, selectedWay); 394 // We have a selection but it isn't suitable. Try again. 395 if(n0 == null) { 378 396 tryAgain(e); 379 397 return; 380 398 } 381 399 382 // the node from which we make a connection 383 Node n0 = null; 384 385 if (selectedNode == null) { 386 if (selectedWay.isFirstLastNode(lastUsedNode)) { 387 n0 = lastUsedNode; 388 } else { 389 // We have a way selected, but no suitable node to continue from. Start anew. 390 tryAgain(e); 391 return; 392 } 393 } else if (selectedWay == null) { 394 n0 = selectedNode; 395 } else { 396 if (selectedWay.isFirstLastNode(selectedNode)) { 397 n0 = selectedNode; 398 } else { 399 // We have a way and node selected, but it's not at the start/end of the way. Start anew. 400 tryAgain(e); 401 return; 402 } 403 } 404 405 // Prevent creation of ways that look like this: <----> 406 // This happens if users want to draw a no-exit-sideway from the main way like this: 407 // ^ 408 // |<----> 409 // | 410 // The solution isn't ideal because the main way will end in the side way, which is bad for 411 // navigation software ("drive straight on") but at least easier to fix. Maybe users will fix 412 // it on their own, too. At least it's better than producing an error. 413 if(selectedWay != null && selectedWay.nodes != null) { 414 int posn0 = selectedWay.nodes.indexOf(n0); 415 if( posn0 != -1 && // n0 is part of way 416 (posn0 >= 1 && n.equals(selectedWay.nodes.get(posn0-1))) || // previous node 417 (posn0 < selectedWay.nodes.size()-1) && n.equals(selectedWay.nodes.get(posn0+1))) { // next node 418 Main.ds.setSelected(n); 419 lastUsedNode = n; 420 return; 421 } 422 } 400 if(isSelfContainedWay(selectedWay, n0, n)) 401 return; 423 402 424 403 // User clicked last node again, finish way 425 404 if(n0 == n) { 426 lastUsedNode = null; 427 wayIsFinished = true; 428 Main.map.selectSelectTool(true); 405 finishDrawing(); 429 406 return; 430 407 } … … 460 437 // Connected to a node that's already in the way 461 438 if(way.nodes.contains(n)) { 462 //System.out.println("Stop drawing, node is part of current way");463 439 wayIsFinished = true; 464 440 selection.clear(); … … 498 474 Main.main.undoRedo.add(c); 499 475 if(!wayIsFinished) lastUsedNode = n; 476 500 477 computeHelperLine(); 501 478 removeHighlighting(); … … 503 480 } 504 481 482 /** 483 * Prevent creation of ways that look like this: <----> 484 * This happens if users want to draw a no-exit-sideway from the main way like this: 485 * ^ 486 * |<----> 487 * | 488 * The solution isn't ideal because the main way will end in the side way, which is bad for 489 * navigation software ("drive straight on") but at least easier to fix. Maybe users will fix 490 * it on their own, too. At least it's better than producing an error. 491 * 492 * @param Way the way to check 493 * @param Node the current node (i.e. the one the connection will be made from) 494 * @param Node the target node (i.e. the one the connection will be made to) 495 * @return Boolean True if this would create a selfcontaining way, false otherwise. 496 */ 497 private boolean isSelfContainedWay(Way selectedWay, Node currentNode, Node targetNode) { 498 if(selectedWay != null && selectedWay.nodes != null) { 499 int posn0 = selectedWay.nodes.indexOf(currentNode); 500 if( posn0 != -1 && // n0 is part of way 501 (posn0 >= 1 && targetNode.equals(selectedWay.nodes.get(posn0-1))) || // previous node 502 (posn0 < selectedWay.nodes.size()-1) && targetNode.equals(selectedWay.nodes.get(posn0+1))) { // next node 503 Main.ds.setSelected(targetNode); 504 lastUsedNode = targetNode; 505 return true; 506 } 507 } 508 509 return false; 510 } 511 512 /** 513 * Finds a node to continue drawing from. Decision is based upon given node and way. 514 * @param selectedNode Currently selected node, may be null 515 * @param selectedWay Currently selected way, may be null 516 * @return Node if a suitable node is found, null otherwise 517 */ 518 private Node findNodeToContinueFrom(Node selectedNode, Way selectedWay) { 519 // No nodes or ways have been selected, this occurs when a relation 520 // has been selected or the selection is empty 521 if(selectedNode == null && selectedWay == null) 522 return null; 523 524 if (selectedNode == null) { 525 if (selectedWay.isFirstLastNode(lastUsedNode)) 526 return lastUsedNode; 527 528 // We have a way selected, but no suitable node to continue from. Start anew. 529 return null; 530 } 531 532 if (selectedWay == null) 533 return selectedNode; 534 535 if (selectedWay.isFirstLastNode(selectedNode)) 536 return selectedNode; 537 538 // We have a way and node selected, but it's not at the start/end of the way. Start anew. 539 return null; 540 } 541 505 542 @Override public void mouseMoved(MouseEvent e) { 506 543 if(!Main.map.mapView.isDrawableLayer()) … … 510 547 // AWTEvent didn't make it through the security manager. Unclear 511 548 // if that can ever happen but better be safe. 512 549 updateKeyModifiers(e); 550 mousePos = e.getPoint(); 551 552 addHighlighting(); 553 computeHelperLine(); 554 } 555 556 private void updateKeyModifiers(InputEvent e) { 513 557 ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0; 514 558 alt = (e.getModifiers() & ActionEvent.ALT_MASK) != 0; 515 559 shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0; 516 mousePos = e.getPoint(); 517 518 addHighlighting(); 519 computeHelperLine(); 560 } 561 562 private void updateKeyModifiers(MouseEvent e) { 563 ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0; 564 alt = (e.getModifiers() & ActionEvent.ALT_MASK) != 0; 565 shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0; 520 566 } 521 567 … … 532 578 return; 533 579 } 534 580 535 581 double distance = -1; 536 582 double angle = -1; … … 548 594 Main.map.statusLine.setDist(-1); 549 595 550 if (!ctrl && mousePos != null) {596 if (!ctrl && !shift && mousePos != null) { 551 597 currentMouseNode = Main.map.mapView.getNearestNode(mousePos); 552 598 } … … 586 632 if (selectedNode == null) { 587 633 if (selectedWay == null) return; 588 if ( lastUsedNode == selectedWay.nodes.get(0) || lastUsedNode == selectedWay.nodes.get(selectedWay.nodes.size()-1)) {634 if (selectedWay.isFirstLastNode(lastUsedNode)) { 589 635 currentBaseNode = lastUsedNode; 590 636 if (lastUsedNode == selectedWay.nodes.get(selectedWay.nodes.size()-1) && selectedWay.nodes.size() > 1) { … … 601 647 602 648 if (currentBaseNode == null || currentBaseNode == currentMouseNode) { 649 updateStatusLine(); 603 650 return; // Don't create zero length way segments. 604 651 } … … 617 664 updateStatusLine(); 618 665 619 if ( (!drawHelperLine || wayIsFinished) && !drawTargetHighlight) return;666 if (!drawHelperLine || wayIsFinished) return; 620 667 Main.map.mapView.repaint(); 621 668 } … … 739 786 740 787 // helper for adjustNode 741 static double det(double a, double b, double c, double d) 742 { 788 static double det(double a, double b, double c, double d) { 743 789 return a * d - b * c; 744 790 } … … 750 796 if (Main.map.mapView == null) return; 751 797 if (mousePos == null) return; 752 753 // if shift key is held ("no auto-connect"), don't draw a line754 if (shift) return;755 798 756 799 // don't draw line if we don't know where from or where to … … 782 825 783 826 @Override public String getModeHelpText() { 784 String rv; 785 786 if (currentBaseNode != null && !shift) { 787 if (mouseOnExistingNode != null) { 788 if (alt && /* FIXME: way exists */true) 789 rv = tr("Click to create a new way to the existing node."); 827 String rv = ""; 828 /* 829 * No modifiers: all (Connect, Node Re-Use, Auto-Weld) 830 * CTRL: disables node re-use, auto-weld 831 * Shift: disables node re-use 832 * ALT: disables connect 833 */ 834 835 /* 836 * Status line text generation is split into two parts to keep it maintainable. 837 * First part looks at what will happen to the new node inserted on click and 838 * the second part will look if a connection is made or not. 839 * 840 * Note that this help text is not absolutely accurate as it doesn't catch any special 841 * cases (e.g. when preventing <---> ways). The only special that it catches is when 842 * a way is about to be finished. 843 * 844 * First check what happens to the new node. 845 */ 846 847 // oldHighlights stores the current highlights. If this 848 // list is empty we can assume that we won't do any joins 849 if(ctrl || oldHighlights.isEmpty()) 850 rv = tr("Create new node."); 851 else if(shift) { 852 // We already know oldHighlights is not empty, but shift is pressed. 853 // We can assume the new node will be joined into an existing way 854 rv = tr("Insert new node into {0} way(s).", oldHighlights.size()); 855 } else { 856 // oldHighlights may store a node or way, check if it's a node 857 for(OsmPrimitive x : oldHighlights) { 858 if(x instanceof Node) 859 rv = tr("Select node under cursor."); 790 860 else 791 rv =tr("Click to make a connection to the existing node."); 792 } else { 793 if (alt && /* FIXME: way exists */true) 794 rv = tr("Click to insert a node and create a new way."); 795 else 796 rv = tr("Click to insert a new node and make a connection."); 797 } 798 } 799 else { 800 rv = tr("Click to insert a new node."); 801 } 802 803 //rv.append(tr("Click to add a new node. Ctrl: no node re-use/auto-insert. Shift: no auto-connect. Alt: new way")); 804 //rv.append(tr("Click to add a new node. Ctrl: no node re-use/auto-insert. Shift: no auto-connect. Alt: new way")); 805 return rv.toString(); 861 rv = tr("Insert new node into {0} way(s).", oldHighlights.size()); 862 break; 863 } 864 } 865 866 /* 867 * Check whether a connection will be made 868 */ 869 if (currentBaseNode != null) { 870 if(alt) 871 rv += " " + tr("Start new way from last node."); 872 else 873 rv += " " + tr("Continue way from last node."); 874 } 875 876 /* 877 * Handle special case: Highlighted node == selected node => finish drawing 878 */ 879 Node n = mouseOnExistingNode; 880 if(n != null && Main.ds.getSelectedNodes().contains(n)) { 881 rv = tr("Finish drawing."); 882 } 883 884 /* 885 * Handle special case: Self-Overlapping or closing way 886 */ 887 if(Main.ds.getSelectedWays().size() > 0 && !wayIsFinished && !alt) { 888 Way w = (Way) Main.ds.getSelectedWays().iterator().next(); 889 for(Node m : w.nodes) { 890 if(m.equals(mouseOnExistingNode) || mouseOnExistingWays.contains(w)) { 891 rv += " " + tr("Finish drawing."); 892 break; 893 } 894 } 895 } 896 897 return rv; 806 898 } 807 899
Note:
See TracChangeset
for help on using the changeset viewer.