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}