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