source: josm/trunk/src/org/openstreetmap/josm/gui/layer/WMSLayer.java@ 13815

Last change on this file since 13815 was 13742, checked in by wiktorn, 6 years ago

Checkstyle fixes

  • Property svn:eol-style set to native
File size: 7.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.layer;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.event.ActionEvent;
7import java.util.ArrayList;
8import java.util.Arrays;
9import java.util.Collection;
10import java.util.List;
11import java.util.Objects;
12
13import javax.swing.AbstractAction;
14import javax.swing.Action;
15
16import org.apache.commons.jcs.access.CacheAccess;
17import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
18import org.openstreetmap.josm.Main;
19import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry;
20import org.openstreetmap.josm.data.coor.LatLon;
21import org.openstreetmap.josm.data.imagery.AbstractWMSTileSource;
22import org.openstreetmap.josm.data.imagery.ImageryInfo;
23import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType;
24import org.openstreetmap.josm.data.imagery.ImageryLayerInfo;
25import org.openstreetmap.josm.data.imagery.TemplatedWMSTileSource;
26import org.openstreetmap.josm.data.imagery.WMSCachedTileLoader;
27import org.openstreetmap.josm.data.imagery.WMSEndpointTileSource;
28import org.openstreetmap.josm.data.preferences.BooleanProperty;
29import org.openstreetmap.josm.data.preferences.IntegerProperty;
30import org.openstreetmap.josm.data.projection.Projection;
31import org.openstreetmap.josm.data.projection.Projections;
32import org.openstreetmap.josm.gui.MainApplication;
33import org.openstreetmap.josm.gui.layer.imagery.TileSourceDisplaySettings;
34import org.openstreetmap.josm.tools.CheckParameterUtil;
35import org.openstreetmap.josm.tools.Logging;
36import org.openstreetmap.josm.tools.Utils;
37
38/**
39 * This is a layer that grabs the current screen from an WMS server. The data
40 * fetched this way is tiled and managed to the disc to reduce server load.
41 *
42 */
43public class WMSLayer extends AbstractCachedTileSourceLayer<AbstractWMSTileSource> {
44 private static final String PREFERENCE_PREFIX = "imagery.wms";
45 /**
46 * Registers all setting properties
47 */
48 static {
49 new TileSourceDisplaySettings(PREFERENCE_PREFIX);
50 }
51
52 /** default tile size for WMS Layer */
53 public static final IntegerProperty PROP_IMAGE_SIZE = new IntegerProperty(PREFERENCE_PREFIX + ".imageSize", 512);
54
55 /** should WMS layer autozoom in default mode */
56 public static final BooleanProperty PROP_DEFAULT_AUTOZOOM = new BooleanProperty(PREFERENCE_PREFIX + ".default_autozoom", true);
57
58 private static final String CACHE_REGION_NAME = "WMS";
59
60 private List<String> serverProjections;
61
62 /**
63 * Constructs a new {@code WMSLayer}.
64 * @param info ImageryInfo description of the layer
65 */
66 public WMSLayer(ImageryInfo info) {
67 super(info);
68 CheckParameterUtil.ensureThat(
69 info.getImageryType() == ImageryType.WMS || info.getImageryType() == ImageryType.WMS_ENDPOINT, "ImageryType is WMS");
70 CheckParameterUtil.ensureParameterNotNull(info.getUrl(), "info.url");
71 if (info.getImageryType() == ImageryType.WMS) {
72 TemplatedWMSTileSource.checkUrl(info.getUrl());
73
74 }
75 this.serverProjections = new ArrayList<>(info.getServerProjections());
76 }
77
78 @Override
79 protected TileSourceDisplaySettings createDisplaySettings() {
80 return new TileSourceDisplaySettings(PREFERENCE_PREFIX);
81 }
82
83 @Override
84 public Action[] getMenuEntries() {
85 List<Action> ret = new ArrayList<>();
86 ret.addAll(Arrays.asList(super.getMenuEntries()));
87 ret.add(SeparatorLayerAction.INSTANCE);
88 ret.add(new LayerSaveAction(this));
89 ret.add(new LayerSaveAsAction(this));
90 ret.add(new BookmarkWmsAction());
91 return ret.toArray(new Action[0]);
92 }
93
94 @Override
95 protected AbstractWMSTileSource getTileSource() {
96 AbstractWMSTileSource tileSource;
97 if (info.getImageryType() == ImageryType.WMS) {
98 tileSource = new TemplatedWMSTileSource(info, chooseProjection(Main.getProjection()));
99 } else {
100 /*
101 * Chicken-and-egg problem. We want to create tile source, but supported projections we can get only
102 * from this tile source. So create tilesource first with dummy Main.getProjection(), and then update
103 * once we update server projections.
104 *
105 * Thus:
106 * * it is not required to provide projections for wms_endpoint imagery types
107 * * we always use current definitions returned by server
108 */
109 WMSEndpointTileSource endpointTileSource = new WMSEndpointTileSource(info, Main.getProjection());
110 this.serverProjections = endpointTileSource.getServerProjections();
111 endpointTileSource.setTileProjection(chooseProjection(Main.getProjection()));
112 tileSource = endpointTileSource;
113 }
114 info.setAttribution(tileSource);
115 return tileSource;
116 }
117
118 /**
119 * This action will add a WMS layer menu entry with the current WMS layer
120 * URL and name extended by the current resolution.
121 * When using the menu entry again, the WMS cache will be used properly.
122 */
123 public class BookmarkWmsAction extends AbstractAction {
124 /**
125 * Constructs a new {@code BookmarkWmsAction}.
126 */
127 public BookmarkWmsAction() {
128 super(tr("Set WMS Bookmark"));
129 }
130
131 @Override
132 public void actionPerformed(ActionEvent ev) {
133 ImageryLayerInfo.addLayer(new ImageryInfo(info));
134 }
135 }
136
137 @Override
138 public Collection<String> getNativeProjections() {
139 return serverProjections;
140 }
141
142 @Override
143 public void projectionChanged(Projection oldValue, Projection newValue) {
144 super.projectionChanged(oldValue, newValue);
145 Projection tileProjection = chooseProjection(newValue);
146 if (!Objects.equals(tileSource.getTileProjection(), tileProjection)) {
147 tileSource.setTileProjection(tileProjection);
148 }
149 }
150
151 private Projection chooseProjection(Projection requested) {
152 if (serverProjections.contains(requested.toCode())) {
153 return requested;
154 } else {
155 LatLon center = MainApplication.isDisplayingMapView() ?
156 requested.eastNorth2latlon(MainApplication.getMap().mapView.getCenter()) : null;
157 Projection firstNonNullproj = null;
158 Projection firstProjInBounds = null;
159 for (String code : serverProjections) {
160 Projection proj = Projections.getProjectionByCode(code);
161 if (proj != null) {
162 if (firstNonNullproj == null) {
163 firstNonNullproj = proj;
164 }
165 if (center != null && proj.getWorldBoundsLatLon().contains(center)) {
166 firstProjInBounds = proj;
167 break;
168 }
169 }
170 }
171 if (firstProjInBounds != null) {
172 return selectProjection(firstProjInBounds);
173 } else if (firstNonNullproj != null) {
174 return selectProjection(firstNonNullproj);
175 }
176 Logging.warn(tr("Unable to find supported projection for layer {0}. Using {1}.", getName(), requested.toCode()));
177 return requested;
178 }
179 }
180
181 private Projection selectProjection(Projection proj) {
182 Logging.info(tr("Reprojecting layer {0} from {1} to {2}. For best image quality and performance,"
183 + " switch to one of the supported projections: {3}",
184 getName(), proj.toCode(), Main.getProjection().toCode(), Utils.join(", ", getNativeProjections())));
185 return proj;
186 }
187
188 @Override
189 protected Class<? extends TileLoader> getTileLoaderClass() {
190 return WMSCachedTileLoader.class;
191 }
192
193 @Override
194 protected String getCacheName() {
195 return CACHE_REGION_NAME;
196 }
197
198 /**
199 * @return cache region for WMS layer
200 */
201 public static CacheAccess<String, BufferedImageCacheEntry> getCache() {
202 return AbstractCachedTileSourceLayer.getCache(CACHE_REGION_NAME);
203 }
204}
Note: See TracBrowser for help on using the repository browser.