diff --git data/maps.xsd data/maps.xsd
index 43ca799..f420af8 100644
|
|
|
688 | 688 | <xs:attribute name="metadata-key" type="xs:string" /> |
689 | 689 | </xs:complexType> |
690 | 690 | </xs:element> |
| 691 | <!-- is imagery properly georeferenced (i.e. no need to check offsets). Defaults to false. Affects showing warnings. --> |
| 692 | <xs:element name="valid-georeference" minOccurs="0" maxOccurs="1" type="xs:boolean" /> |
| 693 | <!-- does imagery server supports JOSM 4326 to 3857 reprojection and non-square queries. Affects showing warnings. --> |
| 694 | <xs:element name="epsg4326to3857Supported" minOccurs="0" maxOccurs="1" type="xs:boolean" /> |
691 | 695 | </xs:choice> |
692 | 696 | </xs:sequence> |
693 | 697 | <xs:attribute name="last-check" type="xs:date" use="optional" /> |
diff --git src/org/openstreetmap/josm/actions/AddImageryLayerAction.java src/org/openstreetmap/josm/actions/AddImageryLayerAction.java
index 192d9f8..e6ed3b4 100644
|
|
public class AddImageryLayerAction extends JosmAction implements AdaptableAction
|
82 | 82 | ? getWMSLayerInfo() : info; |
83 | 83 | if (infoToAdd != null) { |
84 | 84 | Main.main.addLayer(ImageryLayer.create(infoToAdd)); |
85 | | AlignImageryPanel.addNagPanelIfNeeded(); |
| 85 | AlignImageryPanel.addNagPanelIfNeeded(infoToAdd); |
86 | 86 | } |
87 | 87 | } catch (IllegalArgumentException ex) { |
88 | 88 | if (ex.getMessage() == null || ex.getMessage().isEmpty()) { |
diff --git src/org/openstreetmap/josm/data/imagery/ImageryInfo.java src/org/openstreetmap/josm/data/imagery/ImageryInfo.java
index ff0ed6b..e51325b 100644
|
|
public class ImageryInfo extends TileSourceInfo implements Comparable<ImageryInf
|
199 | 199 | private String countryCode = ""; |
200 | 200 | /** icon used in menu */ |
201 | 201 | private String icon; |
202 | | // when adding a field, also adapt the ImageryInfo(ImageryInfo) constructor, equals method, and ImageryPreferenceEntry |
| 202 | private boolean isGeoreferenceValid = false; |
| 203 | private boolean isEpsg4326To3857Supported = false; |
| 204 | // when adding a field, also adapt the ImageryInfo(ImageryInfo) and ImageryInfo(ImageryPreferenceEntry) constructor, equals method, and ImageryPreferenceEntry |
203 | 205 | |
204 | 206 | /** |
205 | 207 | * Auxiliary class to save an {@link ImageryInfo} object in the preferences. |
… |
… |
public class ImageryInfo extends TileSourceInfo implements Comparable<ImageryInf
|
229 | 231 | @pref Map<String, String> noTileHeaders; |
230 | 232 | @pref int tileSize = OsmMercator.DEFAUL_TILE_SIZE; |
231 | 233 | @pref Map<String, String> metadataHeaders; |
| 234 | @pref boolean valid_georeference; |
| 235 | @pref boolean supports_epsg_4326_to_3857_conversion; |
232 | 236 | |
233 | 237 | /** |
234 | 238 | * Constructs a new empty WMS {@code ImageryPreferenceEntry}. |
… |
… |
public class ImageryInfo extends TileSourceInfo implements Comparable<ImageryInf
|
291 | 295 | } |
292 | 296 | |
293 | 297 | tileSize = i.getTileSize(); |
| 298 | |
| 299 | valid_georeference = i.isGeoreferenceValid(); |
| 300 | supports_epsg_4326_to_3857_conversion = i.isEpsg4326To3857Supported(); |
| 301 | |
294 | 302 | } |
295 | 303 | |
296 | 304 | @Override |
… |
… |
public class ImageryInfo extends TileSourceInfo implements Comparable<ImageryInf
|
412 | 420 | } |
413 | 421 | setTileSize(e.tileSize); |
414 | 422 | metadataHeaders = e.metadataHeaders; |
| 423 | isEpsg4326To3857Supported = e.supports_epsg_4326_to_3857_conversion; |
| 424 | isGeoreferenceValid = e.valid_georeference; |
415 | 425 | } |
416 | 426 | |
417 | 427 | /** |
… |
… |
public class ImageryInfo extends TileSourceInfo implements Comparable<ImageryInf
|
440 | 450 | this.description = i.description; |
441 | 451 | this.noTileHeaders = i.noTileHeaders; |
442 | 452 | this.metadataHeaders = i.metadataHeaders; |
| 453 | this.isEpsg4326To3857Supported = i.isEpsg4326To3857Supported; |
| 454 | this.isGeoreferenceValid = i.isGeoreferenceValid; |
443 | 455 | } |
444 | 456 | |
445 | 457 | @Override |
… |
… |
public class ImageryInfo extends TileSourceInfo implements Comparable<ImageryInf
|
992 | 1004 | public void setMetadataHeaders(Map<String, String> metadataHeaders) { |
993 | 1005 | this.metadataHeaders = metadataHeaders; |
994 | 1006 | } |
| 1007 | |
| 1008 | public boolean isEpsg4326To3857Supported() { |
| 1009 | return isEpsg4326To3857Supported; |
| 1010 | } |
| 1011 | |
| 1012 | public void setEpsg4326To3857Supported(boolean isEpsg4326To3857Supported) { |
| 1013 | this.isEpsg4326To3857Supported = isEpsg4326To3857Supported; |
| 1014 | } |
| 1015 | |
| 1016 | public boolean isGeoreferenceValid() { |
| 1017 | return isGeoreferenceValid; |
| 1018 | } |
| 1019 | |
| 1020 | public void setGeoreferenceValid(boolean isGeoreferenceValid) { |
| 1021 | this.isGeoreferenceValid = isGeoreferenceValid; |
| 1022 | } |
| 1023 | |
995 | 1024 | } |
diff --git src/org/openstreetmap/josm/gui/layer/AlignImageryPanel.java src/org/openstreetmap/josm/gui/layer/AlignImageryPanel.java
index 2fb1c44..5da7153 100644
|
|
import java.awt.event.ActionEvent;
|
11 | 11 | import java.awt.event.ActionListener; |
12 | 12 | |
13 | 13 | import javax.swing.JButton; |
| 14 | import javax.swing.JCheckBox; |
14 | 15 | import javax.swing.JLabel; |
15 | 16 | import javax.swing.JPanel; |
16 | 17 | import javax.swing.border.CompoundBorder; |
… |
… |
import javax.swing.border.EmptyBorder;
|
18 | 19 | import javax.swing.border.EtchedBorder; |
19 | 20 | |
20 | 21 | import org.openstreetmap.josm.Main; |
| 22 | import org.openstreetmap.josm.data.imagery.ImageryInfo; |
| 23 | import org.openstreetmap.josm.data.preferences.BooleanProperty; |
21 | 24 | import org.openstreetmap.josm.gui.widgets.UrlLabel; |
22 | 25 | import org.openstreetmap.josm.tools.GBC; |
23 | 26 | import org.openstreetmap.josm.tools.ImageProvider; |
… |
… |
import org.openstreetmap.josm.tools.ImageProvider;
|
28 | 31 | * @author zverik |
29 | 32 | */ |
30 | 33 | public class AlignImageryPanel extends JPanel { |
31 | | private static final String PREF = "imagery.offsetnagging"; |
32 | 34 | |
33 | | public AlignImageryPanel(boolean oneLine) { |
| 35 | /** |
| 36 | * @param oneLine if true, show the nagging message in one line, otherwise - in two lines |
| 37 | * @param showAgain show again property |
| 38 | * @param infoToAdd imagery info for which the nagging message is shown |
| 39 | */ |
| 40 | public AlignImageryPanel(boolean oneLine, final BooleanProperty showAgain, ImageryInfo infoToAdd) { |
34 | 41 | Font font = getFont().deriveFont(Font.PLAIN, 14.0f); |
35 | | JLabel nagLabel = new JLabel(tr("Aerial imagery might be misaligned. Please check its offset using GPS tracks!")); |
| 42 | JLabel nagLabel = new JLabel(tr("Aerial imagery \"{0}\" might be misaligned. Please check its offset using GPS tracks!", infoToAdd.getName())); |
36 | 43 | UrlLabel detailsList = new UrlLabel(tr("http://wiki.openstreetmap.org/wiki/Using_Imagery"), tr("Details...")); |
37 | 44 | nagLabel.setLabelFor(detailsList); |
38 | 45 | nagLabel.setFont(font); |
39 | 46 | detailsList.setFont(font); |
| 47 | final JCheckBox doNotShowAgain = new JCheckBox(tr("Do not show this message again")); |
| 48 | doNotShowAgain.setOpaque(false); |
40 | 49 | |
41 | 50 | JButton closeButton = new JButton(ImageProvider.get("misc", "black_x")); |
42 | 51 | closeButton.setContentAreaFilled(false); |
… |
… |
public class AlignImageryPanel extends JPanel {
|
48 | 57 | public void actionPerformed(ActionEvent e) { |
49 | 58 | if (Main.isDisplayingMapView()) { |
50 | 59 | Main.map.removeTopPanel(AlignImageryPanel.class); |
51 | | Main.pref.put(PREF, false); |
| 60 | if (doNotShowAgain.isSelected()) { |
| 61 | showAgain.put(false); |
| 62 | } |
52 | 63 | } |
53 | 64 | } |
54 | 65 | }); |
… |
… |
public class AlignImageryPanel extends JPanel {
|
57 | 68 | if (!oneLine) { // tune for small screens |
58 | 69 | add(nagLabel, GBC.std(1, 1).fill()); |
59 | 70 | add(detailsList, GBC.std(1, 2).fill()); |
| 71 | add(doNotShowAgain, GBC.std(1, 3).fill()); |
60 | 72 | add(closeButton, GBC.std(2, 1).span(1, 2).anchor(GBC.EAST)); |
61 | 73 | } else { |
62 | 74 | add(nagLabel, GBC.std(1, 1).fill()); |
63 | 75 | add(detailsList, GBC.std(2, 1).fill()); |
| 76 | add(doNotShowAgain, GBC.std(1, 2).fill()); |
64 | 77 | add(closeButton, GBC.std(3, 1).anchor(GBC.EAST)); |
65 | 78 | } |
66 | 79 | setBorder(new CompoundBorder(new EtchedBorder(EtchedBorder.LOWERED), new EmptyBorder(12, 12, 12, 12))); |
67 | 80 | setBackground(new Color(224, 236, 249)); |
68 | 81 | } |
69 | 82 | |
70 | | public static void addNagPanelIfNeeded() { |
71 | | if (Main.isDisplayingMapView() && !Main.pref.getBoolean("expert") && Main.pref.getBoolean(PREF, true)) { |
| 83 | /** |
| 84 | * @param infoToAdd ImageryInfo for which the nag panel should be created |
| 85 | */ |
| 86 | public static void addNagPanelIfNeeded(ImageryInfo infoToAdd) { |
| 87 | BooleanProperty showAgain = new BooleanProperty("message.imagery.nagPanel." + infoToAdd.getUrl(), true); |
| 88 | if (Main.isDisplayingMapView() && showAgain.get() && !infoToAdd.isGeoreferenceValid() ) { |
72 | 89 | if (Main.map.getTopPanel(AlignImageryPanel.class) == null) { |
73 | 90 | double w = Toolkit.getDefaultToolkit().getScreenSize().getWidth(); |
74 | | AlignImageryPanel p = new AlignImageryPanel(w > 1300); |
| 91 | AlignImageryPanel p = new AlignImageryPanel(w > 1300, showAgain, infoToAdd); |
75 | 92 | Main.map.addTopPanel(p); |
76 | 93 | } |
77 | 94 | } |
diff --git src/org/openstreetmap/josm/gui/layer/WMSLayer.java src/org/openstreetmap/josm/gui/layer/WMSLayer.java
index 96268ed..17d1e2d 100644
|
|
import org.openstreetmap.josm.data.imagery.WMSCachedTileLoader;
|
28 | 28 | import org.openstreetmap.josm.data.preferences.BooleanProperty; |
29 | 29 | import org.openstreetmap.josm.data.preferences.IntegerProperty; |
30 | 30 | import org.openstreetmap.josm.data.projection.Projection; |
| 31 | import org.openstreetmap.josm.gui.ExtendedDialog; |
31 | 32 | |
32 | 33 | /** |
33 | 34 | * This is a layer that grabs the current screen from an WMS server. The data |
… |
… |
public class WMSLayer extends AbstractCachedTileSourceLayer {
|
112 | 113 | |
113 | 114 | @Override |
114 | 115 | public boolean isProjectionSupported(Projection proj) { |
115 | | return supportedProjections == null || supportedProjections.isEmpty() || supportedProjections.contains(proj.toCode()); |
| 116 | return supportedProjections == null || supportedProjections.isEmpty() || supportedProjections.contains(proj.toCode()) || |
| 117 | (info.isEpsg4326To3857Supported() && supportedProjections.contains("EPSG:4326") && "EPSG:3857".equals(Main.getProjection().toCode())); |
116 | 118 | } |
117 | 119 | |
118 | 120 | @Override |
… |
… |
public class WMSLayer extends AbstractCachedTileSourceLayer {
|
123 | 125 | } |
124 | 126 | String appendix = ""; |
125 | 127 | |
126 | | if (supportedProjections.contains("EPSG:4326") && "EPSG:3857".equals(Main.getProjection().toCode())) { |
| 128 | if (isReprojectionPossible()) { |
127 | 129 | appendix = ". " + tr("JOSM will use EPSG:4326 to query the server, but results may vary " |
128 | 130 | + "depending on the WMS server"); |
129 | 131 | } |
… |
… |
public class WMSLayer extends AbstractCachedTileSourceLayer {
|
132 | 134 | |
133 | 135 | @Override |
134 | 136 | public void projectionChanged(Projection oldValue, Projection newValue) { |
135 | | super.projectionChanged(oldValue, newValue); |
| 137 | // do not call super - we need custom warning dialog |
| 138 | |
| 139 | if (!isProjectionSupported(newValue)) { |
| 140 | String message = tr("The layer {0} does not support the new projection {1}.\n" |
| 141 | + " Supported projections are: {2}\n" |
| 142 | + "Change the projection again or remove the layer.", |
| 143 | getName(), newValue.toCode(), nameSupportedProjections()); |
| 144 | |
| 145 | ExtendedDialog warningDialog = new ExtendedDialog(Main.parent, tr("Warning"), new String[]{tr("OK")}).setContent(message); |
| 146 | |
| 147 | if (isReprojectionPossible()) { |
| 148 | warningDialog.toggleEnable("imagery.wms.projectionSupportWarnings." + tileSource.getBaseUrl()); |
| 149 | } |
| 150 | warningDialog.showDialog(); |
| 151 | } |
136 | 152 | |
137 | 153 | if (!newValue.equals(oldValue) && tileSource instanceof TemplatedWMSTileSource) { |
138 | 154 | ((TemplatedWMSTileSource) tileSource).initProjection(newValue); |
… |
… |
public class WMSLayer extends AbstractCachedTileSourceLayer {
|
155 | 171 | public static CacheAccess<String, BufferedImageCacheEntry> getCache() { |
156 | 172 | return AbstractCachedTileSourceLayer.getCache(CACHE_REGION_NAME); |
157 | 173 | } |
| 174 | |
| 175 | private boolean isReprojectionPossible() { |
| 176 | return supportedProjections.contains("EPSG:4326") && "EPSG:3857".equals(Main.getProjection().toCode()); |
| 177 | } |
158 | 178 | } |
diff --git src/org/openstreetmap/josm/io/imagery/ImageryReader.java src/org/openstreetmap/josm/io/imagery/ImageryReader.java
index d88380e..5bee3ae 100644
|
|
public class ImageryReader {
|
142 | 142 | "country-code", |
143 | 143 | "icon", |
144 | 144 | "tile-size", |
| 145 | "validGeoreference", |
| 146 | "epsg4326to3857Supported", |
145 | 147 | }).contains(qName)) { |
146 | 148 | newState = State.ENTRY_ATTRIBUTE; |
147 | 149 | lang = atts.getValue("lang"); |
… |
… |
public class ImageryReader {
|
323 | 325 | entry.setTileSize(tileSize.intValue()); |
324 | 326 | } |
325 | 327 | break; |
| 328 | case "valid-georeference": |
| 329 | entry.setGeoreferenceValid(new Boolean(accumulator.toString())); |
| 330 | break; |
| 331 | case "epsg4326to3857Supported": |
| 332 | entry.setEpsg4326To3857Supported(new Boolean(accumulator.toString())); |
| 333 | break; |
326 | 334 | } |
327 | 335 | break; |
328 | 336 | case BOUNDS: |