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

Last change on this file since 12652 was 12652, checked in by michael2402, 4 months ago

Apply #15167: Merge OSM and overpass download dialog. Patch by bafonins

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