Ticket #7503: same_thing_for_draw_action.patch
| File same_thing_for_draw_action.patch, 16.9 KB (added by , 14 years ago) |
|---|
-
src/org/openstreetmap/josm/actions/mapmode/DrawAction.java
1 1 // License: GPL. See LICENSE file for details. 2 2 package org.openstreetmap.josm.actions.mapmode; 3 3 4 import javax.swing.JCheckBoxMenuItem;5 import javax.swing.JMenuItem;4 import static org.openstreetmap.josm.gui.help.HelpUtil.ht; 5 import static org.openstreetmap.josm.tools.I18n.marktr; 6 6 import static org.openstreetmap.josm.tools.I18n.tr; 7 7 import static org.openstreetmap.josm.tools.I18n.trn; 8 import static org.openstreetmap.josm.tools.I18n.marktr;9 import static org.openstreetmap.josm.gui.help.HelpUtil.ht;10 8 11 9 import java.awt.AWTEvent; 12 10 import java.awt.BasicStroke; 13 11 import java.awt.Color; 14 12 import java.awt.Cursor; 15 13 import java.awt.Graphics2D; 16 import java.awt.MenuItem;17 14 import java.awt.Point; 18 15 import java.awt.Stroke; 19 16 import java.awt.Toolkit; … … 37 34 import java.util.Map; 38 35 import java.util.Set; 39 36 import java.util.TreeSet; 37 40 38 import javax.swing.AbstractAction; 39 import javax.swing.JCheckBoxMenuItem; 40 import javax.swing.JMenuItem; 41 41 import javax.swing.JOptionPane; 42 42 import javax.swing.JPopupMenu; 43 43 import javax.swing.Timer; … … 65 65 import org.openstreetmap.josm.gui.layer.MapViewPaintable; 66 66 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 67 67 import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher; 68 import org.openstreetmap.josm.tools.Geometry; 68 69 import org.openstreetmap.josm.tools.ImageProvider; 69 70 import org.openstreetmap.josm.tools.Pair; 70 71 import org.openstreetmap.josm.tools.Shortcut; 71 72 import org.openstreetmap.josm.tools.Utils; 72 import org.openstreetmap.josm.tools.Geometry;73 73 74 74 /** 75 75 * Mapmode to add nodes, create and extend ways. … … 83 83 84 84 private Node mouseOnExistingNode; 85 85 private Set<Way> mouseOnExistingWays = new HashSet<Way>(); 86 // old highlights store which primitives are currently highlighted. This 87 // is true, even if target highlighting is disabled since the status bar 88 // derives its information from this list as well. 86 89 private Set<OsmPrimitive> oldHighlights = new HashSet<OsmPrimitive>(); 90 // new highlights contains a list of primitives that should be highlighted 91 // but haven’t been so far. The idea is to compare old and new and only 92 // repaint if there are changes. 93 private Set<OsmPrimitive> newHighlights = new HashSet<OsmPrimitive>(); 87 94 private boolean drawHelperLine; 88 95 private boolean wayIsFinished = false; 89 96 private boolean drawTargetHighlight; … … 131 138 */ 132 139 private void redrawIfRequired() { 133 140 updateStatusLine(); 141 // repaint required if the helper line is active. 142 boolean needsRepaint = drawHelperLine && !wayIsFinished; 143 // move newHighlights to oldHighlights; only update changed primitives 144 for(OsmPrimitive x : newHighlights) { 145 if(oldHighlights.contains(x)) { 146 continue; 147 } 148 needsRepaint = true; 149 x.setHighlighted(true); 150 } 151 oldHighlights.removeAll(newHighlights); 152 for(OsmPrimitive x : oldHighlights) { 153 x.setHighlighted(false); 154 needsRepaint = true; 155 } 156 oldHighlights = newHighlights; 157 134 158 if ((!drawHelperLine || wayIsFinished) && !drawTargetHighlight) 135 159 return; 160 136 161 // update selection to reflect which way being modified 137 162 if (currentBaseNode != null && getCurrentDataSet().getSelected().isEmpty() == false) { 138 163 Way continueFrom = getWayForNode(currentBaseNode); 139 if (alt && continueFrom != null ) {164 if (alt && continueFrom != null && (!currentBaseNode.isSelected() || continueFrom.isSelected())) { 140 165 getCurrentDataSet().beginUpdate(); // to prevent the selection listener to screw around with the state 141 166 getCurrentDataSet().addSelected(currentBaseNode); 142 167 getCurrentDataSet().clearSelection(continueFrom); 143 168 getCurrentDataSet().endUpdate(); 144 } else if (!alt && continueFrom != null) { 169 needsRepaint = true; 170 } else if (!alt && continueFrom != null && !continueFrom.isSelected()) { 145 171 getCurrentDataSet().addSelected(continueFrom); 172 needsRepaint = true; 146 173 } 147 174 } 148 Main.map.mapView.repaint(); 175 176 //System.out.println("redrawIfrequired near the end: " + needsRepaint); 177 if(needsRepaint) { 178 Main.map.mapView.repaint(); 179 } 149 180 } 150 181 151 182 @Override … … 201 232 Main.map.statusLine.getAnglePanel().removeMouseListener(snapHelper.anglePopupListener); 202 233 203 234 removeHighlighting(); 235 redrawIfRequired(); 204 236 try { 205 237 Toolkit.getDefaultToolkit().removeAWTEventListener(this); 206 238 } catch (SecurityException ex) { … … 227 259 updateKeyModifiers((InputEvent) event); 228 260 computeHelperLine(); 229 261 addHighlighting(); 230 redrawIfRequired();231 262 } 232 263 233 264 // events for crossplatform key holding processing … … 277 308 return; 278 309 computeHelperLine(); 279 310 addHighlighting(); 280 redrawIfRequired();281 311 } 282 312 283 313 private void tryAgain(MouseEvent e) { … … 706 736 707 737 computeHelperLine(); 708 738 addHighlighting(); 709 redrawIfRequired();710 739 } 711 740 712 741 /** … … 723 752 return; 724 753 } 725 754 726 double distance = -1;727 double angle = -1;728 729 755 Collection<OsmPrimitive> selection = getCurrentDataSet().getSelected(); 730 756 731 757 Node currentMouseNode = null; … … 758 784 } 759 785 760 786 determineCurrentBaseNodeAndPreviousNode(selection); 761 if (previousNode == null) snapHelper.noSnapNow(); 787 if (previousNode == null) { 788 snapHelper.noSnapNow(); 789 } 762 790 763 791 if (currentBaseNode == null || currentBaseNode == currentMouseNode) 764 792 return; // Don't create zero length way segments. 765 793 766 794 767 795 double curHdg = Math.toDegrees(currentBaseNode.getEastNorth() 768 .heading(currentMouseEastNorth));796 .heading(currentMouseEastNorth)); 769 797 double baseHdg=-1; 770 798 if (previousNode != null) { 771 799 baseHdg = Math.toDegrees(previousNode.getEastNorth() 772 .heading(currentBaseNode.getEastNorth()));800 .heading(currentBaseNode.getEastNorth())); 773 801 } 774 802 775 803 snapHelper.checkAngleSnapping(currentMouseEastNorth,baseHdg, curHdg); … … 822 850 } else if (!selectedWay.isDeleted()) { // fix #7118 823 851 if (selectedNode == selectedWay.getNode(0)){ 824 852 currentBaseNode = selectedNode; 825 if (selectedWay.getNodesCount()>1) previousNode = selectedWay.getNode(1); 853 if (selectedWay.getNodesCount()>1) { 854 previousNode = selectedWay.getNode(1); 855 } 826 856 } 827 857 if (selectedNode == selectedWay.lastNode()) { 828 858 currentBaseNode = selectedNode; 829 if (selectedWay.getNodesCount()>1) 859 if (selectedWay.getNodesCount()>1) { 830 860 previousNode = selectedWay.getNode(selectedWay.getNodesCount()-2); 861 } 831 862 } 832 863 } 833 864 } … … 966 997 EastNorth p2=ws.getSecondNode().getEastNorth(); 967 998 if (snapHelper.dir2!=null && currentBaseNode!=null) { 968 999 EastNorth xPoint = Geometry.getSegmentSegmentIntersection(p1, p2, snapHelper.dir2, currentBaseNode.getEastNorth()); 969 if (xPoint!=null) n.setEastNorth(xPoint); 1000 if (xPoint!=null) { 1001 n.setEastNorth(xPoint); 1002 } 970 1003 } 971 1004 } 972 1005 /** 973 1006 * Takes the data from computeHelperLine to determine which ways/nodes should be highlighted 974 * (if feature enabled). Also sets the target cursor if appropriate. 1007 * (if feature enabled). Also sets the target cursor if appropriate. It adds the to-be- 1008 * highlighted primitives to newHighlights but does not actually highlight them. This work is 1009 * done in redrawIfRequired. This means, calling addHighlighting() without redrawIfRequired() 1010 * will leave the data in an inconsistent state. 1011 * 1012 * The status bar derives its information from oldHighlights, so in order to update the status 1013 * bar both addHighlighting() and repaintIfRequired() are needed, since former fills newHighlights 1014 * and latter processes them into oldHighlights. 975 1015 */ 976 1016 private void addHighlighting() { 977 removeHighlighting(); 1017 newHighlights = new HashSet<OsmPrimitive>(); 1018 978 1019 // if ctrl key is held ("no join"), don't highlight anything 979 1020 if (ctrl) { 980 1021 Main.map.mapView.setNewCursor(cursor, this); 1022 redrawIfRequired(); 981 1023 return; 982 1024 } 983 1025 … … 989 1031 990 1032 if (mouseOnExistingNode != null) { 991 1033 Main.map.mapView.setNewCursor(cursorJoinNode, this); 992 // We also need this list for the statusbar help text 993 oldHighlights.add(mouseOnExistingNode); 994 if(drawTargetHighlight) { 995 mouseOnExistingNode.setHighlighted(true); 996 } 1034 newHighlights.add(mouseOnExistingNode); 1035 redrawIfRequired(); 997 1036 return; 998 1037 } 999 1038 1000 1039 // Insert the node into all the nearby way segments 1001 1040 if (mouseOnExistingWays.size() == 0) { 1002 1041 Main.map.mapView.setNewCursor(cursor, this); 1042 redrawIfRequired(); 1003 1043 return; 1004 1044 } 1005 1045 1006 1046 Main.map.mapView.setNewCursor(cursorJoinWay, this); 1007 1008 // We also need this list for the statusbar help text 1009 oldHighlights.addAll(mouseOnExistingWays); 1010 if (!drawTargetHighlight) return; 1011 for (Way w : mouseOnExistingWays) { 1012 w.setHighlighted(true); 1013 } 1047 newHighlights.addAll(mouseOnExistingWays); 1048 redrawIfRequired(); 1014 1049 } 1015 1050 1016 1051 /** 1017 * Removes target highlighting from primitives 1052 * Removes target highlighting from primitives. 1018 1053 */ 1019 1054 private void removeHighlighting() { 1020 for(OsmPrimitive prim : oldHighlights) { 1021 prim.setHighlighted(false); 1022 } 1023 oldHighlights = new HashSet<OsmPrimitive>(); 1055 newHighlights = new HashSet<OsmPrimitive>(); 1056 redrawIfRequired(); 1024 1057 } 1025 1058 1026 1059 public void paint(Graphics2D g, MapView mv, Bounds box) { 1027 1060 // sanity checks 1028 1061 if (Main.map.mapView == null || mousePos == null 1029 // don't draw line if we don't know where from or where to1030 || currentBaseNode == null || currentMouseEastNorth == null1031 // don't draw line if mouse is outside window1032 || !Main.map.mapView.getBounds().contains(mousePos))1062 // don't draw line if we don't know where from or where to 1063 || currentBaseNode == null || currentMouseEastNorth == null 1064 // don't draw line if mouse is outside window 1065 || !Main.map.mapView.getBounds().contains(mousePos)) 1033 1066 return; 1034 1067 1035 1068 Graphics2D g2 = g; 1036 1069 snapHelper.drawIfNeeded(g2,mv); 1037 1070 if (!drawHelperLine || wayIsFinished || shift) 1038 return;1071 return; 1039 1072 1040 1073 if (!snapHelper.isActive()) { // else use color and stoke from snapHelper.draw 1041 1074 g2.setColor(selectedColor); 1042 1075 g2.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 1043 } else if (!snapHelper.drawConstructionGeometry) {1076 } else if (!snapHelper.drawConstructionGeometry) 1044 1077 return; 1045 }1046 1078 GeneralPath b = new GeneralPath(); 1047 1079 Point p1=mv.getPoint(currentBaseNode); 1048 1080 Point p2=mv.getPoint(currentMouseEastNorth); … … 1168 1200 n=(Node) p; // found one node 1169 1201 wayIsFinished=false; 1170 1202 } else { 1171 // if more than 1 node were affected by previous command,1172 // we have no way to continue, so we forget about found node1203 // if more than 1 node were affected by previous command, 1204 // we have no way to continue, so we forget about found node 1173 1205 n=null; 1174 1206 break; 1175 1207 } 1176 1208 } 1177 1209 } 1178 1210 // select last added node - maybe we will continue drawing from it 1179 if (n!=null) getCurrentDataSet().addSelected(n); 1180 } 1211 if (n!=null) { 1212 getCurrentDataSet().addSelected(n); 1213 } 1214 } 1181 1215 } 1182 1216 1183 1217 private class SnapHelper { … … 1225 1259 fixed=false; absoluteFix=false; 1226 1260 1227 1261 Collection<String> angles = Main.pref.getCollection("draw.anglesnap.angles", 1228 Arrays.asList("0","30","45","60","90","120","135","150","180"));1262 Arrays.asList("0","30","45","60","90","120","135","150","180")); 1229 1263 1230 1264 snapAngles = new double[2*angles.size()]; 1231 1265 int i=0; … … 1250 1284 snapHelperColor = Main.pref.getColor(marktr("draw angle snap"), Color.ORANGE); 1251 1285 1252 1286 highlightColor = Main.pref.getColor(marktr("draw angle snap highlight"), 1253 new Color(Color.ORANGE.getRed(),Color.ORANGE.getGreen(),Color.ORANGE.getBlue(),128));1287 new Color(Color.ORANGE.getRed(),Color.ORANGE.getGreen(),Color.ORANGE.getBlue(),128)); 1254 1288 highlightStroke = new BasicStroke(10, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); 1255 1289 1256 1290 float dash1[] = { 4.0f }; 1257 1291 helperStroke = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, 1258 BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f);1292 BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f); 1259 1293 } 1260 1294 1261 1295 public void saveAngles(String ... angles) { … … 1336 1370 1337 1371 if (snapOn && (activeBaseHeading>=0)) { 1338 1372 angle = curHeading - activeBaseHeading; 1339 if (angle < 0) angle+=360; 1340 if (angle > 360) angle=0; 1373 if (angle < 0) { 1374 angle+=360; 1375 } 1376 if (angle > 360) { 1377 angle=0; 1378 } 1341 1379 1342 1380 double nearestAngle; 1343 1381 if (fixed) { … … 1380 1418 1381 1419 if (baseHeading >=0 ) { // there is previous line segment with some heading 1382 1420 angle = hdg - baseHeading; 1383 if (angle < 0) angle+=360; 1384 if (angle > 360) angle=0; 1421 if (angle < 0) { 1422 angle+=360; 1423 } 1424 if (angle > 360) { 1425 angle=0; 1426 } 1385 1427 } 1386 1428 showStatusInfo(angle, hdg, distance); 1387 1429 } … … 1456 1498 1457 1499 double hdg = segmentPoint1.heading(segmentPoint2); 1458 1500 hdg=Math.toDegrees(hdg); 1459 if (hdg<0) hdg+=360; 1460 if (hdg>360) hdg-=360; 1501 if (hdg<0) { 1502 hdg+=360; 1503 } 1504 if (hdg>360) { 1505 hdg-=360; 1506 } 1461 1507 //fixed=true; 1462 1508 //absoluteFix=true; 1463 1509 customBaseHeading=hdg; … … 1466 1512 private void nextSnapMode() { 1467 1513 if (snapOn) { 1468 1514 // turn off snapping if we are in fixed mode or no actile snapping line exist 1469 if (fixed || !active) { snapOn=false; unsetFixedMode(); } 1470 else setFixedMode(); 1515 if (fixed || !active) { snapOn=false; unsetFixedMode(); } else { 1516 setFixedMode(); 1517 } 1471 1518 } else { 1472 1519 snapOn=true; 1473 1520 unsetFixedMode(); … … 1521 1568 bestAngle=snapAngles[i]; 1522 1569 } 1523 1570 } 1524 if (Math.abs(bestAngle-360) < 1e-3) 1571 if (Math.abs(bestAngle-360) < 1e-3) { 1525 1572 bestAngle=0; 1573 } 1526 1574 return bestAngle; 1527 1575 } 1528 1576 … … 1535 1583 } 1536 1584 1537 1585 private void unFixOrTurnOff() { 1538 if (absoluteFix) 1586 if (absoluteFix) { 1539 1587 unsetFixedMode(); 1540 else1588 } else { 1541 1589 toggleSnapping(); 1590 } 1542 1591 } 1543 1592 1544 1593 MouseListener anglePopupListener = new PopupMenuLauncher( new JPopupMenu() { … … 1609 1658 private class SnapChangeAction extends JosmAction { 1610 1659 public SnapChangeAction() { 1611 1660 super(tr("Angle snapping"), "anglesnap", 1612 tr("Switch angle snapping mode while drawing"), null, false);1661 tr("Switch angle snapping mode while drawing"), null, false); 1613 1662 putValue("help", ht("/Action/Draw/AngleSnap")); 1614 1663 } 1615 1664 1616 1665 @Override 1617 1666 public void actionPerformed(ActionEvent e) { 1618 if (snapHelper!=null) snapHelper.toggleSnapping(); 1667 if (snapHelper!=null) { 1668 snapHelper.toggleSnapping(); 1669 } 1619 1670 } 1620 1671 } 1621 1672 }
