Ticket #6694: snapbutton.patch
| File snapbutton.patch, 11.6 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; 4 5 import static org.openstreetmap.josm.tools.I18n.tr; 5 6 import static org.openstreetmap.josm.tools.I18n.trn; 6 7 import static org.openstreetmap.josm.tools.I18n.marktr; 8 import static org.openstreetmap.josm.gui.help.HelpUtil.ht; 7 9 8 10 import java.awt.AWTEvent; 9 11 import java.awt.BasicStroke; … … 36 38 37 39 import javax.swing.SwingUtilities; 38 40 import org.openstreetmap.josm.Main; 41 import org.openstreetmap.josm.actions.JosmAction; 39 42 import org.openstreetmap.josm.command.AddCommand; 40 43 import org.openstreetmap.josm.command.ChangeCommand; 41 44 import org.openstreetmap.josm.command.Command; … … 50 53 import org.openstreetmap.josm.data.osm.Way; 51 54 import org.openstreetmap.josm.data.osm.WaySegment; 52 55 import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors; 56 import org.openstreetmap.josm.gui.MainMenu; 53 57 import org.openstreetmap.josm.gui.MapFrame; 54 58 import org.openstreetmap.josm.gui.MapView; 55 59 import org.openstreetmap.josm.gui.layer.Layer; … … 89 93 private Shortcut extraShortcut; 90 94 private Shortcut backspaceShortcut; 91 95 92 boolean snapOn; 96 private JCheckBoxMenuItem snapCheckboxMenuItem; 97 93 98 94 99 public DrawAction(MapFrame mapFrame) { 95 100 super(tr("Draw"), "node/autonode", tr("Draw nodes"), … … 99 104 // Add extra shortcut N 100 105 extraShortcut = Shortcut.registerShortcut("mapmode:drawfocus", tr("Mode: Draw Focus"), KeyEvent.VK_N, Shortcut.GROUP_EDIT); 101 106 Main.registerActionShortcut(this, extraShortcut); 102 107 108 snapCheckboxMenuItem = MainMenu.addWithCheckbox(Main.main.menu.editMenu, new SnapChangeAction(), MainMenu.WINDOW_MENU_GROUP.VOLATILE); 109 snapHelper.setMenuCheckBox(snapCheckboxMenuItem); 103 110 cursorJoinNode = ImageProvider.getCursor("crosshair", "joinnode"); 104 111 cursorJoinWay = ImageProvider.getCursor("crosshair", "joinway"); 105 112 } … … 134 141 drawTargetHighlight = Main.pref.getBoolean("draw.target-highlight", true); 135 142 wayIsFinished = false; 136 143 snapHelper.init(); 144 snapCheckboxMenuItem.getAction().setEnabled(true); 137 145 138 146 backspaceShortcut = Shortcut.registerShortcut("mapmode:backspace", tr("Backspace in Add mode"), KeyEvent.VK_BACK_SPACE, Shortcut.GROUP_EDIT); 139 147 Main.registerActionShortcut(new BackSpaceAction(), backspaceShortcut); … … 159 167 DataSet.removeSelectionListener(this); 160 168 Main.unregisterActionShortcut(backspaceShortcut); 161 169 snapHelper.unsetFixedMode(); 162 170 snapCheckboxMenuItem.getAction().setEnabled(false); 171 163 172 removeHighlighting(); 164 173 try { 165 174 Toolkit.getDefaultToolkit().removeAWTEventListener(this); … … 264 273 // request focus in order to enable the expected keyboard shortcuts 265 274 // 266 275 Main.map.mapView.requestFocus(); 267 276 268 277 if(e.getClickCount() > 1 && mousePos != null && mousePos.equals(oldMousePos)) { 269 278 // A double click equals "user clicked last node again, finish way" 270 279 // Change draw tool only if mouse position is nearly the same, as … … 324 333 } 325 334 } else { // n==null, no node found in clicked area 326 335 EastNorth mouseEN = Main.map.mapView.getEastNorth(e.getX(), e.getY()); 327 newEN = snap On? snapHelper.getSnapPoint(mouseEN) : mouseEN;336 newEN = snapHelper.isSnapOn() ? snapHelper.getSnapPoint(mouseEN) : mouseEN; 328 337 n = new Node(newEN); //create node at clicked point 329 338 newNode = true; 330 339 } … … 698 707 angle += angle < 0 ? 360 : 0; 699 708 } 700 709 701 if (snapOn)snapHelper.checkAngleSnapping(currentMouseEastNorth,angle);710 snapHelper.checkAngleSnapping(currentMouseEastNorth,angle); 702 711 703 712 Main.map.statusLine.setAngle(angle); 704 713 Main.map.statusLine.setHeading(hdg); … … 948 957 if (!Main.map.mapView.getBounds().contains(mousePos)) return; 949 958 950 959 Graphics2D g2 = g; 951 if (snapOn) snapHelper.draw(g2,mv);960 snapHelper.drawIfNeeded(g2,mv); 952 961 if (!drawHelperLine || wayIsFinished || shift) return; 953 962 954 963 if (!snapHelper.isActive()) { // else use color and stoke from snapHelper.draw 955 964 g2.setColor(selectedColor); 956 965 g2.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 966 } else { 967 if (!snapHelper.drawConstructionGeometry) return; 957 968 } 958 969 GeneralPath b = new GeneralPath(); 959 970 Point p1=mv.getPoint(currentBaseNode); … … 1018 1029 } else { 1019 1030 rv += " " + tr("Continue way from last node."); 1020 1031 } 1021 if (snap On) {1032 if (snapHelper.isSnapOn()) { 1022 1033 rv += " "+ tr("Angle snapping ON."); 1023 1034 } 1024 1035 } … … 1092 1103 } 1093 1104 1094 1105 private class SnapHelper { 1106 boolean snapOn; // snapping is turned on 1107 1095 1108 private boolean active; // snapping is activa for current mouse position 1096 1109 private boolean fixed; // snap angle is fixed 1097 1110 private boolean absoluteFix; // snap angle is absolute 1111 1112 private boolean drawConstructionGeometry; 1113 private boolean showProjectedPoint; 1114 private boolean showAngle; 1115 1098 1116 EastNorth dir2; 1099 1117 EastNorth projected; 1100 1118 String labelText; … … 1110 1128 Color snapHelperColor; 1111 1129 private Stroke normalStroke; 1112 1130 private Stroke helperStroke; 1113 1131 1132 JCheckBoxMenuItem checkBox; 1133 1114 1134 private void init() { 1115 1135 snapOn=false; 1136 checkBox.setState(snapOn); 1116 1137 fixed=false; absoluteFix=false; 1117 1138 1118 1139 Collection<String> angles = Main.pref.getCollection("draw.anglesnap.angles", 1119 1140 Arrays.asList("0","30","45","60","90","120","135","150","210","225","240","270","300","315","330")); 1120 1141 … … 1130 1151 i++; 1131 1152 } 1132 1153 snapAngleTolerance = Main.pref.getDouble("draw.anglesnap.tolerance", 5.0); 1154 drawConstructionGeometry = Main.pref.getBoolean("draw.anglesnap.drawConstructionGeometry", true); 1155 showProjectedPoint = Main.pref.getBoolean("draw.anglesnap.drawProjectedPoint", true); 1156 showAngle = Main.pref.getBoolean("draw.anglesnap.showAngle", true); 1133 1157 1134 1158 normalStroke = new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); 1135 1159 snapHelperColor = Main.pref.getColor(marktr("draw angle snap"), Color.ORANGE); … … 1146 1170 labelText=null; 1147 1171 } 1148 1172 1149 private void draw(Graphics2D g2, MapView mv) { 1173 private void drawIfNeeded(Graphics2D g2, MapView mv) { 1174 if (!snapOn) return; 1150 1175 if (!active) return; 1151 1176 Point p1=mv.getPoint(currentBaseNode); 1152 1177 Point p2=mv.getPoint(dir2); 1153 1178 Point p3=mv.getPoint(projected); 1154 1179 GeneralPath b; 1155 1156 g2.setColor(snapHelperColor); 1157 g2.setStroke(helperStroke); 1158 1159 b = new GeneralPath(); 1160 if (absoluteFix) { 1161 b.moveTo(p2.x,p2.y); 1162 b.lineTo(2*p1.x-p2.x,2*p1.y-p2.y); // bi-directional line 1163 } else { 1164 b.moveTo(p2.x,p2.y); 1165 b.lineTo(p3.x,p3.y); 1166 } 1167 g2.draw(b); 1180 if (drawConstructionGeometry) { 1181 g2.setColor(snapHelperColor); 1182 g2.setStroke(helperStroke); 1168 1183 1184 b = new GeneralPath(); 1185 if (absoluteFix) { 1186 b.moveTo(p2.x,p2.y); 1187 b.lineTo(2*p1.x-p2.x,2*p1.y-p2.y); // bi-directional line 1188 } else { 1189 b.moveTo(p2.x,p2.y); 1190 b.lineTo(p3.x,p3.y); 1191 } 1192 g2.draw(b); 1193 } 1194 1169 1195 g2.setColor(selectedColor); 1170 1196 g2.setStroke(normalStroke); 1171 1197 b = new GeneralPath(); … … 1174 1200 g2.draw(b); 1175 1201 1176 1202 g2.drawString(labelText, p3.x-5, p3.y+20); 1177 g2.setStroke(normalStroke); 1178 g2.drawOval(p3.x-5, p3.y-5, 10, 10); // projected point 1203 if (showProjectedPoint) { 1204 g2.setStroke(normalStroke); 1205 g2.drawOval(p3.x-5, p3.y-5, 10, 10); // projected point 1206 } 1179 1207 1180 1208 g2.setColor(snapHelperColor); 1181 1209 g2.setStroke(helperStroke); … … 1190 1218 /* If mouse position is close to line at 15-30-45-... angle, remembers this direction 1191 1219 */ 1192 1220 private void checkAngleSnapping(EastNorth currentEN, double angle) { 1221 if (!snapOn) return; 1193 1222 if (!absoluteFix && previousNode==null) return; 1194 1223 1195 1224 double nearestAngle; … … 1207 1236 1208 1237 EastNorth p0 = currentBaseNode.getEastNorth(); 1209 1238 e0=p0.east(); n0=p0.north(); 1210 1211 if (fixed) {1212 if (absoluteFix) labelText = "=";1213 else labelText = String.format(fixFmt, (int) nearestAngle);1214 } else labelText = String.format("%d", (int) nearestAngle);1215 1239 1240 if (showAngle) { 1241 if (fixed) { 1242 if (absoluteFix) labelText = "="; 1243 else labelText = String.format(fixFmt, (int) nearestAngle); 1244 } else labelText = String.format("%d", (int) nearestAngle); 1245 } else { 1246 if (fixed) { 1247 if (absoluteFix) labelText = "="; 1248 else labelText = String.format(tr("FIX"),0); 1249 } else labelText=""; 1250 } 1251 1216 1252 if (absoluteFix) { 1217 1253 de=0; dn=1; 1218 1254 } else { … … 1260 1296 snapOn=true; 1261 1297 unsetFixedMode(); 1262 1298 } 1299 checkBox.setState(snapOn); 1263 1300 } 1264 1301 1302 private void toggleSnapping() { 1303 snapOn = !snapOn; 1304 checkBox.setState(snapOn); 1305 unsetFixedMode(); 1306 } 1307 1265 1308 private boolean isActive() { 1266 1309 return active; 1267 1310 } … … 1289 1332 absoluteFix=true; 1290 1333 lastAngle=hdg; 1291 1334 } 1335 1336 private void setMenuCheckBox(JCheckBoxMenuItem checkBox) { 1337 this.checkBox = checkBox; 1338 } 1339 1340 private boolean isSnapOn() { 1341 return snapOn; 1342 } 1292 1343 } 1344 1345 private class SnapChangeAction extends JosmAction { 1346 public SnapChangeAction() { 1347 super(tr("Angle snapping"), "anglesnap", 1348 tr("Switches angle snapping mode while drawing"), 1349 Shortcut.registerShortcut("draw:anglesnap", tr("Draw: {0}",tr("Angle snapping")), 1350 KeyEvent.VK_H, Shortcut.GROUP_EDIT), false); 1351 putValue("help", ht("/Action/Draw/AngleSnap")); 1352 } 1353 @Override 1354 public void actionPerformed(ActionEvent e) { 1355 if (snapHelper!=null) snapHelper.toggleSnapping(); 1356 } 1357 1358 } 1293 1359 }
