001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.preferences.imagery; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.event.ActionEvent; 007import java.awt.event.ActionListener; 008import java.awt.event.ItemEvent; 009import java.awt.event.ItemListener; 010import java.beans.PropertyChangeEvent; 011import java.beans.PropertyChangeListener; 012import java.io.IOException; 013import java.net.MalformedURLException; 014import java.net.URL; 015 016import javax.swing.DefaultComboBoxModel; 017import javax.swing.JButton; 018import javax.swing.JCheckBox; 019import javax.swing.JComboBox; 020import javax.swing.JLabel; 021import javax.swing.JOptionPane; 022import javax.swing.JScrollPane; 023 024import org.openstreetmap.josm.Main; 025import org.openstreetmap.josm.data.imagery.ImageryInfo; 026import org.openstreetmap.josm.gui.bbox.SlippyMapBBoxChooser; 027import org.openstreetmap.josm.gui.util.GuiHelper; 028import org.openstreetmap.josm.gui.widgets.JosmTextArea; 029import org.openstreetmap.josm.io.imagery.WMSImagery; 030import org.openstreetmap.josm.tools.GBC; 031import org.openstreetmap.josm.tools.Utils; 032 033/** 034 * An imagery panel used to add WMS imagery sources. 035 * @since 2599 036 */ 037public class AddWMSLayerPanel extends AddImageryPanel { 038 039 private final transient WMSImagery wms = new WMSImagery(); 040 private final JCheckBox endpoint = new JCheckBox(tr("Store WMS endpoint only, select layers at usage")); 041 private final transient WMSLayerTree tree = new WMSLayerTree(); 042 private final JComboBox<String> formats = new JComboBox<>(); 043 private final JLabel wmsInstruction; 044 private final JosmTextArea wmsUrl = new JosmTextArea(3, 40); 045 private final JButton showBounds = new JButton(tr("Show bounds")); 046 047 /** 048 * Constructs a new {@code AddWMSLayerPanel}. 049 */ 050 public AddWMSLayerPanel() { 051 052 add(new JLabel(tr("1. Enter service URL")), GBC.eol()); 053 add(rawUrl, GBC.eol().fill()); 054 rawUrl.setLineWrap(true); 055 JButton getLayers = new JButton(tr("Get layers")); 056 add(getLayers, GBC.eop().fill()); 057 058 add(new JLabel(tr("2. Select layers")), GBC.eol()); 059 add(endpoint, GBC.eol().fill()); 060 add(new JScrollPane(tree.getLayerTree()), GBC.eol().fill().weight(1, 100)); 061 062 showBounds.setEnabled(false); 063 add(showBounds, GBC.eop().fill()); 064 065 add(new JLabel(tr("3. Select image format")), GBC.eol()); 066 add(formats, GBC.eol().fill()); 067 068 wmsInstruction = new JLabel(tr("4. Verify generated WMS URL")); 069 add(wmsInstruction, GBC.eol()); 070 wmsInstruction.setLabelFor(wmsUrl); 071 add(wmsUrl, GBC.eop().fill()); 072 wmsUrl.setLineWrap(true); 073 074 add(new JLabel(tr("5. Enter name for this layer")), GBC.eol()); 075 add(name, GBC.eop().fill()); 076 077 getLayers.addActionListener(new ActionListener() { 078 @Override 079 public void actionPerformed(ActionEvent e) { 080 try { 081 wms.attemptGetCapabilities(rawUrl.getText()); 082 tree.updateTree(wms); 083 formats.setModel(new DefaultComboBoxModel<>(wms.getFormats().toArray(new String[0]))); 084 formats.setSelectedItem(wms.getPreferredFormats()); 085 } catch (MalformedURLException ex) { 086 Main.error(ex, false); 087 JOptionPane.showMessageDialog(getParent(), tr("Invalid service URL."), 088 tr("WMS Error"), JOptionPane.ERROR_MESSAGE); 089 } catch (IOException ex) { 090 Main.error(ex, false); 091 JOptionPane.showMessageDialog(getParent(), tr("Could not retrieve WMS layer list."), 092 tr("WMS Error"), JOptionPane.ERROR_MESSAGE); 093 } catch (WMSImagery.WMSGetCapabilitiesException ex) { 094 String incomingData = ex.getIncomingData().trim(); 095 String title = tr("WMS Error"); 096 String message = tr("Could not parse WMS layer list."); 097 Main.error(ex, "Could not parse WMS layer list. Incoming data:\n"+incomingData); 098 if ((incomingData.startsWith("<html>") || incomingData.startsWith("<HTML>")) 099 && (incomingData.endsWith("</html>") || incomingData.endsWith("</HTML>"))) { 100 GuiHelper.notifyUserHtmlError(AddWMSLayerPanel.this, title, message, incomingData); 101 } else { 102 if (ex.getMessage() != null) { 103 message += '\n' + ex.getMessage(); 104 } 105 JOptionPane.showMessageDialog(getParent(), message, title, JOptionPane.ERROR_MESSAGE); 106 } 107 } 108 } 109 }); 110 111 endpoint.addItemListener(new ItemListener() { 112 @Override 113 public void itemStateChanged(ItemEvent e) { 114 tree.getLayerTree().setEnabled(!endpoint.isSelected()); 115 showBounds.setEnabled(!endpoint.isSelected()); 116 wmsInstruction.setEnabled(!endpoint.isSelected()); 117 formats.setEnabled(!endpoint.isSelected()); 118 wmsUrl.setEnabled(!endpoint.isSelected()); 119 if (endpoint.isSelected()) { 120 URL url = wms.getServiceUrl(); 121 if (url != null) { 122 name.setText(url.getHost()); 123 } 124 } else { 125 onLayerSelectionChanged(); 126 } 127 } 128 }); 129 130 tree.getLayerTree().addPropertyChangeListener("selectedLayers", new PropertyChangeListener() { 131 @Override 132 public void propertyChange(PropertyChangeEvent evt) { 133 onLayerSelectionChanged(); 134 } 135 }); 136 137 formats.addActionListener(new ActionListener() { 138 @Override 139 public void actionPerformed(ActionEvent e) { 140 onLayerSelectionChanged(); 141 } 142 }); 143 144 showBounds.addActionListener(new ActionListener() { 145 @Override 146 public void actionPerformed(ActionEvent e) { 147 if (tree.getSelectedLayers().get(0).bounds != null) { 148 SlippyMapBBoxChooser mapPanel = new SlippyMapBBoxChooser(); 149 mapPanel.setBoundingBox(tree.getSelectedLayers().get(0).bounds); 150 JOptionPane.showMessageDialog(null, mapPanel, tr("Show Bounds"), JOptionPane.PLAIN_MESSAGE); 151 } else { 152 JOptionPane.showMessageDialog(null, tr("No bounding box was found for this layer."), 153 tr("WMS Error"), JOptionPane.ERROR_MESSAGE); 154 } 155 } 156 }); 157 158 registerValidableComponent(endpoint); 159 registerValidableComponent(rawUrl); 160 registerValidableComponent(wmsUrl); 161 } 162 163 protected final void onLayerSelectionChanged() { 164 if (wms.getServiceUrl() != null) { 165 wmsUrl.setText(wms.buildGetMapUrl(tree.getSelectedLayers(), (String) formats.getSelectedItem())); 166 name.setText(wms.getServiceUrl().getHost() + ": " + Utils.join(", ", tree.getSelectedLayers())); 167 } 168 showBounds.setEnabled(tree.getSelectedLayers().size() == 1); 169 } 170 171 @Override 172 public ImageryInfo getImageryInfo() { 173 final ImageryInfo info; 174 if (endpoint.isSelected()) { 175 info = new ImageryInfo(getImageryName(), getImageryRawUrl()); 176 info.setImageryType(ImageryInfo.ImageryType.WMS_ENDPOINT); 177 } else { 178 info = wms.toImageryInfo(getImageryName(), tree.getSelectedLayers()); 179 info.setUrl(getWmsUrl()); 180 } 181 return info; 182 } 183 184 protected final String getWmsUrl() { 185 return sanitize(wmsUrl.getText(), ImageryInfo.ImageryType.WMS); 186 } 187 188 @Override 189 protected boolean isImageryValid() { 190 if (getImageryName().isEmpty()) { 191 return false; 192 } 193 if (endpoint.isSelected()) { 194 return !getImageryRawUrl().isEmpty(); 195 } else { 196 return !getWmsUrl().isEmpty(); 197 } 198 } 199}