From 19ccf18472593b6e653888e370a0313134e441b1 Mon Sep 17 00:00:00 2001
From: Robert Scott <code@humanleg.org.uk>
Date: Sun, 30 Sep 2018 12:33:27 +0100
Subject: [PATCH v1 2/4] SlippyMapBBoxChooser: redesign getAllTileSources to
perform deduplication of provided tile sources
this also enables us to easily ensure currently active TileSource remains present & selected in
the source menu even when it's no longer supplied by TileSourceProviders
---
.../josm/gui/bbox/SlippyMapBBoxChooser.java | 45 +++++++++++++---------
.../josm/gui/dialogs/MinimapDialogTest.java | 35 +++++++++++++++++
2 files changed, 61 insertions(+), 19 deletions(-)
diff --git a/src/org/openstreetmap/josm/gui/bbox/SlippyMapBBoxChooser.java b/src/org/openstreetmap/josm/gui/bbox/SlippyMapBBoxChooser.java
index 907a5152f..4b322854d 100644
|
a
|
b
|
import java.util.Arrays;
|
| 16 | 16 | import java.util.Collections; |
| 17 | 17 | import java.util.HashMap; |
| 18 | 18 | import java.util.HashSet; |
| | 19 | import java.util.LinkedHashMap; |
| 19 | 20 | import java.util.List; |
| 20 | 21 | import java.util.Map; |
| 21 | 22 | import java.util.Set; |
| 22 | 23 | import java.util.concurrent.CopyOnWriteArrayList; |
| 23 | 24 | import java.util.concurrent.TimeUnit; |
| | 25 | import java.util.stream.Collectors; |
| 24 | 26 | |
| 25 | 27 | import javax.swing.ButtonModel; |
| 26 | 28 | import javax.swing.JOptionPane; |
| … |
… |
public class SlippyMapBBoxChooser extends JMapViewer implements BBoxChooser, Cha
|
| 78 | 80 | * TMS TileSource provider for the slippymap chooser |
| 79 | 81 | */ |
| 80 | 82 | public static class TMSTileSourceProvider implements TileSourceProvider { |
| 81 | | private static final Set<String> existingSlippyMapUrls = new HashSet<>(); |
| 82 | | static { |
| 83 | | // Urls that already exist in the slippymap chooser and shouldn't be copied from TMS layer list |
| 84 | | existingSlippyMapUrls.add("https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png"); // Mapnik |
| 85 | | } |
| 86 | 83 | |
| 87 | 84 | @Override |
| 88 | 85 | public List<TileSource> getTileSources() { |
| 89 | 86 | if (!TMSLayer.PROP_ADD_TO_SLIPPYMAP_CHOOSER.get()) return Collections.<TileSource>emptyList(); |
| 90 | 87 | List<TileSource> sources = new ArrayList<>(); |
| 91 | 88 | for (ImageryInfo info : ImageryLayerInfo.instance.getLayers()) { |
| 92 | | if (existingSlippyMapUrls.contains(info.getUrl())) { |
| 93 | | continue; |
| 94 | | } |
| 95 | 89 | try { |
| 96 | 90 | TileSource source = TMSLayer.getTileSourceStatic(info); |
| 97 | 91 | if (source != null) { |
| … |
… |
public class SlippyMapBBoxChooser extends JMapViewer implements BBoxChooser, Cha
|
| 177 | 171 | } |
| 178 | 172 | setMaxTilesInMemory(Config.getPref().getInt("slippy_map_chooser.max_tiles", 1000)); |
| 179 | 173 | |
| 180 | | List<TileSource> tileSources = getAllTileSources(); |
| | 174 | List<TileSource> tileSources = new ArrayList<>(getAllTileSources().values()); |
| 181 | 175 | |
| 182 | 176 | this.showDownloadAreaButtonModel = new JToggleButton.ToggleButtonModel(); |
| 183 | 177 | this.showDownloadAreaButtonModel.setSelected(PROP_SHOWDLAREA.get()); |
| … |
… |
public class SlippyMapBBoxChooser extends JMapViewer implements BBoxChooser, Cha
|
| 210 | 204 | new SlippyMapControler(this, this); |
| 211 | 205 | } |
| 212 | 206 | |
| 213 | | private static List<TileSource> getAllTileSources() { |
| 214 | | List<TileSource> tileSources = new ArrayList<>(); |
| 215 | | for (TileSourceProvider provider: providers) { |
| 216 | | tileSources.addAll(provider.getTileSources()); |
| 217 | | } |
| 218 | | return tileSources; |
| | 207 | private static LinkedHashMap<String, TileSource> getAllTileSources() { |
| | 208 | // using a LinkedHashMap of <id, TileSource> to retain ordering but provide deduplication |
| | 209 | return providers.stream().flatMap( |
| | 210 | provider -> provider.getTileSources().stream() |
| | 211 | ).collect(Collectors.toMap( |
| | 212 | TileSource::getId, |
| | 213 | ts -> ts, |
| | 214 | (old, _new) -> old, |
| | 215 | () -> new LinkedHashMap<String, TileSource>() |
| | 216 | )); |
| 219 | 217 | } |
| 220 | 218 | |
| 221 | 219 | /** |
| … |
… |
public class SlippyMapBBoxChooser extends JMapViewer implements BBoxChooser, Cha
|
| 358 | 356 | this.tileController.setTileCache(new MemoryTileCache()); |
| 359 | 357 | this.setTileSource(tileSource); |
| 360 | 358 | PROP_MAPSTYLE.put(tileSource.getName()); // TODO Is name really unique? |
| 361 | | if (this.iSourceButton.getCurrentSource() != tileSource) { // prevent infinite recursion |
| 362 | | this.iSourceButton.setCurrentMap(tileSource); |
| 363 | | } |
| | 359 | |
| | 360 | // we need to refresh the tile sources in case the deselected source should no longer be present |
| | 361 | // (and only remained there because its removal was deferred while the source was still the |
| | 362 | // selected one). this should also have the effect of propagating the new selection to the |
| | 363 | // iSourceButton & menu: it attempts to re-select the current source when rebuilding its menu. |
| | 364 | this.refreshTileSources(); |
| 364 | 365 | } |
| 365 | 366 | |
| 366 | 367 | @Override |
| … |
… |
public class SlippyMapBBoxChooser extends JMapViewer implements BBoxChooser, Cha
|
| 416 | 417 | * @since 6364 |
| 417 | 418 | */ |
| 418 | 419 | public final void refreshTileSources() { |
| 419 | | iSourceButton.setSources(getAllTileSources()); |
| | 420 | final LinkedHashMap<String, TileSource> newTileSources = getAllTileSources(); |
| | 421 | final TileSource currentTileSource = this.getTileController().getTileSource(); |
| | 422 | |
| | 423 | // re-add the currently active TileSource to prevent inconsistent display of menu |
| | 424 | newTileSources.putIfAbsent(currentTileSource.getId(), currentTileSource); |
| | 425 | |
| | 426 | this.iSourceButton.setSources(new ArrayList<>(newTileSources.values())); |
| 420 | 427 | } |
| 421 | 428 | } |
diff --git a/test/unit/org/openstreetmap/josm/gui/dialogs/MinimapDialogTest.java b/test/unit/org/openstreetmap/josm/gui/dialogs/MinimapDialogTest.java
index f8a61a41b..9d9fa63e3 100644
|
a
|
b
|
import org.openstreetmap.josm.TestUtils;
|
| 30 | 30 | import org.openstreetmap.josm.data.Bounds; |
| 31 | 31 | import org.openstreetmap.josm.data.DataSource; |
| 32 | 32 | import org.openstreetmap.josm.data.osm.DataSet; |
| | 33 | import org.openstreetmap.josm.data.imagery.ImageryLayerInfo; |
| 33 | 34 | import org.openstreetmap.josm.data.projection.ProjectionRegistry; |
| 34 | 35 | import org.openstreetmap.josm.data.projection.Projections; |
| 35 | 36 | import org.openstreetmap.josm.gui.MainApplication; |
| … |
… |
public class MinimapDialogTest {
|
| 257 | 258 | } |
| 258 | 259 | |
| 259 | 260 | /** |
| | 261 | * Tests that the currently selected source being removed from ImageryLayerInfo will remain present and |
| | 262 | * selected in the source menu even after the tile sources have been refreshed. |
| | 263 | * @throws Exception if any error occurs |
| | 264 | */ |
| | 265 | @Test |
| | 266 | public void testRemovedSourceStillSelected() throws Exception { |
| | 267 | // relevant prefs starting out empty, should choose the first source and have shown download area enabled |
| | 268 | // (not that there's a data layer for it to use) |
| | 269 | |
| | 270 | this.setUpMiniMap(); |
| | 271 | |
| | 272 | this.clickSourceMenuItemByLabel("Green Tiles"); |
| | 273 | |
| | 274 | ImageryLayerInfo.instance.remove( |
| | 275 | ImageryLayerInfo.instance.getLayers().stream().filter(i -> i.getName().equals("Green Tiles")).findAny().get() |
| | 276 | ); |
| | 277 | |
| | 278 | this.assertSingleSelectedSourceLabel("Green Tiles"); |
| | 279 | |
| | 280 | this.slippyMap.refreshTileSources(); |
| | 281 | |
| | 282 | this.assertSingleSelectedSourceLabel("Green Tiles"); |
| | 283 | |
| | 284 | // call paint to trigger new tile fetch |
| | 285 | this.paintSlippyMap(); |
| | 286 | |
| | 287 | Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished); |
| | 288 | |
| | 289 | this.paintSlippyMap(); |
| | 290 | |
| | 291 | assertEquals(0xff00ff00, paintedSlippyMap.getRGB(0, 0)); |
| | 292 | } |
| | 293 | |
| | 294 | /** |
| 260 | 295 | * Tests minimap obeys a saved "mapstyle" preference on startup. |
| 261 | 296 | * @throws Exception if any error occurs |
| 262 | 297 | */ |