| | 1 | // License: GPL. For details, see LICENSE file. |
| | 2 | package utilsplugin2; |
| | 3 | |
| | 4 | import static org.openstreetmap.josm.tools.I18n.tr; |
| | 5 | |
| | 6 | import java.awt.Color; |
| | 7 | import java.awt.Component; |
| | 8 | import java.awt.GridBagLayout; |
| | 9 | import java.awt.event.ActionEvent; |
| | 10 | import java.awt.event.FocusEvent; |
| | 11 | import java.awt.event.FocusListener; |
| | 12 | import java.awt.event.WindowAdapter; |
| | 13 | import java.awt.event.WindowEvent; |
| | 14 | import java.text.NumberFormat; |
| | 15 | import java.text.ParsePosition; |
| | 16 | import java.util.ArrayList; |
| | 17 | import java.util.List; |
| | 18 | import java.util.Locale; |
| | 19 | import java.util.regex.Matcher; |
| | 20 | import java.util.regex.Pattern; |
| | 21 | |
| | 22 | import javax.swing.AbstractAction; |
| | 23 | import javax.swing.BorderFactory; |
| | 24 | import javax.swing.JLabel; |
| | 25 | import javax.swing.JPanel; |
| | 26 | import javax.swing.JSeparator; |
| | 27 | import javax.swing.JTabbedPane; |
| | 28 | |
| | 29 | import javax.swing.text.Document; |
| | 30 | import javax.swing.JTextArea; |
| | 31 | import javax.swing.JScrollPane; |
| | 32 | import javax.swing.ButtonGroup; |
| | 33 | import javax.swing.JRadioButton; |
| | 34 | |
| | 35 | import javax.swing.UIManager; |
| | 36 | import javax.swing.event.ChangeEvent; |
| | 37 | import javax.swing.event.ChangeListener; |
| | 38 | import javax.swing.event.DocumentEvent; |
| | 39 | import javax.swing.event.DocumentListener; |
| | 40 | |
| | 41 | import org.openstreetmap.josm.Main; |
| | 42 | import org.openstreetmap.josm.data.coor.CoordinateFormat; |
| | 43 | import org.openstreetmap.josm.data.coor.LatLon; |
| | 44 | import org.openstreetmap.josm.gui.ExtendedDialog; |
| | 45 | import org.openstreetmap.josm.gui.widgets.HtmlPanel; |
| | 46 | import org.openstreetmap.josm.tools.GBC; |
| | 47 | import org.openstreetmap.josm.tools.ImageProvider; |
| | 48 | import org.openstreetmap.josm.tools.WindowGeometry; |
| | 49 | |
| | 50 | public class LatLonDialog extends ExtendedDialog { |
| | 51 | private static final Color BG_COLOR_ERROR = new Color(255,224,224); |
| | 52 | |
| | 53 | public JTabbedPane tabs; |
| | 54 | private JTextArea taLatLon; |
| | 55 | private JScrollPane spScroll; |
| | 56 | private JRadioButton rbNodes; |
| | 57 | private JRadioButton rbWay; |
| | 58 | private JRadioButton rbClosedWay; |
| | 59 | private ButtonGroup bgType; |
| | 60 | private String geomType; |
| | 61 | |
| | 62 | private LatLon[] latLonCoordinates; |
| | 63 | |
| | 64 | private static final double ZERO = 0.0; |
| | 65 | private static final String DEG = "\u00B0"; |
| | 66 | private static final String MIN = "\u2032"; |
| | 67 | private static final String SEC = "\u2033"; |
| | 68 | |
| | 69 | private static final char N_TR = LatLon.NORTH.charAt(0); |
| | 70 | private static final char S_TR = LatLon.SOUTH.charAt(0); |
| | 71 | private static final char E_TR = LatLon.EAST.charAt(0); |
| | 72 | private static final char W_TR = LatLon.WEST.charAt(0); |
| | 73 | |
| | 74 | private static final Pattern p = Pattern.compile( |
| | 75 | "([+|-]?\\d+[.,]\\d+)|" // (1) |
| | 76 | + "([+|-]?\\d+)|" // (2) |
| | 77 | + "("+DEG+"|o|deg)|" // (3) |
| | 78 | + "('|"+MIN+"|min)|" // (4) |
| | 79 | + "(\"|"+SEC+"|sec)|" // (5) |
| | 80 | + "(,|;)|" // (6) |
| | 81 | + "([NSEW"+N_TR+S_TR+E_TR+W_TR+"])|"// (7) |
| | 82 | + "\\s+|" |
| | 83 | + "(.+)"); |
| | 84 | |
| | 85 | protected JPanel buildLatLon() { |
| | 86 | JPanel pnl = new JPanel(new GridBagLayout()); |
| | 87 | pnl.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); |
| | 88 | |
| | 89 | pnl.add(new JLabel(tr("Coordinates:")), GBC.std().insets(0,10,5,0)); |
| | 90 | |
| | 91 | taLatLon = new JTextArea(5,24); |
| | 92 | taLatLon.getDocument().addDocumentListener(new CoordinateListener()); |
| | 93 | spScroll = new JScrollPane(taLatLon); |
| | 94 | pnl.add(spScroll, GBC.eol().insets(0,10,0,0).fill().weight(2.0, 2.0)); |
| | 95 | |
| | 96 | //Radio button setup |
| | 97 | bgType = new ButtonGroup(); |
| | 98 | |
| | 99 | rbNodes = new JRadioButton("Nodes", true); |
| | 100 | rbNodes.setActionCommand("nodes"); |
| | 101 | bgType.add(rbNodes); |
| | 102 | pnl.add(rbNodes, GBC.eol()); |
| | 103 | |
| | 104 | rbWay = new JRadioButton("Way"); |
| | 105 | rbWay.setActionCommand("way"); |
| | 106 | bgType.add(rbWay); |
| | 107 | pnl.add(rbWay, GBC.eol()); |
| | 108 | |
| | 109 | rbClosedWay = new JRadioButton("Closed Way (Area)"); |
| | 110 | rbClosedWay.setActionCommand("area"); |
| | 111 | bgType.add(rbClosedWay); |
| | 112 | pnl.add(rbClosedWay, GBC.eol()); |
| | 113 | |
| | 114 | //pnl.add(bgType, GBC.eol().insets(0,10,0,0).fill(GBC.HORIZONTAL).weight(2.0, 0.0)); |
| | 115 | //pnl.add(new JRadioButton("test")); |
| | 116 | //pnl.add(bgType); |
| | 117 | |
| | 118 | pnl.add(new JSeparator(), GBC.eol().fill(GBC.HORIZONTAL).insets(0,5,0,5)); |
| | 119 | |
| | 120 | pnl.add(new HtmlPanel( |
| | 121 | tr("Enter the coordinates for the new nodes, one for each line.<br/>If you enter two lines with the same coordinates there will be generated duplicate nodes.<br/>You can separate longitude and latitude with space, comma or semicolon.<br/>" + |
| | 122 | "Use positive numbers or N, E characters to indicate North or East cardinal direction.<br/>" + |
| | 123 | "For South and West cardinal directions you can use either negative numbers or S, W characters.<br/>" + |
| | 124 | "Coordinate value can be in one of three formats:<ul>" + |
| | 125 | "<li><i>degrees</i><tt>°</tt></li>" + |
| | 126 | "<li><i>degrees</i><tt>°</tt> <i>minutes</i><tt>'</tt></li>" + |
| | 127 | "<li><i>degrees</i><tt>°</tt> <i>minutes</i><tt>'</tt> <i>seconds</i><tt>"</tt></li>" + |
| | 128 | "</ul>" + |
| | 129 | "Symbols <tt>°</tt>, <tt>'</tt>, <tt>′</tt>, <tt>"</tt>, <tt>″</tt> are optional.<br/><br/>" + |
| | 130 | "Some examples:<ul>" + |
| | 131 | "<li>49.29918° 19.24788°</li>" + |
| | 132 | "<li>N 49.29918 E 19.24788</li>" + |
| | 133 | "<li>W 49°29.918' S 19°24.788'</li>" + |
| | 134 | "<li>N 49°29'04" E 19°24'43"</li>" + |
| | 135 | "<li>49.29918 N, 19.24788 E</li>" + |
| | 136 | "<li>49°29'21" N 19°24'38" E</li>" + |
| | 137 | "<li>49 29 51, 19 24 18</li>" + |
| | 138 | "<li>49 29, 19 24</li>" + |
| | 139 | "<li>E 49 29, N 19 24</li>" + |
| | 140 | "<li>49° 29; 19° 24</li>" + |
| | 141 | "<li>N 49° 29, W 19° 24</li>" + |
| | 142 | "<li>49° 29.5 S, 19° 24.6 E</li>" + |
| | 143 | "<li>N 49 29.918 E 19 15.88</li>" + |
| | 144 | "<li>49 29.4 19 24.5</li>" + |
| | 145 | "<li>-49 29.4 N -19 24.5 W</li></ul>" + |
| | 146 | "<li>48 deg 42' 52.13\" N, 21 deg 11' 47.60\" E</li></ul>" |
| | 147 | )), |
| | 148 | GBC.eol().fill().weight(1.0, 1.0)); |
| | 149 | |
| | 150 | // parse and verify input on the fly |
| | 151 | // |
| | 152 | LatLonInputVerifier inputVerifier = new LatLonInputVerifier(); |
| | 153 | taLatLon.getDocument().addDocumentListener(inputVerifier); |
| | 154 | |
| | 155 | // select the text in the field on focus |
| | 156 | // |
| | 157 | TextFieldFocusHandler focusHandler = new TextFieldFocusHandler(); |
| | 158 | taLatLon.addFocusListener(focusHandler); |
| | 159 | return pnl; |
| | 160 | } |
| | 161 | |
| | 162 | protected void build() { |
| | 163 | tabs = new JTabbedPane(); |
| | 164 | tabs.addTab(tr("Lat/Lon"), buildLatLon()); |
| | 165 | tabs.getModel().addChangeListener(new ChangeListener() { |
| | 166 | @Override |
| | 167 | public void stateChanged(ChangeEvent e) { |
| | 168 | switch (tabs.getModel().getSelectedIndex()) { |
| | 169 | case 0: parseLatLonUserInput(); break; |
| | 170 | default: throw new AssertionError(); |
| | 171 | } |
| | 172 | } |
| | 173 | }); |
| | 174 | setContent(tabs, false); |
| | 175 | } |
| | 176 | |
| | 177 | public LatLonDialog(Component parent, String title, String help) { |
| | 178 | super(Main.parent, tr("Add Node..."), new String[] { tr("Ok"), tr("Cancel") }); |
| | 179 | setButtonIcons(new String[] { "ok", "cancel" }); |
| | 180 | configureContextsensitiveHelp("/Action/AddNode", true); |
| | 181 | |
| | 182 | build(); |
| | 183 | setCoordinates(null); |
| | 184 | } |
| | 185 | |
| | 186 | public void setCoordinates(LatLon[] ll) { |
| | 187 | if (ll == null) { |
| | 188 | ll = new LatLon[] {}; |
| | 189 | } |
| | 190 | this.latLonCoordinates = ll; |
| | 191 | String text = ""; |
| | 192 | for (LatLon latlon : ll) { |
| | 193 | text = text + latlon.latToString(CoordinateFormat.getDefaultFormat()) + " " + latlon.lonToString(CoordinateFormat.getDefaultFormat()) + "\n"; |
| | 194 | } |
| | 195 | taLatLon.setText(text); |
| | 196 | setOkEnabled(true); |
| | 197 | } |
| | 198 | |
| | 199 | public LatLon[] getCoordinates() { |
| | 200 | return latLonCoordinates; |
| | 201 | } |
| | 202 | |
| | 203 | public LatLon[] getLatLonCoordinates() { |
| | 204 | return latLonCoordinates; |
| | 205 | } |
| | 206 | |
| | 207 | public String getGeomType() { |
| | 208 | return bgType.getSelection().getActionCommand(); |
| | 209 | } |
| | 210 | |
| | 211 | protected void setErrorFeedback(JTextArea tf, String message) { |
| | 212 | tf.setBorder(BorderFactory.createLineBorder(Color.RED, 1)); |
| | 213 | tf.setToolTipText(message); |
| | 214 | tf.setBackground(BG_COLOR_ERROR); |
| | 215 | } |
| | 216 | |
| | 217 | protected void clearErrorFeedback(JTextArea tf, String message) { |
| | 218 | tf.setBorder(UIManager.getBorder("TextField.border")); |
| | 219 | tf.setToolTipText(message); |
| | 220 | tf.setBackground(UIManager.getColor("TextField.background")); |
| | 221 | } |
| | 222 | |
| | 223 | protected Double parseDoubleFromUserInput(String input) { |
| | 224 | if (input == null) return null; |
| | 225 | // remove white space and an optional degree symbol |
| | 226 | // |
| | 227 | input = input.trim(); |
| | 228 | input = input.replaceAll(DEG, ""); |
| | 229 | |
| | 230 | // try to parse using the current locale |
| | 231 | // |
| | 232 | NumberFormat f = NumberFormat.getNumberInstance(); |
| | 233 | Number n=null; |
| | 234 | ParsePosition pp = new ParsePosition(0); |
| | 235 | n = f.parse(input,pp); |
| | 236 | if (pp.getErrorIndex() >= 0 || pp.getIndex()<input.length()) { |
| | 237 | // fall back - try to parse with the english locale |
| | 238 | // |
| | 239 | pp = new ParsePosition(0); |
| | 240 | f = NumberFormat.getNumberInstance(Locale.ENGLISH); |
| | 241 | n = f.parse(input, pp); |
| | 242 | if (pp.getErrorIndex() >= 0 || pp.getIndex()<input.length()) |
| | 243 | return null; |
| | 244 | } |
| | 245 | return n== null ? null : n.doubleValue(); |
| | 246 | } |
| | 247 | |
| | 248 | protected void parseLatLonUserInput() { |
| | 249 | LatLon[] latLons; |
| | 250 | try { |
| | 251 | latLons = parseLatLons(taLatLon.getText()); |
| | 252 | Boolean working = true; |
| | 253 | int i=0; |
| | 254 | while (working && i < latLons.length) { |
| | 255 | if (!LatLon.isValidLat(latLons[i].lat()) || !LatLon.isValidLon(latLons[i].lon())) { |
| | 256 | latLons = null; |
| | 257 | working = false; |
| | 258 | } |
| | 259 | i++; |
| | 260 | } |
| | 261 | } catch (IllegalArgumentException e) { |
| | 262 | latLons = null; |
| | 263 | } |
| | 264 | if (latLons == null) { |
| | 265 | setErrorFeedback(taLatLon, tr("Please enter a GPS coordinates")); |
| | 266 | latLonCoordinates = null; |
| | 267 | setOkEnabled(false); |
| | 268 | } else { |
| | 269 | clearErrorFeedback(taLatLon,tr("Please enter a GPS coordinates")); |
| | 270 | latLonCoordinates = latLons; |
| | 271 | setOkEnabled(true); |
| | 272 | } |
| | 273 | } |
| | 274 | |
| | 275 | private void setOkEnabled(boolean b) { |
| | 276 | if (buttons != null && buttons.size() > 0) { |
| | 277 | buttons.get(0).setEnabled(b); |
| | 278 | } |
| | 279 | } |
| | 280 | |
| | 281 | @Override |
| | 282 | public void setVisible(boolean visible) { |
| | 283 | if (visible) { |
| | 284 | WindowGeometry.centerInWindow(Main.parent, getSize()).applySafe(this); |
| | 285 | } |
| | 286 | super.setVisible(visible); |
| | 287 | } |
| | 288 | |
| | 289 | class LatLonInputVerifier implements DocumentListener { |
| | 290 | public void changedUpdate(DocumentEvent e) { |
| | 291 | parseLatLonUserInput(); |
| | 292 | } |
| | 293 | |
| | 294 | public void insertUpdate(DocumentEvent e) { |
| | 295 | parseLatLonUserInput(); |
| | 296 | } |
| | 297 | |
| | 298 | public void removeUpdate(DocumentEvent e) { |
| | 299 | parseLatLonUserInput(); |
| | 300 | } |
| | 301 | } |
| | 302 | |
| | 303 | static class TextFieldFocusHandler implements FocusListener { |
| | 304 | public void focusGained(FocusEvent e) { |
| | 305 | Component c = e.getComponent(); |
| | 306 | if (c instanceof JTextArea) { |
| | 307 | JTextArea tf = (JTextArea)c; |
| | 308 | tf.selectAll(); |
| | 309 | } |
| | 310 | } |
| | 311 | public void focusLost(FocusEvent e) {} |
| | 312 | } |
| | 313 | |
| | 314 | private static LatLon[] parseLatLons(final String text) { |
| | 315 | String lines[] = text.split("\\r?\\n"); |
| | 316 | List<LatLon> latLons = new ArrayList<LatLon>(); |
| | 317 | for (String line : lines) { |
| | 318 | latLons.add(parseLatLon(line)); |
| | 319 | } |
| | 320 | return latLons.toArray(new LatLon[]{}); |
| | 321 | } |
| | 322 | |
| | 323 | private static LatLon parseLatLon(final String coord) { |
| | 324 | final Matcher m = p.matcher(coord); |
| | 325 | |
| | 326 | final StringBuilder sb = new StringBuilder(); |
| | 327 | final List<Object> list = new ArrayList<Object>(); |
| | 328 | |
| | 329 | while (m.find()) { |
| | 330 | if (m.group(1) != null) { |
| | 331 | sb.append('R'); // floating point number |
| | 332 | list.add(Double.parseDouble(m.group(1).replace(',', '.'))); |
| | 333 | } else if (m.group(2) != null) { |
| | 334 | sb.append('Z'); // integer number |
| | 335 | list.add(Double.parseDouble(m.group(2))); |
| | 336 | } else if (m.group(3) != null) { |
| | 337 | sb.append('o'); // degree sign |
| | 338 | } else if (m.group(4) != null) { |
| | 339 | sb.append('\''); // seconds sign |
| | 340 | } else if (m.group(5) != null) { |
| | 341 | sb.append('"'); // minutes sign |
| | 342 | } else if (m.group(6) != null) { |
| | 343 | sb.append(','); // separator |
| | 344 | } else if (m.group(7) != null) { |
| | 345 | sb.append("x"); // cardinal direction |
| | 346 | String c = m.group(7).toUpperCase(); |
| | 347 | if (c.equals("N") || c.equals("S") || c.equals("E") || c.equals("W")) { |
| | 348 | list.add(c); |
| | 349 | } else { |
| | 350 | list.add(c.replace(N_TR, 'N').replace(S_TR, 'S') |
| | 351 | .replace(E_TR, 'E').replace(W_TR, 'W')); |
| | 352 | } |
| | 353 | } else if (m.group(8) != null) { |
| | 354 | throw new IllegalArgumentException("invalid token: " + m.group(8)); |
| | 355 | } |
| | 356 | } |
| | 357 | |
| | 358 | final String pattern = sb.toString(); |
| | 359 | |
| | 360 | final Object[] params = list.toArray(); |
| | 361 | final LatLonHolder latLon = new LatLonHolder(); |
| | 362 | |
| | 363 | if (pattern.matches("Ro?,?Ro?")) { |
| | 364 | setLatLonObj(latLon, |
| | 365 | params[0], ZERO, ZERO, "N", |
| | 366 | params[1], ZERO, ZERO, "E"); |
| | 367 | } else if (pattern.matches("xRo?,?xRo?")) { |
| | 368 | setLatLonObj(latLon, |
| | 369 | params[1], ZERO, ZERO, params[0], |
| | 370 | params[3], ZERO, ZERO, params[2]); |
| | 371 | } else if (pattern.matches("Ro?x,?Ro?x")) { |
| | 372 | setLatLonObj(latLon, |
| | 373 | params[0], ZERO, ZERO, params[1], |
| | 374 | params[2], ZERO, ZERO, params[3]); |
| | 375 | } else if (pattern.matches("Zo[RZ]'?,?Zo[RZ]'?|Z[RZ],?Z[RZ]")) { |
| | 376 | setLatLonObj(latLon, |
| | 377 | params[0], params[1], ZERO, "N", |
| | 378 | params[2], params[3], ZERO, "E"); |
| | 379 | } else if (pattern.matches("xZo[RZ]'?,?xZo[RZ]'?|xZo?[RZ],?xZo?[RZ]")) { |
| | 380 | setLatLonObj(latLon, |
| | 381 | params[1], params[2], ZERO, params[0], |
| | 382 | params[4], params[5], ZERO, params[3]); |
| | 383 | } else if (pattern.matches("Zo[RZ]'?x,?Zo[RZ]'?x|Zo?[RZ]x,?Zo?[RZ]x")) { |
| | 384 | setLatLonObj(latLon, |
| | 385 | params[0], params[1], ZERO, params[2], |
| | 386 | params[3], params[4], ZERO, params[5]); |
| | 387 | } else if (pattern.matches("ZoZ'[RZ]\"?x,?ZoZ'[RZ]\"?x|ZZ[RZ]x,?ZZ[RZ]x")) { |
| | 388 | setLatLonObj(latLon, |
| | 389 | params[0], params[1], params[2], params[3], |
| | 390 | params[4], params[5], params[6], params[7]); |
| | 391 | } else if (pattern.matches("xZoZ'[RZ]\"?,?xZoZ'[RZ]\"?|xZZ[RZ],?xZZ[RZ]")) { |
| | 392 | setLatLonObj(latLon, |
| | 393 | params[1], params[2], params[3], params[0], |
| | 394 | params[5], params[6], params[7], params[4]); |
| | 395 | } else if (pattern.matches("ZZ[RZ],?ZZ[RZ]")) { |
| | 396 | setLatLonObj(latLon, |
| | 397 | params[0], params[1], params[2], "N", |
| | 398 | params[3], params[4], params[5], "E"); |
| | 399 | } else { |
| | 400 | throw new IllegalArgumentException("invalid format: " + pattern); |
| | 401 | } |
| | 402 | |
| | 403 | return new LatLon(latLon.lat, latLon.lon); |
| | 404 | } |
| | 405 | |
| | 406 | private static class LatLonHolder { |
| | 407 | double lat, lon; |
| | 408 | } |
| | 409 | |
| | 410 | private static void setLatLonObj(final LatLonHolder latLon, |
| | 411 | final Object coord1deg, final Object coord1min, final Object coord1sec, final Object card1, |
| | 412 | final Object coord2deg, final Object coord2min, final Object coord2sec, final Object card2) { |
| | 413 | |
| | 414 | setLatLon(latLon, |
| | 415 | (Double) coord1deg, (Double) coord1min, (Double) coord1sec, (String) card1, |
| | 416 | (Double) coord2deg, (Double) coord2min, (Double) coord2sec, (String) card2); |
| | 417 | } |
| | 418 | |
| | 419 | private static void setLatLon(final LatLonHolder latLon, |
| | 420 | final double coord1deg, final double coord1min, final double coord1sec, final String card1, |
| | 421 | final double coord2deg, final double coord2min, final double coord2sec, final String card2) { |
| | 422 | |
| | 423 | setLatLon(latLon, coord1deg, coord1min, coord1sec, card1); |
| | 424 | setLatLon(latLon, coord2deg, coord2min, coord2sec, card2); |
| | 425 | } |
| | 426 | |
| | 427 | private static void setLatLon(final LatLonHolder latLon, final double coordDeg, final double coordMin, final double coordSec, final String card) { |
| | 428 | if (coordDeg < -180 || coordDeg > 180 || coordMin < 0 || coordMin >= 60 || coordSec < 0 || coordSec > 60) { |
| | 429 | throw new IllegalArgumentException("out of range"); |
| | 430 | } |
| | 431 | |
| | 432 | double coord = (coordDeg < 0 ? -1 : 1) * (Math.abs(coordDeg) + coordMin / 60 + coordSec / 3600); |
| | 433 | coord = card.equals("N") || card.equals("E") ? coord : -coord; |
| | 434 | if (card.equals("N") || card.equals("S")) { |
| | 435 | latLon.lat = coord; |
| | 436 | } else { |
| | 437 | latLon.lon = coord; |
| | 438 | } |
| | 439 | } |
| | 440 | |
| | 441 | public String getLatLonText() { |
| | 442 | return taLatLon.getText(); |
| | 443 | } |
| | 444 | |
| | 445 | public void setLatLonText(String text) { |
| | 446 | taLatLon.setText(text); |
| | 447 | } |
| | 448 | |
| | 449 | private class CoordinateListener implements DocumentListener { |
| | 450 | public void changedUpdate(DocumentEvent e) { |
| | 451 | //not fired |
| | 452 | } |
| | 453 | public void insertUpdate(DocumentEvent e) { |
| | 454 | updateButtons(); |
| | 455 | } |
| | 456 | public void removeUpdate(DocumentEvent e) { |
| | 457 | updateButtons(); |
| | 458 | } |
| | 459 | private void updateButtons() { |
| | 460 | String text = taLatLon.getText(); |
| | 461 | String[] lines = text.split("\r\n|\r|\n"); |
| | 462 | rbNodes.setEnabled(true); |
| | 463 | rbWay.setEnabled(true); |
| | 464 | rbClosedWay.setEnabled(true); |
| | 465 | if (lines.length < 3) { |
| | 466 | rbClosedWay.setEnabled(false); |
| | 467 | bgType.setSelected(rbNodes.getModel(), true); |
| | 468 | } |
| | 469 | if (lines.length < 2) { |
| | 470 | rbWay.setEnabled(false); |
| | 471 | bgType.setSelected(rbNodes.getModel(), true); |
| | 472 | } |
| | 473 | } |
| | 474 | } |
| | 475 | } |