001 // License: GPL. For details, see LICENSE file. 002 package org.openstreetmap.josm.gui.widgets; 003 004 import static org.openstreetmap.josm.tools.I18n.tr; 005 006 import java.util.ArrayList; 007 import java.util.List; 008 import java.util.StringTokenizer; 009 010 import javax.swing.JTextField; 011 import javax.swing.text.JTextComponent; 012 013 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 014 import org.openstreetmap.josm.data.osm.PrimitiveId; 015 import org.openstreetmap.josm.data.osm.SimplePrimitiveId; 016 017 /** 018 * @author Matthias Julius 019 */ 020 public class OsmIdTextField extends JTextField { 021 022 private OsmIdValidator validator; 023 024 public OsmIdTextField() { 025 validator = OsmIdValidator.decorate(this); 026 } 027 028 public void setType(OsmPrimitiveType type) { 029 validator.type = type; 030 } 031 032 /** 033 * Get entered ID list - supports "1,2,3" "1 2 ,3" or even "1 2 3 v2 6 v8" 034 * @return list of id's 035 */ 036 public List<PrimitiveId> getIds() { 037 return validator.ids; 038 } 039 040 public boolean readOsmIds() { 041 return validator.readOsmIds(); 042 } 043 044 public void performValidation() { 045 validator.validate(); 046 } 047 048 public void clearTextIfInvalid() { 049 if (!validator.isValid()) 050 setText(""); 051 validator.validate(); 052 } 053 054 /** 055 * Validator for a changeset ID entered in a {@link JTextComponent}. 056 * 057 */ 058 static private class OsmIdValidator extends AbstractTextComponentValidator { 059 060 static public OsmIdValidator decorate(JTextComponent tc) { 061 return new OsmIdValidator(tc); 062 } 063 064 private List<PrimitiveId> ids = new ArrayList<PrimitiveId>(); 065 private OsmPrimitiveType type; 066 067 public OsmIdValidator(JTextComponent tc) { 068 super(tc, false); 069 } 070 071 @Override 072 public boolean isValid() { 073 return readOsmIds(); 074 } 075 076 @Override 077 public void validate() { 078 if (!isValid()) { 079 feedbackInvalid(tr("The current value is not a valid OSM ID. Please enter an integer value > 0")); 080 } else { 081 feedbackValid(tr("Please enter an integer value > 0")); 082 } 083 } 084 085 public boolean readOsmIds() { 086 String value = getComponent().getText(); 087 char c; 088 if (value == null || value.trim().length() == 0) { 089 return false; 090 } 091 ids.clear(); 092 StringTokenizer st = new StringTokenizer(value, ",.+/ \t\n"); 093 String s; 094 while (st.hasMoreTokens()) { 095 s = st.nextToken(); 096 // convert tokens to int skipping v-words (version v2 etc) 097 c = s.charAt(0); 098 if (c == 'v') { 099 continue; 100 } else { 101 try { 102 ids.add(SimplePrimitiveId.fromString(s)); 103 } catch (IllegalArgumentException ex) { 104 try { 105 long id = Long.parseLong(s); 106 if (id <= 0) { 107 return false; 108 } else if (type == OsmPrimitiveType.NODE) { 109 ids.add(new SimplePrimitiveId(id, OsmPrimitiveType.NODE)); 110 } else if (type == OsmPrimitiveType.WAY) { 111 ids.add(new SimplePrimitiveId(id, OsmPrimitiveType.WAY)); 112 } else if (type == OsmPrimitiveType.RELATION) { 113 ids.add(new SimplePrimitiveId(id, OsmPrimitiveType.RELATION)); 114 } else { 115 return false; 116 } 117 } catch (IllegalArgumentException ex2) { 118 return false; 119 } 120 } 121 } 122 } 123 return true; 124 } 125 } 126 }