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

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

see #15654 - fix icon flickering (regression from r13250)

  • Property svn:eol-style set to native
File size: 8.9 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.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.LayerDetails;
37import org.openstreetmap.josm.io.imagery.WMSImagery.WMSGetCapabilitiesException;
38import org.openstreetmap.josm.tools.CheckParameterUtil;
39import org.openstreetmap.josm.tools.GBC;
40import org.openstreetmap.josm.tools.ImageProvider;
41import org.openstreetmap.josm.tools.Logging;
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 return getWMSLayerInfo(info);
98 case WMTS:
99 // specify which layer to use
100 DefaultLayer layerId = new WMTSTileSource(info).userSelectLayer();
101 if (layerId != null) {
102 ImageryInfo copy = new ImageryInfo(info);
103 Collection<DefaultLayer> defaultLayers = new ArrayList<>(1);
104 defaultLayers.add(layerId);
105 copy.setDefaultLayers(defaultLayers);
106 return copy;
107 }
108 // layer not selected - refuse to add
109 return null;
110 default:
111 return info;
112 }
113 } catch (MalformedURLException ex) {
114 if (!GraphicsEnvironment.isHeadless()) {
115 JOptionPane.showMessageDialog(Main.parent, tr("Invalid service URL."),
116 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
117 }
118 Logging.log(Logging.LEVEL_ERROR, ex);
119 } catch (IOException ex) {
120 if (!GraphicsEnvironment.isHeadless()) {
121 JOptionPane.showMessageDialog(Main.parent, tr("Could not retrieve WMS layer list."),
122 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
123 }
124 Logging.log(Logging.LEVEL_ERROR, ex);
125 } catch (WMSGetCapabilitiesException ex) {
126 if (!GraphicsEnvironment.isHeadless()) {
127 JOptionPane.showMessageDialog(Main.parent, tr("Could not parse WMS layer list."),
128 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
129 }
130 Logging.log(Logging.LEVEL_ERROR, "Could not parse WMS layer list. Incoming data:\n"+ex.getIncomingData(), ex);
131 }
132 return null;
133 }
134
135 @Override
136 public void actionPerformed(ActionEvent e) {
137 if (!isEnabled()) return;
138 try {
139 final ImageryInfo infoToAdd = convertImagery(info);
140 if (infoToAdd != null) {
141 getLayerManager().addLayer(ImageryLayer.create(infoToAdd));
142 AlignImageryPanel.addNagPanelIfNeeded(infoToAdd);
143 }
144 } catch (IllegalArgumentException ex) {
145 if (ex.getMessage() == null || ex.getMessage().isEmpty() || GraphicsEnvironment.isHeadless()) {
146 throw ex;
147 } else {
148 JOptionPane.showMessageDialog(Main.parent,
149 ex.getMessage(), tr("Error"),
150 JOptionPane.ERROR_MESSAGE);
151 }
152 }
153 }
154
155 /**
156 * Asks user to choose a WMS layer from a WMS endpoint.
157 * @param info the WMS endpoint.
158 * @return chosen WMS layer, or null
159 * @throws IOException if any I/O error occurs while contacting the WMS endpoint
160 * @throws WMSGetCapabilitiesException if the WMS getCapabilities request fails
161 */
162 protected static ImageryInfo getWMSLayerInfo(ImageryInfo info) throws IOException, WMSGetCapabilitiesException {
163 CheckParameterUtil.ensureThat(ImageryType.WMS_ENDPOINT.equals(info.getImageryType()), "wms_endpoint imagery type expected");
164
165 final WMSImagery wms = new WMSImagery();
166 wms.attemptGetCapabilities(info.getUrl());
167
168 final WMSLayerTree tree = new WMSLayerTree();
169 tree.updateTree(wms);
170 List<String> wmsFormats = wms.getFormats();
171 final JComboBox<String> formats = new JComboBox<>(wmsFormats.toArray(new String[0]));
172 formats.setSelectedItem(wms.getPreferredFormats());
173 formats.setToolTipText(tr("Select image format for WMS layer"));
174
175 if (!GraphicsEnvironment.isHeadless() && 1 != new SelectWmsLayersDialog(tree, formats).showDialog().getValue()) {
176 return null;
177 }
178
179 final String url = wms.buildGetMapUrl(
180 tree.getSelectedLayers(), (String) formats.getSelectedItem());
181 Set<String> supportedCrs = new HashSet<>();
182 boolean first = true;
183 StringBuilder layersString = new StringBuilder();
184 for (LayerDetails layer: tree.getSelectedLayers()) {
185 if (first) {
186 supportedCrs.addAll(layer.getProjections());
187 first = false;
188 }
189 layersString.append(layer.name);
190 layersString.append(", ");
191 supportedCrs.retainAll(layer.getProjections());
192 }
193
194 // copy all information from WMS
195 ImageryInfo ret = new ImageryInfo(info);
196 // and update according to user choice
197 ret.setUrl(url);
198 ret.setImageryType(ImageryType.WMS);
199 if (layersString.length() > 2) {
200 ret.setName(ret.getName() + ' ' + layersString.substring(0, layersString.length() - 2));
201 }
202 ret.setServerProjections(supportedCrs);
203 return ret;
204 }
205
206 @Override
207 protected void updateEnabledState() {
208 if (info.isBlacklisted()) {
209 setEnabled(false);
210 } else {
211 setEnabled(true);
212 }
213 }
214
215 @Override
216 public String toString() {
217 return "AddImageryLayerAction [info=" + info + ']';
218 }
219}
Note: See TracBrowser for help on using the repository browser.