Ticket #5604: LatLonDialog.java.patch

File LatLonDialog.java.patch, 11.8 KB (added by *Martin*, 14 years ago)

the patch

  • src/org/openstreetmap/josm/gui/dialogs/LatLonDialog.java

     
    1616import java.awt.event.WindowEvent;
    1717import java.text.NumberFormat;
    1818import java.text.ParsePosition;
     19import java.util.ArrayList;
     20import java.util.List;
    1921import java.util.Locale;
     22import java.util.regex.Matcher;
     23import java.util.regex.Pattern;
    2024
    2125import javax.swing.AbstractAction;
    2226import javax.swing.BorderFactory;
     
    4448public class LatLonDialog extends JDialog {
    4549    private static final Color BG_COLOR_ERROR = new Color(255,224,224);
    4650
    47     private JTextField tfLat;
    48     private JTextField tfLon;
     51    private JTextField tfLatLon;
     52//    private JTextField tfLon;
    4953    private String help;
    5054    private boolean canceled = false;
    5155    private LatLon coordinates;
     
    5660        JPanel pnl = new JPanel(new GridBagLayout());
    5761        pnl.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    5862        pnl.add(new JLabel("<html>"+
    59                 tr("Enter the coordinates for the new node.") +
     63                tr("Enter the coordinates for the new node.") /*+
    6064                "<br>" + tr("Use decimal degrees.") +
    61                 "<br>" + tr("Negative values denote Western/Southern hemisphere.")),
     65                "<br>" + tr("Negative values denote Western/Southern hemisphere.")*/),
    6266                GBC.eol());
    6367
    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));
     68        pnl.add(new JLabel(tr("Coordinates")), GBC.std().insets(0,10,5,0));
     69        tfLatLon = new JTextField(24);
     70        pnl.add(tfLatLon, GBC.eol().insets(0,10,0,0));
     71//        pnl.add(new JLabel(tr("Longitude")), GBC.std().insets(0,0,5,10));
     72//        tfLon = new JTextField(12);
     73//        pnl.add(tfLon, GBC.eol().insets(0,0,0,10));
    7074
    7175        // parse and verify input on the fly
    7276        //
    7377        LatLonInputVerifier inputVerifier = new LatLonInputVerifier();
    74         tfLat.getDocument().addDocumentListener(inputVerifier);
    75         tfLon.getDocument().addDocumentListener(inputVerifier);
     78        tfLatLon.getDocument().addDocumentListener(inputVerifier);
     79//        tfLon.getDocument().addDocumentListener(inputVerifier);
    7680
    7781        // select the text in the field on focus
    7882        //
    7983        TextFieldFocusHandler focusHandler = new TextFieldFocusHandler();
    80         tfLat.addFocusListener(focusHandler);
    81         tfLon.addFocusListener(focusHandler);
     84        tfLatLon.addFocusListener(focusHandler);
     85//        tfLon.addFocusListener(focusHandler);
    8286        return pnl;
    8387    }
    8488
     
    130134            coordinates = new LatLon(0,0);
    131135        }
    132136        this.coordinates = coordinates;
    133         tfLat.setText(coordinates.latToString(CoordinateFormat.DECIMAL_DEGREES));
    134         tfLon.setText(coordinates.lonToString(CoordinateFormat.DECIMAL_DEGREES));
     137        tfLatLon.setText(coordinates.latToString(CoordinateFormat.DEGREES_MINUTES_SECONDS) + " " + coordinates.lonToString(CoordinateFormat.DEGREES_MINUTES_SECONDS));
     138//        tfLon.setText(coordinates.lonToString(CoordinateFormat.DECIMAL_DEGREES));
    135139        actOK.setEnabled(true);
    136140    }
    137141
     
    176180        return n== null ? null : n.doubleValue();
    177181    }
    178182
    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"));
    186         }
    187         return d;
    188     }
    189183
    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     }
     184//    protected Double parseLonFromUserInput() {
     185//        Double d = parseDoubleFromUserInput(tfLon.getText());
     186//        if (d == null || ! LatLon.isValidLon(d)) {
     187//            setErrorFeedback(tfLon, tr("Please enter a valid longitude in the range -180..180"));
     188//            return null;
     189//        } else {
     190//            clearErrorFeedback(tfLon,tr("Please enter a longitude in the range -180..180"));
     191//        }
     192//        return d;
     193//    }
    200194
    201195    protected void parseUserInput() {
    202         Double lat = parseLatFromUserInput();
    203         Double lon = parseLonFromUserInput();
    204         if (lat == null || lon == null) {
     196        LatLon latLon;
     197        try {
     198            latLon = parse(tfLatLon.getText());
     199            if (!LatLon.isValidLat(latLon.lat()) || !LatLon.isValidLon(latLon.lon())) {
     200                latLon = null;
     201            }
     202        } catch (IllegalArgumentException e) {
     203            latLon = null;
     204        }
     205        if (latLon == null) {
     206            setErrorFeedback(tfLatLon, tr("Please enter a GPS coordinates"));
    205207            coordinates = null;
    206208            actOK.setEnabled(false);
    207209        } else {
    208             coordinates = new LatLon(lat,lon);
     210            clearErrorFeedback(tfLatLon,tr("Please enter a GPS coordinates"));
     211            coordinates = latLon;
    209212            actOK.setEnabled(true);
    210213        }
    211214    }
     
    287290
    288291        @Override
    289292        public void windowOpened(WindowEvent e) {
    290             tfLat.requestFocusInWindow();
     293            tfLatLon.requestFocusInWindow();
    291294        }
    292295    }
    293296
     297
     298
     299
     300
     301
     302
     303
     304
     305    private static final double ZERO = 0.0;
     306
     307    private static final Pattern p = Pattern.compile("([+|-]?\\d+\\.\\d*)|([+|-]?\\d+)|(°|o|deg)|('|′|min)|(\"|″|sec)|(,|;)|([NSEW])|\\s+|(.+)", Pattern.CASE_INSENSITIVE);
     308
     309
     310    private static LatLon parse(final String coord) {
     311//        System.out.println("=======================");
     312//        System.out.println("Input: " + coord);
     313
     314        final Matcher m = p.matcher(coord);
     315
     316        final StringBuilder sb = new StringBuilder();
     317        final List<Object> list = new ArrayList<Object>();
     318
     319        while (m.find()) {
     320            if (m.group(1) != null) {
     321                sb.append('R');
     322                list.add(Double.parseDouble(m.group(1)));
     323            } else if (m.group(2) != null) {
     324                sb.append('Z');
     325                list.add(Double.parseDouble(m.group(2)));
     326            } else if (m.group(3) != null) {
     327                sb.append('°');
     328            } else if (m.group(4) != null) {
     329                sb.append('\'');
     330            } else if (m.group(5) != null) {
     331                sb.append('"');
     332            } else if (m.group(6) != null) {
     333                sb.append(',');
     334            } else if (m.group(7) != null) {
     335                sb.append("x");
     336                list.add(m.group(7).toUpperCase());
     337            } else if (m.group(8) != null) {
     338                throw new IllegalArgumentException("invalid token: " + m.group(8));
     339            }
     340        }
     341
     342        final String pattern = sb.toString();
     343
     344//        System.out.println("Pattern: " + sb.toString());
     345
     346        final Object[] params = list.toArray();
     347        final LatLonHolder latLon = new LatLonHolder();
     348
     349        if (pattern.matches("R°?,?R°?")) {
     350            setLatLon(latLon,
     351                    params[0], ZERO, ZERO, "N",
     352                    params[1], ZERO, ZERO, "E");
     353        } else if (pattern.matches("xR°?,?xR°?")) {
     354            setLatLon(latLon,
     355                    params[1], ZERO, ZERO, params[0],
     356                    params[3], ZERO, ZERO, params[2]);
     357        } else if (pattern.matches("R°?x,?R°?x")) {
     358            setLatLon(latLon,
     359                    params[0], ZERO, ZERO, params[1],
     360                    params[2], ZERO, ZERO, params[3]);
     361        } else if (pattern.matches("Z°[RZ]'?,?Z°[RZ]'?")) {
     362            setLatLon(latLon,
     363                    params[0], params[1], ZERO, "N",
     364                    params[2], params[3], ZERO, "E");
     365        } else if (pattern.matches("Z[RZ],?Z[RZ]")) {
     366            setLatLon(latLon,
     367                    params[0], params[1], ZERO, "N",
     368                    params[2], params[3], ZERO, "E");
     369        } else if (pattern.matches("xZ°[RZ]'?,?xZ°[RZ]'?|xZ°?[RZ],?xZ°?[RZ]")) {
     370            setLatLon(latLon,
     371                    params[1], params[2], ZERO, params[0],
     372                    params[4], params[5], ZERO, params[3]);
     373        } else if (pattern.matches("Z°[RZ]'?x,?Z°[RZ]'?x|Z°?[RZ]x,?Z°?[RZ]x")) {
     374            setLatLon(latLon,
     375                    params[0], params[1], ZERO, params[2],
     376                    params[3], params[4], ZERO, params[5]);
     377        } else if (pattern.matches("Z°Z'[RZ]\"?x,?Z°Z'[RZ]\"?x|ZZ[RZ]x,?ZZ[RZ]x")) {
     378            setLatLon(latLon,
     379                    params[0], params[1], params[2], params[3],
     380                    params[4], params[5], params[6], params[7]);
     381        } else if (pattern.matches("xZ°Z'[RZ]\"?,?xZ°Z'[RZ]\"?|xZZ[RZ],?xZZ[RZ]")) {
     382            setLatLon(latLon,
     383                    params[1], params[2], params[3], params[0],
     384                    params[5], params[6], params[7], params[4]);
     385        } else if (pattern.matches("ZZ[RZ],?ZZ[RZ]")) {
     386            setLatLon(latLon,
     387                    params[0], params[1], params[2], "N",
     388                    params[3], params[4], params[5], "E");
     389        } else {
     390            throw new IllegalArgumentException("invalid format: " + pattern);
     391        }
     392
     393        return new LatLon(latLon.lat, latLon.lon);
     394    }
     395
     396
     397    private static class LatLonHolder {
     398        double lat, lon;
     399    }
     400
     401
     402    private static void setLatLon(final LatLonHolder latLon,
     403            final Object coord1deg, final Object coord1min, final Object coord1sec, final Object card1,
     404            final Object coord2deg, final Object coord2min, final Object coord2sec, final Object card2) {
     405
     406        setLatLon(latLon,
     407                (double) (Double) coord1deg, (double) (Double) coord1min, (double) (Double) coord1sec, (String) card1,
     408                (double) (Double) coord2deg, (double) (Double) coord2min, (double) (Double) coord2sec, (String) card2);
     409    }
     410
     411
     412    private static void setLatLon(final LatLonHolder latLon,
     413            final double coord1deg, final double coord1min, final double coord1sec, final String card1,
     414            final double coord2deg, final double coord2min, final double coord2sec, final String card2) {
     415
     416        setLatLon(latLon, coord1deg, coord1min, coord1sec, card1);
     417        setLatLon(latLon, coord2deg, coord2min, coord2sec, card2);
     418    }
     419
     420
     421    private static void setLatLon(final LatLonHolder latLon, final double coordDeg, final double coordMin, final double coordSec, final String card) {
     422        if (coordDeg < -180 || coordDeg > 180 || coordMin < 0 || coordMin >= 60 || coordSec < 0 || coordSec > 60) {
     423            throw new IllegalArgumentException("out of range");
     424        }
     425
     426        double coord = Math.signum(coordDeg) * (Math.abs(coordDeg) + coordMin / 60 + coordSec / 3600);
     427        coord = card.equals("N") || card.equals("E") ? coord : -coord;
     428        if (card.equals("N") || card.equals("S")) {
     429            latLon.lat = coord;
     430        } else {
     431            latLon.lon = coord;
     432        }
     433    }
     434
     435
     436
    294437}