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