001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.actions;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.Dimension;
007import java.awt.GridBagLayout;
008import java.awt.event.ActionEvent;
009import java.io.IOException;
010import java.net.MalformedURLException;
011
012import javax.swing.Action;
013import javax.swing.ImageIcon;
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.io.imagery.WMSImagery;
027import org.openstreetmap.josm.tools.GBC;
028import org.openstreetmap.josm.tools.ImageProvider;
029
030public class AddImageryLayerAction extends JosmAction implements AdaptableAction {
031
032    private static final int MAX_ICON_SIZE = 24;
033    private final ImageryInfo info;
034
035    public AddImageryLayerAction(ImageryInfo info) {
036        super(info.getMenuName(), /* ICON */"imagery_menu", tr("Add imagery layer {0}",info.getName()), null, false, false);
037        putValue("toolbar", "imagery_" + info.getToolbarName());
038        this.info = info;
039        installAdapters();
040
041        // change toolbar icon from if specified
042        try {
043            if (info.getIcon() != null) {
044                ImageIcon i = new ImageProvider(info.getIcon()).setOptional(true).
045                        setMaxHeight(MAX_ICON_SIZE).setMaxWidth(MAX_ICON_SIZE).get();
046                if (i != null) {
047                    putValue(Action.SMALL_ICON, i);
048                }
049            }
050        } catch (Exception ex) {
051            throw new RuntimeException(ex.getMessage(), ex);
052        }
053    }
054
055    @Override
056    public void actionPerformed(ActionEvent e) {
057        if (!isEnabled()) return;
058        try {
059            final ImageryInfo infoToAdd = ImageryType.WMS_ENDPOINT.equals(info.getImageryType())
060                    ? getWMSLayerInfo() : info;
061            if (infoToAdd != null) {
062                Main.main.addLayer(ImageryLayer.create(infoToAdd));
063                AlignImageryPanel.addNagPanelIfNeeded();
064            }
065        } catch (IllegalArgumentException ex) {
066            if (ex.getMessage() == null || ex.getMessage().isEmpty()) {
067                throw ex;
068            } else {
069                JOptionPane.showMessageDialog(Main.parent,
070                        ex.getMessage(), tr("Error"),
071                        JOptionPane.ERROR_MESSAGE);
072            }
073        }
074    }
075
076    protected ImageryInfo getWMSLayerInfo() {
077        try {
078            assert (ImageryType.WMS_ENDPOINT.equals(info.getImageryType()));
079            final WMSImagery wms = new WMSImagery();
080            wms.attemptGetCapabilities(info.getUrl());
081
082            final WMSLayerTree tree = new WMSLayerTree();
083            tree.updateTree(wms);
084            final JComboBox formats = new JComboBox(wms.getFormats().toArray());
085            formats.setToolTipText(tr("Select image format for WMS layer"));
086
087            if (1 != new ExtendedDialog(Main.parent, tr("Select WMS layers"), new String[]{tr("Add layers"), tr("Cancel")}) {{
088                final JScrollPane scrollPane = new JScrollPane(tree.getLayerTree());
089                scrollPane.setPreferredSize(new Dimension(400, 400));
090                final JPanel panel = new JPanel(new GridBagLayout());
091                panel.add(scrollPane, GBC.eol().fill());
092                panel.add(formats, GBC.eol().fill(GBC.HORIZONTAL));
093                setContent(panel);
094            }}.showDialog().getValue()) {
095                return null;
096            }
097
098            final String url = wms.buildGetMapUrl(
099                    tree.getSelectedLayers(), (String) formats.getSelectedItem());
100            return new ImageryInfo(info.getName(), url, "wms", info.getEulaAcceptanceRequired(), info.getCookies());
101        } // exception handling from AddWMSLayerPanel.java
102        catch (MalformedURLException ex) {
103            JOptionPane.showMessageDialog(Main.parent, tr("Invalid service URL."),
104                    tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
105        } catch (IOException ex) {
106            JOptionPane.showMessageDialog(Main.parent, tr("Could not retrieve WMS layer list."),
107                    tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
108        } catch (WMSImagery.WMSGetCapabilitiesException ex) {
109            JOptionPane.showMessageDialog(Main.parent, tr("Could not parse WMS layer list."),
110                    tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
111            Main.error("Could not parse WMS layer list. Incoming data:\n"+ex.getIncomingData());
112        }
113        return null;
114    }
115
116    protected boolean isLayerAlreadyPresent() {
117        if (Main.isDisplayingMapView()) {
118            for (ImageryLayer layer : Main.map.mapView.getLayersOfType(ImageryLayer.class)) {
119                if (info.equals(layer.getInfo())) {
120                    return true;
121                }
122            }
123        }
124        return false;
125    }
126
127    @Override
128    protected void updateEnabledState() {
129        // never enable blacklisted entries. Do not add same imagery layer twice (fix #2519)
130        if (info.isBlacklisted() /*|| isLayerAlreadyPresent()*/) { // FIXME check disabled to allow several instances with different settings (see #7981)
131            setEnabled(false);
132        } else if (info.getImageryType() == ImageryType.TMS || info.getImageryType() == ImageryType.BING || info.getImageryType() == ImageryType.SCANEX) {
133            setEnabled(true);
134        } else if (Main.isDisplayingMapView() && !Main.map.mapView.getAllLayers().isEmpty()) {
135            setEnabled(true);
136        } else {
137            setEnabled(false);
138        }
139    }
140}