Changeset 12778 in osm for applications/editors/josm/plugins/namefinder
- Timestamp:
- 2009-01-01T18:28:53+01:00 (17 years ago)
- Location:
- applications/editors/josm/plugins/namefinder/namefinder
- Files:
-
- 2 edited
-
NameFinderPlugin.java (modified) (1 diff)
-
PlaceSelection.java (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/namefinder/namefinder/NameFinderPlugin.java
r2925 r12778 10 10 /** 11 11 * Main class for the name finder plugin. 12 * 13 * 12 * 13 * 14 14 * @author Frederik Ramm <frederik@remote.org> 15 15 * 16 16 */ 17 public class NameFinderPlugin extends Plugin 18 { 19 public NameFinderPlugin() 17 public class NameFinderPlugin extends Plugin 18 { 19 public NameFinderPlugin() 20 20 { 21 21 } 22 23 @Override public void addDownloadSelection(List<DownloadSelection> list) 22 23 @Override public void addDownloadSelection(List<DownloadSelection> list) 24 24 { 25 list.add(new PlaceSelection());25 list.add(new PlaceSelection()); 26 26 } 27 27 28 28 } -
applications/editors/josm/plugins/namefinder/namefinder/PlaceSelection.java
r12563 r12778 42 42 public class PlaceSelection implements DownloadSelection { 43 43 44 private JTextField searchTerm = new JTextField();45 private JButton submitSearch = new JButton(tr("Search..."));46 private DefaultTableModel searchResults = new DefaultTableModel() {47 @Override public boolean isCellEditable(int row, int col) { return false; }48 };49 private JTable searchResultDisplay = new JTable(searchResults);50 private boolean updatingSelf;51 52 /**53 * Data storage for search results.54 */55 class SearchResult56 {57 public String name;58 public String type;59 public String nearestPlace;60 public String description;61 public double lat;62 public double lon;63 public int zoom;64 }65 66 /**67 * A very primitive parser for the name finder's output.68 * Structure of xml described here: http://wiki.openstreetmap.org/index.php/Name_finder69 *70 */71 private class Parser extends DefaultHandler72 {73 private SearchResult currentResult = null;74 private StringBuffer description = null;75 private int depth = 0;76 /**77 * Detect starting elements.78 * 79 */80 @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException81 {82 depth++;83 try 84 {85 if (qName.equals("searchresults"))86 {87 searchResults.setRowCount(0);88 }89 else if (qName.equals("named") && (depth == 2))90 { 91 currentResult = new PlaceSelection.SearchResult();92 currentResult.name = atts.getValue("name");93 currentResult.type = atts.getValue("info");94 currentResult.lat = Double.parseDouble(atts.getValue("lat"));95 currentResult.lon = Double.parseDouble(atts.getValue("lon"));96 currentResult.zoom = Integer.parseInt(atts.getValue("zoom"));97 searchResults.addRow(new Object[] { currentResult, currentResult, currentResult, currentResult });98 }99 else if (qName.equals("description") && (depth == 3))100 {101 description = new StringBuffer();102 }103 else if (qName.equals("named") && (depth == 4))104 {105 // this is a "named" place in the nearest places list.106 String info = atts.getValue("info");107 if ("city".equals(info) || "town".equals(info) || "village".equals(info)) {108 currentResult.nearestPlace = atts.getValue("name");109 }110 }111 }112 catch (NumberFormatException x)113 {114 x.printStackTrace(); // SAXException does not chain correctly115 throw new SAXException(x.getMessage(), x);116 } 117 catch (NullPointerException x)118 {119 x.printStackTrace(); // SAXException does not chain correctly120 throw new SAXException(tr("NullPointerException, Possibly some missing tags."), x);121 }122 }123 /** 124 * Detect ending elements.125 */126 @Override public void endElement(String namespaceURI, String localName, String qName) throws SAXException127 {128 129 if (qName.equals("searchresults"))130 {131 }132 else if (qName.equals("description") && description != null)133 {134 currentResult.description = description.toString();135 description = null;136 }137 depth--;138 139 }140 /** 141 * Read characters for description.142 */143 @Override public void characters(char[] data, int start, int length) throws org.xml.sax.SAXException144 {145 if (description != null)146 {147 description.append(data, start, length);148 }149 }150 }151 152 /**153 * This queries David Earl's server. Needless to say, stuff should be configurable, and154 * error handling improved.155 */156 public void queryServer(final JComponent component)157 {158 final Cursor oldCursor = component.getCursor();159 160 // had to put this in a thread as it wouldn't update the cursor properly before.161 Runnable r = new Runnable() {162 public void run() {163 try164 {165 String searchtext = searchTerm.getText();166 if(searchtext.length()==0)167 {168 JOptionPane.showMessageDialog(Main.parent,tr("Please enter a search string"));169 }170 else171 {172 component.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));173 component.repaint();174 URL url = new URL("http://gazetteer.openstreetmap.org/namefinder/search.xml?find="175 +java.net.URLEncoder.encode(searchTerm.getText(), "UTF-8"));176 HttpURLConnection activeConnection = (HttpURLConnection)url.openConnection();177 //System.out.println("got return: "+activeConnection.getResponseCode());178 activeConnection.setConnectTimeout(15000);179 InputStream inputStream = activeConnection.getInputStream();180 InputSource inputSource = new InputSource(new InputStreamReader(inputStream, "UTF-8"));181 SAXParserFactory.newInstance().newSAXParser().parse(inputSource, new Parser());182 }183 }184 catch (Exception x)185 {186 JOptionPane.showMessageDialog(Main.parent,tr("Cannot read place search results from server"));187 x.printStackTrace();188 }189 component.setCursor(oldCursor);190 }191 };192 new Thread(r).start();193 }194 195 /**196 * Adds a new tab to the download dialog in JOSM.197 * 198 * This method is, for all intents and purposes, the constructor for this class.199 */200 public void addGui(final DownloadDialog gui) {201 JPanel panel = new JPanel();202 panel.setLayout(new GridBagLayout());203 204 // this is manually tuned so that it looks nice on a GNOME205 // desktop - maybe needs some cross platform proofing.206 panel.add(new JLabel(tr("Enter a place name to search for:")), GBC.eol().insets(5, 5, 5, 5));207 panel.add(searchTerm, GBC.std().fill(GBC.BOTH).insets(5, 0, 5, 4));208 panel.add(submitSearch, GBC.eol().insets(5, 0, 5, 5));209 Dimension btnSize = submitSearch.getPreferredSize();210 btnSize.setSize(btnSize.width, btnSize.height * 0.8);211 submitSearch.setPreferredSize(btnSize);212 213 GBC c = GBC.std().fill().insets(5, 0, 5, 5);214 c.gridwidth = 2;215 JScrollPane scrollPane = new JScrollPane(searchResultDisplay);216 scrollPane.setPreferredSize(new Dimension(200,200));217 panel.add(scrollPane, c);218 gui.tabpane.add(panel, tr("Places"));219 220 scrollPane.setPreferredSize(scrollPane.getPreferredSize());221 222 // when the button is clicked223 submitSearch.addActionListener(new ActionListener() {224 public void actionPerformed(ActionEvent e) {225 queryServer(gui);226 }227 });228 229 searchTerm.addActionListener(new ActionListener() {230 public void actionPerformed(ActionEvent e) {231 queryServer(gui);232 }233 });234 235 searchResults.addColumn(tr("name"));236 searchResults.addColumn(tr("type"));237 searchResults.addColumn(tr("near"));238 searchResults.addColumn(tr("zoom"));239 240 // TODO - this is probably not the coolest way to set relative sizes?241 searchResultDisplay.getColumn(tr("name")).setPreferredWidth(200);242 searchResultDisplay.getColumn(tr("type")).setPreferredWidth(100);243 searchResultDisplay.getColumn(tr("near")).setPreferredWidth(100);244 searchResultDisplay.getColumn(tr("zoom")).setPreferredWidth(50);245 searchResultDisplay.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);246 247 // display search results in a table. for simplicity, the table contains248 // the same SearchResult object in each of the four columns, but it is rendered249 // differently depending on the column.250 searchResultDisplay.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {251 @Override public Component getTableCellRendererComponent(JTable table, Object value,44 private JTextField searchTerm = new JTextField(); 45 private JButton submitSearch = new JButton(tr("Search...")); 46 private DefaultTableModel searchResults = new DefaultTableModel() { 47 @Override public boolean isCellEditable(int row, int col) { return false; } 48 }; 49 private JTable searchResultDisplay = new JTable(searchResults); 50 private boolean updatingSelf; 51 52 /** 53 * Data storage for search results. 54 */ 55 class SearchResult 56 { 57 public String name; 58 public String type; 59 public String nearestPlace; 60 public String description; 61 public double lat; 62 public double lon; 63 public int zoom; 64 } 65 66 /** 67 * A very primitive parser for the name finder's output. 68 * Structure of xml described here: http://wiki.openstreetmap.org/index.php/Name_finder 69 * 70 */ 71 private class Parser extends DefaultHandler 72 { 73 private SearchResult currentResult = null; 74 private StringBuffer description = null; 75 private int depth = 0; 76 /** 77 * Detect starting elements. 78 * 79 */ 80 @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException 81 { 82 depth++; 83 try 84 { 85 if (qName.equals("searchresults")) 86 { 87 searchResults.setRowCount(0); 88 } 89 else if (qName.equals("named") && (depth == 2)) 90 { 91 currentResult = new PlaceSelection.SearchResult(); 92 currentResult.name = atts.getValue("name"); 93 currentResult.type = atts.getValue("info"); 94 currentResult.lat = Double.parseDouble(atts.getValue("lat")); 95 currentResult.lon = Double.parseDouble(atts.getValue("lon")); 96 currentResult.zoom = Integer.parseInt(atts.getValue("zoom")); 97 searchResults.addRow(new Object[] { currentResult, currentResult, currentResult, currentResult }); 98 } 99 else if (qName.equals("description") && (depth == 3)) 100 { 101 description = new StringBuffer(); 102 } 103 else if (qName.equals("named") && (depth == 4)) 104 { 105 // this is a "named" place in the nearest places list. 106 String info = atts.getValue("info"); 107 if ("city".equals(info) || "town".equals(info) || "village".equals(info)) { 108 currentResult.nearestPlace = atts.getValue("name"); 109 } 110 } 111 } 112 catch (NumberFormatException x) 113 { 114 x.printStackTrace(); // SAXException does not chain correctly 115 throw new SAXException(x.getMessage(), x); 116 } 117 catch (NullPointerException x) 118 { 119 x.printStackTrace(); // SAXException does not chain correctly 120 throw new SAXException(tr("NullPointerException, Possibly some missing tags."), x); 121 } 122 } 123 /** 124 * Detect ending elements. 125 */ 126 @Override public void endElement(String namespaceURI, String localName, String qName) throws SAXException 127 { 128 129 if (qName.equals("searchresults")) 130 { 131 } 132 else if (qName.equals("description") && description != null) 133 { 134 currentResult.description = description.toString(); 135 description = null; 136 } 137 depth--; 138 139 } 140 /** 141 * Read characters for description. 142 */ 143 @Override public void characters(char[] data, int start, int length) throws org.xml.sax.SAXException 144 { 145 if (description != null) 146 { 147 description.append(data, start, length); 148 } 149 } 150 } 151 152 /** 153 * This queries David Earl's server. Needless to say, stuff should be configurable, and 154 * error handling improved. 155 */ 156 public void queryServer(final JComponent component) 157 { 158 final Cursor oldCursor = component.getCursor(); 159 160 // had to put this in a thread as it wouldn't update the cursor properly before. 161 Runnable r = new Runnable() { 162 public void run() { 163 try 164 { 165 String searchtext = searchTerm.getText(); 166 if(searchtext.length()==0) 167 { 168 JOptionPane.showMessageDialog(Main.parent,tr("Please enter a search string")); 169 } 170 else 171 { 172 component.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 173 component.repaint(); 174 URL url = new URL("http://gazetteer.openstreetmap.org/namefinder/search.xml?find=" 175 +java.net.URLEncoder.encode(searchTerm.getText(), "UTF-8")); 176 HttpURLConnection activeConnection = (HttpURLConnection)url.openConnection(); 177 //System.out.println("got return: "+activeConnection.getResponseCode()); 178 activeConnection.setConnectTimeout(15000); 179 InputStream inputStream = activeConnection.getInputStream(); 180 InputSource inputSource = new InputSource(new InputStreamReader(inputStream, "UTF-8")); 181 SAXParserFactory.newInstance().newSAXParser().parse(inputSource, new Parser()); 182 } 183 } 184 catch (Exception x) 185 { 186 JOptionPane.showMessageDialog(Main.parent,tr("Cannot read place search results from server")); 187 x.printStackTrace(); 188 } 189 component.setCursor(oldCursor); 190 } 191 }; 192 new Thread(r).start(); 193 } 194 195 /** 196 * Adds a new tab to the download dialog in JOSM. 197 * 198 * This method is, for all intents and purposes, the constructor for this class. 199 */ 200 public void addGui(final DownloadDialog gui) { 201 JPanel panel = new JPanel(); 202 panel.setLayout(new GridBagLayout()); 203 204 // this is manually tuned so that it looks nice on a GNOME 205 // desktop - maybe needs some cross platform proofing. 206 panel.add(new JLabel(tr("Enter a place name to search for:")), GBC.eol().insets(5, 5, 5, 5)); 207 panel.add(searchTerm, GBC.std().fill(GBC.BOTH).insets(5, 0, 5, 4)); 208 panel.add(submitSearch, GBC.eol().insets(5, 0, 5, 5)); 209 Dimension btnSize = submitSearch.getPreferredSize(); 210 btnSize.setSize(btnSize.width, btnSize.height * 0.8); 211 submitSearch.setPreferredSize(btnSize); 212 213 GBC c = GBC.std().fill().insets(5, 0, 5, 5); 214 c.gridwidth = 2; 215 JScrollPane scrollPane = new JScrollPane(searchResultDisplay); 216 scrollPane.setPreferredSize(new Dimension(200,200)); 217 panel.add(scrollPane, c); 218 gui.tabpane.add(panel, tr("Places")); 219 220 scrollPane.setPreferredSize(scrollPane.getPreferredSize()); 221 222 // when the button is clicked 223 submitSearch.addActionListener(new ActionListener() { 224 public void actionPerformed(ActionEvent e) { 225 queryServer(gui); 226 } 227 }); 228 229 searchTerm.addActionListener(new ActionListener() { 230 public void actionPerformed(ActionEvent e) { 231 queryServer(gui); 232 } 233 }); 234 235 searchResults.addColumn(tr("name")); 236 searchResults.addColumn(tr("type")); 237 searchResults.addColumn(tr("near")); 238 searchResults.addColumn(tr("zoom")); 239 240 // TODO - this is probably not the coolest way to set relative sizes? 241 searchResultDisplay.getColumn(tr("name")).setPreferredWidth(200); 242 searchResultDisplay.getColumn(tr("type")).setPreferredWidth(100); 243 searchResultDisplay.getColumn(tr("near")).setPreferredWidth(100); 244 searchResultDisplay.getColumn(tr("zoom")).setPreferredWidth(50); 245 searchResultDisplay.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 246 247 // display search results in a table. for simplicity, the table contains 248 // the same SearchResult object in each of the four columns, but it is rendered 249 // differently depending on the column. 250 searchResultDisplay.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() { 251 @Override public Component getTableCellRendererComponent(JTable table, Object value, 252 252 boolean isSelected, boolean hasFocus, int row, int column) { 253 super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);254 if (value != null) {255 SearchResult sr = (SearchResult) value;256 switch(column) {257 case 0:258 setText(sr.name);259 break;260 case 1:261 setText(sr.type);262 break;263 case 2:264 setText(sr.nearestPlace);265 break;266 case 3:267 setText(Integer.toString(sr.zoom));268 break;269 }270 setToolTipText("<html>"+((SearchResult)value).description+"</html>");271 }272 return this;273 }274 });275 276 // if item is selected in list, notify dialog277 searchResultDisplay.getSelectionModel().addListSelectionListener(new ListSelectionListener() {278 public void valueChanged(ListSelectionEvent lse) {279 if (lse.getValueIsAdjusting()) return;280 SearchResult r = null;281 try 282 {283 r = (SearchResult) searchResults.getValueAt(lse.getFirstIndex(), 0);284 }285 catch (Exception x)286 {287 // Ignore288 }289 if (r != null)290 {291 double size = 180.0 / Math.pow(2, r.zoom);292 gui.minlat = r.lat - size / 2;293 gui.maxlat = r.lat + size / 2;294 gui.minlon = r.lon - size;295 gui.maxlon = r.lon + size;296 updatingSelf = true;297 gui.boundingBoxChanged(null);298 updatingSelf = false;299 }300 }301 });302 303 // TODO - we'd like to finish the download dialog upon double-click but304 // don't know how to bypass the JOptionPane in which the whole thing is305 // displayed.306 searchResultDisplay.addMouseListener(new MouseAdapter() {307 @Override public void mouseClicked(MouseEvent e) {308 if (e.getClickCount() > 1) {309 if (searchResultDisplay.getSelectionModel().getMinSelectionIndex() > -1) {310 // add sensible action here.311 }312 }313 }314 });315 316 }317 318 // if bounding box selected on other tab, de-select item319 public void boundingBoxChanged(DownloadDialog gui) {320 if (!updatingSelf) searchResultDisplay.clearSelection();321 }253 super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 254 if (value != null) { 255 SearchResult sr = (SearchResult) value; 256 switch(column) { 257 case 0: 258 setText(sr.name); 259 break; 260 case 1: 261 setText(sr.type); 262 break; 263 case 2: 264 setText(sr.nearestPlace); 265 break; 266 case 3: 267 setText(Integer.toString(sr.zoom)); 268 break; 269 } 270 setToolTipText("<html>"+((SearchResult)value).description+"</html>"); 271 } 272 return this; 273 } 274 }); 275 276 // if item is selected in list, notify dialog 277 searchResultDisplay.getSelectionModel().addListSelectionListener(new ListSelectionListener() { 278 public void valueChanged(ListSelectionEvent lse) { 279 if (lse.getValueIsAdjusting()) return; 280 SearchResult r = null; 281 try 282 { 283 r = (SearchResult) searchResults.getValueAt(lse.getFirstIndex(), 0); 284 } 285 catch (Exception x) 286 { 287 // Ignore 288 } 289 if (r != null) 290 { 291 double size = 180.0 / Math.pow(2, r.zoom); 292 gui.minlat = r.lat - size / 2; 293 gui.maxlat = r.lat + size / 2; 294 gui.minlon = r.lon - size; 295 gui.maxlon = r.lon + size; 296 updatingSelf = true; 297 gui.boundingBoxChanged(null); 298 updatingSelf = false; 299 } 300 } 301 }); 302 303 // TODO - we'd like to finish the download dialog upon double-click but 304 // don't know how to bypass the JOptionPane in which the whole thing is 305 // displayed. 306 searchResultDisplay.addMouseListener(new MouseAdapter() { 307 @Override public void mouseClicked(MouseEvent e) { 308 if (e.getClickCount() > 1) { 309 if (searchResultDisplay.getSelectionModel().getMinSelectionIndex() > -1) { 310 // add sensible action here. 311 } 312 } 313 } 314 }); 315 316 } 317 318 // if bounding box selected on other tab, de-select item 319 public void boundingBoxChanged(DownloadDialog gui) { 320 if (!updatingSelf) searchResultDisplay.clearSelection(); 321 } 322 322 }
Note:
See TracChangeset
for help on using the changeset viewer.
