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

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

see #12313 - fix NPE, checkstyle violations and two failing unit tests

  • Property svn:eol-style set to native
File size: 8.4 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.HashSet;
16import java.util.List;
17import java.util.Set;
18
19import javax.swing.JComboBox;
20import javax.swing.JOptionPane;
21import javax.swing.JPanel;
22import javax.swing.JScrollPane;
23
24import org.openstreetmap.josm.Main;
25import org.openstreetmap.josm.data.imagery.DefaultLayer;
26import org.openstreetmap.josm.data.imagery.ImageryInfo;
27import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType;
28import org.openstreetmap.josm.data.imagery.WMTSTileSource;
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.imagery.WMSLayerTree;
33import org.openstreetmap.josm.gui.util.GuiHelper;
34import org.openstreetmap.josm.io.imagery.WMSImagery;
35import org.openstreetmap.josm.io.imagery.WMSImagery.LayerDetails;
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;
40
41/**
42 * Action displayed in imagery menu to add a new imagery layer.
43 * @since 3715
44 */
45public class AddImageryLayerAction extends JosmAction implements AdaptableAction {
46 private final transient ImageryInfo info;
47
48 static class SelectWmsLayersDialog extends ExtendedDialog {
49 SelectWmsLayersDialog(WMSLayerTree tree, JComboBox<String> formats) {
50 super(Main.parent, tr("Select WMS layers"), new String[]{tr("Add layers"), tr("Cancel")});
51 final JScrollPane scrollPane = new JScrollPane(tree.getLayerTree());
52 scrollPane.setPreferredSize(new Dimension(400, 400));
53 final JPanel panel = new JPanel(new GridBagLayout());
54 panel.add(scrollPane, GBC.eol().fill());
55 panel.add(formats, GBC.eol().fill(GBC.HORIZONTAL));
56 setContent(panel);
57 }
58 }
59
60 /**
61 * Constructs a new {@code AddImageryLayerAction} for the given {@code ImageryInfo}.
62 * If an http:// icon is specified, it is fetched asynchronously.
63 * @param info The imagery info
64 */
65 public AddImageryLayerAction(ImageryInfo info) {
66 super(info.getMenuName(), /* ICON */"imagery_menu", tr("Add imagery layer {0}", info.getName()), null, false, false);
67 putValue("toolbar", "imagery_" + info.getToolbarName());
68 putValue("help", ht("/Preferences/Imagery"));
69 String tooltip = info.getToolTipText();
70 if (tooltip != null) {
71 setTooltip(tooltip.replaceAll("</?html>", ""));
72 }
73 this.info = info;
74 installAdapters();
75
76 // change toolbar icon from if specified
77 String icon = info.getIcon();
78 if (icon != null) {
79 new ImageProvider(icon).setOptional(true).getResourceAsync().thenAccept(result -> {
80 if (result != null) {
81 GuiHelper.runInEDT(() -> result.attachImageIcon(this));
82 }
83 });
84 }
85 }
86
87 /**
88 * Converts general ImageryInfo to specific one, that does not need any user action to initialize
89 * see: https://josm.openstreetmap.de/ticket/13868
90 * @param info ImageryInfo that will be converted (or returned when no conversion needed)
91 * @return ImageryInfo object that's ready to be used to create TileSource
92 */
93 private ImageryInfo convertImagery(ImageryInfo info) {
94 try {
95 switch(info.getImageryType()) {
96 case WMS_ENDPOINT:
97 // convert to WMS type
98 return getWMSLayerInfo();
99 case WMTS:
100 // specify which layer to use
101 DefaultLayer layerId = new WMTSTileSource(info).userSelectLayer();
102 if (layerId != null) {
103 ImageryInfo copy = new ImageryInfo(info);
104 Collection<DefaultLayer> defaultLayers = new ArrayList<>(1);
105 defaultLayers.add(layerId);
106 copy.setDefaultLayers(defaultLayers);
107 return copy;
108 }
109 // layer not selected - refuse to add
110 return null;
111 default:
112 return info;
113 }
114 } catch (MalformedURLException ex) {
115 if (!GraphicsEnvironment.isHeadless()) {
116 JOptionPane.showMessageDialog(Main.parent, tr("Invalid service URL."),
117 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
118 }
119 Main.error(ex, false);
120 } catch (IOException ex) {
121 if (!GraphicsEnvironment.isHeadless()) {
122 JOptionPane.showMessageDialog(Main.parent, tr("Could not retrieve WMS layer list."),
123 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
124 }
125 Main.error(ex, false);
126 } catch (WMSGetCapabilitiesException ex) {
127 if (!GraphicsEnvironment.isHeadless()) {
128 JOptionPane.showMessageDialog(Main.parent, tr("Could not parse WMS layer list."),
129 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
130 }
131 Main.error(ex, "Could not parse WMS layer list. Incoming data:\n"+ex.getIncomingData());
132 }
133 return null;
134 }
135
136 @Override
137 public void actionPerformed(ActionEvent e) {
138 if (!isEnabled()) return;
139 try {
140 final ImageryInfo infoToAdd = convertImagery(info);
141 if (infoToAdd != null) {
142 Main.getLayerManager().addLayer(ImageryLayer.create(infoToAdd));
143 AlignImageryPanel.addNagPanelIfNeeded(infoToAdd);
144 }
145 } catch (IllegalArgumentException ex) {
146 if (ex.getMessage() == null || ex.getMessage().isEmpty() || GraphicsEnvironment.isHeadless()) {
147 throw ex;
148 } else {
149 JOptionPane.showMessageDialog(Main.parent,
150 ex.getMessage(), tr("Error"),
151 JOptionPane.ERROR_MESSAGE);
152 }
153 }
154 }
155
156 protected ImageryInfo getWMSLayerInfo() throws IOException, WMSGetCapabilitiesException {
157 CheckParameterUtil.ensureThat(ImageryType.WMS_ENDPOINT.equals(info.getImageryType()), "wms_endpoint imagery type expected");
158
159 final WMSImagery wms = new WMSImagery();
160 wms.attemptGetCapabilities(info.getUrl());
161
162 final WMSLayerTree tree = new WMSLayerTree();
163 tree.updateTree(wms);
164 List<String> wmsFormats = wms.getFormats();
165 final JComboBox<String> formats = new JComboBox<>(wmsFormats.toArray(new String[wmsFormats.size()]));
166 formats.setSelectedItem(wms.getPreferredFormats());
167 formats.setToolTipText(tr("Select image format for WMS layer"));
168
169 if (!GraphicsEnvironment.isHeadless() && 1 != new SelectWmsLayersDialog(tree, formats).showDialog().getValue()) {
170 return null;
171 }
172
173 final String url = wms.buildGetMapUrl(
174 tree.getSelectedLayers(), (String) formats.getSelectedItem());
175 Set<String> supportedCrs = new HashSet<>();
176 boolean first = true;
177 StringBuilder layersString = new StringBuilder();
178 for (LayerDetails layer: tree.getSelectedLayers()) {
179 if (first) {
180 supportedCrs.addAll(layer.getProjections());
181 first = false;
182 }
183 layersString.append(layer.name);
184 layersString.append(", ");
185 supportedCrs.retainAll(layer.getProjections());
186 }
187
188 // copy all information from WMS
189 ImageryInfo ret = new ImageryInfo(info);
190 // and update according to user choice
191 ret.setUrl(url);
192 ret.setImageryType(ImageryType.WMS);
193 if (layersString.length() > 2) {
194 ret.setName(ret.getName() + ' ' + layersString.substring(0, layersString.length() - 2));
195 }
196 ret.setServerProjections(supportedCrs);
197 return ret;
198 }
199
200 @Override
201 protected void updateEnabledState() {
202 if (info.isBlacklisted()) {
203 setEnabled(false);
204 } else {
205 setEnabled(true);
206 }
207 }
208}
Note: See TracBrowser for help on using the repository browser.