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