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

Last change on this file since 6316 was 6316, checked in by Don-vip, 5 years ago

Sonar/FindBugs - Loose coupling

  • Property svn:eol-style set to native
File size: 9.3 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.event.ActionEvent;
9import java.awt.event.KeyEvent;
10import java.util.ArrayList;
11import java.util.List;
12import java.util.regex.Matcher;
13import java.util.regex.Pattern;
14
15import javax.swing.ButtonGroup;
16import javax.swing.JLabel;
17import javax.swing.JOptionPane;
18import javax.swing.JPanel;
19import javax.swing.JRadioButton;
20
21import org.openstreetmap.josm.Main;
22import org.openstreetmap.josm.data.imagery.ImageryInfo;
23import org.openstreetmap.josm.gui.ExtendedDialog;
24import org.openstreetmap.josm.gui.layer.WMSLayer;
25import org.openstreetmap.josm.tools.GBC;
26import org.openstreetmap.josm.tools.Shortcut;
27import org.openstreetmap.josm.tools.UrlLabel;
28import org.openstreetmap.josm.tools.Utils;
29import org.openstreetmap.josm.gui.widgets.JosmTextField;
30
31public class MapRectifierWMSmenuAction extends JosmAction {
32    /**
33     * Class that bundles all required information of a rectifier service
34     */
35    public static class RectifierService {
36        private final String name;
37        private final String url;
38        private final String wmsUrl;
39        private final Pattern urlRegEx;
40        private final Pattern idValidator;
41        public JRadioButton btn;
42
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 List<RectifierService> services = new ArrayList<RectifierService>();
67
68    public MapRectifierWMSmenuAction() {
69        super(tr("Rectified Image..."),
70                "OLmarker",
71                tr("Download Rectified Images From Various Services"),
72                Shortcut.registerShortcut("imagery:rectimg",
73                        tr("Imagery: {0}", tr("Rectified Image...")),
74                        KeyEvent.CHAR_UNDEFINED, Shortcut.NONE),
75                true
76        );
77
78        // Add default services
79        services.add(
80                new RectifierService("Metacarta Map Rectifier",
81                        "http://labs.metacarta.com/rectifier/",
82                        "http://labs.metacarta.com/rectifier/wms.cgi?id=__s__&srs=EPSG:4326"
83                        + "&Service=WMS&Version=1.1.0&Request=GetMap&format=image/png&",
84                        // This matches more than the "classic" WMS link, so users can pretty much
85                        // copy any link as long as it includes the ID
86                        "labs\\.metacarta\\.com/(?:.*?)(?:/|=)([0-9]+)(?:\\?|/|\\.|$)",
87                "^[0-9]+$")
88        );
89        services.add(
90                new RectifierService("Map Warper",
91                        "http://mapwarper.net/",
92                        "http://mapwarper.net/maps/wms/__s__?request=GetMap&version=1.1.1"
93                        + "&styles=&format=image/png&srs=epsg:4326&exceptions=application/vnd.ogc.se_inimage&",
94                        // This matches more than the "classic" WMS link, so users can pretty much
95                        // copy any link as long as it includes the ID
96                        "(?:mapwarper\\.net|warper\\.geothings\\.net)/(?:.*?)/([0-9]+)(?:\\?|/|\\.|$)",
97                "^[0-9]+$")
98        );
99
100        // This service serves the purpose of "just this once" without forcing the user
101        // to commit the link to the preferences
102
103        // Clipboard content gets trimmed, so matching whitespace only ensures that this
104        // service will never be selected automatically.
105        services.add(new RectifierService(tr("Custom WMS Link"), "", "", "^\\s+$", ""));
106    }
107
108    @Override
109    public void actionPerformed(ActionEvent e) {
110        if (!isEnabled()) return;
111        JPanel panel = new JPanel(new GridBagLayout());
112        panel.add(new JLabel(tr("Supported Rectifier Services:")), GBC.eol());
113
114        JosmTextField tfWmsUrl = new JosmTextField(30);
115
116        String clip = Utils.getClipboardContent();
117        clip = clip == null ? "" : clip.trim();
118        ButtonGroup group = new ButtonGroup();
119
120        JRadioButton firstBtn = null;
121        for(RectifierService s : services) {
122            JRadioButton serviceBtn = new JRadioButton(s.name);
123            if(firstBtn == null) {
124                firstBtn = serviceBtn;
125            }
126            // Checks clipboard contents against current service if no match has been found yet.
127            // If the contents match, they will be inserted into the text field and the corresponding
128            // service will be pre-selected.
129            if(!clip.isEmpty() && tfWmsUrl.getText().isEmpty()
130                    && (s.urlRegEx.matcher(clip).find() || s.idValidator.matcher(clip).matches())) {
131                serviceBtn.setSelected(true);
132                tfWmsUrl.setText(clip);
133            }
134            s.btn = serviceBtn;
135            group.add(serviceBtn);
136            if(!s.url.isEmpty()) {
137                panel.add(serviceBtn, GBC.std());
138                panel.add(new UrlLabel(s.url, tr("Visit Homepage")), GBC.eol().anchor(GridBagConstraints.EAST));
139            } else {
140                panel.add(serviceBtn, GBC.eol().anchor(GridBagConstraints.WEST));
141            }
142        }
143
144        // Fallback in case no match was found
145        if(tfWmsUrl.getText().isEmpty() && firstBtn != null) {
146            firstBtn.setSelected(true);
147        }
148
149        panel.add(new JLabel(tr("WMS URL or Image ID:")), GBC.eol());
150        panel.add(tfWmsUrl, GBC.eol().fill(GridBagConstraints.HORIZONTAL));
151
152        ExtendedDialog diag = new ExtendedDialog(Main.parent,
153                tr("Add Rectified Image"),
154
155                new String[] {tr("Add Rectified Image"), tr("Cancel")});
156        diag.setContent(panel);
157        diag.setButtonIcons(new String[] {"OLmarker.png", "cancel.png"});
158
159        // This repeatedly shows the dialog in case there has been an error.
160        // The loop is break;-ed if the users cancels
161        outer: while(true) {
162            diag.showDialog();
163            int answer = diag.getValue();
164            // Break loop when the user cancels
165            if(answer != 1) {
166                break;
167            }
168
169            String text = tfWmsUrl.getText().trim();
170            // Loop all services until we find the selected one
171            for(RectifierService s : services) {
172                if(!s.isSelected()) {
173                    continue;
174                }
175
176                // We've reached the custom WMS URL service
177                // Just set the URL and hope everything works out
178                if(s.wmsUrl.isEmpty()) {
179                    addWMSLayer(s.name + " (" + text + ")", text);
180                    break outer;
181                }
182
183                // First try to match if the entered string as an URL
184                Matcher m = s.urlRegEx.matcher(text);
185                if(m.find()) {
186                    String id = m.group(1);
187                    String newURL = s.wmsUrl.replaceAll("__s__", id);
188                    String title = s.name + " (" + id + ")";
189                    addWMSLayer(title, newURL);
190                    break outer;
191                }
192                // If not, look if it's a valid ID for the selected service
193                if(s.idValidator.matcher(text).matches()) {
194                    String newURL = s.wmsUrl.replaceAll("__s__", text);
195                    String title = s.name + " (" + text + ")";
196                    addWMSLayer(title, newURL);
197                    break outer;
198                }
199
200                // We've found the selected service, but the entered string isn't suitable for
201                // it. So quit checking the other radio buttons
202                break;
203            }
204
205            // and display an error message. The while(true) ensures that the dialog pops up again
206            JOptionPane.showMessageDialog(Main.parent,
207                    tr("Couldn''t match the entered link or id to the selected service. Please try again."),
208                    tr("No valid WMS URL or id"),
209                    JOptionPane.ERROR_MESSAGE);
210            diag.setVisible(true);
211        }
212    }
213
214    /**
215     * Adds a WMS Layer with given title and URL
216     * @param title Name of the layer as it will shop up in the layer manager
217     * @param url URL to the WMS server
218     */
219    private void addWMSLayer(String title, String url) {
220        Main.main.addLayer(new WMSLayer(new ImageryInfo(title, url)));
221    }
222
223    @Override
224    protected void updateEnabledState() {
225        setEnabled(Main.isDisplayingMapView() && !Main.map.mapView.getAllLayers().isEmpty());
226    }
227}
Note: See TracBrowser for help on using the repository browser.