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

Last change on this file since 16155 was 16155, checked in by Don-vip, 4 years ago

fix #18943 - add data types caption in Download along dialogues

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