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}