Updated to worldwind release 20070817
[worldwind-tracker.git] / gov / nasa / worldwind / examples / WMSLayersPanel.java
blob0324477dc7965a1017391e70bfcd60293625ed69
1 /*
2 Copyright (C) 2001, 2006 United States Government
3 as represented by the Administrator of the
4 National Aeronautics and Space Administration.
5 All Rights Reserved.
6 */
7 package gov.nasa.worldwind.examples;
9 import gov.nasa.worldwind.WorldWindow;
10 import gov.nasa.worldwind.avlist.*;
11 import gov.nasa.worldwind.layers.*;
12 import gov.nasa.worldwind.wms.*;
13 import org.w3c.dom.*;
15 import javax.swing.*;
16 import javax.swing.border.*;
17 import javax.xml.parsers.*;
18 import java.awt.*;
19 import java.awt.event.*;
20 import java.net.*;
22 /**
23 * @author tag
24 * @version $Id: WMSLayersPanel.java 2471 2007-07-31 21:50:57Z tgaskins $
26 public class WMSLayersPanel extends JPanel
28 private final WorldWindow wwd;
29 private final URI serverURI;
30 private final Dimension size;
31 private final LayerList layerList = new LayerList();
32 private final Thread loadingThread;
33 private Capabilities caps;
35 public WMSLayersPanel(WorldWindow wwd, String server, Dimension size) throws URISyntaxException
37 super(new BorderLayout());
39 // See if the server name is a valid URI. Throw an exception if not.
40 this.serverURI = new URI(server.trim()); // throws an exception if server name is not a valid uri.
42 this.wwd = wwd;
43 this.size = size;
44 this.setPreferredSize(this.size);
46 this.makeProgressPanel();
48 // Thread off a retrieval of the server's capabilities document and update of this panel.
49 this.loadingThread = new Thread(new Runnable()
51 public void run()
53 load();
55 });
56 this.loadingThread.start();
59 private void load()
61 try
63 // Retrieve the server's capabilities document and parse it into a DOM.
64 // Set up the DOM.
65 DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
66 docBuilderFactory.setNamespaceAware(true);
67 DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
68 Document doc;
70 // Request the capabilities document from the server.
71 CapabilitiesRequest req = new CapabilitiesRequest(serverURI);
72 doc = docBuilder.parse(req.toString());
74 // Parse the DOM as a capabilities document.
75 this.caps = Capabilities.parse(doc);
77 catch (Exception e)
79 e.printStackTrace();
80 return;
83 // Gather up all the named layers and make a world wind layer for each.
84 final Element[] namedLayers = WMSLayersPanel.this.caps.getNamedLayers();
85 if (namedLayers == null)
86 return;
88 try
90 for (Element layerCaps : namedLayers)
92 Element[] styles = caps.getLayerStyles(layerCaps);
93 if (styles == null)
95 Layer layer = createLayer(WMSLayersPanel.this.caps, layerCaps, null);
96 WMSLayersPanel.this.layerList.add(layer);
98 else
100 for (Element style : styles)
102 Layer layer = createLayer(WMSLayersPanel.this.caps, layerCaps, style);
103 WMSLayersPanel.this.layerList.add(layer);
108 catch (Exception e)
110 e.printStackTrace();
111 return;
114 // Fill the panel with the layer titles.
115 EventQueue.invokeLater(new Runnable()
117 public void run()
119 WMSLayersPanel.this.removeAll();
120 makeLayersPanel(layerList);
125 public LayerList getLayerList()
127 return this.layerList;
130 public Capabilities getCaps()
132 return this.caps;
135 private void makeProgressPanel()
137 // Create the panel holding the progress bar during loading.
139 JPanel outerPanel = new JPanel(new BorderLayout());
140 outerPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
141 outerPanel.setPreferredSize(this.size);
143 JPanel innerPanel = new JPanel(new BorderLayout());
144 innerPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
145 JProgressBar progressBar = new JProgressBar();
146 progressBar.setIndeterminate(true);
147 innerPanel.add(progressBar, BorderLayout.CENTER);
149 JButton cancelButton = new JButton("Cancel");
150 innerPanel.add(cancelButton, BorderLayout.EAST);
151 cancelButton.addActionListener(new AbstractAction()
153 public void actionPerformed(ActionEvent actionEvent)
155 if (loadingThread.isAlive())
156 loadingThread.interrupt();
158 Container c = WMSLayersPanel.this.getParent();
159 c.remove(WMSLayersPanel.this);
163 outerPanel.add(innerPanel, BorderLayout.NORTH);
164 this.add(outerPanel, BorderLayout.CENTER);
165 this.revalidate();
168 private void makeLayersPanel(LayerList layerList)
170 // Create the panel holding the layer names.
171 JPanel layersPanel = new JPanel(new GridLayout(0, 1, 0, 15));
172 layersPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
174 // Add the server's layers to the panel.
175 for (Layer layer : layerList)
177 addLayerToPanel(layersPanel, WMSLayersPanel.this.wwd, layer);
180 // Put the name panel in a scroll bar.
181 JScrollPane scrollPane = new JScrollPane(layersPanel);
182 scrollPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
183 scrollPane.setPreferredSize(size);
185 // Add the scroll bar and name panel to a titled panel that will resize with the main window.
186 JPanel westPanel = new JPanel(new GridLayout(0, 1, 0, 10));
187 westPanel.setBorder(
188 new CompoundBorder(BorderFactory.createEmptyBorder(9, 9, 9, 9), new TitledBorder("Layers")));
189 westPanel.add(scrollPane);
190 this.add(westPanel, BorderLayout.CENTER);
192 this.revalidate();
195 public String getServerDisplayString()
197 // Find the best available name for the server.
199 if (caps == null)
201 // Capabilities have not yet been retrieved, so use the host name of the server's URI.
202 return this.serverURI.getHost();
205 if (this.caps.getTitle() != null && this.caps.getTitle().length() > 0)
206 return this.caps.getTitle();
208 if (this.caps.getName() != null && this.caps.getName().length() > 0)
209 return this.caps.getName();
211 return null;
214 private Layer createLayer(Capabilities caps, Element layerCaps, Element style)
216 // Create the layer specified by the layer's capabilities entry and the selected style.
218 AVListImpl params = new AVListImpl();
219 params.setValue(AVKey.LAYER_NAMES, caps.getLayerName(layerCaps));
220 if (style != null)
221 params.setValue(AVKey.STYLE_NAMES, caps.getStyleName(style));
223 Layer layer = WMSLayerFactory.newLayer(caps, params);
224 layer.setEnabled(false);
226 // Some wms servers are slow, so increase the timeouts and limits used by world wind's retrievers.
227 layer.setValue(AVKey.URL_CONNECT_TIMEOUT, 30000);
228 layer.setValue(AVKey.URL_READ_TIMEOUT, 30000);
229 layer.setValue(AVKey.RETRIEVAL_QUEUE_STALE_REQUEST_LIMIT, 60000);
231 return layer;
234 private void addLayerToPanel(JPanel layersPanel, WorldWindow wwd, Layer layer)
236 // Give a layer a button and label and add it to the layer names panel.
238 LayerAction action = new LayerAction(layer, wwd);
239 JCheckBox jcb = new JCheckBox(action);
240 jcb.setSelected(layer.isEnabled());
241 layersPanel.add(jcb);
244 private class LayerAction extends AbstractAction
246 private WorldWindow wwd;
247 private Layer layer;
249 public LayerAction(Layer layer, WorldWindow wwd)
251 // Capture info we'll need later to control the layer.
252 super(layer.getName());
253 this.wwd = wwd;
254 this.layer = layer;
256 // Add the layer to the world window model's layer list if the layer is enabled.
257 if (layer.isEnabled())
259 ApplicationTemplate.insertBeforePlacenames(this.wwd, this.layer);
263 public void actionPerformed(ActionEvent actionEvent)
265 // If the layer is selected, add it to the world window's current model, else remove it from the model.
266 if (((JCheckBox) actionEvent.getSource()).isSelected())
268 this.layer.setEnabled(true);
269 ApplicationTemplate.insertBeforePlacenames(this.wwd, this.layer);
270 WMSLayersPanel.this.firePropertyChange("LayersPanelUpdated", null, layer);
272 else
274 this.layer.setEnabled(false);
275 this.wwd.getModel().getLayers().remove(layer);
276 WMSLayersPanel.this.firePropertyChange("LayersPanelUpdated", layer, null);
279 // Tell the world window to update.
280 wwd.redraw();