source: josm/trunk/src/org/openstreetmap/josm/gui/download/OSMDownloadSource.java@ 12655

Last change on this file since 12655 was 12655, checked in by michael2402, 7 years ago

See #15167: Add javadoc, improve code style.

File size: 13.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.download;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Color;
7import java.awt.Font;
8import java.awt.GridBagLayout;
9import java.util.ArrayList;
10import java.util.List;
11import java.util.concurrent.ExecutionException;
12import java.util.concurrent.Future;
13
14import javax.swing.Icon;
15import javax.swing.JCheckBox;
16import javax.swing.JLabel;
17import javax.swing.JOptionPane;
18import javax.swing.event.ChangeListener;
19
20import org.openstreetmap.josm.Main;
21import org.openstreetmap.josm.actions.downloadtasks.AbstractDownloadTask;
22import org.openstreetmap.josm.actions.downloadtasks.DownloadGpsTask;
23import org.openstreetmap.josm.actions.downloadtasks.DownloadNotesTask;
24import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
25import org.openstreetmap.josm.actions.downloadtasks.PostDownloadHandler;
26import org.openstreetmap.josm.data.Bounds;
27import org.openstreetmap.josm.data.ProjectionBounds;
28import org.openstreetmap.josm.data.ViewportData;
29import org.openstreetmap.josm.data.preferences.BooleanProperty;
30import org.openstreetmap.josm.gui.MainApplication;
31import org.openstreetmap.josm.gui.MapFrame;
32import org.openstreetmap.josm.gui.util.GuiHelper;
33import org.openstreetmap.josm.tools.GBC;
34import org.openstreetmap.josm.tools.ImageProvider;
35import org.openstreetmap.josm.tools.Logging;
36import org.openstreetmap.josm.tools.Pair;
37
38/**
39 * Class defines the way data is fetched from the OSM server.
40 * @since 12652
41 */
42public class OSMDownloadSource implements DownloadSource<OSMDownloadSource.OSMDownloadData> {
43
44 @Override
45 public AbstractDownloadSourcePanel<OSMDownloadData> createPanel() {
46 return new OSMDownloadSourcePanel(this);
47 }
48
49 @Override
50 public void doDownload(OSMDownloadData data, DownloadSettings settings) {
51 Bounds bbox = settings.getDownloadBounds()
52 .orElseThrow(() -> new IllegalArgumentException("OSM downloads requires bounds"));
53 boolean zoom = settings.zoomToData();
54 boolean newLayer = settings.asNewLayer();
55 List<Pair<AbstractDownloadTask<?>, Future<?>>> tasks = new ArrayList<>();
56
57 if (data.isDownloadOSMData()) {
58 DownloadOsmTask task = new DownloadOsmTask();
59 task.setZoomAfterDownload(zoom && !data.isDownloadGPX() && !data.isDownloadNotes());
60 Future<?> future = task.download(newLayer, bbox, null);
61 MainApplication.worker.submit(new PostDownloadHandler(task, future));
62 if (zoom) {
63 tasks.add(new Pair<>(task, future));
64 }
65 }
66
67 if (data.isDownloadGPX()) {
68 DownloadGpsTask task = new DownloadGpsTask();
69 task.setZoomAfterDownload(zoom && !data.isDownloadOSMData() && !data.isDownloadNotes());
70 Future<?> future = task.download(newLayer, bbox, null);
71 MainApplication.worker.submit(new PostDownloadHandler(task, future));
72 if (zoom) {
73 tasks.add(new Pair<>(task, future));
74 }
75 }
76
77 if (data.isDownloadNotes()) {
78 DownloadNotesTask task = new DownloadNotesTask();
79 task.setZoomAfterDownload(zoom && !data.isDownloadOSMData() && !data.isDownloadGPX());
80 Future<?> future = task.download(false, bbox, null);
81 MainApplication.worker.submit(new PostDownloadHandler(task, future));
82 if (zoom) {
83 tasks.add(new Pair<>(task, future));
84 }
85 }
86
87 if (zoom && tasks.size() > 1) {
88 MainApplication.worker.submit(() -> {
89 ProjectionBounds bounds = null;
90 // Wait for completion of download jobs
91 for (Pair<AbstractDownloadTask<?>, Future<?>> p : tasks) {
92 try {
93 p.b.get();
94 ProjectionBounds b = p.a.getDownloadProjectionBounds();
95 if (bounds == null) {
96 bounds = b;
97 } else if (b != null) {
98 bounds.extend(b);
99 }
100 } catch (InterruptedException | ExecutionException ex) {
101 Logging.warn(ex);
102 }
103 }
104 MapFrame map = MainApplication.getMap();
105 // Zoom to the larger download bounds
106 if (map != null && bounds != null) {
107 final ProjectionBounds pb = bounds;
108 GuiHelper.runInEDTAndWait(() -> map.mapView.zoomTo(new ViewportData(pb)));
109 }
110 });
111 }
112 }
113
114 @Override
115 public String getLabel() {
116 return tr("Download from OSM");
117 }
118
119 @Override
120 public void addGui(DownloadDialog dialog) {
121 dialog.addDownloadSource(this);
122 }
123
124 @Override
125 public boolean onlyExpert() {
126 return false;
127 }
128
129 /**
130 * The GUI representation of the OSM download source.
131 * @since 12652
132 */
133 public static class OSMDownloadSourcePanel extends AbstractDownloadSourcePanel<OSMDownloadData> {
134
135 private final JCheckBox cbDownloadOsmData;
136 private final JCheckBox cbDownloadGpxData;
137 private final JCheckBox cbDownloadNotes;
138 private final JLabel sizeCheck = new JLabel();
139
140 private static final BooleanProperty DOWNLOAD_OSM = new BooleanProperty("download.osm.data", true);
141 private static final BooleanProperty DOWNLOAD_GPS = new BooleanProperty("download.osm.gps", false);
142 private static final BooleanProperty DOWNLOAD_NOTES = new BooleanProperty("download.osm.notes", false);
143
144 /**
145 * Creates a new {@link OSMDownloadSourcePanel}
146 * @param ds The osm download source the panel is for
147 */
148 public OSMDownloadSourcePanel(OSMDownloadSource ds) {
149 super(ds);
150 setLayout(new GridBagLayout());
151
152 // size check depends on selected data source
153 final ChangeListener checkboxChangeListener = e ->
154 DownloadDialog.getInstance().getSelectedDownloadArea().ifPresent(this::updateSizeCheck);
155
156 // adding the download tasks
157 add(new JLabel(tr("Data Sources and Types:")), GBC.std().insets(5, 5, 1, 5).anchor(GBC.CENTER));
158 cbDownloadOsmData = new JCheckBox(tr("OpenStreetMap data"), true);
159 cbDownloadOsmData.setToolTipText(tr("Select to download OSM data in the selected download area."));
160 cbDownloadOsmData.getModel().addChangeListener(checkboxChangeListener);
161
162 cbDownloadGpxData = new JCheckBox(tr("Raw GPS data"));
163 cbDownloadGpxData.setToolTipText(tr("Select to download GPS traces in the selected download area."));
164 cbDownloadGpxData.getModel().addChangeListener(checkboxChangeListener);
165
166 cbDownloadNotes = new JCheckBox(tr("Notes"));
167 cbDownloadNotes.setToolTipText(tr("Select to download notes in the selected download area."));
168 cbDownloadNotes.getModel().addChangeListener(checkboxChangeListener);
169
170 Font labelFont = sizeCheck.getFont();
171 sizeCheck.setFont(labelFont.deriveFont(Font.PLAIN, labelFont.getSize()));
172
173 add(cbDownloadOsmData, GBC.std().insets(1, 5, 1, 5));
174 add(cbDownloadGpxData, GBC.std().insets(1, 5, 1, 5));
175 add(cbDownloadNotes, GBC.eol().insets(1, 5, 1, 5));
176 add(sizeCheck, GBC.eol().anchor(GBC.EAST).insets(5, 5, 5, 2));
177 }
178
179 @Override
180 public OSMDownloadData getData() {
181 return new OSMDownloadData(
182 isDownloadOsmData(),
183 isDownloadNotes(),
184 isDownloadGpxData());
185 }
186
187 @Override
188 public void rememberSettings() {
189 DOWNLOAD_OSM.put(isDownloadOsmData());
190 DOWNLOAD_GPS.put(isDownloadGpxData());
191 DOWNLOAD_NOTES.put(isDownloadNotes());
192 }
193
194 @Override
195 public void restoreSettings() {
196 cbDownloadOsmData.setSelected(DOWNLOAD_OSM.get());
197 cbDownloadGpxData.setSelected(DOWNLOAD_GPS.get());
198 cbDownloadNotes.setSelected(DOWNLOAD_NOTES.get());
199 }
200
201 @Override
202 public boolean checkDownload(DownloadSettings settings) {
203 /*
204 * It is mandatory to specify the area to download from OSM.
205 */
206 if (!settings.getDownloadBounds().isPresent()) {
207 JOptionPane.showMessageDialog(
208 this.getParent(),
209 tr("Please select a download area first."),
210 tr("Error"),
211 JOptionPane.ERROR_MESSAGE
212 );
213
214 return false;
215 }
216
217 /*
218 * Checks if the user selected the type of data to download. At least one the following
219 * must be chosen : raw osm data, gpx data, notes.
220 * If none of those are selected, then the corresponding dialog is shown to inform the user.
221 */
222 if (!isDownloadOsmData() && !isDownloadGpxData() && !isDownloadNotes()) {
223 JOptionPane.showMessageDialog(
224 this.getParent(),
225 tr("<html>Neither <strong>{0}</strong> nor <strong>{1}</strong> nor <strong>{2}</strong> is enabled.<br>"
226 + "Please choose to either download OSM data, or GPX data, or Notes, or all.</html>",
227 cbDownloadOsmData.getText(),
228 cbDownloadGpxData.getText(),
229 cbDownloadNotes.getText()
230 ),
231 tr("Error"),
232 JOptionPane.ERROR_MESSAGE
233 );
234
235 return false;
236 }
237
238 this.rememberSettings();
239
240 return true;
241 }
242
243 /**
244 * Replies true if the user selected to download OSM data
245 *
246 * @return true if the user selected to download OSM data
247 */
248 public boolean isDownloadOsmData() {
249 return cbDownloadOsmData.isSelected();
250 }
251
252 /**
253 * Replies true if the user selected to download GPX data
254 *
255 * @return true if the user selected to download GPX data
256 */
257 public boolean isDownloadGpxData() {
258 return cbDownloadGpxData.isSelected();
259 }
260
261 /**
262 * Replies true if user selected to download notes
263 *
264 * @return true if user selected to download notes
265 */
266 public boolean isDownloadNotes() {
267 return cbDownloadNotes.isSelected();
268 }
269
270 @Override
271 public Icon getIcon() {
272 return ImageProvider.get("download");
273 }
274
275 @Override
276 public void boudingBoxChanged(Bounds bbox) {
277 updateSizeCheck(bbox);
278 }
279
280 private void updateSizeCheck(Bounds bbox) {
281 boolean isAreaTooLarge = false;
282 if (bbox == null) {
283 sizeCheck.setText(tr("No area selected yet"));
284 sizeCheck.setForeground(Color.darkGray);
285 } else if (!isDownloadNotes() && !isDownloadOsmData() && !isDownloadGpxData()) {
286 isAreaTooLarge = false;
287 } else if (isDownloadNotes() && !isDownloadOsmData() && !isDownloadGpxData()) {
288 // see max_note_request_area in https://github.com/openstreetmap/openstreetmap-website/blob/master/config/example.application.yml
289 isAreaTooLarge = bbox.getArea() > Main.pref.getDouble("osm-server.max-request-area-notes", 25);
290 } else {
291 // see max_request_area in https://github.com/openstreetmap/openstreetmap-website/blob/master/config/example.application.yml
292 isAreaTooLarge = bbox.getArea() > Main.pref.getDouble("osm-server.max-request-area", 0.25);
293 }
294
295 displaySizeCheckResult(isAreaTooLarge);
296 }
297
298 private void displaySizeCheckResult(boolean isAreaTooLarge) {
299 if (isAreaTooLarge) {
300 sizeCheck.setText(tr("Download area too large; will probably be rejected by server"));
301 sizeCheck.setForeground(Color.red);
302 } else {
303 sizeCheck.setText(tr("Download area ok, size probably acceptable to server"));
304 sizeCheck.setForeground(Color.darkGray);
305 }
306 }
307
308 }
309
310 /**
311 * Encapsulates data that is required to download from the OSM server.
312 */
313 static class OSMDownloadData {
314 private final boolean downloadOSMData;
315 private final boolean downloadNotes;
316 private final boolean downloadGPX;
317
318 OSMDownloadData(boolean downloadOSMData, boolean downloadNotes, boolean downloadGPX) {
319 this.downloadOSMData = downloadOSMData;
320 this.downloadNotes = downloadNotes;
321 this.downloadGPX = downloadGPX;
322 }
323
324 boolean isDownloadOSMData() {
325 return downloadOSMData;
326 }
327
328 boolean isDownloadNotes() {
329 return downloadNotes;
330 }
331
332 boolean isDownloadGPX() {
333 return downloadGPX;
334 }
335 }
336}
Note: See TracBrowser for help on using the repository browser.