Changeset 4782 in josm for trunk/src/org/openstreetmap
- Timestamp:
- 2012-01-10T19:46:35+01:00 (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java
r4776 r4782 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; … … 16 18 import java.awt.event.AWTEventListener; 17 19 import java.awt.event.ActionEvent; 20 import java.awt.event.ActionListener; 18 21 import java.awt.event.InputEvent; 19 22 import java.awt.event.KeyEvent; … … 32 35 import java.util.Set; 33 36 37 import java.util.TreeSet; 34 38 import javax.swing.AbstractAction; 35 39 import javax.swing.JOptionPane; 36 40 37 41 import javax.swing.SwingUtilities; 42 import javax.swing.Timer; 38 43 import org.openstreetmap.josm.Main; 44 import org.openstreetmap.josm.actions.JosmAction; 39 45 import org.openstreetmap.josm.command.AddCommand; 40 46 import org.openstreetmap.josm.command.ChangeCommand; … … 51 57 import org.openstreetmap.josm.data.osm.WaySegment; 52 58 import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors; 59 import org.openstreetmap.josm.gui.MainMenu; 53 60 import org.openstreetmap.josm.gui.MapFrame; 54 61 import org.openstreetmap.josm.gui.MapView; … … 90 97 private Shortcut backspaceShortcut; 91 98 92 boolean snapOn; 99 private JCheckBoxMenuItem snapCheckboxMenuItem; 100 93 101 94 102 public DrawAction(MapFrame mapFrame) { … … 100 108 extraShortcut = Shortcut.registerShortcut("mapmode:drawfocus", tr("Mode: Draw Focus"), KeyEvent.VK_N, Shortcut.GROUP_EDIT); 101 109 Main.registerActionShortcut(this, extraShortcut); 102 110 111 snapCheckboxMenuItem = MainMenu.addWithCheckbox(Main.main.menu.editMenu, new SnapChangeAction(), MainMenu.WINDOW_MENU_GROUP.VOLATILE); 112 snapHelper.setMenuCheckBox(snapCheckboxMenuItem); 103 113 cursorJoinNode = ImageProvider.getCursor("crosshair", "joinnode"); 104 114 cursorJoinWay = ImageProvider.getCursor("crosshair", "joinway"); … … 135 145 wayIsFinished = false; 136 146 snapHelper.init(); 147 snapCheckboxMenuItem.getAction().setEnabled(true); 148 149 timer = new Timer(0, new ActionListener() { 150 @Override 151 public void actionPerformed(ActionEvent ae) { 152 timer.stop(); 153 if (set.remove(releaseEvent.getKeyCode())) { 154 doKeyReleaseEvent(releaseEvent); 155 } 156 } 157 158 }); 137 159 138 160 backspaceShortcut = Shortcut.registerShortcut("mapmode:backspace", tr("Backspace in Add mode"), KeyEvent.VK_BACK_SPACE, Shortcut.GROUP_EDIT); … … 160 182 Main.unregisterActionShortcut(backspaceShortcut); 161 183 snapHelper.unsetFixedMode(); 162 184 snapCheckboxMenuItem.getAction().setEnabled(false); 185 163 186 removeHighlighting(); 164 187 try { … … 183 206 return; 184 207 if (event instanceof KeyEvent) { 185 KeyEvent ke = (KeyEvent) event; 186 if (ke.getKeyCode() == KeyEvent.VK_TAB && 187 ke.getID()==KeyEvent.KEY_PRESSED) { 188 snapHelper.nextSnapMode(); 189 } 208 processKeyEvent((KeyEvent) event); 190 209 } // toggle angle snapping 191 210 updateKeyModifiers((InputEvent) event); … … 194 213 redrawIfRequired(); 195 214 } 215 216 217 // events for crossplatform key holding processing 218 // thanks to http://www.arco.in-berlin.de/keyevent.html 219 private final TreeSet<Integer> set = new TreeSet<Integer>(); 220 private KeyEvent releaseEvent; 221 private Timer timer; 222 void processKeyEvent(KeyEvent e) { 223 if (e.getKeyCode() != KeyEvent.VK_TAB) return; 224 e.consume(); 225 226 if (e.getID() == KeyEvent.KEY_PRESSED) { 227 if (timer.isRunning()) { 228 timer.stop(); 229 } else { 230 if (set.add((e.getKeyCode()))) doKeyPressEvent(e); 231 } 232 233 } 234 if (e.getID() == KeyEvent.KEY_RELEASED) { 235 if (timer.isRunning()) { 236 timer.stop(); 237 if (set.remove(e.getKeyCode())) { 238 doKeyReleaseEvent(e); 239 } 240 } else { 241 releaseEvent = e; 242 timer.restart(); 243 } 244 } 245 246 } 247 248 private void doKeyPressEvent(KeyEvent e) { 249 if (e.getKeyCode() != KeyEvent.VK_TAB) return; 250 snapHelper.setFixedMode(); 251 computeHelperLine(); redrawIfRequired(); 252 } 253 private void doKeyReleaseEvent(KeyEvent e) { 254 if (e.getKeyCode() != KeyEvent.VK_TAB) return; 255 snapHelper.unFixOrTurnOff(); 256 computeHelperLine(); redrawIfRequired(); 257 } 258 196 259 /** 197 260 * redraw to (possibly) get rid of helper line if selection changes. … … 265 328 // 266 329 Main.map.mapView.requestFocus(); 267 330 268 331 if(e.getClickCount() > 1 && mousePos != null && mousePos.equals(oldMousePos)) { 269 332 // A double click equals "user clicked last node again, finish way" … … 325 388 } else { // n==null, no node found in clicked area 326 389 EastNorth mouseEN = Main.map.mapView.getEastNorth(e.getX(), e.getY()); 327 newEN = snap On? snapHelper.getSnapPoint(mouseEN) : mouseEN;390 newEN = snapHelper.isSnapOn() ? snapHelper.getSnapPoint(mouseEN) : mouseEN; 328 391 n = new Node(newEN); //create node at clicked point 329 392 newNode = true; … … 699 762 } 700 763 701 if (snapOn)snapHelper.checkAngleSnapping(currentMouseEastNorth,angle);764 snapHelper.checkAngleSnapping(currentMouseEastNorth,angle); 702 765 703 766 Main.map.statusLine.setAngle(angle); … … 949 1012 950 1013 Graphics2D g2 = g; 951 if (snapOn)snapHelper.draw(g2,mv);1014 snapHelper.drawIfNeeded(g2,mv); 952 1015 if (!drawHelperLine || wayIsFinished || shift) return; 953 1016 … … 955 1018 g2.setColor(selectedColor); 956 1019 g2.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 1020 } else { 1021 if (!snapHelper.drawConstructionGeometry) return; 957 1022 } 958 1023 GeneralPath b = new GeneralPath(); … … 1019 1084 rv += " " + tr("Continue way from last node."); 1020 1085 } 1021 if (snap On) {1022 rv += " "+ tr("Angle snapping ON.");1086 if (snapHelper.isSnapOn()) { 1087 rv += " "+ tr("Angle snapping active."); 1023 1088 } 1024 1089 } … … 1093 1158 1094 1159 private class SnapHelper { 1160 boolean snapOn; // snapping is turned on 1161 1095 1162 private boolean active; // snapping is activa for current mouse position 1096 1163 private boolean fixed; // snap angle is fixed 1097 1164 private boolean absoluteFix; // snap angle is absolute 1165 1166 private boolean drawConstructionGeometry; 1167 private boolean showProjectedPoint; 1168 private boolean showAngle; 1169 1098 1170 EastNorth dir2; 1099 1171 EastNorth projected; … … 1111 1183 private Stroke normalStroke; 1112 1184 private Stroke helperStroke; 1113 1114 private void init() { 1185 1186 JCheckBoxMenuItem checkBox; 1187 1188 public void init() { 1115 1189 snapOn=false; 1190 checkBox.setState(snapOn); 1116 1191 fixed=false; absoluteFix=false; 1117 1192 1118 1193 Collection<String> angles = Main.pref.getCollection("draw.anglesnap.angles", 1119 1194 Arrays.asList("0","30","45","60","90","120","135","150","210","225","240","270","300","315","330")); … … 1131 1206 } 1132 1207 snapAngleTolerance = Main.pref.getDouble("draw.anglesnap.tolerance", 5.0); 1208 drawConstructionGeometry = Main.pref.getBoolean("draw.anglesnap.drawConstructionGeometry", true); 1209 showProjectedPoint = Main.pref.getBoolean("draw.anglesnap.drawProjectedPoint", true); 1210 showAngle = Main.pref.getBoolean("draw.anglesnap.showAngle", true); 1133 1211 1134 1212 normalStroke = new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); … … 1141 1219 } 1142 1220 1143 p rivate void noSnapNow() {1144 active=false;1145 dir2=null; projected=null;1146 labelText=null;1147 } 1148 1149 private void draw(Graphics2D g2, MapView mv) {1221 public void setMenuCheckBox(JCheckBoxMenuItem checkBox) { 1222 this.checkBox = checkBox; 1223 } 1224 1225 1226 public void drawIfNeeded(Graphics2D g2, MapView mv) { 1227 if (!snapOn) return; 1150 1228 if (!active) return; 1151 1229 Point p1=mv.getPoint(currentBaseNode); … … 1153 1231 Point p3=mv.getPoint(projected); 1154 1232 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); 1233 if (drawConstructionGeometry) { 1234 g2.setColor(snapHelperColor); 1235 g2.setStroke(helperStroke); 1236 1237 b = new GeneralPath(); 1238 if (absoluteFix) { 1239 b.moveTo(p2.x,p2.y); 1240 b.lineTo(2*p1.x-p2.x,2*p1.y-p2.y); // bi-directional line 1241 } else { 1242 b.moveTo(p2.x,p2.y); 1243 b.lineTo(p3.x,p3.y); 1244 } 1245 g2.draw(b); 1246 } 1168 1247 1169 1248 g2.setColor(selectedColor); … … 1175 1254 1176 1255 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 1256 if (showProjectedPoint) { 1257 g2.setStroke(normalStroke); 1258 g2.drawOval(p3.x-5, p3.y-5, 10, 10); // projected point 1259 } 1179 1260 1180 1261 g2.setColor(snapHelperColor); … … 1183 1264 } 1184 1265 1185 private double getAngleDelta(double a, double b) {1186 double delta = Math.abs(a-b);1187 if (delta>180) return 360-delta; else return delta;1188 }1189 1190 1266 /* If mouse position is close to line at 15-30-45-... angle, remembers this direction 1191 1267 */ 1192 private void checkAngleSnapping(EastNorth currentEN, double angle) { 1268 public void checkAngleSnapping(EastNorth currentEN, double angle) { 1269 if (!snapOn) return; 1193 1270 if (!absoluteFix && previousNode==null) return; 1194 1271 … … 1208 1285 EastNorth p0 = currentBaseNode.getEastNorth(); 1209 1286 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); 1287 1288 if (showAngle) { 1289 if (fixed) { 1290 if (absoluteFix) labelText = "="; 1291 else labelText = String.format(fixFmt, (int) nearestAngle); 1292 } else labelText = String.format("%d", (int) nearestAngle); 1293 } else { 1294 if (fixed) { 1295 if (absoluteFix) labelText = "="; 1296 else labelText = String.format(tr("FIX"),0); 1297 } else labelText=""; 1298 } 1215 1299 1216 1300 if (absoluteFix) { … … 1237 1321 } 1238 1322 1239 p rivateEastNorth getSnapPoint(EastNorth p) {1323 public EastNorth getSnapPoint(EastNorth p) { 1240 1324 if (!active) return p; 1241 1325 double de=p.east()-e0; … … 1246 1330 } 1247 1331 1248 private void unsetFixedMode() { 1249 fixed=false; absoluteFix=false; 1250 lastAngle=0; 1251 active=false; 1252 } 1253 1254 private void nextSnapMode() { 1255 if (snapOn) { 1256 // turn off snapping if we are in fixed mode or no actile snapping line exist 1257 if (fixed || !active) { snapOn=false; unsetFixedMode(); } 1258 else if (active) { fixed=true; } 1259 } else { 1260 snapOn=true; 1261 unsetFixedMode(); 1262 } 1263 } 1264 1265 private boolean isActive() { 1266 return active; 1267 } 1268 1269 private double getNearestAngle(double angle) { 1270 double delta,minDelta=1e5, bestAngle=0.0; 1271 for (int i=0; i<snapAngles.length; i++) { 1272 delta = getAngleDelta(angle,snapAngles[i]); 1273 if (delta<minDelta) { 1274 minDelta=delta; 1275 bestAngle=snapAngles[i]; 1276 } 1277 } 1278 if (Math.abs(bestAngle-360)<1e-3) bestAngle=0; 1279 return bestAngle; 1280 } 1281 1282 private void fixToSegment(WaySegment seg) { 1332 1333 public void noSnapNow() { 1334 active=false; 1335 dir2=null; projected=null; 1336 labelText=null; 1337 } 1338 1339 public void fixToSegment(WaySegment seg) { 1283 1340 if (seg==null) return; 1284 1341 double hdg = seg.getFirstNode().getEastNorth().heading(seg.getSecondNode().getEastNorth()); … … 1290 1347 lastAngle=hdg; 1291 1348 } 1349 1350 private void nextSnapMode() { 1351 if (snapOn) { 1352 // turn off snapping if we are in fixed mode or no actile snapping line exist 1353 if (fixed || !active) { snapOn=false; unsetFixedMode(); } 1354 else setFixedMode(); 1355 } else { 1356 snapOn=true; 1357 unsetFixedMode(); 1358 } 1359 checkBox.setState(snapOn); 1360 } 1361 1362 private void toggleSnapping() { 1363 snapOn = !snapOn; 1364 checkBox.setState(snapOn); 1365 unsetFixedMode(); 1366 } 1367 1368 public void setFixedMode() { 1369 if (active) { fixed=true; } 1370 } 1371 1372 1373 public void unsetFixedMode() { 1374 fixed=false; absoluteFix=false; 1375 lastAngle=0; 1376 active=false; 1377 } 1378 1379 public boolean isActive() { 1380 return active; 1381 } 1382 1383 public boolean isSnapOn() { 1384 return snapOn; 1385 } 1386 1387 private double getNearestAngle(double angle) { 1388 double delta,minDelta=1e5, bestAngle=0.0; 1389 for (int i=0; i<snapAngles.length; i++) { 1390 delta = getAngleDelta(angle,snapAngles[i]); 1391 if (delta<minDelta) { 1392 minDelta=delta; 1393 bestAngle=snapAngles[i]; 1394 } 1395 } 1396 if (Math.abs(bestAngle-360)<1e-3) bestAngle=0; 1397 return bestAngle; 1398 } 1399 1400 private double getAngleDelta(double a, double b) { 1401 double delta = Math.abs(a-b); 1402 if (delta>180) return 360-delta; else return delta; 1403 } 1404 1405 private void unFixOrTurnOff() { 1406 if (absoluteFix) unsetFixedMode(); else toggleSnapping(); 1407 } 1408 } 1409 1410 private class SnapChangeAction extends JosmAction { 1411 public SnapChangeAction() { 1412 super(tr("Angle snapping"), "anglesnap", 1413 tr("Switch angle snapping mode while drawing"), 1414 null, false); 1415 putValue("help", ht("/Action/Draw/AngleSnap")); 1416 } 1417 @Override 1418 public void actionPerformed(ActionEvent e) { 1419 if (snapHelper!=null) snapHelper.toggleSnapping(); 1420 } 1421 1292 1422 } 1293 1423 }
Note:
See TracChangeset
for help on using the changeset viewer.