source: josm/trunk/src/org/openstreetmap/josm/actions/Map_Rectifier_WMSmenuAction.java@ 4043

Last change on this file since 4043 was 3733, checked in by Upliner, 13 years ago

Offset bookmarks: don't create submenus when only 1 choice is available.
Also, make possible to add TMS layers from "Getting started" screen.

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