Changeset 14300 in josm
- Timestamp:
- 2018-10-06T22:01:03+02:00 (6 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/bbox/SlippyMapBBoxChooser.java
r14273 r14300 16 16 import java.util.Collections; 17 17 import java.util.HashMap; 18 import java.util. HashSet;18 import java.util.LinkedHashMap; 19 19 import java.util.List; 20 20 import java.util.Map; 21 import java.util.Set;22 21 import java.util.concurrent.CopyOnWriteArrayList; 23 22 import java.util.concurrent.TimeUnit; 23 import java.util.stream.Collectors; 24 24 25 25 import javax.swing.ButtonModel; … … 53 53 import org.openstreetmap.josm.gui.MainApplication; 54 54 import org.openstreetmap.josm.gui.layer.AbstractCachedTileSourceLayer; 55 import org.openstreetmap.josm.gui.layer.ImageryLayer; 55 56 import org.openstreetmap.josm.gui.layer.MainLayerManager; 56 57 import org.openstreetmap.josm.gui.layer.TMSLayer; … … 61 62 * This panel displays a map and lets the user chose a {@link BBox}. 62 63 */ 63 public class SlippyMapBBoxChooser extends JMapViewer implements BBoxChooser, ChangeListener, MainLayerManager.ActiveLayerChangeListener {64 64 public class SlippyMapBBoxChooser extends JMapViewer implements BBoxChooser, ChangeListener, 65 MainLayerManager.ActiveLayerChangeListener, MainLayerManager.LayerChangeListener { 65 66 /** 66 67 * A list of tile sources that can be used for displaying the map. … … 76 77 77 78 /** 78 * TMS TileSource provider for the slippymap chooser 79 */ 80 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 } 79 * TileSource provider for the slippymap chooser. 80 * @since 14300 81 */ 82 public abstract static class AbstractImageryInfoBasedTileSourceProvider implements TileSourceProvider { 83 /** 84 * Returns the list of imagery infos backing tile sources. 85 * @return the list of imagery infos backing tile sources 86 */ 87 public abstract List<ImageryInfo> getImageryInfos(); 86 88 87 89 @Override … … 89 91 if (!TMSLayer.PROP_ADD_TO_SLIPPYMAP_CHOOSER.get()) return Collections.<TileSource>emptyList(); 90 92 List<TileSource> sources = new ArrayList<>(); 91 for (ImageryInfo info : ImageryLayerInfo.instance.getLayers()) { 92 if (existingSlippyMapUrls.contains(info.getUrl())) { 93 continue; 94 } 93 for (ImageryInfo info : this.getImageryInfos()) { 95 94 try { 96 95 TileSource source = TMSLayer.getTileSourceStatic(info); … … 112 111 113 112 /** 113 * TileSource provider for the slippymap chooser - providing sources from imagery sources menu 114 * @since 14300 115 */ 116 public static class TMSTileSourceProvider extends AbstractImageryInfoBasedTileSourceProvider { 117 @Override 118 public List<ImageryInfo> getImageryInfos() { 119 return ImageryLayerInfo.instance.getLayers(); 120 } 121 } 122 123 /** 124 * TileSource provider for the slippymap chooser - providing sources from current layers 125 * @since 14300 126 */ 127 public static class CurrentLayersTileSourceProvider extends AbstractImageryInfoBasedTileSourceProvider { 128 @Override 129 public List<ImageryInfo> getImageryInfos() { 130 return MainApplication.getLayerManager().getLayers().stream().filter( 131 layer -> layer instanceof ImageryLayer 132 ).map( 133 layer -> ((ImageryLayer) layer).getInfo() 134 ).collect(Collectors.toList()); 135 } 136 } 137 138 /** 114 139 * Plugins that wish to add custom tile sources to slippy map choose should call this method 115 140 * @param tileSourceProvider new tile source provider … … 123 148 addTileSourceProvider(() -> Arrays.<TileSource>asList(new OsmTileSource.Mapnik())); 124 149 addTileSourceProvider(new TMSTileSourceProvider()); 150 addTileSourceProvider(new CurrentLayersTileSourceProvider()); 125 151 } 126 152 … … 178 204 setMaxTilesInMemory(Config.getPref().getInt("slippy_map_chooser.max_tiles", 1000)); 179 205 180 List<TileSource> tileSources = getAllTileSources();206 List<TileSource> tileSources = new ArrayList<>(getAllTileSources().values()); 181 207 182 208 this.showDownloadAreaButtonModel = new JToggleButton.ToggleButtonModel(); … … 211 237 } 212 238 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; 239 private static LinkedHashMap<String, TileSource> getAllTileSources() { 240 // using a LinkedHashMap of <id, TileSource> to retain ordering but provide deduplication 241 return providers.stream().flatMap( 242 provider -> provider.getTileSources().stream() 243 ).collect(Collectors.toMap( 244 TileSource::getId, 245 ts -> ts, 246 (oldTs, newTs) -> oldTs, 247 LinkedHashMap::new 248 )); 219 249 } 220 250 … … 359 389 this.setTileSource(tileSource); 360 390 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 } 391 392 // we need to refresh the tile sources in case the deselected source should no longer be present 393 // (and only remained there because its removal was deferred while the source was still the 394 // selected one). this should also have the effect of propagating the new selection to the 395 // iSourceButton & menu: it attempts to re-select the current source when rebuilding its menu. 396 this.refreshTileSources(); 364 397 } 365 398 … … 417 450 */ 418 451 public final void refreshTileSources() { 419 iSourceButton.setSources(getAllTileSources()); 420 } 452 final LinkedHashMap<String, TileSource> newTileSources = getAllTileSources(); 453 final TileSource currentTileSource = this.getTileController().getTileSource(); 454 455 // re-add the currently active TileSource to prevent inconsistent display of menu 456 newTileSources.putIfAbsent(currentTileSource.getId(), currentTileSource); 457 458 this.iSourceButton.setSources(new ArrayList<>(newTileSources.values())); 459 } 460 461 @Override 462 public void layerAdded(MainLayerManager.LayerAddEvent e) { 463 if (e.getAddedLayer() instanceof ImageryLayer) { 464 this.refreshTileSources(); 465 } 466 } 467 468 @Override 469 public void layerRemoving(MainLayerManager.LayerRemoveEvent e) { 470 if (e.getRemovedLayer() instanceof ImageryLayer) { 471 this.refreshTileSources(); 472 } 473 } 474 475 @Override 476 public void layerOrderChanged(MainLayerManager.LayerOrderChangeEvent e) {} 421 477 } -
trunk/src/org/openstreetmap/josm/gui/bbox/SourceButton.java
r12962 r14300 82 82 83 83 // attempt to initialize button group matching current state of slippyMapBBoxChooser 84 buttonModel.setSelected(this.slippyMapBBoxChooser.getTileController().getTileSource() == ts);84 buttonModel.setSelected(this.slippyMapBBoxChooser.getTileController().getTileSource().getId().equals(ts.getId())); 85 85 } 86 86 -
trunk/src/org/openstreetmap/josm/gui/dialogs/MinimapDialog.java
r12630 r14300 38 38 slippyMap.setSizeButtonVisible(false); 39 39 slippyMap.addPropertyChangeListener(BBoxChooser.BBOX_PROP, this); 40 MainApplication.getLayerManager().addLayerChangeListener(slippyMap); 40 41 } 41 42 -
trunk/test/unit/org/openstreetmap/josm/gui/dialogs/MinimapDialogTest.java
r14201 r14300 3 3 4 4 import static java.util.concurrent.TimeUnit.MILLISECONDS; 5 import static org.junit.Assert.assertArrayEquals; 5 6 import static org.junit.Assert.assertEquals; 6 7 import static org.junit.Assert.assertFalse; … … 14 15 import java.awt.event.ComponentEvent; 15 16 import java.awt.image.BufferedImage; 17 import java.util.ArrayList; 16 18 import java.util.Arrays; 17 19 import java.util.Map; … … 31 33 import org.openstreetmap.josm.data.DataSource; 32 34 import org.openstreetmap.josm.data.osm.DataSet; 35 import org.openstreetmap.josm.data.imagery.ImageryInfo; 36 import org.openstreetmap.josm.data.imagery.ImageryLayerInfo; 33 37 import org.openstreetmap.josm.data.projection.ProjectionRegistry; 34 38 import org.openstreetmap.josm.data.projection.Projections; … … 37 41 import org.openstreetmap.josm.gui.bbox.SlippyMapBBoxChooser; 38 42 import org.openstreetmap.josm.gui.bbox.SourceButton; 43 import org.openstreetmap.josm.gui.layer.ImageryLayer; 39 44 import org.openstreetmap.josm.gui.layer.LayerManagerTest.TestLayer; 40 45 import org.openstreetmap.josm.gui.layer.OsmDataLayer; … … 128 133 } 129 134 135 protected void assertSourceLabelsVisible(final String... labels) { 136 GuiHelper.runInEDTAndWaitWithException(() -> { 137 final ArrayList<String> menuLabels = new ArrayList<>(); 138 final JPopupMenu menu = this.sourceButton.getPopupMenu(); 139 for (Component c: menu.getComponents()) { 140 if (c instanceof JPopupMenu.Separator) { 141 break; 142 } 143 menuLabels.add(((JMenuItem) c).getText()); 144 } 145 146 assertArrayEquals( 147 labels, 148 menuLabels.toArray() 149 ); 150 }); 151 } 152 130 153 private MinimapDialog minimap; 131 154 private SlippyMapBBoxChooser slippyMap; … … 218 241 219 242 assertEquals("Green Tiles", Config.getPref().get("slippy_map_chooser.mapstyle", "Fail")); 243 } 244 245 /** 246 * Tests that the apparently-selected TileSource survives the tile sources being refreshed. 247 * @throws Exception if any error occurs 248 */ 249 @Test 250 public void testRefreshSourcesRetainsSelection() throws Exception { 251 // relevant prefs starting out empty, should choose the first source and have shown download area enabled 252 // (not that there's a data layer for it to use) 253 254 this.setUpMiniMap(); 255 256 this.clickSourceMenuItemByLabel("Magenta Tiles"); 257 this.assertSingleSelectedSourceLabel("Magenta Tiles"); 258 259 // call paint to trigger new tile fetch 260 this.paintSlippyMap(); 261 262 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished); 263 264 this.paintSlippyMap(); 265 266 assertEquals(0xffff00ff, paintedSlippyMap.getRGB(0, 0)); 267 268 this.slippyMap.refreshTileSources(); 269 270 this.assertSingleSelectedSourceLabel("Magenta Tiles"); 271 272 // call paint to trigger new tile fetch 273 this.paintSlippyMap(); 274 275 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished); 276 277 this.paintSlippyMap(); 278 279 assertEquals(0xffff00ff, paintedSlippyMap.getRGB(0, 0)); 280 } 281 282 /** 283 * Tests that the currently selected source being removed from ImageryLayerInfo will remain present and 284 * selected in the source menu even after the tile sources have been refreshed. 285 * @throws Exception if any error occurs 286 */ 287 @Test 288 public void testRemovedSourceStillSelected() throws Exception { 289 // relevant prefs starting out empty, should choose the first source and have shown download area enabled 290 // (not that there's a data layer for it to use) 291 292 this.setUpMiniMap(); 293 294 this.clickSourceMenuItemByLabel("Green Tiles"); 295 296 ImageryLayerInfo.instance.remove( 297 ImageryLayerInfo.instance.getLayers().stream().filter(i -> i.getName().equals("Green Tiles")).findAny().get() 298 ); 299 300 this.assertSingleSelectedSourceLabel("Green Tiles"); 301 302 this.slippyMap.refreshTileSources(); 303 304 this.assertSingleSelectedSourceLabel("Green Tiles"); 305 306 // call paint to trigger new tile fetch 307 this.paintSlippyMap(); 308 309 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished); 310 311 this.paintSlippyMap(); 312 313 assertEquals(0xff00ff00, paintedSlippyMap.getRGB(0, 0)); 314 } 315 316 /** 317 * Tests the tile source list includes sources only present in the LayerManager 318 * @throws Exception if any error occurs 319 */ 320 @Test 321 public void testTileSourcesFromCurrentLayers() throws Exception { 322 // relevant prefs starting out empty, should choose the first (ImageryLayerInfo) source and have shown download area enabled 323 // (not that there's a data layer for it to use) 324 325 final ImageryInfo magentaTilesInfo = ImageryLayerInfo.instance.getLayers().stream().filter( 326 i -> i.getName().equals("Magenta Tiles") 327 ).findAny().get(); 328 final ImageryInfo blackTilesInfo = ImageryLayerInfo.instance.getLayers().stream().filter( 329 i -> i.getName().equals("Black Tiles") 330 ).findAny().get(); 331 332 // first we will remove "Magenta Tiles" from ImageryLayerInfo 333 ImageryLayerInfo.instance.remove(magentaTilesInfo); 334 335 this.setUpMiniMap(); 336 337 assertSourceLabelsVisible( 338 "White Tiles", 339 "Black Tiles", 340 "Green Tiles" 341 ); 342 343 final ImageryLayer magentaTilesLayer = ImageryLayer.create(magentaTilesInfo); 344 GuiHelper.runInEDT(() -> MainApplication.getLayerManager().addLayer(magentaTilesLayer)); 345 346 assertSourceLabelsVisible( 347 "White Tiles", 348 "Black Tiles", 349 "Green Tiles", 350 "Magenta Tiles" 351 ); 352 353 this.clickSourceMenuItemByLabel("Magenta Tiles"); 354 this.assertSingleSelectedSourceLabel("Magenta Tiles"); 355 356 // call paint to trigger new tile fetch 357 this.paintSlippyMap(); 358 359 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished); 360 361 this.paintSlippyMap(); 362 363 assertEquals(0xffff00ff, paintedSlippyMap.getRGB(0, 0)); 364 365 final ImageryLayer blackTilesLayer = ImageryLayer.create(blackTilesInfo); 366 GuiHelper.runInEDT(() -> MainApplication.getLayerManager().addLayer(blackTilesLayer)); 367 368 assertSourceLabelsVisible( 369 "White Tiles", 370 "Black Tiles", 371 "Green Tiles", 372 "Magenta Tiles" 373 ); 374 375 this.clickSourceMenuItemByLabel("Black Tiles"); 376 this.assertSingleSelectedSourceLabel("Black Tiles"); 377 378 // call paint to trigger new tile fetch 379 this.paintSlippyMap(); 380 381 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished); 382 383 this.paintSlippyMap(); 384 385 assertEquals(0xff000000, paintedSlippyMap.getRGB(0, 0)); 386 387 // removing magentaTilesLayer while it is *not* the selected TileSource should make it disappear 388 // immediately 389 GuiHelper.runInEDT(() -> MainApplication.getLayerManager().removeLayer(magentaTilesLayer)); 390 391 assertSourceLabelsVisible( 392 "White Tiles", 393 "Black Tiles", 394 "Green Tiles" 395 ); 396 this.assertSingleSelectedSourceLabel("Black Tiles"); 397 398 final ImageryLayer magentaTilesLayer2 = ImageryLayer.create(magentaTilesInfo); 399 GuiHelper.runInEDT(() -> MainApplication.getLayerManager().addLayer(magentaTilesLayer2)); 400 401 assertSourceLabelsVisible( 402 "White Tiles", 403 "Black Tiles", 404 "Green Tiles", 405 "Magenta Tiles" 406 ); 407 408 this.clickSourceMenuItemByLabel("Magenta Tiles"); 409 this.assertSingleSelectedSourceLabel("Magenta Tiles"); 410 411 // call paint to trigger new tile fetch 412 this.paintSlippyMap(); 413 414 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished); 415 416 this.paintSlippyMap(); 417 418 assertEquals(0xffff00ff, paintedSlippyMap.getRGB(0, 0)); 419 420 // removing magentaTilesLayer while it *is* the selected TileSource... 421 GuiHelper.runInEDT(() -> MainApplication.getLayerManager().removeLayer(magentaTilesLayer2)); 422 423 assertSourceLabelsVisible( 424 "White Tiles", 425 "Black Tiles", 426 "Green Tiles", 427 "Magenta Tiles" 428 ); 429 this.assertSingleSelectedSourceLabel("Magenta Tiles"); 430 431 this.clickSourceMenuItemByLabel("Green Tiles"); 432 this.assertSingleSelectedSourceLabel("Green Tiles"); 433 assertSourceLabelsVisible( 434 "White Tiles", 435 "Black Tiles", 436 "Green Tiles" 437 ); 438 439 // removing blackTilesLayer shouldn't remove it from the menu as it is already in ImageryLayerInfo 440 GuiHelper.runInEDT(() -> MainApplication.getLayerManager().removeLayer(blackTilesLayer)); 441 442 this.assertSingleSelectedSourceLabel("Green Tiles"); 443 assertSourceLabelsVisible( 444 "White Tiles", 445 "Black Tiles", 446 "Green Tiles" 447 ); 220 448 } 221 449
Note:
See TracChangeset
for help on using the changeset viewer.