source: josm/trunk/src/org/openstreetmap/josm/actions/AddImageryLayerAction.java@ 13755

Last change on this file since 13755 was 13741, checked in by wiktorn, 6 years ago

PMD fixes

  • Property svn:eol-style set to native
File size: 11.3 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.Dimension;
8import java.awt.GraphicsEnvironment;
9import java.awt.GridBagLayout;
10import java.awt.event.ActionEvent;
11import java.io.IOException;
12import java.net.MalformedURLException;
13import java.util.ArrayList;
14import java.util.Collection;
15import java.util.List;
16import java.util.stream.Collectors;
17
18import javax.swing.JComboBox;
19import javax.swing.JOptionPane;
20import javax.swing.JPanel;
21import javax.swing.JScrollPane;
22
23import org.openstreetmap.josm.Main;
24import org.openstreetmap.josm.data.imagery.DefaultLayer;
25import org.openstreetmap.josm.data.imagery.ImageryInfo;
26import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType;
27import org.openstreetmap.josm.data.imagery.WMTSTileSource;
28import org.openstreetmap.josm.data.imagery.WMTSTileSource.WMTSGetCapabilitiesException;
29import org.openstreetmap.josm.gui.ExtendedDialog;
30import org.openstreetmap.josm.gui.layer.AlignImageryPanel;
31import org.openstreetmap.josm.gui.layer.ImageryLayer;
32import org.openstreetmap.josm.gui.preferences.ToolbarPreferences;
33import org.openstreetmap.josm.gui.preferences.imagery.WMSLayerTree;
34import org.openstreetmap.josm.gui.util.GuiHelper;
35import org.openstreetmap.josm.io.imagery.WMSImagery;
36import org.openstreetmap.josm.io.imagery.WMSImagery.WMSGetCapabilitiesException;
37import org.openstreetmap.josm.tools.CheckParameterUtil;
38import org.openstreetmap.josm.tools.GBC;
39import org.openstreetmap.josm.tools.ImageProvider;
40import org.openstreetmap.josm.tools.Logging;
41import org.openstreetmap.josm.tools.bugreport.ReportedException;
42
43/**
44 * Action displayed in imagery menu to add a new imagery layer.
45 * @since 3715
46 */
47public class AddImageryLayerAction extends JosmAction implements AdaptableAction {
48 private final transient ImageryInfo info;
49
50 static class SelectWmsLayersDialog extends ExtendedDialog {
51 SelectWmsLayersDialog(WMSLayerTree tree, JComboBox<String> formats) {
52 super(Main.parent, tr("Select WMS layers"), tr("Add layers"), tr("Cancel"));
53 final JScrollPane scrollPane = new JScrollPane(tree.getLayerTree());
54 scrollPane.setPreferredSize(new Dimension(400, 400));
55 final JPanel panel = new JPanel(new GridBagLayout());
56 panel.add(scrollPane, GBC.eol().fill());
57 panel.add(formats, GBC.eol().fill(GBC.HORIZONTAL));
58 setContent(panel);
59 }
60 }
61
62 /**
63 * Constructs a new {@code AddImageryLayerAction} for the given {@code ImageryInfo}.
64 * If an http:// icon is specified, it is fetched asynchronously.
65 * @param info The imagery info
66 */
67 public AddImageryLayerAction(ImageryInfo info) {
68 super(info.getMenuName(), /* ICON */"imagery_menu", tr("Add imagery layer {0}", info.getName()), null,
69 true, ToolbarPreferences.IMAGERY_PREFIX + info.getToolbarName(), false);
70 putValue("help", ht("/Preferences/Imagery"));
71 setTooltip(info.getToolTipText().replaceAll("</?html>", ""));
72 this.info = info;
73 installAdapters();
74
75 // change toolbar icon from if specified
76 String icon = info.getIcon();
77 if (icon != null) {
78 new ImageProvider(icon).setOptional(true).getResourceAsync(result -> {
79 if (result != null) {
80 GuiHelper.runInEDT(() -> result.attachImageIcon(this));
81 }
82 });
83 }
84 }
85
86 /**
87 * Converts general ImageryInfo to specific one, that does not need any user action to initialize
88 * see: https://josm.openstreetmap.de/ticket/13868
89 * @param info ImageryInfo that will be converted (or returned when no conversion needed)
90 * @return ImageryInfo object that's ready to be used to create TileSource
91 */
92 private ImageryInfo convertImagery(ImageryInfo info) {
93 try {
94 switch(info.getImageryType()) {
95 case WMS_ENDPOINT:
96 // convert to WMS type
97 if (info.getDefaultLayers() == null || info.getDefaultLayers().isEmpty()) {
98 return getWMSLayerInfo(info);
99 } else {
100 return info;
101 }
102 case WMTS:
103 // specify which layer to use
104 if (info.getDefaultLayers() == null || info.getDefaultLayers().isEmpty()) {
105 DefaultLayer layerId = new WMTSTileSource(info).userSelectLayer();
106 if (layerId != null) {
107 ImageryInfo copy = new ImageryInfo(info);
108 List<DefaultLayer> defaultLayers = new ArrayList<>(1);
109 defaultLayers.add(layerId);
110 copy.setDefaultLayers(defaultLayers);
111 return copy;
112 }
113 return null;
114 } else {
115 return info;
116 }
117 default:
118 return info;
119 }
120 } catch (MalformedURLException ex) {
121 if (!GraphicsEnvironment.isHeadless()) {
122 JOptionPane.showMessageDialog(Main.parent, tr("Invalid service URL."),
123 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
124 }
125 Logging.log(Logging.LEVEL_ERROR, ex);
126 } catch (IOException ex) {
127 if (!GraphicsEnvironment.isHeadless()) {
128 JOptionPane.showMessageDialog(Main.parent, tr("Could not retrieve WMS layer list."),
129 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
130 }
131 Logging.log(Logging.LEVEL_ERROR, ex);
132 } catch (WMSGetCapabilitiesException ex) {
133 if (!GraphicsEnvironment.isHeadless()) {
134 JOptionPane.showMessageDialog(Main.parent, tr("Could not parse WMS layer list."),
135 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
136 }
137 Logging.log(Logging.LEVEL_ERROR, "Could not parse WMS layer list. Incoming data:\n"+ex.getIncomingData(), ex);
138 } catch (WMTSGetCapabilitiesException e) {
139 if (!GraphicsEnvironment.isHeadless()) {
140 JOptionPane.showMessageDialog(Main.parent, tr("Could not parse WMTS layer list."),
141 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
142 }
143 Logging.log(Logging.LEVEL_ERROR, "Could not parse WMTS layer list.", e);
144 }
145 return null;
146 }
147
148 @Override
149 public void actionPerformed(ActionEvent e) {
150 if (!isEnabled()) return;
151 ImageryLayer layer = null;
152 try {
153 final ImageryInfo infoToAdd = convertImagery(info);
154 if (infoToAdd != null) {
155 layer = ImageryLayer.create(infoToAdd);
156 getLayerManager().addLayer(layer);
157 AlignImageryPanel.addNagPanelIfNeeded(infoToAdd);
158 }
159 } catch (IllegalArgumentException | ReportedException ex) {
160 if (ex.getMessage() == null || ex.getMessage().isEmpty() || GraphicsEnvironment.isHeadless()) {
161 throw ex;
162 } else {
163 Logging.error(ex);
164 JOptionPane.showMessageDialog(Main.parent, ex.getMessage(), tr("Error"), JOptionPane.ERROR_MESSAGE);
165 if (layer != null) {
166 getLayerManager().removeLayer(layer);
167 }
168 }
169 }
170 }
171
172 /**
173 * Asks user to choose a WMS layer from a WMS endpoint.
174 * @param info the WMS endpoint.
175 * @return chosen WMS layer, or null
176 * @throws IOException if any I/O error occurs while contacting the WMS endpoint
177 * @throws WMSGetCapabilitiesException if the WMS getCapabilities request fails
178 */
179 protected static ImageryInfo getWMSLayerInfo(ImageryInfo info) throws IOException, WMSGetCapabilitiesException {
180 try {
181 CheckParameterUtil.ensureThat(ImageryType.WMS_ENDPOINT.equals(info.getImageryType()), "wms_endpoint imagery type expected");
182 final WMSImagery wms = new WMSImagery(info.getUrl());
183
184 final WMSLayerTree tree = new WMSLayerTree();
185 tree.updateTree(wms);
186
187 Collection<String> wmsFormats = wms.getFormats();
188 final JComboBox<String> formats = new JComboBox<>(wmsFormats.toArray(new String[0]));
189 formats.setSelectedItem(wms.getPreferredFormat());
190 formats.setToolTipText(tr("Select image format for WMS layer"));
191
192 if (!GraphicsEnvironment.isHeadless()) {
193 if (1 != new ExtendedDialog(Main.parent, tr("Select WMS layers"), new String[]{tr("Add layers"), tr("Cancel")}) { {
194 final JScrollPane scrollPane = new JScrollPane(tree.getLayerTree());
195 scrollPane.setPreferredSize(new Dimension(400, 400));
196 final JPanel panel = new JPanel(new GridBagLayout());
197 panel.add(scrollPane, GBC.eol().fill());
198 panel.add(formats, GBC.eol().fill(GBC.HORIZONTAL));
199 setContent(panel);
200 } }.showDialog().getValue()) {
201 return null;
202 }
203 }
204
205 final String url = wms.buildGetMapUrl(
206 tree.getSelectedLayers().stream().map(x -> x.getName()).collect(Collectors.toList()),
207 (List<String>) null,
208 (String) formats.getSelectedItem(),
209 true // TODO: ask the user if (s)he wants transparent layer
210 );
211
212 String selectedLayers = tree.getSelectedLayers().stream()
213 .map(x -> x.getName())
214 .collect(Collectors.joining(", "));
215 ImageryInfo ret = new ImageryInfo(info.getName() + selectedLayers,
216 url,
217 "wms",
218 info.getEulaAcceptanceRequired(),
219 info.getCookies());
220
221 ret.setServerProjections(wms.getServerProjections(tree.getSelectedLayers()));
222
223 return ret;
224 } catch (MalformedURLException ex) {
225 if (!GraphicsEnvironment.isHeadless()) {
226 JOptionPane.showMessageDialog(Main.parent, tr("Invalid service URL."),
227 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
228 }
229 Logging.log(Logging.LEVEL_ERROR, ex);
230 } catch (IOException ex) {
231 if (!GraphicsEnvironment.isHeadless()) {
232 JOptionPane.showMessageDialog(Main.parent, tr("Could not retrieve WMS layer list."),
233 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
234 }
235 Logging.log(Logging.LEVEL_ERROR, ex);
236 } catch (WMSGetCapabilitiesException ex) {
237 if (!GraphicsEnvironment.isHeadless()) {
238 JOptionPane.showMessageDialog(Main.parent, tr("Could not parse WMS layer list."),
239 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
240 }
241 Logging.log(Logging.LEVEL_ERROR, "Could not parse WMS layer list. Incoming data:\n"+ex.getIncomingData(), ex);
242 }
243 return null;
244 }
245
246 @Override
247 protected void updateEnabledState() {
248 if (info.isBlacklisted()) {
249 setEnabled(false);
250 } else {
251 setEnabled(true);
252 }
253 }
254
255 @Override
256 public String toString() {
257 return "AddImageryLayerAction [info=" + info + ']';
258 }
259}
Note: See TracBrowser for help on using the repository browser.