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

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

fix #14451 - Local imagery toolbar buttons disappear on restart

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