Changeset 3656 in josm for trunk


Ignore:
Timestamp:
2010-11-15T00:02:20+01:00 (14 years ago)
Author:
bastiK
Message:

applied #5604 (patch by m.zdila) - support different formats of GPS coordinates in Add Node

Location:
trunk/src/org/openstreetmap/josm
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/AddNodeAction.java

    r3363 r3656  
    2020 */
    2121public final class AddNodeAction extends JosmAction {
     22    // remember input from last time
     23    private String text;
     24
    2225    //static private final Logger logger = Logger.getLogger(AddNodeAction.class.getName());
    2326
     
    3437
    3538        LatLonDialog dialog = new LatLonDialog(Main.parent, tr("Add Node..."), ht("/Action/AddNode"));
     39
     40        if (text != null) {
     41            dialog.setText(text);
     42        }
     43
    3644        dialog.setVisible(true);
    3745        if (dialog.isCanceled())
     
    4149        if (coordinates == null)
    4250            return;
     51
     52        text = dialog.getText();
     53
    4354        Node nnew = new Node(coordinates);
    4455
  • trunk/src/org/openstreetmap/josm/data/coor/LatLon.java

    r3438 r3656  
    9999    }
    100100
    101     private final static String SOUTH = trc("compass", "S");
    102     private final static String NORTH = trc("compass", "N");
     101    public final static String SOUTH = trc("compass", "S");
     102    public final static String NORTH = trc("compass", "N");
    103103    public String latToString(CoordinateFormat d) {
    104104        switch(d) {
     
    115115    }
    116116
    117     private final static String WEST = trc("compass", "W");
    118     private final static String EAST = trc("compass", "E");
     117    public final static String WEST = trc("compass", "W");
     118    public final static String EAST = trc("compass", "E");
    119119    public String lonToString(CoordinateFormat d) {
    120120        switch(d) {
  • trunk/src/org/openstreetmap/josm/gui/dialogs/LatLonDialog.java

    r3501 r3656  
    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;
     
    2630import javax.swing.JOptionPane;
    2731import javax.swing.JPanel;
     32import javax.swing.JSeparator;
    2833import javax.swing.JTextField;
    2934import javax.swing.KeyStroke;
     
    3843import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
    3944import org.openstreetmap.josm.gui.help.HelpUtil;
     45import org.openstreetmap.josm.gui.widgets.HtmlPanel;
    4046import org.openstreetmap.josm.tools.GBC;
    4147import org.openstreetmap.josm.tools.ImageProvider;
     
    4551    private static final Color BG_COLOR_ERROR = new Color(255,224,224);
    4652
    47     private JTextField tfLat;
    48     private JTextField tfLon;
     53    private JTextField tfLatLon;
    4954    private String help;
    5055    private boolean canceled = false;
     
    5358    private CancelAction actCancel;
    5459
     60    private static final double ZERO = 0.0;
     61    private static final String DEG = "\u00B0";
     62    private static final String MIN = "\u2032";
     63    private static final String SEC = "\u2033";
     64
     65    private static final char N_TR = LatLon.NORTH.charAt(0);
     66    private static final char S_TR = LatLon.SOUTH.charAt(0);
     67    private static final char E_TR = LatLon.EAST.charAt(0);
     68    private static final char W_TR = LatLon.WEST.charAt(0);
     69
     70    private static final Pattern p = Pattern.compile(
     71            "([+|-]?\\d+[.,]\\d+)|"             // (1)
     72            + "([+|-]?\\d+)|"                   // (2)
     73            + "("+DEG+"|o|deg)|"                // (3)
     74            + "('|"+MIN+"|min)|"                // (4)
     75            + "(\"|"+SEC+"|sec)|"               // (5)
     76            + "(,|;)|"                          // (6)
     77            + "([NSEW"+N_TR+S_TR+E_TR+W_TR+"])|"// (7)
     78            + "\\s+|"
     79            + "(.+)");
     80
    5581    protected JPanel buildInputForm() {
    5682        JPanel pnl = new JPanel(new GridBagLayout());
    5783        pnl.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    58         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                 GBC.eol());
    63 
    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));
     84
     85        pnl.add(new JLabel(tr("Coordinates:")), GBC.std().insets(0,10,5,0));
     86        tfLatLon = new JTextField(24);
     87        pnl.add(tfLatLon, GBC.eol().insets(0,10,0,0).fill(GBC.HORIZONTAL).weight(1.0, 0.0));
     88
     89        pnl.add(new JSeparator(), GBC.eol().fill(GBC.HORIZONTAL).insets(0,5,0,5));
     90
     91        pnl.add(new HtmlPanel(
     92                tr("Enter the coordinates for the new node.<br/>You can separate longitude and latitude with space, comma or semicolon.<br/>" +
     93                                "Use positive numbers or N, E characters to indicate North or East cardinal direction.<br/>" +
     94                                "For South and West cardinal directions you can use either negative numbers or S, W characters.<br/>" +
     95                                "Coordinate value can be in one of three formats:<ul>" +
     96                        "<li><i>degrees</i><tt>&deg;</tt></li>" +
     97                        "<li><i>degrees</i><tt>&deg;</tt> <i>minutes</i><tt>&#39;</tt></li>" +
     98                        "<li><i>degrees</i><tt>&deg;</tt> <i>minutes</i><tt>&#39;</tt> <i>seconds</i><tt>&quot</tt></li>" +
     99                                "</ul>" +
     100                                "Symbols <tt>&deg;</tt>, <tt>&#39;</tt>, <tt>&prime;</tt>, <tt>&quot;</tt>, <tt>&Prime;</tt> are optional.<br/><br/>" +
     101                                "Some examples:<ul>" +
     102                        "<li>49.29918&deg; 19.24788&deg;</li>" +
     103                        "<li>N 49.29918 E 19.24788</li>" +
     104                        "<li>W 49&deg;29.918&#39; S 19&deg;24.788&#39;</li>" +
     105                        "<li>N 49&deg;29&#39;04&quot; E 19&deg;24&#39;43&quot;</li>" +
     106                        "<li>49.29918 N, 19.24788 E</li>" +
     107                        "<li>49&deg;29&#39;21&quot; N 19&deg;24&#39;38&quot; E</li>" +
     108                        "<li>49 29 51, 19 24 18</li>" +
     109                        "<li>49 29, 19 24</li>" +
     110                        "<li>E 49 29, N 19 24</li>" +
     111                        "<li>49&deg; 29; 19&deg; 24</li>" +
     112                        "<li>N 49&deg; 29, W 19&deg; 24</li>" +
     113                        "<li>49&deg; 29.5 S, 19&deg; 24.6 E</li>" +
     114                        "<li>N 49 29.918 E 19 15.88</li>" +
     115                        "<li>49 29.4 19 24.5</li>" +
     116                        "<li>-49 29.4 N -19 24.5 W</li></ul>" +
     117                        "<li>48 deg 42' 52.13\" N, 21 deg 11' 47.60\" E</li></ul>"
     118                                )),
     119                GBC.eol().fill().weight(1.0, 1.0));
    70120
    71121        // parse and verify input on the fly
    72122        //
    73123        LatLonInputVerifier inputVerifier = new LatLonInputVerifier();
    74         tfLat.getDocument().addDocumentListener(inputVerifier);
    75         tfLon.getDocument().addDocumentListener(inputVerifier);
     124        tfLatLon.getDocument().addDocumentListener(inputVerifier);
    76125
    77126        // select the text in the field on focus
    78127        //
    79128        TextFieldFocusHandler focusHandler = new TextFieldFocusHandler();
    80         tfLat.addFocusListener(focusHandler);
    81         tfLon.addFocusListener(focusHandler);
     129        tfLatLon.addFocusListener(focusHandler);
    82130        return pnl;
    83131    }
     
    131179        }
    132180        this.coordinates = coordinates;
    133         tfLat.setText(coordinates.latToString(CoordinateFormat.DECIMAL_DEGREES));
    134         tfLon.setText(coordinates.lonToString(CoordinateFormat.DECIMAL_DEGREES));
     181        tfLatLon.setText(coordinates.latToString(CoordinateFormat.DEGREES_MINUTES_SECONDS) + " " + coordinates.lonToString(CoordinateFormat.DEGREES_MINUTES_SECONDS));
    135182        actOK.setEnabled(true);
    136183    }
     
    157204        //
    158205        input = input.trim();
    159         input = input.replaceAll("\u00B0", ""); // the degree symbol
     206        input = input.replaceAll(DEG, "");
    160207
    161208        // try to parse using the current locale
     
    177224    }
    178225
    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     }
    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 
    201226    protected void parseUserInput() {
    202         Double lat = parseLatFromUserInput();
    203         Double lon = parseLonFromUserInput();
    204         if (lat == null || lon == null) {
     227        LatLon latLon;
     228        try {
     229            latLon = parse(tfLatLon.getText());
     230            if (!LatLon.isValidLat(latLon.lat()) || !LatLon.isValidLon(latLon.lon())) {
     231                latLon = null;
     232            }
     233        } catch (IllegalArgumentException e) {
     234            latLon = null;
     235        }
     236        if (latLon == null) {
     237            setErrorFeedback(tfLatLon, tr("Please enter a GPS coordinates"));
    205238            coordinates = null;
    206239            actOK.setEnabled(false);
    207240        } else {
    208             coordinates = new LatLon(lat,lon);
     241            clearErrorFeedback(tfLatLon,tr("Please enter a GPS coordinates"));
     242            coordinates = latLon;
    209243            actOK.setEnabled(true);
    210244        }
     
    288322        @Override
    289323        public void windowOpened(WindowEvent e) {
    290             tfLat.requestFocusInWindow();
    291         }
    292     }
    293 
     324            tfLatLon.requestFocusInWindow();
     325        }
     326    }
     327
     328    private static LatLon parse(final String coord) {
     329        final Matcher m = p.matcher(coord);
     330
     331        final StringBuilder sb = new StringBuilder();
     332        final List<Object> list = new ArrayList<Object>();
     333
     334        while (m.find()) {
     335            if (m.group(1) != null) {
     336                sb.append('R');     // floating point number
     337                list.add(Double.parseDouble(m.group(1).replace(',', '.')));
     338            } else if (m.group(2) != null) {
     339                sb.append('Z');     // integer number
     340                list.add(Double.parseDouble(m.group(2)));
     341            } else if (m.group(3) != null) {
     342                sb.append('o');     // degree sign
     343            } else if (m.group(4) != null) {
     344                sb.append('\'');    // seconds sign
     345            } else if (m.group(5) != null) {
     346                sb.append('"');     // minutes sign
     347            } else if (m.group(6) != null) {
     348                sb.append(',');     // separator
     349            } else if (m.group(7) != null) {
     350                sb.append("x");     // cardinal direction
     351                String c = m.group(7).toUpperCase();
     352                if (c.equals("N") || c.equals("S") || c.equals("E") || c.equals("W")) {
     353                    list.add(c);
     354                } else {
     355                    list.add(c.replace(N_TR, 'N').replace(S_TR, 'S')
     356                            .replace(E_TR, 'E').replace(W_TR, 'W'));
     357                }
     358            } else if (m.group(8) != null) {
     359                throw new IllegalArgumentException("invalid token: " + m.group(8));
     360            }
     361        }
     362
     363        final String pattern = sb.toString();
     364
     365        final Object[] params = list.toArray();
     366        final LatLonHolder latLon = new LatLonHolder();
     367
     368        if (pattern.matches("Ro?,?Ro?")) {
     369            setLatLonObj(latLon,
     370                    params[0], ZERO, ZERO, "N",
     371                    params[1], ZERO, ZERO, "E");
     372        } else if (pattern.matches("xRo?,?xRo?")) {
     373            setLatLonObj(latLon,
     374                    params[1], ZERO, ZERO, params[0],
     375                    params[3], ZERO, ZERO, params[2]);
     376        } else if (pattern.matches("Ro?x,?Ro?x")) {
     377            setLatLonObj(latLon,
     378                    params[0], ZERO, ZERO, params[1],
     379                    params[2], ZERO, ZERO, params[3]);
     380        } else if (pattern.matches("Zo[RZ]'?,?Zo[RZ]'?|Z[RZ],?Z[RZ]")) {
     381            setLatLonObj(latLon,
     382                    params[0], params[1], ZERO, "N",
     383                    params[2], params[3], ZERO, "E");
     384        } else if (pattern.matches("xZo[RZ]'?,?xZo[RZ]'?|xZo?[RZ],?xZo?[RZ]")) {
     385            setLatLonObj(latLon,
     386                    params[1], params[2], ZERO, params[0],
     387                    params[4], params[5], ZERO, params[3]);
     388        } else if (pattern.matches("Zo[RZ]'?x,?Zo[RZ]'?x|Zo?[RZ]x,?Zo?[RZ]x")) {
     389            setLatLonObj(latLon,
     390                    params[0], params[1], ZERO, params[2],
     391                    params[3], params[4], ZERO, params[5]);
     392        } else if (pattern.matches("ZoZ'[RZ]\"?x,?ZoZ'[RZ]\"?x|ZZ[RZ]x,?ZZ[RZ]x")) {
     393            setLatLonObj(latLon,
     394                    params[0], params[1], params[2], params[3],
     395                    params[4], params[5], params[6], params[7]);
     396        } else if (pattern.matches("xZoZ'[RZ]\"?,?xZoZ'[RZ]\"?|xZZ[RZ],?xZZ[RZ]")) {
     397            setLatLonObj(latLon,
     398                    params[1], params[2], params[3], params[0],
     399                    params[5], params[6], params[7], params[4]);
     400        } else if (pattern.matches("ZZ[RZ],?ZZ[RZ]")) {
     401            setLatLonObj(latLon,
     402                    params[0], params[1], params[2], "N",
     403                    params[3], params[4], params[5], "E");
     404        } else {
     405            throw new IllegalArgumentException("invalid format: " + pattern);
     406        }
     407
     408        return new LatLon(latLon.lat, latLon.lon);
     409    }
     410
     411    private static class LatLonHolder {
     412        double lat, lon;
     413    }
     414
     415    private static void setLatLonObj(final LatLonHolder latLon,
     416            final Object coord1deg, final Object coord1min, final Object coord1sec, final Object card1,
     417            final Object coord2deg, final Object coord2min, final Object coord2sec, final Object card2) {
     418
     419        setLatLon(latLon,
     420                (Double) coord1deg, (Double) coord1min, (Double) coord1sec, (String) card1,
     421                (Double) coord2deg, (Double) coord2min, (Double) coord2sec, (String) card2);
     422    }
     423
     424    private static void setLatLon(final LatLonHolder latLon,
     425            final double coord1deg, final double coord1min, final double coord1sec, final String card1,
     426            final double coord2deg, final double coord2min, final double coord2sec, final String card2) {
     427
     428        setLatLon(latLon, coord1deg, coord1min, coord1sec, card1);
     429        setLatLon(latLon, coord2deg, coord2min, coord2sec, card2);
     430    }
     431
     432    private static void setLatLon(final LatLonHolder latLon, final double coordDeg, final double coordMin, final double coordSec, final String card) {
     433        if (coordDeg < -180 || coordDeg > 180 || coordMin < 0 || coordMin >= 60 || coordSec < 0 || coordSec > 60) {
     434            throw new IllegalArgumentException("out of range");
     435        }
     436
     437        double coord = (coordDeg < 0 ? -1 : 1) * (Math.abs(coordDeg) + coordMin / 60 + coordSec / 3600);
     438        coord = card.equals("N") || card.equals("E") ? coord : -coord;
     439        if (card.equals("N") || card.equals("S")) {
     440            latLon.lat = coord;
     441        } else {
     442            latLon.lon = coord;
     443        }
     444    }
     445
     446    public String getText() {
     447        return tfLatLon.getText();
     448    }
     449
     450    public void setText(String text) {
     451        tfLatLon.setText(text);
     452    }
    294453}
Note: See TracChangeset for help on using the changeset viewer.