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.PleaseWaitRunnable;
024import org.openstreetmap.josm.gui.layer.AbstractTileSourceLayer;
025import org.openstreetmap.josm.gui.progress.ProgressTaskId;
026import org.openstreetmap.josm.gui.progress.ProgressTaskIds;
027import org.openstreetmap.josm.io.OsmTransferException;
028import org.openstreetmap.josm.tools.ImageProvider;
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"), ImageProvider.get("downloadalongtrack"));
044        this.data = data;
045    }
046
047    static class PrecacheWmsTask extends PleaseWaitRunnable {
048
049        private final AbstractTileSourceLayer<? extends AbstractTMSTileSource> layer;
050        private final List<LatLon> points;
051        private AbstractTileSourceLayer<? extends AbstractTMSTileSource>.PrecacheTask precacheTask;
052
053        protected PrecacheWmsTask(AbstractTileSourceLayer<? extends AbstractTMSTileSource> layer, List<LatLon> points) {
054            super(tr("Precaching WMS"));
055            this.layer = layer;
056            this.points = points;
057        }
058
059        @Override
060        protected void realRun() throws SAXException, IOException, OsmTransferException {
061            precacheTask = layer.downloadAreaToCache(progressMonitor, points, 0, 0);
062            synchronized (this) {
063                try {
064                    while (!precacheTask.isFinished() && !progressMonitor.isCanceled()) {
065                        wait(200);
066                    }
067                } catch (InterruptedException ex) {
068                    Main.warn("InterruptedException in "+getClass().getSimpleName()+" while precaching WMS");
069                }
070            }
071        }
072
073        @Override
074        protected void finish() {
075            // Do nothing
076        }
077
078        @Override
079        protected void cancel() {
080            precacheTask.cancel();
081        }
082
083        @Override
084        public ProgressTaskId canRunInBackground() {
085            return ProgressTaskIds.PRECACHE_WMS;
086        }
087    }
088
089    PrecacheWmsTask createTask() {
090        List<LatLon> points = new ArrayList<>();
091        for (GpxTrack trk : data.tracks) {
092            for (GpxTrackSegment segment : trk.getSegments()) {
093                for (WayPoint p : segment.getWayPoints()) {
094                    points.add(p.getCoor());
095                }
096            }
097        }
098        for (WayPoint p : data.waypoints) {
099            points.add(p.getCoor());
100        }
101        AbstractTileSourceLayer<? extends AbstractTMSTileSource> layer = askedLayer();
102        return layer != null ? new PrecacheWmsTask(layer, points) : null;
103    }
104
105    @Override
106    public void actionPerformed(ActionEvent e) {
107        PrecacheWmsTask task = createTask();
108        if (task != null) {
109            Main.worker.execute(task);
110        }
111    }
112
113    @SuppressWarnings({ "rawtypes", "unchecked" })
114    protected AbstractTileSourceLayer<? extends AbstractTMSTileSource> askedLayer() {
115        if (!Main.isDisplayingMapView()) {
116            return null;
117        }
118        List<AbstractTileSourceLayer> targetLayers = Main.map.mapView.getLayersOfType(AbstractTileSourceLayer.class);
119        if (targetLayers.isEmpty()) {
120            if (!GraphicsEnvironment.isHeadless()) {
121                warnNoImageryLayers();
122            }
123            return null;
124        }
125        return AbstractMergeAction.askTargetLayer(targetLayers.toArray(new AbstractTileSourceLayer[0]),
126                tr("Please select the imagery layer."),
127                tr("Select imagery layer"),
128                tr("Download"), "dialogs/down");
129    }
130
131    protected void warnNoImageryLayers() {
132        JOptionPane.showMessageDialog(Main.parent, tr("There are no imagery layers."), tr("No imagery layers"), JOptionPane.WARNING_MESSAGE);
133    }
134}