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