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

Last change on this file since 13352 was 13123, checked in by Don-vip, 6 years ago

javadoc

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