Ignore:
Timestamp:
2015-09-13T00:06:23+02:00 (9 years ago)
Author:
wiktorn
Message:

Support situations, where WMTS service provides more than one tile set for one projection.

Closes: #10623

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/imagery/WMTSTileSource.java

    r8674 r8752  
    1515import java.util.Collection;
    1616import java.util.Comparator;
     17import java.util.HashSet;
    1718import java.util.Map;
    1819import java.util.Set;
     
    2324import java.util.regex.Pattern;
    2425
    25 import javax.swing.JList;
    2626import javax.swing.JPanel;
     27import javax.swing.JTable;
    2728import javax.swing.ListSelectionModel;
     29import javax.swing.table.AbstractTableModel;
    2830import javax.xml.XMLConstants;
    2931import javax.xml.namespace.QName;
     
    98100        private String format;
    99101        private String name;
    100         private Map<String, TileMatrixSet> tileMatrixSetByCRS = new ConcurrentHashMap<>();
     102        private TileMatrixSet tileMatrixSet;
    101103        private String baseUrl;
    102104        private String style;
     
    129131    private static final class SelectLayerDialog extends ExtendedDialog {
    130132        private final Layer[] layers;
    131         private final JList<String> list;
     133        private final JTable list;
    132134
    133135        public SelectLayerDialog(Collection<Layer> layers) {
    134136            super(Main.parent, tr("Select WMTS layer"), new String[]{tr("Add layers"), tr("Cancel")});
    135137            this.layers = layers.toArray(new Layer[]{});
    136             this.list = new JList<>(getLayerNames(layers));
     138            //getLayersTable(layers, Main.getProjection())
     139            this.list = new JTable(
     140                    new AbstractTableModel() {
     141                        @Override
     142                        public Object getValueAt(int rowIndex, int columnIndex) {
     143                            switch (columnIndex) {
     144                            case 0:
     145                                return SelectLayerDialog.this.layers[rowIndex].name;
     146                            case 1:
     147                                return SelectLayerDialog.this.layers[rowIndex].tileMatrixSet.crs;
     148                            case 2:
     149                                return SelectLayerDialog.this.layers[rowIndex].tileMatrixSet.identifier;
     150                            default:
     151                                throw new IllegalArgumentException();
     152                            }
     153                        }
     154
     155                        @Override
     156                        public int getRowCount() {
     157                            return SelectLayerDialog.this.layers.length;
     158                        }
     159
     160                        @Override
     161                        public int getColumnCount() {
     162                            return 3;
     163                        }
     164                        @Override
     165                        public String getColumnName(int column) {
     166                            switch (column) {
     167                            case 0: return tr("Layer name");
     168                            case 1: return tr("Projection");
     169                            case 2: return tr("Matrix set identifier");
     170                            default:
     171                                throw new IllegalArgumentException();
     172                            }
     173                        }
     174                        @Override
     175                        public boolean isCellEditable(int row, int column) { return false; }
     176                    });
    137177            this.list.setPreferredSize(new Dimension(400, 400));
    138178            this.list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
     179            this.list.setRowSelectionAllowed(true);
     180            this.list.setColumnSelectionAllowed(false);
    139181            JPanel panel = new JPanel(new GridBagLayout());
    140182            panel.add(this.list, GBC.eol().fill());
     
    142184        }
    143185
    144         private static String[] getLayerNames(Collection<Layer> layers) {
    145             Collection<String> ret = new ArrayList<>();
    146             for (Layer layer: layers) {
    147                 ret.add(layer.name);
    148             }
    149             return ret.toArray(new String[]{});
    150         }
    151 
    152186        public Layer getSelectedLayer() {
    153             int index = list.getSelectedIndex();
     187            int index = list.getSelectedRow();
    154188            if (index < 0) {
    155189                return null; //nothing selected
     
    175209        this.baseUrl = normalizeCapabilitiesUrl(handleTemplate(info.getUrl()));
    176210        this.layers = getCapabilities();
    177         if (layers.size() > 1) {
    178             final SelectLayerDialog layerSelection = new SelectLayerDialog(layers);
    179             if (layerSelection.showDialog().getValue() == 1) {
    180                 this.currentLayer = layerSelection.getSelectedLayer();
    181                 // TODO: save layer information into ImageryInfo / ImageryPreferences?
    182             }
    183 
    184             if (this.currentLayer == null) {
    185                 // user canceled operation or did not choose any layer
    186                 throw new IllegalArgumentException(tr("No layer selected"));
    187             }
    188 
    189         } else if (layers.size() == 1) {
    190             this.currentLayer = this.layers.iterator().next();
    191         } else {
     211        if (this.layers.isEmpty())
    192212            throw new IllegalArgumentException(tr("No layers defined by getCapabilities document: {0}", info.getUrl()));
    193         }
    194 
    195         initProjection();
     213
     214        // Not needed ? initProjection();
     215    }
     216
     217    private Layer userSelectLayer(Collection<Layer> layers) {
     218        if (layers.size() == 1)
     219            return layers.iterator().next();
     220        Layer ret = null;
     221
     222        final SelectLayerDialog layerSelection = new SelectLayerDialog(layers);
     223        if (layerSelection.showDialog().getValue() == 1) {
     224            ret = layerSelection.getSelectedLayer();
     225            // TODO: save layer information into ImageryInfo / ImageryPreferences?
     226        }
     227        if (ret == null) {
     228            // user canceled operation or did not choose any layer
     229            throw new IllegalArgumentException(tr("No layer selected"));
     230        }
     231        return ret;
    196232    }
    197233
     
    239275            Map<String, TileMatrixSet> matrixSetById = parseMatrices(getByXpath(document, "/Capabilities/Contents/TileMatrixSet"));
    240276            return parseLayer(layersNodeList, matrixSetById);
    241 
    242277        } catch (Exception e) {
    243278            throw new IllegalArgumentException(e);
     
    255290        for (int layerId = 0; layerId < nodeList.getLength(); layerId++) {
    256291            Node layerNode = nodeList.item(layerId);
    257             Layer layer = new Layer();
    258             layer.format = getStringByXpath(layerNode, "Format");
    259             layer.name = getStringByXpath(layerNode, "Identifier");
    260             layer.baseUrl = getStringByXpath(layerNode, "ResourceURL[@resourceType='tile']/@template");
    261             layer.style = getStringByXpath(layerNode, "Style[@isDefault='true']/Identifier");
    262             if (layer.style == null) {
    263                 layer.style = "";
    264             }
    265292            NodeList tileMatrixSetLinks = getByXpath(layerNode, "TileMatrixSetLink");
     293
     294            // we add an layer for all matrix sets to allow user to choose, with which tileset he wants to work
    266295            for (int tileMatrixId = 0; tileMatrixId < tileMatrixSetLinks.getLength(); tileMatrixId++) {
     296                Layer layer = new Layer();
     297                layer.format = getStringByXpath(layerNode, "Format");
     298                layer.name = getStringByXpath(layerNode, "Identifier");
     299                layer.baseUrl = getStringByXpath(layerNode, "ResourceURL[@resourceType='tile']/@template");
     300                layer.style = getStringByXpath(layerNode, "Style[@isDefault='true']/Identifier");
     301                if (layer.style == null) {
     302                    layer.style = "";
     303                }
    267304                Node tileMatrixLink = tileMatrixSetLinks.item(tileMatrixId);
    268305                TileMatrixSet tms = matrixSetById.get(getStringByXpath(tileMatrixLink, "TileMatrixSet"));
    269                 layer.tileMatrixSetByCRS.put(tms.crs, tms);
    270             }
    271             ret.add(layer);
     306                layer.tileMatrixSet = tms;
     307                ret.add(layer);
     308            }
    272309        }
    273310        return ret;
     
    357394     */
    358395    public void initProjection(Projection proj) {
    359         this.currentTileMatrixSet = currentLayer.tileMatrixSetByCRS.get(proj.toCode());
    360         if (this.currentTileMatrixSet == null) {
    361             Main.warn("Unsupported CRS selected");
    362             // take first, maybe it will work (if user sets custom projections, codes will not match)
    363             this.currentTileMatrixSet = currentLayer.tileMatrixSetByCRS.values().iterator().next();
    364         }
     396        String layerName = null;
     397        if (currentLayer != null) {
     398            layerName = currentLayer.name;
     399        }
     400        Collection<Layer> candidates = getLayers(layerName, proj.toCode());
     401        if (!candidates.isEmpty()) {
     402            Layer newLayer = userSelectLayer(candidates);
     403            if (newLayer != null) {
     404                this.currentTileMatrixSet = newLayer.tileMatrixSet;
     405                this.currentLayer = newLayer;
     406            }
     407        }
     408
    365409        this.crsScale = getTileSize() * 0.28e-03 / proj.getMetersPerUnit();
     410    }
     411
     412    private Collection<Layer> getLayers(String name, String projectionCode) {
     413        Collection<Layer> ret = new ArrayList<>();
     414        for (Layer layer: this.layers) {
     415            if ((name == null || name.equals(layer.name)) && (projectionCode == null || projectionCode.equals(layer.tileMatrixSet.crs))) {
     416                ret.add(layer);
     417            }
     418        }
     419        return ret;
    366420    }
    367421
     
    385439    public String getTileUrl(int zoom, int tilex, int tiley) {
    386440        String url;
     441        if (currentLayer == null) {
     442            return "";
     443        }
     444
    387445        switch (transferMode) {
    388446        case KVP:
     
    619677     */
    620678    public Set<String> getSupportedProjections() {
    621         return this.currentLayer.tileMatrixSetByCRS.keySet();
     679        Set<String> ret = new HashSet<>();
     680        if (currentLayer == null) {
     681            for(Layer layer: this.layers) {
     682                ret.add(layer.tileMatrixSet.crs);
     683            }
     684        } else {
     685            for(Layer layer: this.layers) {
     686                if (currentLayer.name.equals(layer.name)) {
     687                    ret.add(layer.tileMatrixSet.crs);
     688                }
     689            }
     690        }
     691        return ret;
    622692    }
    623693
Note: See TracChangeset for help on using the changeset viewer.