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

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

fix #15275 - Download dialog does not remember settings

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