From d7fe108f1f9431996fbee9593d8d9597a0a80c8b Mon Sep 17 00:00:00 2001 From: Taylor Smock Date: Thu, 21 May 2020 12:07:09 -0600 Subject: [PATCH] Initial implementation for setting sources in download * Add checkbox to main UI download panel * For more information, see JOSM-18340 * There have been some modifications so that both JOSM UI panel download methods use the same class to download. * Reuse panel from preferences for setting sources Signed-off-by: Taylor Smock --- .../plugins/mapwithai/MapWithAIPlugin.java | 11 +- .../backend/DownloadMapWithAITask.java | 100 +++++++++++------- .../data/mapwithai/MapWithAILayerInfo.java | 4 + .../download/MapWithAIDownloadOptions.java | 53 ++++++++++ .../gui/download/MapWithAIDownloadReader.java | 38 ++++--- .../download/MapWithAIDownloadSourceType.java | 48 +++++++++ .../mapwithai/MapWithAIProvidersPanel.java | 14 ++- .../download/MapWithAIDownloadReaderTest.java | 1 - 8 files changed, 208 insertions(+), 61 deletions(-) create mode 100644 src/main/java/org/openstreetmap/josm/plugins/mapwithai/gui/download/MapWithAIDownloadOptions.java create mode 100644 src/main/java/org/openstreetmap/josm/plugins/mapwithai/gui/download/MapWithAIDownloadSourceType.java diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/MapWithAIPlugin.java b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/MapWithAIPlugin.java index e7411a0..d97fc98 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/MapWithAIPlugin.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/MapWithAIPlugin.java @@ -23,6 +23,7 @@ import org.openstreetmap.josm.gui.MainApplication; import org.openstreetmap.josm.gui.MainMenu; import org.openstreetmap.josm.gui.MapFrame; import org.openstreetmap.josm.gui.download.DownloadDialog; +import org.openstreetmap.josm.gui.download.OSMDownloadSource; import org.openstreetmap.josm.gui.preferences.PreferenceSetting; import org.openstreetmap.josm.io.remotecontrol.RequestProcessor; import org.openstreetmap.josm.plugins.Plugin; @@ -41,7 +42,9 @@ import org.openstreetmap.josm.plugins.mapwithai.data.validation.tests.RoutingIsl import org.openstreetmap.josm.plugins.mapwithai.data.validation.tests.StreetAddressOrder; import org.openstreetmap.josm.plugins.mapwithai.data.validation.tests.StreetAddressTest; import org.openstreetmap.josm.plugins.mapwithai.data.validation.tests.StubEndsTest; +import org.openstreetmap.josm.plugins.mapwithai.gui.download.MapWithAIDownloadOptions; import org.openstreetmap.josm.plugins.mapwithai.gui.download.MapWithAIDownloadReader; +import org.openstreetmap.josm.plugins.mapwithai.gui.download.MapWithAIDownloadSourceType; import org.openstreetmap.josm.plugins.mapwithai.gui.preferences.MapWithAIPreferences; import org.openstreetmap.josm.spi.preferences.Config; import org.openstreetmap.josm.tools.Destroyable; @@ -101,14 +104,19 @@ public final class MapWithAIPlugin extends Plugin implements Destroyable { MapWithAIDataUtils.addMapWithAIPaintStyles(); + destroyables = new ArrayList<>(); + MapWithAIDownloadOptions mapWithAIDownloadOptions = new MapWithAIDownloadOptions(); + mapWithAIDownloadOptions.addGui(DownloadDialog.getInstance()); + destroyables.add(mapWithAIDownloadOptions); + setVersionInfo(info.localversion); RequestProcessor.addRequestHandlerClass("mapwithai", MapWithAIRemoteControl.class); new MapWithAIRemoteControl(); // instantiate to get action into Remote Control Preferences - destroyables = new ArrayList<>(); destroyables.add(new MapWithAIUploadHook(info)); mapFrameInitialized(null, MainApplication.getMap()); mapWithAIDownloadReader = new MapWithAIDownloadReader(); DownloadDialog.addDownloadSource(mapWithAIDownloadReader); + OSMDownloadSource.addDownloadType(new MapWithAIDownloadSourceType()); MainApplication.worker.execute(() -> UpdateProd.doProd(info.mainversion)); } @@ -171,6 +179,7 @@ public final class MapWithAIPlugin extends Plugin implements Destroyable { destroyables.forEach(Destroyable::destroy); DownloadDialog.removeDownloadSource(mapWithAIDownloadReader); + OSMDownloadSource.removeDownloadType(OSMDownloadSource.getDownloadType(MapWithAIDownloadSourceType.class)); VALIDATORS.forEach(OsmValidator::removeTest); DownloadListener.destroyAll(); } diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/backend/DownloadMapWithAITask.java b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/backend/DownloadMapWithAITask.java index 2f7c8f8..5439e2f 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/backend/DownloadMapWithAITask.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/backend/DownloadMapWithAITask.java @@ -3,28 +3,41 @@ package org.openstreetmap.josm.plugins.mapwithai.backend; import static org.openstreetmap.josm.tools.I18n.tr; +import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.concurrent.Future; +import java.util.stream.Collectors; import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask; import org.openstreetmap.josm.actions.downloadtasks.DownloadParams; import org.openstreetmap.josm.data.Bounds; -import org.openstreetmap.josm.data.ViewportData; -import org.openstreetmap.josm.data.osm.OsmPrimitive; +import org.openstreetmap.josm.data.osm.DataSet; import org.openstreetmap.josm.gui.MainApplication; -import org.openstreetmap.josm.gui.MapFrame; -import org.openstreetmap.josm.gui.io.UpdatePrimitivesTask; +import org.openstreetmap.josm.gui.progress.NullProgressMonitor; import org.openstreetmap.josm.gui.progress.ProgressMonitor; import org.openstreetmap.josm.io.OsmServerReader; +import org.openstreetmap.josm.io.OsmTransferException; +import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAIInfo; +import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAILayerInfo; import org.openstreetmap.josm.tools.Utils; +import org.xml.sax.SAXException; public class DownloadMapWithAITask extends DownloadOsmTask { + private List urls; + + public DownloadMapWithAITask() { + urls = MapWithAILayerInfo.getInstance().getLayers(); + } + @Override public Future download(OsmServerReader reader, DownloadParams settings, Bounds downloadArea, ProgressMonitor progressMonitor) { - return download(new MapWithAIDownloadTask(settings, reader, progressMonitor, zoomAfterDownload), downloadArea); + DownloadTask task = new DownloadTask(settings, tr("MapWithAI Download"), progressMonitor, false, false, + downloadArea); + return MainApplication.worker.submit(task); } @Override @@ -41,49 +54,58 @@ public class DownloadMapWithAITask extends DownloadOsmTask { return null; } - protected class MapWithAIDownloadTask extends DownloadOsmTask.DownloadTask { + protected class DownloadTask extends AbstractInternalTask { + BoundingBoxMapWithAIDownloader downloader; + final Bounds bounds; - /** - * Constructs a new {@code DownloadTask}. - * - * @param settings download settings - * @param reader OSM data reader - * @param progressMonitor progress monitor - */ - public MapWithAIDownloadTask(DownloadParams settings, OsmServerReader reader, ProgressMonitor progressMonitor) { - this(settings, reader, progressMonitor, true); + public DownloadTask(DownloadParams settings, String title, boolean ignoreException, boolean zoomAfterDownload, + Bounds bounds) { + this(settings, title, NullProgressMonitor.INSTANCE, ignoreException, zoomAfterDownload, bounds); } - /** - * Constructs a new {@code DownloadTask}. - * - * @param settings download settings - * @param reader OSM data reader - * @param progressMonitor progress monitor - * @param zoomAfterDownload If true, the map view will zoom to download area - * after download - */ - public MapWithAIDownloadTask(DownloadParams settings, OsmServerReader reader, ProgressMonitor progressMonitor, - boolean zoomAfterDownload) { - super(settings, reader, progressMonitor, zoomAfterDownload); + public DownloadTask(DownloadParams settings, String title, ProgressMonitor progressMonitor, + boolean ignoreException, boolean zoomAfterDownload, Bounds bounds) { + super(settings, title, progressMonitor, ignoreException, zoomAfterDownload); + this.bounds = bounds; } @Override - protected void loadData(String newLayerName, Bounds bounds) { - MapWithAILayer layer = MapWithAIDataUtils.getLayer(true); - Collection primitivesToUpdate = searchPrimitivesToUpdate(bounds, layer.getDataSet()); - layer.mergeFrom(dataSet); - MapFrame map = MainApplication.getMap(); - if (map != null && (zoomAfterDownload - || MainApplication.getLayerManager().getLayers().parallelStream().allMatch(layer::equals))) { - computeBbox(bounds).map(ViewportData::new).ifPresent(map.mapView::zoomTo); + protected void cancel() { + setCanceled(true); + if (downloader != null) { + downloader.cancel(); } - if (!primitivesToUpdate.isEmpty()) { - MainApplication.worker.execute(new UpdatePrimitivesTask(layer, primitivesToUpdate)); + } + + @Override + protected void realRun() throws SAXException, IOException, OsmTransferException { + Collection relevantUrls = urls.stream() + .filter(i -> i.getBounds() == null || i.getBounds().intersects(bounds)) + .collect(Collectors.toList()); + ProgressMonitor monitor = getProgressMonitor(); + if (relevantUrls.size() < 5) { + monitor.indeterminateSubTask(tr("MapWithAI Download")); + } else { + monitor.setTicksCount(relevantUrls.size()); + } + for (MapWithAIInfo info : relevantUrls) { + if (isCanceled()) { + break; + } + downloader = new BoundingBoxMapWithAIDownloader(bounds, info, false); + DataSet ds = downloader.parseOsm(monitor.createSubTaskMonitor(1, true)); + synchronized (DownloadMapWithAITask.DownloadTask.class) { + MapWithAIDataUtils.getLayer(true).getDataSet().mergeFrom(ds); + } + } + } + + @Override + protected void finish() { + if (!isCanceled() && !isFailed()) { + GetDataRunnable.cleanup(MapWithAIDataUtils.getLayer(true).getDataSet(), null); } - layer.onPostDownloadFromServer(bounds); } } - } diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/data/mapwithai/MapWithAILayerInfo.java b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/data/mapwithai/MapWithAILayerInfo.java index 6e552a2..c670c60 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/data/mapwithai/MapWithAILayerInfo.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/data/mapwithai/MapWithAILayerInfo.java @@ -67,6 +67,10 @@ public class MapWithAILayerInfo { /** Unique instance -- MUST be after DEFAULT_LAYER_SITES */ public static final MapWithAILayerInfo instance = new MapWithAILayerInfo(); + public static MapWithAILayerInfo getInstance() { + return instance; + } + /** * Returns the list of source layers sites. * diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/gui/download/MapWithAIDownloadOptions.java b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/gui/download/MapWithAIDownloadOptions.java new file mode 100644 index 0000000..b55a847 --- /dev/null +++ b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/gui/download/MapWithAIDownloadOptions.java @@ -0,0 +1,53 @@ +// License: GPL. For details, see LICENSE file. +package org.openstreetmap.josm.plugins.mapwithai.gui.download; + +import static org.openstreetmap.josm.tools.I18n.tr; + +import java.awt.GridBagLayout; + +import javax.swing.JLabel; +import javax.swing.JPanel; + +import org.openstreetmap.josm.data.Bounds; +import org.openstreetmap.josm.gui.bbox.JosmMapViewer; +import org.openstreetmap.josm.gui.download.DownloadDialog; +import org.openstreetmap.josm.gui.download.DownloadSelection; +import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAILayerInfo; +import org.openstreetmap.josm.plugins.mapwithai.gui.preferences.mapwithai.MapWithAIProvidersPanel; +import org.openstreetmap.josm.tools.Destroyable; +import org.openstreetmap.josm.tools.GBC; + +public class MapWithAIDownloadOptions extends JPanel implements DownloadSelection, Destroyable { + private final JPanel optionPanel; + private DownloadDialog iGui; + private JosmMapViewer defaultMap; + private MapWithAIProvidersPanel mapwithaiProvidersPanel; + + public MapWithAIDownloadOptions() { + optionPanel = new JPanel(new GridBagLayout()); + JPanel favorites = new JPanel(); + favorites.add(new JLabel("TODO: Favorites go here!")); // TODO + optionPanel.add(favorites, GBC.eol().fill(GBC.HORIZONTAL).anchor(GBC.NORTH)); + mapwithaiProvidersPanel = new MapWithAIProvidersPanel(this, MapWithAILayerInfo.getInstance()); + optionPanel.add(mapwithaiProvidersPanel); + } + + @Override + public void addGui(DownloadDialog gui) { + iGui = gui; + iGui.addDownloadAreaSelector(optionPanel, tr("Browse Data Sources")); + } + + @Override + public void setDownloadArea(Bounds area) { + // TODO + } + + @Override + public void destroy() { + if (this.iGui != null) { + this.iGui.remove(this); + } + } + +} diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/gui/download/MapWithAIDownloadReader.java b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/gui/download/MapWithAIDownloadReader.java index fb14184..435d558 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/gui/download/MapWithAIDownloadReader.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/gui/download/MapWithAIDownloadReader.java @@ -10,7 +10,6 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.util.Collection; import java.util.List; -import java.util.concurrent.Future; import java.util.function.Consumer; import javax.swing.Icon; @@ -18,17 +17,13 @@ import javax.swing.JLabel; import javax.swing.JOptionPane; import org.openstreetmap.josm.actions.downloadtasks.DownloadParams; -import org.openstreetmap.josm.actions.downloadtasks.PostDownloadHandler; import org.openstreetmap.josm.data.Bounds; import org.openstreetmap.josm.data.coor.LatLon; -import org.openstreetmap.josm.gui.MainApplication; import org.openstreetmap.josm.gui.download.AbstractDownloadSourcePanel; import org.openstreetmap.josm.gui.download.DownloadDialog; import org.openstreetmap.josm.gui.download.DownloadSettings; import org.openstreetmap.josm.gui.download.DownloadSource; import org.openstreetmap.josm.plugins.mapwithai.MapWithAIPlugin; -import org.openstreetmap.josm.plugins.mapwithai.backend.BoundingBoxMapWithAIDownloader; -import org.openstreetmap.josm.plugins.mapwithai.backend.DetectTaskingManagerUtils; import org.openstreetmap.josm.plugins.mapwithai.backend.DownloadMapWithAITask; import org.openstreetmap.josm.plugins.mapwithai.backend.MapWithAIDataUtils; import org.openstreetmap.josm.plugins.mapwithai.backend.MapWithAIPreferenceHelper; @@ -48,12 +43,9 @@ public class MapWithAIDownloadReader implements DownloadSource i.getBounds() == null || i.getBounds().intersects(area)).forEach(url -> { - Future future = task.download( - new BoundingBoxMapWithAIDownloader(area, url, DetectTaskingManagerUtils.hasTaskingManagerLayer()), - new DownloadParams(), area, null); - MainApplication.worker.execute(new PostDownloadHandler(task, future, data.getErrorReporter())); - }); + DownloadParams params = new DownloadParams(); + params.withNewLayer(settings.asNewLayer()); + task.download(params, area, null); } @Override @@ -151,12 +143,24 @@ public class MapWithAIDownloadReader implements DownloadSource MapWithAIDataUtils.MAXIMUM_SIDE_DIMENSIONS - || width > MapWithAIDataUtils.MAXIMUM_SIDE_DIMENSIONS); + displaySizeCheckResult(isDownloadAreaTooLarge(bbox)); + } + + /** + * Check if the download area is too large + * + * @param bound The bound to check + * @return {@code true} if the area is too large + */ + public static boolean isDownloadAreaTooLarge(Bounds bound) { + double width = Math.max( + bound.getMin().greatCircleDistance(new LatLon(bound.getMinLat(), bound.getMaxLon())), + bound.getMax().greatCircleDistance(new LatLon(bound.getMaxLat(), bound.getMinLon()))); + double height = Math.max( + bound.getMin().greatCircleDistance(new LatLon(bound.getMaxLat(), bound.getMinLon())), + bound.getMax().greatCircleDistance(new LatLon(bound.getMinLat(), bound.getMaxLon()))); + return height > MapWithAIDataUtils.MAXIMUM_SIDE_DIMENSIONS + || width > MapWithAIDataUtils.MAXIMUM_SIDE_DIMENSIONS; } private void displaySizeCheckResult(boolean isAreaTooLarge) { diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/gui/download/MapWithAIDownloadSourceType.java b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/gui/download/MapWithAIDownloadSourceType.java new file mode 100644 index 0000000..03622f2 --- /dev/null +++ b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/gui/download/MapWithAIDownloadSourceType.java @@ -0,0 +1,48 @@ +// License: GPL. For details, see LICENSE file. +package org.openstreetmap.josm.plugins.mapwithai.gui.download; + +import static org.openstreetmap.josm.tools.I18n.tr; + +import javax.swing.JCheckBox; +import javax.swing.event.ChangeListener; + +import org.openstreetmap.josm.actions.downloadtasks.AbstractDownloadTask; +import org.openstreetmap.josm.data.Bounds; +import org.openstreetmap.josm.data.preferences.BooleanProperty; +import org.openstreetmap.josm.gui.download.IDownloadSourceType; +import org.openstreetmap.josm.plugins.mapwithai.backend.DownloadMapWithAITask; + +public class MapWithAIDownloadSourceType implements IDownloadSourceType { + static final BooleanProperty IS_ENABLED = new BooleanProperty("download.mapwithai.data", false); + JCheckBox cbDownloadMapWithAIData; + + @Override + public JCheckBox getCheckBox(ChangeListener checkboxChangeListener) { + if (cbDownloadMapWithAIData == null) { + cbDownloadMapWithAIData = new JCheckBox(tr("MapWithAI data"), true); + cbDownloadMapWithAIData + .setToolTipText(tr("Select to download MapWithAI data in the selected download area.")); + cbDownloadMapWithAIData.getModel().addChangeListener(checkboxChangeListener); + } + if (checkboxChangeListener != null) { + cbDownloadMapWithAIData.getModel().addChangeListener(checkboxChangeListener); + } + return cbDownloadMapWithAIData; + } + + @Override + public Class> getDownloadClass() { + return DownloadMapWithAITask.class; + } + + @Override + public BooleanProperty getBooleanProperty() { + return IS_ENABLED; + } + + @Override + public boolean isDownloadAreaTooLarge(Bounds bound) { + return MapWithAIDownloadReader.MapWithAIDownloadPanel.isDownloadAreaTooLarge(bound); + } + +} diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/gui/preferences/mapwithai/MapWithAIProvidersPanel.java b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/gui/preferences/mapwithai/MapWithAIProvidersPanel.java index 96026f8..d43fccb 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/gui/preferences/mapwithai/MapWithAIProvidersPanel.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/gui/preferences/mapwithai/MapWithAIProvidersPanel.java @@ -29,6 +29,7 @@ import java.util.function.Function; import javax.swing.AbstractAction; import javax.swing.Box; import javax.swing.JButton; +import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; @@ -107,7 +108,7 @@ public class MapWithAIProvidersPanel extends JPanel { public final JToolBar defaultToolbar; // Private members - private final PreferenceTabbedPane gui; + private final JComponent gui; private final transient MapWithAILayerInfo layerInfo; /** @@ -227,7 +228,7 @@ public class MapWithAIProvidersPanel extends JPanel { * @param gui The parent preference tab pane * @param layerInfoArg The list of imagery entries to display */ - public MapWithAIProvidersPanel(final PreferenceTabbedPane gui, MapWithAILayerInfo layerInfoArg) { + public MapWithAIProvidersPanel(final JComponent gui, MapWithAILayerInfo layerInfoArg) { super(new GridBagLayout()); this.gui = gui; this.layerInfo = layerInfoArg; @@ -474,7 +475,14 @@ public class MapWithAIProvidersPanel extends JPanel { if (addDialog.getValue() == 1) { try { - activeModel.addRow(p.getSourceInfo()); + MapWithAIInfo info = p.getSourceInfo(); + if (MapWithAIInfo.MapWithAIType.ESRI.equals(info.getSourceType())) { + for (MapWithAIInfo i : MapWithAILayerInfo.addEsriLayer(info)) { + activeModel.addRow(i); + } + } else { + activeModel.addRow(info); + } } catch (IllegalArgumentException ex) { if (ex.getMessage() == null || ex.getMessage().isEmpty()) { throw ex; diff --git a/test/unit/org/openstreetmap/josm/plugins/mapwithai/gui/download/MapWithAIDownloadReaderTest.java b/test/unit/org/openstreetmap/josm/plugins/mapwithai/gui/download/MapWithAIDownloadReaderTest.java index 8180946..d713413 100644 --- a/test/unit/org/openstreetmap/josm/plugins/mapwithai/gui/download/MapWithAIDownloadReaderTest.java +++ b/test/unit/org/openstreetmap/josm/plugins/mapwithai/gui/download/MapWithAIDownloadReaderTest.java @@ -23,7 +23,6 @@ import org.openstreetmap.josm.plugins.mapwithai.MapWithAIPlugin; import org.openstreetmap.josm.plugins.mapwithai.backend.MapWithAIDataUtils; import org.openstreetmap.josm.plugins.mapwithai.backend.MapWithAIDataUtilsTest; import org.openstreetmap.josm.plugins.mapwithai.backend.MapWithAIPreferenceHelper; -import org.openstreetmap.josm.plugins.mapwithai.gui.download.MapWithAIDownloadReader; import org.openstreetmap.josm.plugins.mapwithai.gui.download.MapWithAIDownloadReader.MapWithAIDownloadData; import org.openstreetmap.josm.plugins.mapwithai.testutils.MapWithAITestRules; import org.openstreetmap.josm.testutils.JOSMTestRules;