001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.layer.gpx;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.event.ActionEvent;
007import java.io.IOException;
008import java.util.List;
009import java.util.stream.Collectors;
010
011import javax.swing.AbstractAction;
012import javax.swing.JOptionPane;
013
014import org.openstreetmap.gui.jmapviewer.tilesources.AbstractTMSTileSource;
015import org.openstreetmap.josm.actions.AbstractMergeAction;
016import org.openstreetmap.josm.data.coor.LatLon;
017import org.openstreetmap.josm.data.gpx.GpxData;
018import org.openstreetmap.josm.data.gpx.WayPoint;
019import org.openstreetmap.josm.gui.MainApplication;
020import org.openstreetmap.josm.gui.PleaseWaitRunnable;
021import org.openstreetmap.josm.gui.layer.AbstractTileSourceLayer;
022import org.openstreetmap.josm.gui.progress.ProgressTaskId;
023import org.openstreetmap.josm.gui.progress.ProgressTaskIds;
024import org.openstreetmap.josm.io.OsmTransferException;
025import org.openstreetmap.josm.tools.ImageProvider;
026import org.openstreetmap.josm.tools.Logging;
027import org.xml.sax.SAXException;
028
029/**
030 * Class downloading WMS and TMS along the GPX track.
031 * @since 5715
032 */
033public class DownloadWmsAlongTrackAction extends AbstractAction {
034
035    private final transient GpxData data;
036
037    /**
038     * @param data that represents GPX track, along which data should be downloaded
039     */
040    public DownloadWmsAlongTrackAction(final GpxData data) {
041        super(tr("Precache imagery tiles along this track"));
042        new ImageProvider("downloadalongtrack").getResource().attachImageIcon(this, true);
043        this.data = data;
044    }
045
046    static class PrecacheWmsTask extends PleaseWaitRunnable {
047
048        private final AbstractTileSourceLayer<? extends AbstractTMSTileSource> layer;
049        private final List<LatLon> points;
050        private AbstractTileSourceLayer<? extends AbstractTMSTileSource>.PrecacheTask precacheTask;
051
052        protected PrecacheWmsTask(AbstractTileSourceLayer<? extends AbstractTMSTileSource> layer, List<LatLon> points) {
053            super(tr("Precaching WMS"));
054            this.layer = layer;
055            this.points = points;
056        }
057
058        @Override
059        protected void realRun() throws SAXException, IOException, OsmTransferException {
060            precacheTask = layer.getDownloadAreaToCacheTask(progressMonitor, points, 0, 0);
061            precacheTask.run();
062            synchronized (this) {
063                try {
064                    while (!precacheTask.isFinished() && !progressMonitor.isCanceled()) {
065                        wait(200);
066                    }
067                } catch (InterruptedException ex) {
068                    Logging.warn("InterruptedException in "+getClass().getSimpleName()+" while precaching WMS");
069                    Thread.currentThread().interrupt();
070                }
071            }
072        }
073
074        @Override
075        protected void finish() {
076            // Do nothing
077        }
078
079        @Override
080        protected void cancel() {
081            precacheTask.cancel();
082        }
083
084        @Override
085        public ProgressTaskId canRunInBackground() {
086            return ProgressTaskIds.PRECACHE_WMS;
087        }
088    }
089
090    PrecacheWmsTask createTask() {
091        List<LatLon> points = data.tracks.stream()
092                .flatMap(trk -> trk.getSegments().stream())
093                .flatMap(segment -> segment.getWayPoints().stream())
094                .map(WayPoint::getCoor)
095                .collect(Collectors.toList());
096        for (WayPoint p : data.waypoints) {
097            points.add(p.getCoor());
098        }
099        AbstractTileSourceLayer<? extends AbstractTMSTileSource> layer = askedLayer();
100        return layer != null ? new PrecacheWmsTask(layer, points) : null;
101    }
102
103    @Override
104    public void actionPerformed(ActionEvent e) {
105        PrecacheWmsTask task = createTask();
106        if (task != null) {
107            MainApplication.worker.execute(task);
108        }
109    }
110
111    @SuppressWarnings({ "rawtypes", "unchecked" })
112    protected AbstractTileSourceLayer<? extends AbstractTMSTileSource> askedLayer() {
113        List<AbstractTileSourceLayer> targetLayers = MainApplication.getLayerManager().getLayersOfType(AbstractTileSourceLayer.class);
114        if (targetLayers.isEmpty()) {
115            warnNoImageryLayers();
116            return null;
117        }
118        return AbstractMergeAction.askTargetLayer(targetLayers.toArray(new AbstractTileSourceLayer[0]),
119                tr("Please select the imagery layer."),
120                tr("Select imagery layer"),
121                tr("Download"), "dialogs/down");
122    }
123
124    protected void warnNoImageryLayers() {
125        JOptionPane.showMessageDialog(MainApplication.getMainFrame(),
126                tr("There are no imagery layers."), tr("No imagery layers"), JOptionPane.WARNING_MESSAGE);
127    }
128}