001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.actions; 003 004import static org.openstreetmap.josm.gui.help.HelpUtil.ht; 005import static org.openstreetmap.josm.tools.I18n.tr; 006 007import java.awt.Dimension; 008import java.awt.GraphicsEnvironment; 009import java.awt.GridBagLayout; 010import java.awt.event.ActionEvent; 011import java.io.IOException; 012import java.net.MalformedURLException; 013import java.util.HashSet; 014import java.util.Set; 015 016import javax.swing.JComboBox; 017import javax.swing.JOptionPane; 018import javax.swing.JPanel; 019import javax.swing.JScrollPane; 020 021import org.openstreetmap.josm.Main; 022import org.openstreetmap.josm.data.imagery.ImageryInfo; 023import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType; 024import org.openstreetmap.josm.gui.ExtendedDialog; 025import org.openstreetmap.josm.gui.layer.AlignImageryPanel; 026import org.openstreetmap.josm.gui.layer.ImageryLayer; 027import org.openstreetmap.josm.gui.preferences.imagery.WMSLayerTree; 028import org.openstreetmap.josm.gui.util.GuiHelper; 029import org.openstreetmap.josm.io.imagery.WMSImagery; 030import org.openstreetmap.josm.io.imagery.WMSImagery.LayerDetails; 031import org.openstreetmap.josm.io.imagery.WMSImagery.WMSGetCapabilitiesException; 032import org.openstreetmap.josm.tools.GBC; 033import org.openstreetmap.josm.tools.ImageProvider; 034import org.openstreetmap.josm.tools.ImageProvider.ImageResourceCallback; 035import org.openstreetmap.josm.tools.ImageResource; 036 037/** 038 * Action displayed in imagery menu to add a new imagery layer. 039 * @since 3715 040 */ 041public class AddImageryLayerAction extends JosmAction implements AdaptableAction { 042 private final transient ImageryInfo info; 043 044 /** 045 * Constructs a new {@code AddImageryLayerAction} for the given {@code ImageryInfo}. 046 * If an http:// icon is specified, it is fetched asynchronously. 047 * @param info The imagery info 048 */ 049 public AddImageryLayerAction(ImageryInfo info) { 050 super(info.getMenuName(), /* ICON */"imagery_menu", tr("Add imagery layer {0}", info.getName()), null, false, false); 051 putValue("toolbar", "imagery_" + info.getToolbarName()); 052 putValue("help", ht("/Preferences/Imagery")); 053 this.info = info; 054 installAdapters(); 055 056 // change toolbar icon from if specified 057 String icon = info.getIcon(); 058 if (icon != null) { 059 new ImageProvider(icon).setOptional(true).getInBackground(new ImageResourceCallback() { 060 @Override 061 public void finished(final ImageResource result) { 062 if (result != null) { 063 GuiHelper.runInEDT(new Runnable() { 064 @Override 065 public void run() { 066 result.attachImageIcon(AddImageryLayerAction.this); 067 } 068 }); 069 } 070 } 071 }); 072 } 073 } 074 075 @Override 076 public void actionPerformed(ActionEvent e) { 077 if (!isEnabled()) return; 078 try { 079 final ImageryInfo infoToAdd = ImageryType.WMS_ENDPOINT.equals(info.getImageryType()) 080 ? getWMSLayerInfo() : info; 081 if (infoToAdd != null) { 082 Main.getLayerManager().addLayer(ImageryLayer.create(infoToAdd)); 083 AlignImageryPanel.addNagPanelIfNeeded(infoToAdd); 084 } 085 } catch (IllegalArgumentException ex) { 086 if (ex.getMessage() == null || ex.getMessage().isEmpty()) { 087 throw ex; 088 } else { 089 JOptionPane.showMessageDialog(Main.parent, 090 ex.getMessage(), tr("Error"), 091 JOptionPane.ERROR_MESSAGE); 092 } 093 } 094 } 095 096 protected ImageryInfo getWMSLayerInfo() { 097 try { 098 assert ImageryType.WMS_ENDPOINT.equals(info.getImageryType()); 099 final WMSImagery wms = new WMSImagery(); 100 wms.attemptGetCapabilities(info.getUrl()); 101 102 final WMSLayerTree tree = new WMSLayerTree(); 103 tree.updateTree(wms); 104 final JComboBox<String> formats = new JComboBox<>(wms.getFormats().toArray(new String[0])); 105 formats.setSelectedItem(wms.getPreferredFormats()); 106 formats.setToolTipText(tr("Select image format for WMS layer")); 107 108 if (!GraphicsEnvironment.isHeadless()) { 109 if (1 != new ExtendedDialog(Main.parent, tr("Select WMS layers"), new String[]{tr("Add layers"), tr("Cancel")}) { { 110 final JScrollPane scrollPane = new JScrollPane(tree.getLayerTree()); 111 scrollPane.setPreferredSize(new Dimension(400, 400)); 112 final JPanel panel = new JPanel(new GridBagLayout()); 113 panel.add(scrollPane, GBC.eol().fill()); 114 panel.add(formats, GBC.eol().fill(GBC.HORIZONTAL)); 115 setContent(panel); 116 } }.showDialog().getValue()) { 117 return null; 118 } 119 } 120 121 final String url = wms.buildGetMapUrl( 122 tree.getSelectedLayers(), (String) formats.getSelectedItem()); 123 Set<String> supportedCrs = new HashSet<>(); 124 boolean first = true; 125 StringBuilder layersString = new StringBuilder(); 126 for (LayerDetails layer: tree.getSelectedLayers()) { 127 if (first) { 128 supportedCrs.addAll(layer.getProjections()); 129 first = false; 130 } 131 layersString.append(layer.name); 132 layersString.append(", "); 133 supportedCrs.retainAll(layer.getProjections()); 134 } 135 136 ImageryInfo ret = new ImageryInfo(info.getName(), url, "wms", info.getEulaAcceptanceRequired(), info.getCookies()); 137 if (layersString.length() > 2) { 138 ret.setName(ret.getName() + ' ' + layersString.substring(0, layersString.length() - 2)); 139 } 140 ret.setServerProjections(supportedCrs); 141 return ret; 142 } catch (MalformedURLException ex) { 143 if (!GraphicsEnvironment.isHeadless()) { 144 JOptionPane.showMessageDialog(Main.parent, tr("Invalid service URL."), 145 tr("WMS Error"), JOptionPane.ERROR_MESSAGE); 146 } 147 Main.error(ex, false); 148 } catch (IOException ex) { 149 if (!GraphicsEnvironment.isHeadless()) { 150 JOptionPane.showMessageDialog(Main.parent, tr("Could not retrieve WMS layer list."), 151 tr("WMS Error"), JOptionPane.ERROR_MESSAGE); 152 } 153 Main.error(ex, false); 154 } catch (WMSGetCapabilitiesException ex) { 155 if (!GraphicsEnvironment.isHeadless()) { 156 JOptionPane.showMessageDialog(Main.parent, tr("Could not parse WMS layer list."), 157 tr("WMS Error"), JOptionPane.ERROR_MESSAGE); 158 } 159 Main.error(ex, "Could not parse WMS layer list. Incoming data:\n"+ex.getIncomingData()); 160 } 161 return null; 162 } 163 164 @Override 165 protected void updateEnabledState() { 166 ImageryType type = info.getImageryType(); 167 // never enable blacklisted entries. Do not add same imagery layer twice (fix #2519) 168 if (info.isBlacklisted()) { 169 setEnabled(false); 170 } else if (type == ImageryType.TMS || type == ImageryType.BING || type == ImageryType.SCANEX) { 171 setEnabled(true); 172 } else { 173 setEnabled(!Main.getLayerManager().getLayers().isEmpty()); 174 } 175 } 176}