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.GridBagLayout; 009import java.awt.event.ActionEvent; 010import java.io.IOException; 011import java.net.MalformedURLException; 012 013import javax.swing.Action; 014import javax.swing.JComboBox; 015import javax.swing.JOptionPane; 016import javax.swing.JPanel; 017import javax.swing.JScrollPane; 018 019import org.openstreetmap.josm.Main; 020import org.openstreetmap.josm.data.imagery.ImageryInfo; 021import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType; 022import org.openstreetmap.josm.gui.ExtendedDialog; 023import org.openstreetmap.josm.gui.actionsupport.AlignImageryPanel; 024import org.openstreetmap.josm.gui.layer.ImageryLayer; 025import org.openstreetmap.josm.gui.preferences.imagery.WMSLayerTree; 026import org.openstreetmap.josm.gui.util.GuiHelper; 027import org.openstreetmap.josm.io.imagery.WMSImagery; 028import org.openstreetmap.josm.tools.GBC; 029import org.openstreetmap.josm.tools.ImageProvider; 030import org.openstreetmap.josm.tools.ImageProvider.ImageResourceCallback; 031import org.openstreetmap.josm.tools.ImageResource; 032 033/** 034 * Action displayed in imagery menu to add a new imagery layer. 035 * @since 3715 036 */ 037public class AddImageryLayerAction extends JosmAction implements AdaptableAction { 038 private final ImageryInfo info; 039 040 /** 041 * Constructs a new {@code AddImageryLayerAction} for the given {@code ImageryInfo}. 042 * If an http:// icon is specified, it is fetched asynchronously. 043 * @param info The imagery info 044 */ 045 public AddImageryLayerAction(ImageryInfo info) { 046 super(info.getMenuName(), /* ICON */"imagery_menu", tr("Add imagery layer {0}",info.getName()), null, false, false); 047 putValue("toolbar", "imagery_" + info.getToolbarName()); 048 putValue("help", ht("/Preferences/Imagery")); 049 this.info = info; 050 installAdapters(); 051 052 // change toolbar icon from if specified 053 try { 054 String icon = info.getIcon(); 055 if (icon != null) { 056 new ImageProvider(icon).setOptional(true).getInBackground(new ImageResourceCallback() { 057 @Override 058 public void finished(final ImageResource result) { 059 if (result != null) { 060 GuiHelper.runInEDT(new Runnable() { 061 @Override 062 public void run() { 063 result.getImageIcon(AddImageryLayerAction.this); 064 } 065 }); 066 } 067 } 068 }); 069 } 070 } catch (Exception ex) { 071 throw new RuntimeException(ex.getMessage(), ex); 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.main.addLayer(ImageryLayer.create(infoToAdd)); 083 AlignImageryPanel.addNagPanelIfNeeded(); 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 (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 final String url = wms.buildGetMapUrl( 120 tree.getSelectedLayers(), (String) formats.getSelectedItem()); 121 return new ImageryInfo(info.getName(), url, "wms", info.getEulaAcceptanceRequired(), info.getCookies()); 122 } // exception handling from AddWMSLayerPanel.java 123 catch (MalformedURLException ex) { 124 JOptionPane.showMessageDialog(Main.parent, tr("Invalid service URL."), 125 tr("WMS Error"), JOptionPane.ERROR_MESSAGE); 126 } catch (IOException ex) { 127 JOptionPane.showMessageDialog(Main.parent, tr("Could not retrieve WMS layer list."), 128 tr("WMS Error"), JOptionPane.ERROR_MESSAGE); 129 } catch (WMSImagery.WMSGetCapabilitiesException ex) { 130 JOptionPane.showMessageDialog(Main.parent, tr("Could not parse WMS layer list."), 131 tr("WMS Error"), JOptionPane.ERROR_MESSAGE); 132 Main.error("Could not parse WMS layer list. Incoming data:\n"+ex.getIncomingData()); 133 } 134 return null; 135 } 136 137 protected boolean isLayerAlreadyPresent() { 138 if (Main.isDisplayingMapView()) { 139 for (ImageryLayer layer : Main.map.mapView.getLayersOfType(ImageryLayer.class)) { 140 if (info.equals(layer.getInfo())) { 141 return true; 142 } 143 } 144 } 145 return false; 146 } 147 148 @Override 149 protected void updateEnabledState() { 150 // never enable blacklisted entries. Do not add same imagery layer twice (fix #2519) 151 if (info.isBlacklisted() /*|| isLayerAlreadyPresent()*/) { // FIXME check disabled to allow several instances with different settings (see #7981) 152 setEnabled(false); 153 } else if (info.getImageryType() == ImageryType.TMS || info.getImageryType() == ImageryType.BING || info.getImageryType() == ImageryType.SCANEX) { 154 setEnabled(true); 155 } else if (Main.isDisplayingMapView() && !Main.map.mapView.getAllLayers().isEmpty()) { 156 setEnabled(true); 157 } else { 158 setEnabled(false); 159 } 160 } 161}