Worldwind public release 0.2.1
[worldwind-tracker.git] / gov / nasa / worldwind / examples / WMSLayersPanel.java
blob8cd4e62b81cff85f5a8dda00b1a4357eb5dcc902
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.*;
10 import gov.nasa.worldwind.layers.*;
11 import gov.nasa.worldwind.wms.*;
12 import org.w3c.dom.*;
14 import javax.swing.*;
15 import javax.swing.border.*;
16 import javax.xml.parsers.*;
17 import java.awt.*;
18 import java.awt.event.*;
19 import java.net.*;
21 /**
22 * @author tag
23 * @version $Id: WMSLayersPanel.java 2131 2007-06-22 22:45:35Z jason $
25 public class WMSLayersPanel extends JPanel
27 private final WorldWindow wwd;
28 private final URI serverURI;
29 private final Dimension size;
30 private final LayerList layerList = new LayerList();
31 private final Thread loadingThread;
32 private Capabilities caps;
34 public WMSLayersPanel(WorldWindow wwd, String server, Dimension size) throws URISyntaxException
36 super(new BorderLayout());
38 // See if the server name is a valid URI. Throw an exception if not.
39 this.serverURI = new URI(server); // throws an exception if server name is not a valid uri.
41 this.wwd = wwd;
42 this.size = size;
43 this.setPreferredSize(this.size);
45 this.makeProgressPanel();
47 // Thread off a retrieval of the server's capabilities document and update of this panel.
48 this.loadingThread = new Thread(new Runnable()
50 public void run()
52 load();
54 });
55 this.loadingThread.start();
58 private void load()
60 try
62 // Retrieve the server's capabilities document and parse it into a DOM.
63 // Set up the DOM.
64 DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
65 docBuilderFactory.setNamespaceAware(true);
66 DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
67 Document doc;
69 // Request the capabilities document from the server.
70 CapabilitiesRequest req = new CapabilitiesRequest(serverURI);
71 doc = docBuilder.parse(req.toString());
73 // Parse the DOM as a capabilities document.
74 this.caps = Capabilities.parse(doc);
76 catch (Exception e)
78 e.printStackTrace();
79 return;
82 // Gather up all the named layers and make a world wind layer for each.
83 final Element[] namedLayers = WMSLayersPanel.this.caps.getNamedLayers();
84 if (namedLayers == null)
85 return;
87 try
89 for (Element layerCaps : namedLayers)
91 Element[] styles = caps.getLayerStyles(layerCaps);
92 if (styles == null)
94 Layer layer = createLayer(WMSLayersPanel.this.caps, layerCaps, null);
95 WMSLayersPanel.this.layerList.add(layer);
97 else
99 for (Element style : styles)
101 Layer layer = createLayer(WMSLayersPanel.this.caps, layerCaps, style);
102 WMSLayersPanel.this.layerList.add(layer);
107 catch (Exception e)
109 e.printStackTrace();
110 return;
113 // Fill the panel with the layer titles.
114 EventQueue.invokeLater(new Runnable()
116 public void run()
118 WMSLayersPanel.this.removeAll();
119 makeLayersPanel(layerList);
124 public LayerList getLayerList()
126 return this.layerList;
129 public Capabilities getCaps()
131 return this.caps;
134 private void makeProgressPanel()
136 // Create the panel holding the progress bar during loading.
138 JPanel outerPanel = new JPanel(new BorderLayout());
139 outerPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
140 outerPanel.setPreferredSize(this.size);
142 JPanel innerPanel = new JPanel(new BorderLayout());
143 innerPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
144 JProgressBar progressBar = new JProgressBar();
145 progressBar.setIndeterminate(true);
146 innerPanel.add(progressBar, BorderLayout.CENTER);
148 JButton cancelButton = new JButton("Cancel");
149 innerPanel.add(cancelButton, BorderLayout.EAST);
150 cancelButton.addActionListener(new AbstractAction()
152 public void actionPerformed(ActionEvent actionEvent)
154 if (loadingThread.isAlive())
155 loadingThread.interrupt();
157 Container c = WMSLayersPanel.this.getParent();
158 c.remove(WMSLayersPanel.this);
162 outerPanel.add(innerPanel, BorderLayout.NORTH);
163 this.add(outerPanel, BorderLayout.CENTER);
164 this.revalidate();
167 private void makeLayersPanel(LayerList layerList)
169 // Create the panel holding the layer names.
170 JPanel layersPanel = new JPanel(new GridLayout(0, 1, 0, 15));
171 layersPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
173 // Add the server's layers to the panel.
174 for (Layer layer : layerList)
176 addLayerToPanel(layersPanel, WMSLayersPanel.this.wwd, layer);
179 // Put the name panel in a scroll bar.
180 JScrollPane scrollPane = new JScrollPane(layersPanel);
181 scrollPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
182 scrollPane.setPreferredSize(size);
184 // Add the scroll bar and name panel to a titled panel that will resize with the main window.
185 JPanel westPanel = new JPanel(new GridLayout(0, 1, 0, 10));
186 westPanel.setBorder(
187 new CompoundBorder(BorderFactory.createEmptyBorder(9, 9, 9, 9), new TitledBorder("Layers")));
188 westPanel.add(scrollPane);
189 this.add(westPanel, BorderLayout.CENTER);
191 this.revalidate();
194 public String getServerDisplayString()
196 // Find the best available name for the server.
198 if (caps == null)
200 // Capabilities have not yet been retrieved, so use the host name of the server's URI.
201 return this.serverURI.getHost();
204 if (this.caps.getTitle() != null && this.caps.getTitle().length() > 0)
205 return this.caps.getTitle();
207 if (this.caps.getName() != null && this.caps.getName().length() > 0)
208 return this.caps.getName();
210 return null;
213 private Layer createLayer(Capabilities caps, Element layerCaps, Element style)
215 // Create the layer specified by the layer's capabilities entry and the selected style.
217 AVListImpl params = new AVListImpl();
218 params.setValue(AVKey.LAYER_NAMES, caps.getLayerName(layerCaps));
219 if (style != null)
220 params.setValue(AVKey.STYLE_NAMES, caps.getStyleName(style));
222 Layer layer = WMSLayerFactory.newLayer(caps, params);
223 layer.setEnabled(false);
225 // Some wms servers are slow, so increase the timeouts and limits used by world wind's retrievers.
226 layer.setValue(AVKey.URL_CONNECT_TIMEOUT, 30000);
227 layer.setValue(AVKey.URL_READ_TIMEOUT, 30000);
228 layer.setValue(AVKey.RETRIEVAL_QUEUE_STALE_REQUEST_LIMIT, 60000);
230 return layer;
233 private void addLayerToPanel(JPanel layersPanel, WorldWindow wwd, Layer layer)
235 // Give a layer a button and label and add it to the layer names panel.
237 LayerAction action = new LayerAction(layer, wwd);
238 JCheckBox jcb = new JCheckBox(action);
239 jcb.setSelected(layer.isEnabled());
240 layersPanel.add(jcb);
243 private class LayerAction extends AbstractAction
245 private WorldWindow wwd;
246 private Layer layer;
248 public LayerAction(Layer layer, WorldWindow wwd)
250 // Capture info we'll need later to control the layer.
251 super(layer.getName());
252 this.wwd = wwd;
253 this.layer = layer;
255 // Add the layer to the world window model's layer list if the layer is enabled.
256 if (layer.isEnabled())
258 ApplicationTemplate.insertBeforePlacenames(this.wwd, this.layer);
262 public void actionPerformed(ActionEvent actionEvent)
264 // If the layer is selected, add it to the world window's current model, else remove it from the model.
265 if (((JCheckBox) actionEvent.getSource()).isSelected())
267 this.layer.setEnabled(true);
268 ApplicationTemplate.insertBeforePlacenames(this.wwd, this.layer);
269 WMSLayersPanel.this.firePropertyChange("LayersPanelUpdated", null, layer);
271 else
273 this.layer.setEnabled(false);
274 this.wwd.getModel().getLayers().remove(layer);
275 WMSLayersPanel.this.firePropertyChange("LayersPanelUpdated", layer, null);
278 // Tell the world window to update.
279 wwd.redraw();