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.Component; 007import java.util.LinkedList; 008import java.util.List; 009 010import javax.swing.JOptionPane; 011import javax.swing.JTree; 012import javax.swing.event.TreeSelectionEvent; 013import javax.swing.event.TreeSelectionListener; 014import javax.swing.tree.DefaultMutableTreeNode; 015import javax.swing.tree.DefaultTreeCellRenderer; 016import javax.swing.tree.DefaultTreeModel; 017import javax.swing.tree.MutableTreeNode; 018import javax.swing.tree.TreePath; 019 020import org.openstreetmap.josm.io.imagery.WMSImagery; 021 022/** 023 * The layer tree of a WMS server. 024 */ 025public class WMSLayerTree { 026 private final MutableTreeNode treeRootNode = new DefaultMutableTreeNode(); 027 private final DefaultTreeModel treeData = new DefaultTreeModel(treeRootNode); 028 private final JTree layerTree = new JTree(treeData); 029 private final List<WMSImagery.LayerDetails> selectedLayers = new LinkedList<>(); 030 private boolean previouslyShownUnsupportedCrsError = false; 031 032 /** 033 * Returns the root node. 034 * @return The root node 035 */ 036 public MutableTreeNode getTreeRootNode() { 037 return treeRootNode; 038 } 039 040 /** 041 * Returns the {@code JTree}. 042 * @return The {@code JTree} 043 */ 044 public JTree getLayerTree() { 045 return layerTree; 046 } 047 048 /** 049 * Returns the list of selected layers. 050 * @return the list of selected layers 051 */ 052 public List<WMSImagery.LayerDetails> getSelectedLayers() { 053 return selectedLayers; 054 } 055 056 /** 057 * Constructs a new {@code WMSLayerTree}. 058 */ 059 public WMSLayerTree() { 060 layerTree.setCellRenderer(new LayerTreeCellRenderer()); 061 layerTree.addTreeSelectionListener(new WMSTreeSelectionListener()); 062 } 063 064 void addLayersToTreeData(MutableTreeNode parent, List<WMSImagery.LayerDetails> layers) { 065 for (WMSImagery.LayerDetails layerDetails : layers) { 066 DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(layerDetails); 067 addLayersToTreeData(treeNode, layerDetails.children); 068 treeData.insertNodeInto(treeNode, parent, 0); 069 } 070 } 071 072 /** 073 * Updates the whole tree with the given WMS imagery info. 074 * @param wms The imagery info for a given WMS server 075 */ 076 public void updateTree(WMSImagery wms) { 077 treeRootNode.setUserObject(wms.getServiceUrl().getHost()); 078 updateTreeList(wms.getLayers()); 079 } 080 081 /** 082 * Updates the list of WMS layers. 083 * @param layers The list of layers to add to the root node 084 */ 085 public void updateTreeList(List<WMSImagery.LayerDetails> layers) { 086 addLayersToTreeData(getTreeRootNode(), layers); 087 getLayerTree().expandRow(0); 088 getLayerTree().expandRow(1); 089 } 090 091 private static class LayerTreeCellRenderer extends DefaultTreeCellRenderer { 092 @Override 093 public Component getTreeCellRendererComponent(JTree tree, Object value, 094 boolean sel, boolean expanded, boolean leaf, int row, 095 boolean hasFocus) { 096 super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, 097 row, hasFocus); 098 DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value; 099 Object userObject = treeNode.getUserObject(); 100 if (userObject instanceof WMSImagery.LayerDetails) { 101 WMSImagery.LayerDetails layer = (WMSImagery.LayerDetails) userObject; 102 setEnabled(layer.isSupported()); 103 } 104 return this; 105 } 106 } 107 108 private class WMSTreeSelectionListener implements TreeSelectionListener { 109 110 @Override 111 public void valueChanged(TreeSelectionEvent e) { 112 TreePath[] selectionRows = layerTree.getSelectionPaths(); 113 if (selectionRows == null) { 114 return; 115 } 116 117 selectedLayers.clear(); 118 for (TreePath i : selectionRows) { 119 Object userObject = ((DefaultMutableTreeNode) i.getLastPathComponent()).getUserObject(); 120 if (userObject instanceof WMSImagery.LayerDetails) { 121 WMSImagery.LayerDetails detail = (WMSImagery.LayerDetails) userObject; 122 if (!detail.isSupported()) { 123 layerTree.removeSelectionPath(i); 124 if (!previouslyShownUnsupportedCrsError) { 125 JOptionPane.showMessageDialog(null, tr("That layer does not support any of JOSM''s projections,\n" + 126 "so you can not use it. This message will not show again."), 127 tr("WMS Error"), JOptionPane.ERROR_MESSAGE); 128 previouslyShownUnsupportedCrsError = true; 129 } 130 } else if (detail.ident != null) { 131 selectedLayers.add(detail); 132 } 133 } 134 } 135 layerTree.firePropertyChange("selectedLayers", /*dummy values*/ false , true); 136 } 137 } 138}