// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.gui.preferences.imagery; import static org.openstreetmap.josm.tools.I18n.tr; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.List; import javax.swing.DefaultComboBoxModel; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.data.imagery.ImageryInfo; import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType; import org.openstreetmap.josm.gui.bbox.SlippyMapBBoxChooser; import org.openstreetmap.josm.gui.util.GuiHelper; import org.openstreetmap.josm.gui.widgets.JosmTextArea; import org.openstreetmap.josm.io.imagery.WMSImagery; import org.openstreetmap.josm.tools.GBC; import org.openstreetmap.josm.tools.Utils; /** * An imagery panel used to add WMS imagery sources. * @since 2599 */ public class AddWMSLayerPanel extends AddImageryPanel { private final transient WMSImagery wms = new WMSImagery(); private final JCheckBox endpoint = new JCheckBox(tr("Store WMS endpoint only, select layers at usage")); private final transient WMSLayerTree tree = new WMSLayerTree(); private final JComboBox<String> formats = new JComboBox<>(); private final JLabel wmsInstruction; private final JosmTextArea wmsUrl = new JosmTextArea(3, 40).transferFocusOnTab(); private final JButton showBounds = new JButton(tr("Show bounds")); /** * Constructs a new {@code AddWMSLayerPanel}. */ public AddWMSLayerPanel() { add(new JLabel(tr("1. Enter service URL")), GBC.eol()); add(rawUrl, GBC.eol().fill()); rawUrl.setLineWrap(true); JButton getLayers = new JButton(tr("Get layers")); add(getLayers, GBC.eop().fill()); add(new JLabel(tr("2. Select layers")), GBC.eol()); add(endpoint, GBC.eol().fill()); add(new JScrollPane(tree.getLayerTree()), GBC.eol().fill().weight(1, 100)); showBounds.setEnabled(false); add(showBounds, GBC.eop().fill()); add(new JLabel(tr("3. Select image format")), GBC.eol()); add(formats, GBC.eol().fill()); wmsInstruction = new JLabel(tr("4. Verify generated WMS URL")); add(wmsInstruction, GBC.eol()); wmsInstruction.setLabelFor(wmsUrl); add(wmsUrl, GBC.eop().fill()); wmsUrl.setLineWrap(true); add(new JLabel(tr("5. Enter name for this layer")), GBC.eol()); add(name, GBC.eop().fill()); getLayers.addActionListener(e -> { try { wms.attemptGetCapabilities(rawUrl.getText()); tree.updateTree(wms); List<String> wmsFormats = wms.getFormats(); formats.setModel(new DefaultComboBoxModel<>(wmsFormats.toArray(new String[wmsFormats.size()]))); formats.setSelectedItem(wms.getPreferredFormats()); } catch (MalformedURLException ex1) { Main.error(ex1, false); JOptionPane.showMessageDialog(getParent(), tr("Invalid service URL."), tr("WMS Error"), JOptionPane.ERROR_MESSAGE); } catch (IOException ex2) { Main.error(ex2, false); JOptionPane.showMessageDialog(getParent(), tr("Could not retrieve WMS layer list."), tr("WMS Error"), JOptionPane.ERROR_MESSAGE); } catch (WMSImagery.WMSGetCapabilitiesException ex3) { String incomingData = ex3.getIncomingData().trim(); String title = tr("WMS Error"); StringBuilder message = new StringBuilder(tr("Could not parse WMS layer list.")); Main.error(ex3, "Could not parse WMS layer list. Incoming data:\n"+incomingData); if ((incomingData.startsWith("<html>") || incomingData.startsWith("<HTML>")) && (incomingData.endsWith("</html>") || incomingData.endsWith("</HTML>"))) { GuiHelper.notifyUserHtmlError(this, title, message.toString(), incomingData); } else { if (ex3.getMessage() != null) { message.append('\n').append(ex3.getMessage()); } JOptionPane.showMessageDialog(getParent(), message.toString(), title, JOptionPane.ERROR_MESSAGE); } } }); endpoint.addItemListener(e -> { tree.getLayerTree().setEnabled(!endpoint.isSelected()); showBounds.setEnabled(!endpoint.isSelected()); wmsInstruction.setEnabled(!endpoint.isSelected()); formats.setEnabled(!endpoint.isSelected()); wmsUrl.setEnabled(!endpoint.isSelected()); if (endpoint.isSelected()) { URL url = wms.getServiceUrl(); if (url != null) { name.setText(url.getHost()); } } else { onLayerSelectionChanged(); } }); tree.getLayerTree().addPropertyChangeListener("selectedLayers", evt -> onLayerSelectionChanged()); formats.addActionListener(e -> onLayerSelectionChanged()); showBounds.addActionListener(e -> { if (tree.getSelectedLayers().get(0).bounds != null) { SlippyMapBBoxChooser mapPanel = new SlippyMapBBoxChooser(); mapPanel.setBoundingBox(tree.getSelectedLayers().get(0).bounds); JOptionPane.showMessageDialog(null, mapPanel, tr("Show Bounds"), JOptionPane.PLAIN_MESSAGE); } else { JOptionPane.showMessageDialog(null, tr("No bounding box was found for this layer."), tr("WMS Error"), JOptionPane.ERROR_MESSAGE); } }); registerValidableComponent(endpoint); registerValidableComponent(rawUrl); registerValidableComponent(wmsUrl); } protected final void onLayerSelectionChanged() { if (wms.getServiceUrl() != null) { wmsUrl.setText(wms.buildGetMapUrl(tree.getSelectedLayers(), (String) formats.getSelectedItem())); name.setText(wms.getServiceUrl().getHost() + ": " + Utils.join(", ", tree.getSelectedLayers())); } showBounds.setEnabled(tree.getSelectedLayers().size() == 1); } @Override public ImageryInfo getImageryInfo() { final ImageryInfo info; if (endpoint.isSelected()) { info = new ImageryInfo(getImageryName(), getImageryRawUrl()); info.setImageryType(ImageryInfo.ImageryType.WMS_ENDPOINT); } else { info = wms.toImageryInfo(getImageryName(), tree.getSelectedLayers()); info.setUrl(getWmsUrl()); info.setImageryType(ImageryType.WMS); } return info; } protected final String getWmsUrl() { return sanitize(wmsUrl.getText(), ImageryInfo.ImageryType.WMS); } @Override protected boolean isImageryValid() { if (getImageryName().isEmpty()) { return false; } if (endpoint.isSelected()) { return !getImageryRawUrl().isEmpty(); } else { return !getWmsUrl().isEmpty(); } } }