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 JOptionPane.showMessageDialog(getParent(), tr("Invalid service URL."), 087 tr("WMS Error"), JOptionPane.ERROR_MESSAGE); 088 } catch (IOException ex) { 089 JOptionPane.showMessageDialog(getParent(), tr("Could not retrieve WMS layer list."), 090 tr("WMS Error"), JOptionPane.ERROR_MESSAGE); 091 } catch (WMSImagery.WMSGetCapabilitiesException ex) { 092 String incomingData = ex.getIncomingData().trim(); 093 String title = tr("WMS Error"); 094 String message = tr("Could not parse WMS layer list."); 095 Main.error("Could not parse WMS layer list. Incoming data:\n"+incomingData); 096 if (incomingData != null 097 && (incomingData.startsWith("<html>") || incomingData.startsWith("<HTML>")) 098 && (incomingData.endsWith("</html>") || incomingData.endsWith("</HTML>"))) { 099 GuiHelper.notifyUserHtmlError(AddWMSLayerPanel.this, title, message, incomingData); 100 } else { 101 JOptionPane.showMessageDialog(getParent(), message, title, JOptionPane.ERROR_MESSAGE); 102 } 103 } 104 } 105 }); 106 107 endpoint.addItemListener(new ItemListener() { 108 @Override 109 public void itemStateChanged(ItemEvent e) { 110 tree.getLayerTree().setEnabled(!endpoint.isSelected()); 111 showBounds.setEnabled(!endpoint.isSelected()); 112 wmsInstruction.setEnabled(!endpoint.isSelected()); 113 formats.setEnabled(!endpoint.isSelected()); 114 wmsUrl.setEnabled(!endpoint.isSelected()); 115 if (endpoint.isSelected()) { 116 URL url = wms.getServiceUrl(); 117 if (url != null) { 118 name.setText(url.getHost()); 119 } 120 } else { 121 onLayerSelectionChanged(); 122 } 123 } 124 }); 125 126 tree.getLayerTree().addPropertyChangeListener("selectedLayers", new PropertyChangeListener() { 127 @Override 128 public void propertyChange(PropertyChangeEvent evt) { 129 onLayerSelectionChanged(); 130 } 131 }); 132 133 formats.addActionListener(new ActionListener() { 134 @Override 135 public void actionPerformed(ActionEvent e) { 136 onLayerSelectionChanged(); 137 } 138 }); 139 140 showBounds.addActionListener(new ActionListener() { 141 @Override 142 public void actionPerformed(ActionEvent e) { 143 if (tree.getSelectedLayers().get(0).bounds != null) { 144 SlippyMapBBoxChooser mapPanel = new SlippyMapBBoxChooser(); 145 mapPanel.setBoundingBox(tree.getSelectedLayers().get(0).bounds); 146 JOptionPane.showMessageDialog(null, mapPanel, tr("Show Bounds"), JOptionPane.PLAIN_MESSAGE); 147 } else { 148 JOptionPane.showMessageDialog(null, tr("No bounding box was found for this layer."), 149 tr("WMS Error"), JOptionPane.ERROR_MESSAGE); 150 } 151 } 152 }); 153 154 registerValidableComponent(endpoint); 155 registerValidableComponent(rawUrl); 156 registerValidableComponent(wmsUrl); 157 } 158 159 protected final void onLayerSelectionChanged() { 160 if (wms.getServiceUrl() != null) { 161 wmsUrl.setText(wms.buildGetMapUrl(tree.getSelectedLayers(), (String) formats.getSelectedItem())); 162 name.setText(wms.getServiceUrl().getHost() + ": " + Utils.join(", ", tree.getSelectedLayers())); 163 } 164 showBounds.setEnabled(tree.getSelectedLayers().size() == 1); 165 } 166 167 @Override 168 public ImageryInfo getImageryInfo() { 169 final ImageryInfo info; 170 if (endpoint.isSelected()) { 171 info = new ImageryInfo(getImageryName(), getImageryRawUrl()); 172 info.setImageryType(ImageryInfo.ImageryType.WMS_ENDPOINT); 173 } else { 174 info = wms.toImageryInfo(getImageryName(), tree.getSelectedLayers()); 175 info.setUrl(getWmsUrl()); 176 } 177 return info; 178 } 179 180 protected final String getWmsUrl() { 181 return sanitize(wmsUrl.getText(), ImageryInfo.ImageryType.WMS); 182 } 183 184 @Override 185 protected boolean isImageryValid() { 186 if (getImageryName().isEmpty()) { 187 return false; 188 } 189 if (endpoint.isSelected()) { 190 return !getImageryRawUrl().isEmpty(); 191 } else { 192 return !getWmsUrl().isEmpty(); 193 } 194 } 195}