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 022public class WMSLayerTree { 023 private final MutableTreeNode treeRootNode = new DefaultMutableTreeNode(); 024 private final DefaultTreeModel treeData = new DefaultTreeModel(treeRootNode); 025 private final JTree layerTree = new JTree(treeData); 026 private final List<WMSImagery.LayerDetails> selectedLayers = new LinkedList<WMSImagery.LayerDetails>(); 027 private boolean previouslyShownUnsupportedCrsError = false; 028 029 public MutableTreeNode getTreeRootNode() { 030 return treeRootNode; 031 } 032 033 public JTree getLayerTree() { 034 return layerTree; 035 } 036 037 public List<WMSImagery.LayerDetails> getSelectedLayers() { 038 return selectedLayers; 039 } 040 041 /** 042 * Constructs a new {@code WMSLayerTree}. 043 */ 044 public WMSLayerTree() { 045 layerTree.setCellRenderer(new LayerTreeCellRenderer()); 046 layerTree.addTreeSelectionListener(new WMSTreeSelectionListener()); 047 } 048 049 void addLayersToTreeData(MutableTreeNode parent, List<WMSImagery.LayerDetails> layers) { 050 for (WMSImagery.LayerDetails layerDetails : layers) { 051 DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(layerDetails); 052 addLayersToTreeData(treeNode, layerDetails.children); 053 treeData.insertNodeInto(treeNode, parent, 0); 054 } 055 } 056 057 public void updateTree(WMSImagery wms) { 058 treeRootNode.setUserObject(wms.getServiceUrl().getHost()); 059 updateTreeList(wms.getLayers()); 060 } 061 062 public void updateTreeList(List<WMSImagery.LayerDetails> layers) { 063 addLayersToTreeData(getTreeRootNode(), layers); 064 getLayerTree().expandRow(0); 065 getLayerTree().expandRow(1); 066 } 067 068 private static class LayerTreeCellRenderer extends DefaultTreeCellRenderer { 069 @Override 070 public Component getTreeCellRendererComponent(JTree tree, Object value, 071 boolean sel, boolean expanded, boolean leaf, int row, 072 boolean hasFocus) { 073 super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, 074 row, hasFocus); 075 DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value; 076 Object userObject = treeNode.getUserObject(); 077 if (userObject instanceof WMSImagery.LayerDetails) { 078 WMSImagery.LayerDetails layer = (WMSImagery.LayerDetails) userObject; 079 setEnabled(layer.isSupported()); 080 } 081 return this; 082 } 083 } 084 085 private class WMSTreeSelectionListener implements TreeSelectionListener { 086 087 @Override 088 public void valueChanged(TreeSelectionEvent e) { 089 TreePath[] selectionRows = layerTree.getSelectionPaths(); 090 if (selectionRows == null) { 091 return; 092 } 093 094 selectedLayers.clear(); 095 for (TreePath i : selectionRows) { 096 Object userObject = ((DefaultMutableTreeNode) i.getLastPathComponent()).getUserObject(); 097 if (userObject instanceof WMSImagery.LayerDetails) { 098 WMSImagery.LayerDetails detail = (WMSImagery.LayerDetails) userObject; 099 if (!detail.isSupported()) { 100 layerTree.removeSelectionPath(i); 101 if (!previouslyShownUnsupportedCrsError) { 102 JOptionPane.showMessageDialog(null, tr("That layer does not support any of JOSM''s projections,\n" + 103 "so you can not use it. This message will not show again."), 104 tr("WMS Error"), JOptionPane.ERROR_MESSAGE); 105 previouslyShownUnsupportedCrsError = true; 106 } 107 } else if (detail.ident != null) { 108 selectedLayers.add(detail); 109 } 110 } 111 } 112 layerTree.firePropertyChange("selectedLayers", /*dummy values*/ false , true); 113 } 114 } 115}