Ticket #16809: v1-0002-SlippyMapBBoxChooser-redesign-getAllTileSources-t.patch

File v1-0002-SlippyMapBBoxChooser-redesign-getAllTileSources-t.patch, 7.7 KB (added by ris, 6 years ago)
  • src/org/openstreetmap/josm/gui/bbox/SlippyMapBBoxChooser.java

    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;  
    1616import java.util.Collections;
    1717import java.util.HashMap;
    1818import java.util.HashSet;
     19import java.util.LinkedHashMap;
    1920import java.util.List;
    2021import java.util.Map;
    2122import java.util.Set;
    2223import java.util.concurrent.CopyOnWriteArrayList;
    2324import java.util.concurrent.TimeUnit;
     25import java.util.stream.Collectors;
    2426
    2527import javax.swing.ButtonModel;
    2628import javax.swing.JOptionPane;
    public class SlippyMapBBoxChooser extends JMapViewer implements BBoxChooser, Cha  
    7880     * TMS TileSource provider for the slippymap chooser
    7981     */
    8082    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         }
    8683
    8784        @Override
    8885        public List<TileSource> getTileSources() {
    8986            if (!TMSLayer.PROP_ADD_TO_SLIPPYMAP_CHOOSER.get()) return Collections.<TileSource>emptyList();
    9087            List<TileSource> sources = new ArrayList<>();
    9188            for (ImageryInfo info : ImageryLayerInfo.instance.getLayers()) {
    92                 if (existingSlippyMapUrls.contains(info.getUrl())) {
    93                     continue;
    94                 }
    9589                try {
    9690                    TileSource source = TMSLayer.getTileSourceStatic(info);
    9791                    if (source != null) {
    public class SlippyMapBBoxChooser extends JMapViewer implements BBoxChooser, Cha  
    177171        }
    178172        setMaxTilesInMemory(Config.getPref().getInt("slippy_map_chooser.max_tiles", 1000));
    179173
    180         List<TileSource> tileSources = getAllTileSources();
     174        List<TileSource> tileSources = new ArrayList<>(getAllTileSources().values());
    181175
    182176        this.showDownloadAreaButtonModel = new JToggleButton.ToggleButtonModel();
    183177        this.showDownloadAreaButtonModel.setSelected(PROP_SHOWDLAREA.get());
    public class SlippyMapBBoxChooser extends JMapViewer implements BBoxChooser, Cha  
    210204        new SlippyMapControler(this, this);
    211205    }
    212206
    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        ));
    219217    }
    220218
    221219    /**
    public class SlippyMapBBoxChooser extends JMapViewer implements BBoxChooser, Cha  
    358356        this.tileController.setTileCache(new MemoryTileCache());
    359357        this.setTileSource(tileSource);
    360358        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();
    364365    }
    365366
    366367    @Override
    public class SlippyMapBBoxChooser extends JMapViewer implements BBoxChooser, Cha  
    416417     * @since 6364
    417418     */
    418419    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()));
    420427    }
    421428}
  • test/unit/org/openstreetmap/josm/gui/dialogs/MinimapDialogTest.java

    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;  
    3030import org.openstreetmap.josm.data.Bounds;
    3131import org.openstreetmap.josm.data.DataSource;
    3232import org.openstreetmap.josm.data.osm.DataSet;
     33import org.openstreetmap.josm.data.imagery.ImageryLayerInfo;
    3334import org.openstreetmap.josm.data.projection.ProjectionRegistry;
    3435import org.openstreetmap.josm.data.projection.Projections;
    3536import org.openstreetmap.josm.gui.MainApplication;
    public class MinimapDialogTest {  
    257258    }
    258259
    259260    /**
     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    /**
    260295     * Tests minimap obeys a saved "mapstyle" preference on startup.
    261296     * @throws Exception if any error occurs
    262297     */