source: josm/trunk/src/org/openstreetmap/josm/actions/MapRectifierWMSmenuAction.java@ 12942

Last change on this file since 12942 was 12716, checked in by Don-vip, 7 years ago

fix #15227 - call generic imagery layer factory instead of WMSLayer constructor

  • Property svn:eol-style set to native
File size: 10.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.GridBagConstraints;
8import java.awt.GridBagLayout;
9import java.awt.event.ActionEvent;
10import java.awt.event.KeyEvent;
11import java.io.IOException;
12import java.util.ArrayList;
13import java.util.List;
14import java.util.regex.Matcher;
15import java.util.regex.Pattern;
16
17import javax.swing.ButtonGroup;
18import javax.swing.JLabel;
19import javax.swing.JOptionPane;
20import javax.swing.JPanel;
21import javax.swing.JRadioButton;
22
23import org.openstreetmap.josm.Main;
24import org.openstreetmap.josm.data.imagery.ImageryInfo;
25import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType;
26import org.openstreetmap.josm.gui.ExtendedDialog;
27import org.openstreetmap.josm.gui.MainApplication;
28import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils;
29import org.openstreetmap.josm.gui.layer.ImageryLayer;
30import org.openstreetmap.josm.gui.widgets.JosmTextField;
31import org.openstreetmap.josm.gui.widgets.UrlLabel;
32import org.openstreetmap.josm.io.imagery.WMSImagery.WMSGetCapabilitiesException;
33import org.openstreetmap.josm.tools.GBC;
34import org.openstreetmap.josm.tools.Logging;
35import org.openstreetmap.josm.tools.Shortcut;
36
37/**
38 * Download rectified images from various services.
39 * @since 3715
40 */
41public class MapRectifierWMSmenuAction extends JosmAction {
42
43 /**
44 * Class that bundles all required information of a rectifier service
45 */
46 public static class RectifierService {
47 private final String name;
48 private final String url;
49 private final String wmsUrl;
50 private final Pattern urlRegEx;
51 private final Pattern idValidator;
52 private JRadioButton btn;
53
54 /**
55 * @param name Name of the rectifing service
56 * @param url URL to the service where users can register, upload, etc.
57 * @param wmsUrl URL to the WMS server where JOSM will grab the images. Insert __s__ where the ID should be placed
58 * @param urlRegEx a regular expression that determines if a given URL is one of the service and returns the WMS id if so
59 * @param idValidator regular expression that checks if a given ID is syntactically valid
60 */
61 public RectifierService(String name, String url, String wmsUrl, String urlRegEx, String idValidator) {
62 this.name = name;
63 this.url = url;
64 this.wmsUrl = wmsUrl;
65 this.urlRegEx = Pattern.compile(urlRegEx);
66 this.idValidator = Pattern.compile(idValidator);
67 }
68
69 private boolean isSelected() {
70 return btn.isSelected();
71 }
72 }
73
74 /**
75 * List of available rectifier services.
76 */
77 private final transient List<RectifierService> services = new ArrayList<>();
78
79 /**
80 * Constructs a new {@code MapRectifierWMSmenuAction}.
81 */
82 public MapRectifierWMSmenuAction() {
83 super(tr("Rectified Image..."),
84 "OLmarker",
85 tr("Download Rectified Images From Various Services"),
86 Shortcut.registerShortcut("imagery:rectimg",
87 tr("Imagery: {0}", tr("Rectified Image...")),
88 KeyEvent.CHAR_UNDEFINED, Shortcut.NONE),
89 true
90 );
91 putValue("help", ht("/Menu/Imagery"));
92
93 // Add default services
94 services.add(
95 new RectifierService("Metacarta Map Rectifier",
96 "http://labs.metacarta.com/rectifier/",
97 "http://labs.metacarta.com/rectifier/wms.cgi?id=__s__&srs=EPSG:4326"
98 + "&Service=WMS&Version=1.1.0&Request=GetMap&format=image/png&",
99 // This matches more than the "classic" WMS link, so users can pretty much
100 // copy any link as long as it includes the ID
101 "labs\\.metacarta\\.com/(?:.*?)(?:/|=)([0-9]+)(?:\\?|/|\\.|$)",
102 "^[0-9]+$")
103 );
104 services.add(
105 new RectifierService("Map Warper",
106 "http://mapwarper.net/",
107 "http://mapwarper.net/maps/wms/__s__?request=GetMap&version=1.1.1"
108 + "&styles=&format=image/png&srs=epsg:4326&exceptions=application/vnd.ogc.se_inimage&",
109 // This matches more than the "classic" WMS link, so users can pretty much
110 // copy any link as long as it includes the ID
111 "(?:mapwarper\\.net|warper\\.geothings\\.net)/(?:.*?)/([0-9]+)(?:\\?|/|\\.|$)",
112 "^[0-9]+$")
113 );
114
115 // This service serves the purpose of "just this once" without forcing the user
116 // to commit the link to the preferences
117
118 // Clipboard content gets trimmed, so matching whitespace only ensures that this
119 // service will never be selected automatically.
120 services.add(new RectifierService(tr("Custom WMS Link"), "", "", "^\\s+$", ""));
121 }
122
123 @Override
124 public void actionPerformed(ActionEvent e) {
125 if (!isEnabled()) return;
126 JPanel panel = new JPanel(new GridBagLayout());
127 panel.add(new JLabel(tr("Supported Rectifier Services:")), GBC.eol());
128
129 JosmTextField tfWmsUrl = new JosmTextField(30);
130
131 String clip = ClipboardUtils.getClipboardStringContent();
132 clip = clip == null ? "" : clip.trim();
133 ButtonGroup group = new ButtonGroup();
134
135 JRadioButton firstBtn = null;
136 for (RectifierService s : services) {
137 JRadioButton serviceBtn = new JRadioButton(s.name);
138 if (firstBtn == null) {
139 firstBtn = serviceBtn;
140 }
141 // Checks clipboard contents against current service if no match has been found yet.
142 // If the contents match, they will be inserted into the text field and the corresponding
143 // service will be pre-selected.
144 if (!clip.isEmpty() && tfWmsUrl.getText().isEmpty()
145 && (s.urlRegEx.matcher(clip).find() || s.idValidator.matcher(clip).matches())) {
146 serviceBtn.setSelected(true);
147 tfWmsUrl.setText(clip);
148 }
149 s.btn = serviceBtn;
150 group.add(serviceBtn);
151 if (!s.url.isEmpty()) {
152 panel.add(serviceBtn, GBC.std());
153 panel.add(new UrlLabel(s.url, tr("Visit Homepage")), GBC.eol().anchor(GridBagConstraints.EAST));
154 } else {
155 panel.add(serviceBtn, GBC.eol().anchor(GridBagConstraints.WEST));
156 }
157 }
158
159 // Fallback in case no match was found
160 if (tfWmsUrl.getText().isEmpty() && firstBtn != null) {
161 firstBtn.setSelected(true);
162 }
163
164 panel.add(new JLabel(tr("WMS URL or Image ID:")), GBC.eol());
165 panel.add(tfWmsUrl, GBC.eol().fill(GridBagConstraints.HORIZONTAL));
166
167 ExtendedDialog diag = new ExtendedDialog(Main.parent,
168 tr("Add Rectified Image"),
169 tr("Add Rectified Image"), tr("Cancel"))
170 .setContent(panel)
171 .setButtonIcons("OLmarker", "cancel");
172
173 // This repeatedly shows the dialog in case there has been an error.
174 // The loop is break;-ed if the users cancels
175 outer: while (true) {
176 diag.showDialog();
177 int answer = diag.getValue();
178 // Break loop when the user cancels
179 if (answer != 1) {
180 break;
181 }
182
183 String text = tfWmsUrl.getText().trim();
184 // Loop all services until we find the selected one
185 for (RectifierService s : services) {
186 if (!s.isSelected()) {
187 continue;
188 }
189
190 // We've reached the custom WMS URL service
191 // Just set the URL and hope everything works out
192 if (s.wmsUrl.isEmpty()) {
193 try {
194 addWMSLayer(s.name + " (" + text + ')', text);
195 break outer;
196 } catch (IllegalStateException ex) {
197 Logging.log(Logging.LEVEL_ERROR, ex);
198 }
199 }
200
201 // First try to match if the entered string as an URL
202 Matcher m = s.urlRegEx.matcher(text);
203 if (m.find()) {
204 String id = m.group(1);
205 String newURL = s.wmsUrl.replaceAll("__s__", id);
206 String title = s.name + " (" + id + ')';
207 addWMSLayer(title, newURL);
208 break outer;
209 }
210 // If not, look if it's a valid ID for the selected service
211 if (s.idValidator.matcher(text).matches()) {
212 String newURL = s.wmsUrl.replaceAll("__s__", text);
213 String title = s.name + " (" + text + ')';
214 addWMSLayer(title, newURL);
215 break outer;
216 }
217
218 // We've found the selected service, but the entered string isn't suitable for
219 // it. So quit checking the other radio buttons
220 break;
221 }
222
223 // and display an error message. The while loop ensures that the dialog pops up again
224 JOptionPane.showMessageDialog(Main.parent,
225 tr("Couldn''t match the entered link or id to the selected service. Please try again."),
226 tr("No valid WMS URL or id"),
227 JOptionPane.ERROR_MESSAGE);
228 diag.setVisible(true);
229 }
230 }
231
232 /**
233 * Adds a WMS Layer with given title and URL
234 * @param title Name of the layer as it will shop up in the layer manager
235 * @param url URL to the WMS server
236 * @throws IllegalStateException if imagery time is neither HTML nor WMS
237 */
238 private static void addWMSLayer(String title, String url) {
239 ImageryInfo info = new ImageryInfo(title, url);
240 if (info.getImageryType() == ImageryType.WMS_ENDPOINT) {
241 try {
242 info = AddImageryLayerAction.getWMSLayerInfo(info);
243 } catch (IOException | WMSGetCapabilitiesException e) {
244 Logging.error(e);
245 JOptionPane.showMessageDialog(Main.parent, e.getMessage(), tr("No valid WMS URL or id"), JOptionPane.ERROR_MESSAGE);
246 return;
247 }
248 }
249 MainApplication.getLayerManager().addLayer(ImageryLayer.create(info));
250 }
251
252 @Override
253 protected void updateEnabledState() {
254 setEnabled(!getLayerManager().getLayers().isEmpty());
255 }
256}
Note: See TracBrowser for help on using the repository browser.