Ticket #5604: LatLonDialog.java.2.patch
File LatLonDialog.java.2.patch, 10.6 KB (added by , 14 years ago) |
---|
-
src/org/openstreetmap/josm/gui/dialogs/LatLonDialog.java
16 16 import java.awt.event.WindowEvent; 17 17 import java.text.NumberFormat; 18 18 import java.text.ParsePosition; 19 import java.util.ArrayList; 20 import java.util.List; 19 21 import java.util.Locale; 22 import java.util.regex.Matcher; 23 import java.util.regex.Pattern; 20 24 21 25 import javax.swing.AbstractAction; 22 26 import javax.swing.BorderFactory; … … 44 48 public class LatLonDialog extends JDialog { 45 49 private static final Color BG_COLOR_ERROR = new Color(255,224,224); 46 50 47 private JTextField tfLat; 48 private JTextField tfLon; 51 private JTextField tfLatLon; 49 52 private String help; 50 53 private boolean canceled = false; 51 54 private LatLon coordinates; … … 56 59 JPanel pnl = new JPanel(new GridBagLayout()); 57 60 pnl.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 58 61 pnl.add(new JLabel("<html>"+ 59 tr("Enter the coordinates for the new node.") + 60 "<br>" + tr("Use decimal degrees.") + 61 "<br>" + tr("Negative values denote Western/Southern hemisphere.")), 62 tr("Enter the coordinates for the new node.")), 62 63 GBC.eol()); 63 64 64 pnl.add(new JLabel(tr("Latitude")), GBC.std().insets(0,10,5,0)); 65 tfLat = new JTextField(12); 66 pnl.add(tfLat, GBC.eol().insets(0,10,0,0)); 67 pnl.add(new JLabel(tr("Longitude")), GBC.std().insets(0,0,5,10)); 68 tfLon = new JTextField(12); 69 pnl.add(tfLon, GBC.eol().insets(0,0,0,10)); 65 pnl.add(new JLabel(tr("Coordinates")), GBC.std().insets(0,10,5,0)); 66 tfLatLon = new JTextField(24); 67 pnl.add(tfLatLon, GBC.eol().insets(0,10,0,0)); 70 68 71 69 // parse and verify input on the fly 72 70 // 73 71 LatLonInputVerifier inputVerifier = new LatLonInputVerifier(); 74 tfLat.getDocument().addDocumentListener(inputVerifier); 75 tfLon.getDocument().addDocumentListener(inputVerifier); 72 tfLatLon.getDocument().addDocumentListener(inputVerifier); 76 73 77 74 // select the text in the field on focus 78 75 // 79 76 TextFieldFocusHandler focusHandler = new TextFieldFocusHandler(); 80 tfLat.addFocusListener(focusHandler); 81 tfLon.addFocusListener(focusHandler); 77 tfLatLon.addFocusListener(focusHandler); 82 78 return pnl; 83 79 } 84 80 … … 130 126 coordinates = new LatLon(0,0); 131 127 } 132 128 this.coordinates = coordinates; 133 tfLat.setText(coordinates.latToString(CoordinateFormat.DECIMAL_DEGREES)); 134 tfLon.setText(coordinates.lonToString(CoordinateFormat.DECIMAL_DEGREES)); 129 tfLatLon.setText(coordinates.latToString(CoordinateFormat.DEGREES_MINUTES_SECONDS) + " " + coordinates.lonToString(CoordinateFormat.DEGREES_MINUTES_SECONDS)); 135 130 actOK.setEnabled(true); 136 131 } 137 132 … … 176 171 return n== null ? null : n.doubleValue(); 177 172 } 178 173 179 protected Double parseLatFromUserInput() { 180 Double d = parseDoubleFromUserInput(tfLat.getText()); 181 if (d == null || ! LatLon.isValidLat(d)) { 182 setErrorFeedback(tfLat, tr("Please enter a valid latitude in the range -90..90")); 183 return null; 184 } else { 185 clearErrorFeedback(tfLat,tr("Please enter a latitude in the range -90..90")); 174 protected void parseUserInput() { 175 LatLon latLon; 176 try { 177 latLon = parse(tfLatLon.getText()); 178 if (!LatLon.isValidLat(latLon.lat()) || !LatLon.isValidLon(latLon.lon())) { 179 latLon = null; 180 } 181 } catch (IllegalArgumentException e) { 182 latLon = null; 186 183 } 187 return d; 188 } 189 190 protected Double parseLonFromUserInput() { 191 Double d = parseDoubleFromUserInput(tfLon.getText()); 192 if (d == null || ! LatLon.isValidLon(d)) { 193 setErrorFeedback(tfLon, tr("Please enter a valid longitude in the range -180..180")); 194 return null; 195 } else { 196 clearErrorFeedback(tfLon,tr("Please enter a longitude in the range -180..180")); 197 } 198 return d; 199 } 200 201 protected void parseUserInput() { 202 Double lat = parseLatFromUserInput(); 203 Double lon = parseLonFromUserInput(); 204 if (lat == null || lon == null) { 184 if (latLon == null) { 185 setErrorFeedback(tfLatLon, tr("Please enter a GPS coordinates")); 205 186 coordinates = null; 206 187 actOK.setEnabled(false); 207 188 } else { 208 coordinates = new LatLon(lat,lon); 189 clearErrorFeedback(tfLatLon,tr("Please enter a GPS coordinates")); 190 coordinates = latLon; 209 191 actOK.setEnabled(true); 210 192 } 211 193 } … … 287 269 288 270 @Override 289 271 public void windowOpened(WindowEvent e) { 290 tfLat .requestFocusInWindow();272 tfLatLon.requestFocusInWindow(); 291 273 } 292 274 } 293 275 276 277 278 private static final double ZERO = 0.0; 279 280 private static final Pattern p = Pattern.compile("([+|-]?\\d+\\.\\d*)|([+|-]?\\d+)|(°|o|deg)|('|′|min)|(\"|″|sec)|(,|;)|([NSEW])|\\s+|(.+)", Pattern.CASE_INSENSITIVE); 281 282 283 private static LatLon parse(final String coord) { 284 final Matcher m = p.matcher(coord); 285 286 final StringBuilder sb = new StringBuilder(); 287 final List<Object> list = new ArrayList<Object>(); 288 289 while (m.find()) { 290 if (m.group(1) != null) { 291 sb.append('R'); 292 list.add(Double.parseDouble(m.group(1))); 293 } else if (m.group(2) != null) { 294 sb.append('Z'); 295 list.add(Double.parseDouble(m.group(2))); 296 } else if (m.group(3) != null) { 297 sb.append('°'); 298 } else if (m.group(4) != null) { 299 sb.append('\''); 300 } else if (m.group(5) != null) { 301 sb.append('"'); 302 } else if (m.group(6) != null) { 303 sb.append(','); 304 } else if (m.group(7) != null) { 305 sb.append("x"); 306 list.add(m.group(7).toUpperCase()); 307 } else if (m.group(8) != null) { 308 throw new IllegalArgumentException("invalid token: " + m.group(8)); 309 } 310 } 311 312 final String pattern = sb.toString(); 313 314 final Object[] params = list.toArray(); 315 final LatLonHolder latLon = new LatLonHolder(); 316 317 if (pattern.matches("R°?,?R°?")) { 318 setLatLon(latLon, 319 params[0], ZERO, ZERO, "N", 320 params[1], ZERO, ZERO, "E"); 321 } else if (pattern.matches("xR°?,?xR°?")) { 322 setLatLon(latLon, 323 params[1], ZERO, ZERO, params[0], 324 params[3], ZERO, ZERO, params[2]); 325 } else if (pattern.matches("R°?x,?R°?x")) { 326 setLatLon(latLon, 327 params[0], ZERO, ZERO, params[1], 328 params[2], ZERO, ZERO, params[3]); 329 } else if (pattern.matches("Z°[RZ]'?,?Z°[RZ]'?|Z[RZ],?Z[RZ]")) { 330 setLatLon(latLon, 331 params[0], params[1], ZERO, "N", 332 params[2], params[3], ZERO, "E"); 333 } else if (pattern.matches("xZ°[RZ]'?,?xZ°[RZ]'?|xZ°?[RZ],?xZ°?[RZ]")) { 334 setLatLon(latLon, 335 params[1], params[2], ZERO, params[0], 336 params[4], params[5], ZERO, params[3]); 337 } else if (pattern.matches("Z°[RZ]'?x,?Z°[RZ]'?x|Z°?[RZ]x,?Z°?[RZ]x")) { 338 setLatLon(latLon, 339 params[0], params[1], ZERO, params[2], 340 params[3], params[4], ZERO, params[5]); 341 } else if (pattern.matches("Z°Z'[RZ]\"?x,?Z°Z'[RZ]\"?x|ZZ[RZ]x,?ZZ[RZ]x")) { 342 setLatLon(latLon, 343 params[0], params[1], params[2], params[3], 344 params[4], params[5], params[6], params[7]); 345 } else if (pattern.matches("xZ°Z'[RZ]\"?,?xZ°Z'[RZ]\"?|xZZ[RZ],?xZZ[RZ]")) { 346 setLatLon(latLon, 347 params[1], params[2], params[3], params[0], 348 params[5], params[6], params[7], params[4]); 349 } else if (pattern.matches("ZZ[RZ],?ZZ[RZ]")) { 350 setLatLon(latLon, 351 params[0], params[1], params[2], "N", 352 params[3], params[4], params[5], "E"); 353 } else { 354 throw new IllegalArgumentException("invalid format: " + pattern); 355 } 356 357 return new LatLon(latLon.lat, latLon.lon); 358 } 359 360 361 private static class LatLonHolder { 362 double lat, lon; 363 } 364 365 366 private static void setLatLon(final LatLonHolder latLon, 367 final Object coord1deg, final Object coord1min, final Object coord1sec, final Object card1, 368 final Object coord2deg, final Object coord2min, final Object coord2sec, final Object card2) { 369 370 setLatLon(latLon, 371 (double) (Double) coord1deg, (double) (Double) coord1min, (double) (Double) coord1sec, (String) card1, 372 (double) (Double) coord2deg, (double) (Double) coord2min, (double) (Double) coord2sec, (String) card2); 373 } 374 375 376 private static void setLatLon(final LatLonHolder latLon, 377 final double coord1deg, final double coord1min, final double coord1sec, final String card1, 378 final double coord2deg, final double coord2min, final double coord2sec, final String card2) { 379 380 setLatLon(latLon, coord1deg, coord1min, coord1sec, card1); 381 setLatLon(latLon, coord2deg, coord2min, coord2sec, card2); 382 } 383 384 385 private static void setLatLon(final LatLonHolder latLon, final double coordDeg, final double coordMin, final double coordSec, final String card) { 386 if (coordDeg < -180 || coordDeg > 180 || coordMin < 0 || coordMin >= 60 || coordSec < 0 || coordSec > 60) { 387 throw new IllegalArgumentException("out of range"); 388 } 389 390 double coord = (coordDeg < 0 ? -1 : 1) * (Math.abs(coordDeg) + coordMin / 60 + coordSec / 3600); 391 coord = card.equals("N") || card.equals("E") ? coord : -coord; 392 if (card.equals("N") || card.equals("S")) { 393 latLon.lat = coord; 394 } else { 395 latLon.lon = coord; 396 } 397 } 398 294 399 }