source: josm/src/org/openstreetmap/josm/actions/DownloadAction.java@ 98

Last change on this file since 98 was 98, checked in by imi, 18 years ago
  • added Applet version of JOSM (unfinished)
  • fixed display bug if --no-fullscreen and --geometry was specified
File size: 12.4 KB
Line 
1package org.openstreetmap.josm.actions;
2
3import java.awt.Dimension;
4import java.awt.GridBagLayout;
5import java.awt.GridLayout;
6import java.awt.event.ActionEvent;
7import java.awt.event.ActionListener;
8import java.awt.event.InputEvent;
9import java.awt.event.KeyAdapter;
10import java.awt.event.KeyEvent;
11import java.awt.event.KeyListener;
12import java.io.IOException;
13import java.util.Collection;
14import java.util.HashMap;
15
16import javax.swing.DefaultListModel;
17import javax.swing.JButton;
18import javax.swing.JCheckBox;
19import javax.swing.JLabel;
20import javax.swing.JOptionPane;
21import javax.swing.JPanel;
22import javax.swing.JScrollPane;
23import javax.swing.JTextField;
24import javax.swing.KeyStroke;
25import javax.swing.SwingUtilities;
26import javax.swing.event.ListSelectionEvent;
27import javax.swing.event.ListSelectionListener;
28
29import org.jdom.JDOMException;
30import org.openstreetmap.josm.Main;
31import org.openstreetmap.josm.data.Bounds;
32import org.openstreetmap.josm.data.coor.LatLon;
33import org.openstreetmap.josm.data.osm.DataSet;
34import org.openstreetmap.josm.gui.BookmarkList;
35import org.openstreetmap.josm.gui.MapView;
36import org.openstreetmap.josm.gui.PleaseWaitRunnable;
37import org.openstreetmap.josm.gui.WorldChooser;
38import org.openstreetmap.josm.gui.BookmarkList.Bookmark;
39import org.openstreetmap.josm.gui.layer.OsmDataLayer;
40import org.openstreetmap.josm.gui.layer.RawGpsDataLayer;
41import org.openstreetmap.josm.gui.layer.RawGpsDataLayer.GpsPoint;
42import org.openstreetmap.josm.io.OsmServerReader;
43import org.openstreetmap.josm.tools.GBC;
44import org.xml.sax.SAXException;
45
46/**
47 * Action that opens a connection to the osm server and download map data.
48 *
49 * An dialog is displayed asking the user to specify a rectangle to grab.
50 * The url and account settings from the preferences are used.
51 *
52 * @author imi
53 */
54public class DownloadAction extends JosmAction {
55
56 /**
57 * Open the download dialog and download the data.
58 * Run in the worker thread.
59 */
60 private final class DownloadOsmTask extends PleaseWaitRunnable {
61 private final OsmServerReader reader;
62 private DataSet dataSet;
63
64 private DownloadOsmTask(OsmServerReader reader) {
65 super("Downloading data");
66 this.reader = reader;
67 reader.setProgressInformation(currentAction, progress);
68 }
69
70 @Override public void realRun() throws IOException, SAXException {
71 dataSet = reader.parseOsm();
72 }
73
74 @Override protected void finish() {
75 if (dataSet == null)
76 return; // user cancelled download or error occoured
77 if (dataSet.nodes.isEmpty())
78 errorMessage = "No data imported.";
79 Main.main.addLayer(new OsmDataLayer(dataSet, "Data Layer", false));
80 }
81
82 @Override protected void cancel() {
83 reader.cancel();
84 }
85 }
86
87
88 private final class DownloadGpsTask extends PleaseWaitRunnable {
89 private final OsmServerReader reader;
90 private Collection<Collection<GpsPoint>> rawData;
91
92 private DownloadGpsTask(OsmServerReader reader) {
93 super("Downloading GPS data");
94 this.reader = reader;
95 reader.setProgressInformation(currentAction, progress);
96 }
97
98 @Override public void realRun() throws IOException, JDOMException {
99 rawData = reader.parseRawGps();
100 }
101
102 @Override protected void finish() {
103 if (rawData == null)
104 return;
105 String name = latlon[0].getText() + " " + latlon[1].getText() + " x " + latlon[2].getText() + " " + latlon[3].getText();
106 Main.main.addLayer(new RawGpsDataLayer(rawData, name));
107 }
108
109 @Override protected void cancel() {
110 reader.cancel();
111 }
112 }
113
114
115 /**
116 * minlat, minlon, maxlat, maxlon
117 */
118 JTextField[] latlon = new JTextField[]{
119 new JTextField(9),
120 new JTextField(9),
121 new JTextField(9),
122 new JTextField(9)};
123 JCheckBox rawGps = new JCheckBox("Open as raw gps data", false);
124
125 public DownloadAction() {
126 super("Download from OSM", "download", "Download map data from the OSM server.", "Ctrl-Shift-D",
127 KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK));
128 // TODO remove when bug in Java6 is fixed
129 for (JTextField f : latlon)
130 f.setMinimumSize(new Dimension(100,new JTextField().getMinimumSize().height));
131 }
132
133 public void actionPerformed(ActionEvent e) {
134 String osmDataServer = Main.pref.get("osm-server.url");
135 //TODO: Remove this in later versions (temporary only)
136 if (osmDataServer.endsWith("/0.2") || osmDataServer.endsWith("/0.2/")) {
137 int answer = JOptionPane.showConfirmDialog(Main.parent,
138 "You seem to have an outdated server entry in your preferences.\n" +
139 "\n" +
140 "As of JOSM Release 1.2, you must no longer specify the API version in\n" +
141 "the osm url. For the OSM standard server, use http://www.openstreetmap.org/api" +
142 "\n" +
143 "Fix settings and continue?", "Outdated server url detected.", JOptionPane.YES_NO_OPTION);
144 if (answer != JOptionPane.YES_OPTION)
145 return;
146 int cutPos = osmDataServer.endsWith("/0.2") ? 4 : 5;
147 Main.pref.put("osm-server.url", osmDataServer.substring(0, osmDataServer.length()-cutPos));
148 }
149
150 JPanel dlg = new JPanel(new GridBagLayout());
151
152 // World image
153 WorldChooser wc = new WorldChooser();
154 dlg.add(wc, GBC.eop());
155 wc.setToolTipText("Move and zoom the image like the main map. Select an area to download by dragging.");
156
157 // Bounding box edits
158 dlg.add(new JLabel("Bounding box"), GBC.eol());
159 dlg.add(new JLabel("min lat"), GBC.std().insets(10,0,5,0));
160 dlg.add(latlon[0], GBC.std());
161 dlg.add(new JLabel("min lon"), GBC.std().insets(10,0,5,0));
162 dlg.add(latlon[1], GBC.eol());
163 dlg.add(new JLabel("max lat"), GBC.std().insets(10,0,5,0));
164 dlg.add(latlon[2], GBC.std());
165 dlg.add(new JLabel("max lon"), GBC.std().insets(10,0,5,0));
166 dlg.add(latlon[3], GBC.eol());
167 if (Main.map != null) {
168 MapView mv = Main.map.mapView;
169 setEditBounds(new Bounds(
170 mv.getLatLon(0, mv.getHeight()),
171 mv.getLatLon(mv.getWidth(), 0)));
172 rawGps.setSelected(mv.getActiveLayer() instanceof RawGpsDataLayer);
173 }
174 dlg.add(rawGps, GBC.eop());
175
176 // OSM url edit
177 dlg.add(new JLabel("URL from www.openstreetmap.org"), GBC.eol());
178 final JTextField osmUrl = new JTextField();
179 dlg.add(osmUrl, GBC.eop().fill(GBC.HORIZONTAL));
180 final KeyListener osmUrlRefresher = new KeyAdapter(){
181 @Override public void keyTyped(KeyEvent e) {
182 SwingUtilities.invokeLater(new Runnable() {
183 public void run() {
184 try {
185 double latMin = Double.parseDouble(latlon[0].getText());
186 double lonMin = Double.parseDouble(latlon[1].getText());
187 double latMax = Double.parseDouble(latlon[2].getText());
188 double lonMax = Double.parseDouble(latlon[3].getText());
189 double lat = (latMax+latMin)/2;
190 double lon = (lonMax+lonMin)/2;
191 // convert to mercator (for calculation of zoom only)
192 latMin = Math.log(Math.tan(Math.PI/4.0+latMin/180.0*Math.PI/2.0))*180.0/Math.PI;
193 latMax = Math.log(Math.tan(Math.PI/4.0+latMax/180.0*Math.PI/2.0))*180.0/Math.PI;
194 double size = Math.max(Math.abs(latMax-latMin), Math.abs(lonMax-lonMin));
195 int zoom = 0;
196 while (zoom <= 20) {
197 if (size >= 180)
198 break;
199 size *= 2;
200 zoom++;
201 }
202 osmUrl.setText("http://www.openstreetmap.org/index.html?lat="+lat+"&lon="+lon+"&zoom="+zoom);
203 } catch (NumberFormatException x) {
204 osmUrl.setText("");
205 }
206 osmUrl.setCaretPosition(0);
207 }
208 });
209 }
210 };
211 for (JTextField f : latlon)
212 f.addKeyListener(osmUrlRefresher);
213 SwingUtilities.invokeLater(new Runnable() {public void run() {osmUrlRefresher.keyTyped(null);}});
214 osmUrl.addKeyListener(new KeyAdapter(){
215 @Override public void keyTyped(KeyEvent e) {
216 SwingUtilities.invokeLater(new Runnable() {
217 public void run() {
218 Bounds b = osmurl2bounds(osmUrl.getText());
219 if (b != null)
220 setEditBounds(b);
221 else
222 for (JTextField f : latlon)
223 f.setText("");
224 }
225 });
226 }
227 });
228
229 // Bookmarks
230 dlg.add(new JLabel("Bookmarks"), GBC.eol());
231 final BookmarkList bookmarks = new BookmarkList();
232 bookmarks.getSelectionModel().addListSelectionListener(new ListSelectionListener(){
233 public void valueChanged(ListSelectionEvent e) {
234 Bookmark b = (Bookmark)bookmarks.getSelectedValue();
235 for (int i = 0; i < 4; ++i) {
236 latlon[i].setText(b == null ? "" : ""+b.latlon[i]);
237 latlon[i].setCaretPosition(0);
238 }
239 rawGps.setSelected(b == null ? false : b.rawgps);
240 osmUrlRefresher.keyTyped(null);
241 }
242 });
243 wc.addListMarker(bookmarks);
244 dlg.add(new JScrollPane(bookmarks), GBC.eol().fill());
245
246 JPanel buttons = new JPanel(new GridLayout(1,2));
247 JButton add = new JButton("Add");
248 add.addActionListener(new ActionListener(){
249 public void actionPerformed(ActionEvent e) {
250 Bookmark b = readBookmark();
251 if (b == null) {
252 JOptionPane.showMessageDialog(Main.parent, "Please enter the desired coordinates first.");
253 return;
254 }
255 b.name = JOptionPane.showInputDialog(Main.parent, "Please enter a name for the location.");
256 if (b.name != null && !b.name.equals("")) {
257 ((DefaultListModel)bookmarks.getModel()).addElement(b);
258 bookmarks.save();
259 }
260 }
261 });
262 buttons.add(add);
263 JButton remove = new JButton("Remove");
264 remove.addActionListener(new ActionListener(){
265 public void actionPerformed(ActionEvent e) {
266 Object sel = bookmarks.getSelectedValue();
267 if (sel == null) {
268 JOptionPane.showMessageDialog(Main.parent, "Select a bookmark first.");
269 return;
270 }
271 ((DefaultListModel)bookmarks.getModel()).removeElement(sel);
272 bookmarks.save();
273 }
274 });
275 buttons.add(remove);
276 dlg.add(buttons, GBC.eop().fill(GBC.HORIZONTAL));
277
278 Dimension d = dlg.getPreferredSize();
279 wc.setPreferredSize(new Dimension(d.width, d.width/2));
280 wc.addInputFields(latlon, osmUrl, osmUrlRefresher);
281
282 // Finally: the dialog
283 Bookmark b;
284 do {
285 int r = JOptionPane.showConfirmDialog(Main.parent, dlg, "Choose an area",
286 JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
287 if (r != JOptionPane.OK_OPTION)
288 return;
289 b = readBookmark();
290 if (b == null)
291 JOptionPane.showMessageDialog(Main.parent, "Please enter the desired coordinates or click on a bookmark.");
292 } while (b == null);
293
294 double minlon = b.latlon[0];
295 double minlat = b.latlon[1];
296 double maxlon = b.latlon[2];
297 double maxlat = b.latlon[3];
298 download(rawGps.isSelected(), minlon, minlat, maxlon, maxlat);
299 }
300
301 /**
302 * Read a bookmark from the current set edit fields. If one of the fields is
303 * empty or contain illegal chars, <code>null</code> is returned.
304 * The name of the bookmark is <code>null</code>.
305 * @return A bookmark containing information from the edit fields and rawgps
306 * checkbox.
307 */
308 Bookmark readBookmark() {
309 try {
310 Bookmark b = new Bookmark();
311 for (int i = 0; i < 4; ++i) {
312 if (latlon[i].getText().equals(""))
313 return null;
314 b.latlon[i] = Double.parseDouble(latlon[i].getText());
315 }
316 b.rawgps = rawGps.isSelected();
317 return b;
318 } catch (NumberFormatException x) {
319 return null;
320 }
321 }
322
323
324 public static Bounds osmurl2bounds(String url) {
325 int i = url.indexOf('?');
326 if (i == -1)
327 return null;
328 String[] args = url.substring(i+1).split("&");
329 HashMap<String, Double> map = new HashMap<String, Double>();
330 for (String arg : args) {
331 int eq = arg.indexOf('=');
332 if (eq != -1) {
333 try {
334 map.put(arg.substring(0, eq), Double.parseDouble(arg.substring(eq + 1)));
335 } catch (NumberFormatException e) {
336 }
337 }
338 }
339 try {
340 double size = 180.0 / Math.pow(2, map.get("zoom"));
341 return new Bounds(
342 new LatLon(map.get("lat") - size/2, map.get("lon") - size),
343 new LatLon(map.get("lat") + size/2, map.get("lon") + size));
344 } catch (Exception x) { // NPE or IAE
345 return null;
346 }
347 }
348
349 /**
350 * Set the four edit fields to the given bounds coordinates.
351 */
352 private void setEditBounds(Bounds b) {
353 LatLon bottomLeft = b.min;
354 LatLon topRight = b.max;
355 if (bottomLeft.isOutSideWorld())
356 bottomLeft = new LatLon(-89.999, -179.999); // do not use the Projection constants, since this looks better.
357 if (topRight.isOutSideWorld())
358 topRight = new LatLon(89.999, 179.999);
359 latlon[0].setText(""+bottomLeft.lat());
360 latlon[1].setText(""+bottomLeft.lon());
361 latlon[2].setText(""+topRight.lat());
362 latlon[3].setText(""+topRight.lon());
363 for (JTextField f : latlon)
364 f.setCaretPosition(0);
365 }
366
367 /**
368 * Do the download for the given area.
369 */
370 public void download(boolean rawGps, double minlat, double minlon, double maxlat, double maxlon) {
371 OsmServerReader reader = new OsmServerReader(minlat, minlon, maxlat, maxlon);
372 PleaseWaitRunnable task = rawGps ? new DownloadGpsTask(reader) : new DownloadOsmTask(reader);
373 Main.worker.execute(task);
374 task.pleaseWaitDlg.setVisible(true);
375 }
376}
Note: See TracBrowser for help on using the repository browser.