Changeset 11216 in josm


Ignore:
Timestamp:
2016-11-04T09:58:50+01:00 (7 years ago)
Author:
wiktorn
Message:

Move WMTS layer selection out of WMTSLayer constructor and hookUpMapView.

When user declines to choose any WMTSLayer we should just not add the layer at all instead of showing a warning & empty layer content.

This change alignes behaviour of layer between WMTS and WMS_ENDPOINT imagery sources.

This change includes some parts of Work In Progress to unify WMS and WMS_ENDPOINT sources.

Closes: #13868

Location:
trunk/src/org/openstreetmap/josm
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/AddImageryLayerAction.java

    r11181 r11216  
    1111import java.io.IOException;
    1212import java.net.MalformedURLException;
     13import java.util.ArrayList;
     14import java.util.Collection;
    1315import java.util.HashSet;
    1416import java.util.List;
     
    2325import org.openstreetmap.josm.data.imagery.ImageryInfo;
    2426import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType;
     27import org.openstreetmap.josm.data.imagery.WMTSTileSource;
    2528import org.openstreetmap.josm.gui.ExtendedDialog;
    2629import org.openstreetmap.josm.gui.layer.AlignImageryPanel;
     
    3134import org.openstreetmap.josm.io.imagery.WMSImagery.LayerDetails;
    3235import org.openstreetmap.josm.io.imagery.WMSImagery.WMSGetCapabilitiesException;
     36import org.openstreetmap.josm.tools.CheckParameterUtil;
    3337import org.openstreetmap.josm.tools.GBC;
    3438import org.openstreetmap.josm.tools.ImageProvider;
     
    6468    }
    6569
    66     @Override
    67     public void actionPerformed(ActionEvent e) {
    68         if (!isEnabled()) return;
     70    /**
     71     * Converts general ImageryInfo to specific one, that does not need any user action to initialize
     72     * see: https://josm.openstreetmap.de/ticket/13868
     73     * @param info
     74     * @return
     75     */
     76    private ImageryInfo convertImagery(ImageryInfo info) {
    6977        try {
    70             final ImageryInfo infoToAdd = ImageryType.WMS_ENDPOINT.equals(info.getImageryType())
    71                     ? getWMSLayerInfo() : info;
    72             if (infoToAdd != null) {
    73                 Main.getLayerManager().addLayer(ImageryLayer.create(infoToAdd));
    74                 AlignImageryPanel.addNagPanelIfNeeded(infoToAdd);
     78            switch(info.getImageryType()) {
     79            case WMS_ENDPOINT:
     80                // convert to WMS type
     81                return getWMSLayerInfo();
     82            case WMTS:
     83                // specify which layer to use
     84                String layerId = new WMTSTileSource(info).userSelectLayer();
     85                if (layerId != null) {
     86                    ImageryInfo copy = new ImageryInfo(info);
     87                    Collection<String> defaultLayers = new ArrayList<>(1);
     88                    defaultLayers.add(layerId);
     89                    copy.setDefaultLayers(defaultLayers);
     90                    return copy;
     91                }
     92                // layer not selected - refuse to add
     93                return null;
     94            default:
     95                return info;
    7596            }
    76         } catch (IllegalArgumentException ex) {
    77             if (ex.getMessage() == null || ex.getMessage().isEmpty() || GraphicsEnvironment.isHeadless()) {
    78                 throw ex;
    79             } else {
    80                 JOptionPane.showMessageDialog(Main.parent,
    81                         ex.getMessage(), tr("Error"),
    82                         JOptionPane.ERROR_MESSAGE);
    83             }
    84         }
    85     }
    86 
    87     protected ImageryInfo getWMSLayerInfo() {
    88         try {
    89             assert ImageryType.WMS_ENDPOINT.equals(info.getImageryType());
    90             final WMSImagery wms = new WMSImagery();
    91             wms.attemptGetCapabilities(info.getUrl());
    92 
    93             final WMSLayerTree tree = new WMSLayerTree();
    94             tree.updateTree(wms);
    95             List<String> wmsFormats = wms.getFormats();
    96             final JComboBox<String> formats = new JComboBox<>(wmsFormats.toArray(new String[wmsFormats.size()]));
    97             formats.setSelectedItem(wms.getPreferredFormats());
    98             formats.setToolTipText(tr("Select image format for WMS layer"));
    99 
    100             if (!GraphicsEnvironment.isHeadless()) {
    101                 if (1 != new ExtendedDialog(Main.parent, tr("Select WMS layers"), new String[]{tr("Add layers"), tr("Cancel")}) { {
    102                     final JScrollPane scrollPane = new JScrollPane(tree.getLayerTree());
    103                     scrollPane.setPreferredSize(new Dimension(400, 400));
    104                     final JPanel panel = new JPanel(new GridBagLayout());
    105                     panel.add(scrollPane, GBC.eol().fill());
    106                     panel.add(formats, GBC.eol().fill(GBC.HORIZONTAL));
    107                     setContent(panel);
    108                 } }.showDialog().getValue()) {
    109                     return null;
    110                 }
    111             }
    112 
    113             final String url = wms.buildGetMapUrl(
    114                     tree.getSelectedLayers(), (String) formats.getSelectedItem());
    115             Set<String> supportedCrs = new HashSet<>();
    116             boolean first = true;
    117             StringBuilder layersString = new StringBuilder();
    118             for (LayerDetails layer: tree.getSelectedLayers()) {
    119                 if (first) {
    120                     supportedCrs.addAll(layer.getProjections());
    121                     first = false;
    122                 }
    123                 layersString.append(layer.name);
    124                 layersString.append(", ");
    125                 supportedCrs.retainAll(layer.getProjections());
    126             }
    127 
    128             ImageryInfo ret = new ImageryInfo(info.getName(), url, "wms", info.getEulaAcceptanceRequired(), info.getCookies());
    129             if (layersString.length() > 2) {
    130                 ret.setName(ret.getName() + ' ' + layersString.substring(0, layersString.length() - 2));
    131             }
    132             ret.setServerProjections(supportedCrs);
    133             return ret;
    13497        } catch (MalformedURLException ex) {
    13598            if (!GraphicsEnvironment.isHeadless()) {
     
    155118
    156119    @Override
     120    public void actionPerformed(ActionEvent e) {
     121        if (!isEnabled()) return;
     122        try {
     123            final ImageryInfo infoToAdd = convertImagery(info);
     124            if (infoToAdd != null) {
     125                Main.getLayerManager().addLayer(ImageryLayer.create(infoToAdd));
     126                AlignImageryPanel.addNagPanelIfNeeded(infoToAdd);
     127            }
     128        } catch (IllegalArgumentException ex) {
     129            if (ex.getMessage() == null || ex.getMessage().isEmpty() || GraphicsEnvironment.isHeadless()) {
     130                throw ex;
     131            } else {
     132                JOptionPane.showMessageDialog(Main.parent,
     133                        ex.getMessage(), tr("Error"),
     134                        JOptionPane.ERROR_MESSAGE);
     135            }
     136        }
     137    }
     138
     139    protected ImageryInfo getWMSLayerInfo() throws IOException, WMSGetCapabilitiesException {
     140        CheckParameterUtil.ensureThat(ImageryType.WMS_ENDPOINT.equals(info.getImageryType()), "wms_endpoint imagery type expected");
     141
     142        final WMSImagery wms = new WMSImagery();
     143        wms.attemptGetCapabilities(info.getUrl());
     144
     145        final WMSLayerTree tree = new WMSLayerTree();
     146        tree.updateTree(wms);
     147        List<String> wmsFormats = wms.getFormats();
     148        final JComboBox<String> formats = new JComboBox<>(wmsFormats.toArray(new String[wmsFormats.size()]));
     149        formats.setSelectedItem(wms.getPreferredFormats());
     150        formats.setToolTipText(tr("Select image format for WMS layer"));
     151
     152        if (!GraphicsEnvironment.isHeadless()) {
     153            if (1 != new ExtendedDialog(Main.parent, tr("Select WMS layers"), new String[]{tr("Add layers"), tr("Cancel")}) { {
     154                final JScrollPane scrollPane = new JScrollPane(tree.getLayerTree());
     155                scrollPane.setPreferredSize(new Dimension(400, 400));
     156                final JPanel panel = new JPanel(new GridBagLayout());
     157                panel.add(scrollPane, GBC.eol().fill());
     158                panel.add(formats, GBC.eol().fill(GBC.HORIZONTAL));
     159                setContent(panel);
     160            } }.showDialog().getValue()) {
     161                return null;
     162            }
     163        }
     164
     165        final String url = wms.buildGetMapUrl(
     166                tree.getSelectedLayers(), (String) formats.getSelectedItem());
     167        Set<String> supportedCrs = new HashSet<>();
     168        boolean first = true;
     169        StringBuilder layersString = new StringBuilder();
     170        for (LayerDetails layer: tree.getSelectedLayers()) {
     171            if (first) {
     172                supportedCrs.addAll(layer.getProjections());
     173                first = false;
     174            }
     175            layersString.append(layer.name);
     176            layersString.append(", ");
     177            supportedCrs.retainAll(layer.getProjections());
     178        }
     179
     180        ImageryInfo ret = new ImageryInfo(info.getName(), url, "wms", info.getEulaAcceptanceRequired(), info.getCookies());
     181        if (layersString.length() > 2) {
     182            ret.setName(ret.getName() + ' ' + layersString.substring(0, layersString.length() - 2));
     183        }
     184        ret.setServerProjections(supportedCrs);
     185        return ret;
     186    }
     187
     188    @Override
    157189    protected void updateEnabledState() {
    158190        if (info.isBlacklisted()) {
  • trunk/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java

    r10735 r11216  
    1717import java.util.regex.Matcher;
    1818import java.util.regex.Pattern;
     19import java.util.stream.Collectors;
    1920
    2021import javax.swing.ImageIcon;
     
    193194    private boolean isGeoreferenceValid;
    194195    private boolean isEpsg4326To3857Supported;
     196    /** which layers should be activated by default on layer addition. **/
     197    private Collection<String> defaultLayers = Collections.emptyList();
    195198    // when adding a field, also adapt the ImageryInfo(ImageryInfo)
    196199    // and ImageryInfo(ImageryPreferenceEntry) constructor, equals method, and ImageryPreferenceEntry
     
    227230        @pref boolean valid_georeference;
    228231        @pref boolean supports_epsg_4326_to_3857_conversion;
     232        // TODO: disabled until change of layers is implemented
     233        // @pref String default_layers;
    229234
    230235        /**
     
    271276                }
    272277            }
    273             if (!i.serverProjections.isEmpty()) {
    274                 StringBuilder val = new StringBuilder();
    275                 for (String p : i.serverProjections) {
    276                     if (val.length() > 0) {
    277                         val.append(',');
    278                     }
    279                     val.append(p);
    280                 }
    281                 projections = val.toString();
    282             }
     278            projections = i.serverProjections.stream().collect(Collectors.joining(","));
    283279            if (i.noTileHeaders != null && !i.noTileHeaders.isEmpty()) {
    284280                noTileHeaders = new MultiMap<>(i.noTileHeaders);
     
    297293            valid_georeference = i.isGeoreferenceValid();
    298294            supports_epsg_4326_to_3857_conversion = i.isEpsg4326To3857Supported();
     295            // TODO disabled until change of layers is implemented
     296            // default_layers = i.defaultLayers.stream().collect(Collectors.joining(","));
    299297        }
    300298
     
    423421        isEpsg4326To3857Supported = e.supports_epsg_4326_to_3857_conversion;
    424422        isGeoreferenceValid = e.valid_georeference;
     423        // TODO disabled until change of layers is implemented
     424        // defaultLayers = Arrays.asList(e.default_layers.split(","));
    425425    }
    426426
     
    454454        this.isEpsg4326To3857Supported = i.isEpsg4326To3857Supported;
    455455        this.isGeoreferenceValid = i.isGeoreferenceValid;
     456        this.defaultLayers = i.defaultLayers;
    456457    }
    457458
     
    497498                Objects.equals(this.noTileHeaders, other.noTileHeaders) &&
    498499                Objects.equals(this.noTileChecksums, other.noTileChecksums) &&
    499                 Objects.equals(this.metadataHeaders, other.metadataHeaders);
     500                Objects.equals(this.metadataHeaders, other.metadataHeaders) &&
     501                Objects.equals(this.defaultLayers, other.defaultLayers);
    500502    }
    501503
     
    11471149       return l;
    11481150    }
     1151
     1152    /**
     1153     * Returns default layers that should be shown for this Imagery (if at all supported by imagery provider)
     1154     * If no layer is set to default and there is more than one imagery available, then user will be asked to choose the layer
     1155     * to work on
     1156     * @return Collection of the layer names
     1157     */
     1158    public Collection<String> getDefaultLayers() {
     1159        return defaultLayers;
     1160    }
     1161
     1162    /**
     1163     * Sets the default layers that user will work with
     1164     * @param layers
     1165     */
     1166    public void setDefaultLayers(Collection<String> layers) {
     1167        this.defaultLayers = layers;
     1168    }
    11491169}
  • trunk/src/org/openstreetmap/josm/data/imagery/WMTSTileSource.java

    r11189 r11216  
    1616import java.util.List;
    1717import java.util.Map;
     18import java.util.Map.Entry;
    1819import java.util.Set;
    1920import java.util.SortedSet;
     
    2324import java.util.regex.Matcher;
    2425import java.util.regex.Pattern;
     26import java.util.stream.Collectors;
    2527
    2628import javax.swing.JPanel;
     
    159161
    160162    private static final class SelectLayerDialog extends ExtendedDialog {
    161         private final transient Layer[] layers;
     163        private final transient List<Entry<String,List<Layer>>> layers;
    162164        private final JTable list;
    163165
    164166        SelectLayerDialog(Collection<Layer> layers) {
    165167            super(Main.parent, tr("Select WMTS layer"), new String[]{tr("Add layers"), tr("Cancel")});
    166             this.layers = layers.toArray(new Layer[layers.size()]);
     168            this.layers = groupLayersByName(layers);
    167169            //getLayersTable(layers, Main.getProjection())
    168170            this.list = new JTable(
     
    172174                            switch (columnIndex) {
    173175                            case 0:
    174                                 return SelectLayerDialog.this.layers[rowIndex].name;
     176                                return SelectLayerDialog.this.layers.get(rowIndex).getKey();
    175177                            case 1:
    176                                 return SelectLayerDialog.this.layers[rowIndex].tileMatrixSet.crs;
     178                                return SelectLayerDialog.this.layers.get(rowIndex).getValue()
     179                                        .stream()
     180                                        .map(x -> x.tileMatrixSet.crs)
     181                                        .collect(Collectors.joining(", "));
    177182                            case 2:
    178                                 return SelectLayerDialog.this.layers[rowIndex].tileMatrixSet.identifier;
     183                                return SelectLayerDialog.this.layers.get(rowIndex).getValue()
     184                                        .stream()
     185                                        .map(x -> x.tileMatrixSet.identifier)
     186                                        .collect(Collectors.joining(", "));
    179187                            default:
    180188                                throw new IllegalArgumentException();
     
    184192                        @Override
    185193                        public int getRowCount() {
    186                             return SelectLayerDialog.this.layers.length;
     194                            return SelectLayerDialog.this.layers.size();
    187195                        }
    188196
     
    216224        }
    217225
    218         public Layer getSelectedLayer() {
     226        private List<Entry<String, List<Layer>>> groupLayersByName(Collection<Layer> layers) {
     227            Map<String, List<Layer>> layerByName = layers.stream().collect(Collectors.groupingBy(x -> x.name));
     228            return layerByName.entrySet().stream().sorted(Map.Entry.comparingByKey()).collect(Collectors.toList());
     229        }
     230
     231        public String getSelectedLayer() {
    219232            int index = list.getSelectedRow();
    220233            if (index < 0) {
    221234                return null; //nothing selected
    222235            }
    223             return layers[index];
     236            return layers.get(index).getKey();
    224237        }
    225238    }
     
    234247    private ScaleList nativeScaleList;
    235248
     249    private String defaultLayer;
     250
    236251    /**
    237252     * Creates a tile source based on imagery info
     
    242257    public WMTSTileSource(ImageryInfo info) throws IOException {
    243258        super(info);
     259        CheckParameterUtil.ensureThat(info.getDefaultLayers().size() < 2, "At most 1 default layer for WMTS is supported");
     260
    244261        this.baseUrl = GetCapabilitiesParseHelper.normalizeCapabilitiesUrl(handleTemplate(info.getUrl()));
    245262        this.layers = getCapabilities();
     263        this.defaultLayer = info.getDefaultLayers().isEmpty() ? null : info.getDefaultLayers().iterator().next();
    246264        if (this.layers.isEmpty())
    247265            throw new IllegalArgumentException(tr("No layers defined by getCapabilities document: {0}", info.getUrl()));
    248266    }
    249267
    250     private static Layer userSelectLayer(Collection<Layer> layers) {
    251         if (layers.size() == 1)
    252             return layers.iterator().next();
    253         Layer ret = null;
     268    /**
     269     * Creates a dialog based on this tile source with all available layers and returns the name of selected layer
     270     * @return Name of selected layer
     271     */
     272    public String userSelectLayer() {
     273        Collection<String> layerNames = layers.stream().map(x -> x.name).collect(Collectors.toSet());
     274
     275        // if there is only one layer name no point in asking
     276        if (layerNames.size() == 1)
     277            return layerNames.iterator().next();
    254278
    255279        final SelectLayerDialog layerSelection = new SelectLayerDialog(layers);
    256280        if (layerSelection.showDialog().getValue() == 1) {
    257             ret = layerSelection.getSelectedLayer();
    258             // TODO: save layer information into ImageryInfo / ImageryPreferences?
    259         }
    260         if (ret == null) {
    261             // user canceled operation or did not choose any layer
    262             throw new IllegalArgumentException(tr("No layer selected"));
    263         }
    264         return ret;
     281            return layerSelection.getSelectedLayer();
     282        }
     283        return null;
    265284    }
    266285
     
    536555        // getLayers will return only layers matching the name, if the user already choose the layer
    537556        // so we will not ask the user again to chose the layer, if he just changes projection
    538         Collection<Layer> candidates = getLayers(currentLayer != null ? currentLayer.name : null, proj.toCode());
    539         if (!candidates.isEmpty()) {
    540             Layer newLayer = userSelectLayer(candidates);
     557        Collection<Layer> candidates = getLayers(currentLayer != null ? currentLayer.name : defaultLayer, proj.toCode());
     558        if (candidates.size() == 1) {
     559
     560            Layer newLayer = candidates.iterator().next();
    541561            if (newLayer != null) {
    542562                this.currentTileMatrixSet = newLayer.tileMatrixSet;
     
    548568                this.nativeScaleList = new ScaleList(scales);
    549569            }
     570        } else if (candidates.size() > 1) {
     571            Main.warn("More than one layer WMTS available: {0} for projection {1} and name {2}. Do not know which to process",
     572                    candidates.stream().map(x -> x.name + ": " + x.tileMatrixSet.identifier).collect(Collectors.joining(", ")),
     573                    proj.toCode(),
     574                    currentLayer != null ? currentLayer.name : defaultLayer
     575                    );
    550576        }
    551577        this.crsScale = getTileSize() * 0.28e-03 / proj.getMetersPerUnit();
Note: See TracChangeset for help on using the changeset viewer.