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

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

SonarQube fixes

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