001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.layer; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import org.apache.commons.jcs.access.CacheAccess; 007import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader; 008import org.openstreetmap.gui.jmapviewer.tilesources.AbstractTMSTileSource; 009import org.openstreetmap.gui.jmapviewer.tilesources.ScanexTileSource; 010import org.openstreetmap.gui.jmapviewer.tilesources.TMSTileSource; 011import org.openstreetmap.gui.jmapviewer.tilesources.TemplatedTMSTileSource; 012import org.openstreetmap.josm.Main; 013import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry; 014import org.openstreetmap.josm.data.imagery.CachedAttributionBingAerialTileSource; 015import org.openstreetmap.josm.data.imagery.ImageryInfo; 016import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType; 017import org.openstreetmap.josm.data.imagery.TMSCachedTileLoader; 018import org.openstreetmap.josm.data.preferences.BooleanProperty; 019import org.openstreetmap.josm.data.preferences.IntegerProperty; 020import org.openstreetmap.josm.data.projection.Projection; 021 022/** 023 * Class that displays a slippy map layer. 024 * 025 * @author Frederik Ramm 026 * @author LuVar <lubomir.varga@freemap.sk> 027 * @author Dave Hansen <dave@sr71.net> 028 * @author Upliner <upliner@gmail.com> 029 * 030 */ 031public class TMSLayer extends AbstractCachedTileSourceLayer { 032 private static final String CACHE_REGION_NAME = "TMS"; 033 034 private static final String PREFERENCE_PREFIX = "imagery.tms"; 035 036 /** minimum zoom level for TMS layer */ 037 public static final IntegerProperty PROP_MIN_ZOOM_LVL = new IntegerProperty(PREFERENCE_PREFIX + ".min_zoom_lvl", 038 AbstractTileSourceLayer.PROP_MIN_ZOOM_LVL.get()); 039 /** maximum zoom level for TMS layer */ 040 public static final IntegerProperty PROP_MAX_ZOOM_LVL = new IntegerProperty(PREFERENCE_PREFIX + ".max_zoom_lvl", 041 AbstractTileSourceLayer.PROP_MAX_ZOOM_LVL.get()); 042 /** shall TMS layers be added to download dialog */ 043 public static final BooleanProperty PROP_ADD_TO_SLIPPYMAP_CHOOSER = new BooleanProperty(PREFERENCE_PREFIX + ".add_to_slippymap_chooser", 044 true); 045 046 /** 047 * Create a layer based on ImageryInfo 048 * @param info description of the layer 049 */ 050 public TMSLayer(ImageryInfo info) { 051 super(info); 052 } 053 054 055 /** 056 * Creates and returns a new TileSource instance depending on the {@link ImageryType} 057 * of the passed ImageryInfo object. 058 * 059 * If no appropriate TileSource is found, null is returned. 060 * Currently supported ImageryType are {@link ImageryType#TMS}, 061 * {@link ImageryType#BING}, {@link ImageryType#SCANEX}. 062 * 063 * 064 * @param info imagery info 065 * @return a new TileSource instance or null if no TileSource for the ImageryInfo/ImageryType could be found. 066 * @throws IllegalArgumentException if url from imagery info is null or invalid 067 */ 068 @Override 069 protected AbstractTMSTileSource getTileSource(ImageryInfo info) throws IllegalArgumentException { 070 return getTileSourceStatic(info, new Runnable() { 071 @Override 072 public void run() { 073 Main.debug("Attribution loaded, running loadAllErrorTiles"); 074 TMSLayer.this.loadAllErrorTiles(true); 075 } 076 }); 077 } 078 079 /** 080 * Adds a context menu to the mapView. 081 */ 082 083 @Override 084 public final boolean isProjectionSupported(Projection proj) { 085 return "EPSG:3857".equals(proj.toCode()) || "EPSG:4326".equals(proj.toCode()); 086 } 087 088 @Override 089 public final String nameSupportedProjections() { 090 return tr("EPSG:4326 and Mercator projection are supported"); 091 } 092 093 /** 094 * Creates and returns a new TileSource instance depending on the {@link ImageryType} 095 * of the passed ImageryInfo object. 096 * 097 * If no appropriate TileSource is found, null is returned. 098 * Currently supported ImageryType are {@link ImageryType#TMS}, 099 * {@link ImageryType#BING}, {@link ImageryType#SCANEX}. 100 * 101 * @param info imagery info 102 * @return a new TileSource instance or null if no TileSource for the ImageryInfo/ImageryType could be found. 103 * @throws IllegalArgumentException if url from imagery info is null or invalid 104 */ 105 public static AbstractTMSTileSource getTileSourceStatic(ImageryInfo info) throws IllegalArgumentException { 106 return getTileSourceStatic(info, null); 107 } 108 109 /** 110 * Creates and returns a new TileSource instance depending on the {@link ImageryType} 111 * of the passed ImageryInfo object. 112 * 113 * If no appropriate TileSource is found, null is returned. 114 * Currently supported ImageryType are {@link ImageryType#TMS}, 115 * {@link ImageryType#BING}, {@link ImageryType#SCANEX}. 116 * 117 * @param info imagery info 118 * @param attributionLoadedTask task to be run once attribution is loaded, might be null, if nothing special shall happen 119 * @return a new TileSource instance or null if no TileSource for the ImageryInfo/ImageryType could be found. 120 * @throws IllegalArgumentException if url from imagery info is null or invalid 121 */ 122 public static AbstractTMSTileSource getTileSourceStatic(ImageryInfo info, Runnable attributionLoadedTask) throws IllegalArgumentException { 123 if (info.getImageryType() == ImageryType.TMS) { 124 TemplatedTMSTileSource.checkUrl(info.getUrl()); 125 TMSTileSource t = new TemplatedTMSTileSource(info); 126 info.setAttribution(t); 127 return t; 128 } else if (info.getImageryType() == ImageryType.BING) 129 return new CachedAttributionBingAerialTileSource(info, attributionLoadedTask); 130 else if (info.getImageryType() == ImageryType.SCANEX) { 131 return new ScanexTileSource(info); 132 } 133 return null; 134 } 135 136 @Override 137 protected Class<? extends TileLoader> getTileLoaderClass() { 138 return TMSCachedTileLoader.class; 139 } 140 141 @Override 142 protected String getCacheName() { 143 return CACHE_REGION_NAME; 144 } 145 146 /** 147 * @return cache for TMS region 148 */ 149 public static CacheAccess<String, BufferedImageCacheEntry> getCache() { 150 return AbstractCachedTileSourceLayer.getCache(CACHE_REGION_NAME); 151 } 152 153}