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