source: josm/trunk/src/org/openstreetmap/josm/gui/preferences/imagery/AddWMSLayerPanel.java@ 4968

Last change on this file since 4968 was 4968, checked in by Don-vip, 12 years ago

fix #7386 - Major rework of preferences GUI settings in order to speed up preferences dialog startup time. The building of each preferences tab is delayed until this tab is selected. Plugins that use preferences will need to make some (minor) changes.

  • Property svn:eol-style set to native
File size: 25.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.preferences.imagery;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5import static org.openstreetmap.josm.tools.I18n.trc;
6
7import java.awt.Component;
8import java.awt.Cursor;
9import java.awt.Dimension;
10import java.awt.GridBagConstraints;
11import java.awt.GridBagLayout;
12import java.awt.HeadlessException;
13import java.awt.event.ActionEvent;
14import java.awt.event.ActionListener;
15import java.awt.event.KeyAdapter;
16import java.awt.event.KeyEvent;
17import java.io.BufferedReader;
18import java.io.IOException;
19import java.io.InputStream;
20import java.io.StringReader;
21import java.net.MalformedURLException;
22import java.net.URL;
23import java.net.URLConnection;
24import java.util.HashSet;
25import java.util.Iterator;
26import java.util.LinkedList;
27import java.util.List;
28import java.util.Set;
29import java.util.regex.Pattern;
30
31import javax.swing.JButton;
32import javax.swing.JLabel;
33import javax.swing.JOptionPane;
34import javax.swing.JPanel;
35import javax.swing.JScrollPane;
36import javax.swing.JTabbedPane;
37import javax.swing.JTextArea;
38import javax.swing.JTextField;
39import javax.swing.JTree;
40import javax.swing.event.ChangeEvent;
41import javax.swing.event.ChangeListener;
42import javax.swing.event.TreeSelectionEvent;
43import javax.swing.event.TreeSelectionListener;
44import javax.swing.tree.DefaultMutableTreeNode;
45import javax.swing.tree.DefaultTreeCellRenderer;
46import javax.swing.tree.DefaultTreeModel;
47import javax.swing.tree.MutableTreeNode;
48import javax.swing.tree.TreePath;
49import javax.xml.parsers.DocumentBuilder;
50import javax.xml.parsers.DocumentBuilderFactory;
51import javax.xml.parsers.ParserConfigurationException;
52
53import org.openstreetmap.josm.data.Bounds;
54import org.openstreetmap.josm.data.imagery.ImageryInfo;
55import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType;
56import org.openstreetmap.josm.data.projection.Projection;
57import org.openstreetmap.josm.data.projection.ProjectionSubPrefs;
58import org.openstreetmap.josm.data.projection.Projections;
59import org.openstreetmap.josm.gui.bbox.SlippyMapBBoxChooser;
60import org.openstreetmap.josm.gui.layer.TMSLayer;
61import org.openstreetmap.josm.io.UTFInputStreamReader;
62import org.openstreetmap.josm.tools.GBC;
63import org.w3c.dom.Document;
64import org.w3c.dom.Element;
65import org.w3c.dom.Node;
66import org.w3c.dom.NodeList;
67import org.xml.sax.EntityResolver;
68import org.xml.sax.InputSource;
69import org.xml.sax.SAXException;
70
71
72public class AddWMSLayerPanel extends JPanel {
73 private List<LayerDetails> selectedLayers;
74 private URL serviceUrl;
75 private LayerDetails selectedLayer;
76
77 private JTextField menuName;
78 private JTextArea resultingLayerField;
79 private MutableTreeNode treeRootNode;
80 private DefaultTreeModel treeData;
81 private JTree layerTree;
82 private JButton showBoundsButton;
83
84 private boolean previouslyShownUnsupportedCrsError = false;
85 private JTextArea tmsURL;
86 private JTextField tmsZoom;
87
88 public AddWMSLayerPanel() {
89 super(new GridBagLayout());
90 add(new JLabel(tr("Menu Name")), GBC.std().insets(0,0,5,0));
91 menuName = new JTextField(40);
92 menuName.setText(tr("Unnamed Imagery Layer"));
93 add(menuName, GBC.eop().insets(5,0,0,0).fill(GridBagConstraints.HORIZONTAL));
94
95 final JTabbedPane tabbedPane = new JTabbedPane();
96
97 final JPanel wmsFetchPanel = new JPanel(new GridBagLayout());
98 tabbedPane.addTab(tr("WMS"), wmsFetchPanel);
99 add(tabbedPane, GBC.eop().insets(5,0,0,0).weight(1.0, 1.0).fill(GridBagConstraints.BOTH));
100
101 final JTextArea serviceUrlText = new JTextArea(3, 40);
102 serviceUrlText.setLineWrap(true);
103 serviceUrlText.setText("http://sample.com/wms?");
104 wmsFetchPanel.add(new JLabel(tr("Service URL")), GBC.std().insets(0,0,5,0));
105 JScrollPane scrollPane = new JScrollPane(serviceUrlText,
106 JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
107 JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
108 scrollPane.setMinimumSize(new Dimension(60, 60));
109 wmsFetchPanel.add(scrollPane, GBC.eol().weight(1.0, 0.0).insets(5,0,0,0).fill(GridBagConstraints.HORIZONTAL));
110 JButton getLayersButton = new JButton(tr("Get Layers"));
111 getLayersButton.addActionListener(new ActionListener() {
112 @Override
113 public void actionPerformed(ActionEvent e) {
114 Cursor beforeCursor = getCursor();
115 try {
116 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
117 attemptGetCapabilities(sanitize(serviceUrlText.getText()));
118 } finally {
119 setCursor(beforeCursor);
120 }
121 }
122 });
123 wmsFetchPanel.add(getLayersButton, GBC.eop().anchor(GridBagConstraints.EAST));
124
125 treeRootNode = new DefaultMutableTreeNode();
126 treeData = new DefaultTreeModel(treeRootNode);
127 layerTree = new JTree(treeData);
128 layerTree.setCellRenderer(new LayerTreeCellRenderer());
129 layerTree.addTreeSelectionListener(new TreeSelectionListener() {
130
131 @Override
132 public void valueChanged(TreeSelectionEvent e) {
133 TreePath[] selectionRows = layerTree.getSelectionPaths();
134 if(selectionRows == null) {
135 showBoundsButton.setEnabled(false);
136 selectedLayer = null;
137 return;
138 }
139
140 selectedLayers = new LinkedList<LayerDetails>();
141 for (TreePath i : selectionRows) {
142 Object userObject = ((DefaultMutableTreeNode) i.getLastPathComponent()).getUserObject();
143 if(userObject instanceof LayerDetails) {
144 LayerDetails detail = (LayerDetails) userObject;
145 if(!detail.isSupported()) {
146 layerTree.removeSelectionPath(i);
147 if(!previouslyShownUnsupportedCrsError) {
148 JOptionPane.showMessageDialog(null, tr("That layer does not support any of JOSM''s projections,\n" +
149 "so you can not use it. This message will not show again."),
150 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
151 previouslyShownUnsupportedCrsError = true;
152 }
153 } else if(detail.ident != null) {
154 selectedLayers.add(detail);
155 }
156 }
157 }
158
159 if (!selectedLayers.isEmpty()) {
160 resultingLayerField.setText(buildGetMapUrl());
161
162 if(selectedLayers.size() == 1) {
163 showBoundsButton.setEnabled(true);
164 selectedLayer = selectedLayers.get(0);
165 }
166 } else {
167 showBoundsButton.setEnabled(false);
168 selectedLayer = null;
169 }
170 }
171 });
172 wmsFetchPanel.add(new JScrollPane(layerTree), GBC.eol().weight(1.0, 1.0).insets(5,0,0,0).fill(GridBagConstraints.BOTH));
173
174 JPanel layerManipulationButtons = new JPanel();
175 showBoundsButton = new JButton(tr("Show Bounds"));
176 showBoundsButton.setEnabled(false);
177 showBoundsButton.addActionListener(new ActionListener() {
178 @Override
179 public void actionPerformed(ActionEvent e) {
180 if(selectedLayer.bounds != null) {
181 SlippyMapBBoxChooser mapPanel = new SlippyMapBBoxChooser();
182 mapPanel.setBoundingBox(selectedLayer.bounds);
183 JOptionPane.showMessageDialog(null, mapPanel, tr("Show Bounds"), JOptionPane.PLAIN_MESSAGE);
184 } else {
185 JOptionPane.showMessageDialog(null, tr("No bounding box was found for this layer."),
186 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
187 }
188 }
189 });
190 layerManipulationButtons.add(showBoundsButton);
191
192 wmsFetchPanel.add(layerManipulationButtons, GBC.eol().insets(0,0,5,0));
193
194 final JPanel tmsView = new JPanel(new GridBagLayout());
195 tmsView.add(new JLabel(tr("TMS URL")), GBC.std().insets(0,0,5,0));
196 tmsURL = new JTextArea(3, 40);
197 tmsURL.setLineWrap(true);
198 tmsURL.setText("http://sample.com/tms/{zoom}/{x}/{y}.jpg");
199 tmsURL.addKeyListener(new KeyAdapter() {
200 @Override
201 public void keyReleased(KeyEvent e) {
202 resultingLayerField.setText(buildTMSUrl());
203 }
204 });
205 JScrollPane tmsUrlScrollPane = new JScrollPane(tmsURL,
206 JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
207 JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
208 tmsUrlScrollPane.setMinimumSize(new Dimension(60, 60));
209 tmsView.add(tmsUrlScrollPane, GBC.eol().insets(5,0,0,0).fill(GridBagConstraints.HORIZONTAL));
210 tmsView.add(new JLabel(trc("layer", "Zoom")), GBC.std().insets(0,0,5,0));
211 tmsZoom = new JTextField(3);
212 tmsZoom.addKeyListener(new KeyAdapter() {
213 @Override
214 public void keyReleased(KeyEvent e) {
215 resultingLayerField.setText(buildTMSUrl());
216 }
217 });
218 tmsView.add(tmsZoom, GBC.eol().insets(5,0,0,0).fill(GridBagConstraints.HORIZONTAL));
219 tmsView.add(new JLabel(), GBC.eop().weight(1.0, 1.0).fill(GridBagConstraints.BOTH));
220 tabbedPane.addTab(tr("TMS"), tmsView);
221
222 add(new JLabel(tr("Imagery URL")), GBC.std().insets(0,0,5,0));
223 resultingLayerField = new JTextArea(3, 40);
224 resultingLayerField.setLineWrap(true);
225 JScrollPane bottomScrollPane = new JScrollPane(resultingLayerField,
226 JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
227 bottomScrollPane.setMinimumSize(new Dimension(60, 60));
228 add(bottomScrollPane, GBC.eol().weight(1.0, 0.0).insets(5,0,0,0).fill(GridBagConstraints.HORIZONTAL));
229
230 tabbedPane.addChangeListener(new ChangeListener() {
231 @Override
232 public void stateChanged(ChangeEvent e) {
233 Component sel = tabbedPane.getSelectedComponent();
234 if(tmsView == sel) {
235 resultingLayerField.setText(buildTMSUrl());
236 } else if(wmsFetchPanel == sel) {
237 if(serviceUrl != null) {
238 resultingLayerField.setText(buildGetMapUrl());
239 }
240 }
241 }
242 });
243 }
244
245 private String sanitize(String s) {
246 return s.replaceAll("[\r\n]+","").trim();
247 }
248
249 private String buildTMSUrl() {
250 StringBuilder a = new StringBuilder("tms");
251 String z = sanitize(tmsZoom.getText());
252 if(!z.isEmpty()) {
253 a.append("["+z+"]");
254 }
255 a.append(":");
256 a.append(sanitize(tmsURL.getText()));
257 return a.toString();
258 }
259
260 private String buildRootUrl() {
261 StringBuilder a = new StringBuilder(serviceUrl.getProtocol());
262 a.append("://");
263 a.append(serviceUrl.getHost());
264 if(serviceUrl.getPort() != -1) {
265 a.append(":");
266 a.append(serviceUrl.getPort());
267 }
268 a.append(serviceUrl.getPath());
269 a.append("?");
270 if(serviceUrl.getQuery() != null) {
271 a.append(serviceUrl.getQuery());
272 if (!serviceUrl.getQuery().isEmpty() && !serviceUrl.getQuery().endsWith("&")) {
273 a.append("&");
274 }
275 }
276 return a.toString();
277 }
278
279 private String buildGetMapUrl() {
280 StringBuilder a = new StringBuilder();
281 a.append(buildRootUrl());
282 a.append("FORMAT=image/jpeg&VERSION=1.1.1&SERVICE=WMS&REQUEST=GetMap&Layers=");
283 a.append(commaSepLayerList());
284 a.append("&STYLES=&SRS={proj}&WIDTH={width}&HEIGHT={height}&BBOX={bbox}");
285
286 return a.toString();
287 }
288
289 private String commaSepLayerList() {
290 StringBuilder b = new StringBuilder();
291
292 if (selectedLayers != null) {
293 Iterator<LayerDetails> iterator = selectedLayers.iterator();
294 while (iterator.hasNext()) {
295 LayerDetails layerDetails = iterator.next();
296 b.append(layerDetails.ident);
297 if(iterator.hasNext()) {
298 b.append(",");
299 }
300 }
301 }
302
303 return b.toString();
304 }
305
306 private void showError(String incomingData, Exception e) {
307 JOptionPane.showMessageDialog(this, tr("Could not parse WMS layer list."),
308 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
309 System.err.println("Could not parse WMS layer list. Incoming data:");
310 System.err.println(incomingData);
311 e.printStackTrace();
312 }
313
314 private void attemptGetCapabilities(String serviceUrlStr) {
315 URL getCapabilitiesUrl = null;
316 try {
317 if (!Pattern.compile(".*GetCapabilities.*", Pattern.CASE_INSENSITIVE).matcher(serviceUrlStr).matches()) {
318 // If the url doesn't already have GetCapabilities, add it in
319 getCapabilitiesUrl = new URL(serviceUrlStr);
320 final String getCapabilitiesQuery = "VERSION=1.1.1&SERVICE=WMS&REQUEST=GetCapabilities";
321 if (getCapabilitiesUrl.getQuery() == null) {
322 getCapabilitiesUrl = new URL(serviceUrlStr + "?" + getCapabilitiesQuery);
323 } else if (!getCapabilitiesUrl.getQuery().isEmpty() && !getCapabilitiesUrl.getQuery().endsWith("&")) {
324 getCapabilitiesUrl = new URL(serviceUrlStr + "&" + getCapabilitiesQuery);
325 } else {
326 getCapabilitiesUrl = new URL(serviceUrlStr + getCapabilitiesQuery);
327 }
328 } else {
329 // Otherwise assume it's a good URL and let the subsequent error
330 // handling systems deal with problems
331 getCapabilitiesUrl = new URL(serviceUrlStr);
332 }
333 serviceUrl = new URL(serviceUrlStr);
334 } catch (HeadlessException e) {
335 return;
336 } catch (MalformedURLException e) {
337 JOptionPane.showMessageDialog(this, tr("Invalid service URL."),
338 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
339 return;
340 }
341
342 String incomingData;
343 try {
344 System.out.println("GET "+getCapabilitiesUrl.toString());
345 URLConnection openConnection = getCapabilitiesUrl.openConnection();
346 InputStream inputStream = openConnection.getInputStream();
347 BufferedReader br = new BufferedReader(UTFInputStreamReader.create(inputStream, "UTF-8"));
348 String line;
349 StringBuilder ba = new StringBuilder();
350 while ((line = br.readLine()) != null) {
351 ba.append(line);
352 ba.append("\n");
353 }
354 incomingData = ba.toString();
355 } catch (IOException e) {
356 JOptionPane.showMessageDialog(this, tr("Could not retrieve WMS layer list."),
357 tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
358 return;
359 }
360
361 Document document;
362 try {
363 //System.out.println("WMS capabilities:\n"+incomingData+"\n");
364 DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
365 builderFactory.setValidating(false);
366 builderFactory.setNamespaceAware(true);
367 DocumentBuilder builder = builderFactory.newDocumentBuilder();
368 builder.setEntityResolver(new EntityResolver() {
369 @Override
370 public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
371 System.out.println("Ignoring DTD " + publicId + ", " + systemId);
372 return new InputSource(new StringReader(""));
373 }
374 });
375 document = builder.parse(new InputSource(new StringReader(incomingData)));
376 } catch (ParserConfigurationException e) {
377 showError(incomingData, e);
378 return;
379 } catch (SAXException e) {
380 showError(incomingData, e);
381 return;
382 } catch (IOException e) {
383 showError(incomingData, e);
384 return;
385 }
386
387 // Some WMS service URLs specify a different base URL for their GetMap service
388 Element child = getChild(document.getDocumentElement(), "Capability");
389 child = getChild(child, "Request");
390 child = getChild(child, "GetMap");
391 child = getChild(child, "DCPType");
392 child = getChild(child, "HTTP");
393 child = getChild(child, "Get");
394 child = getChild(child, "OnlineResource");
395 if (child != null) {
396 String baseURL = child.getAttribute("xlink:href");
397 if (baseURL != null && !baseURL.equals(serviceUrlStr)) {
398 try {
399 System.out.println("GetCapabilities specifies a different service URL: " + baseURL);
400 serviceUrl = new URL(baseURL);
401 } catch (MalformedURLException e1) {
402 }
403 }
404 }
405
406 try {
407 treeRootNode.setUserObject(getCapabilitiesUrl.getHost());
408 Element capabilityElem = getChild(document.getDocumentElement(), "Capability");
409 List<Element> children = getChildren(capabilityElem, "Layer");
410 List<LayerDetails> layers = parseLayers(children, new HashSet<String>());
411 updateTreeList(layers);
412 } catch(Exception e) {
413 showError(incomingData, e);
414 return;
415 }
416 }
417
418 private void updateTreeList(List<LayerDetails> layers) {
419 addLayersToTreeData(treeRootNode, layers);
420 layerTree.expandRow(0);
421 }
422
423 private void addLayersToTreeData(MutableTreeNode parent, List<LayerDetails> layers) {
424 for (LayerDetails layerDetails : layers) {
425 DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(layerDetails);
426 addLayersToTreeData(treeNode, layerDetails.children);
427 treeData.insertNodeInto(treeNode, parent, 0);
428 }
429 }
430
431 private List<LayerDetails> parseLayers(List<Element> children, Set<String> parentCrs) {
432 List<LayerDetails> details = new LinkedList<LayerDetails>();
433 for (Element element : children) {
434 details.add(parseLayer(element, parentCrs));
435 }
436 return details;
437 }
438
439 private LayerDetails parseLayer(Element element, Set<String> parentCrs) {
440 String name = getChildContent(element, "Title", null, null);
441 String ident = getChildContent(element, "Name", null, null);
442
443 // The set of supported CRS/SRS for this layer
444 Set<String> crsList = new HashSet<String>();
445 // ...including this layer's already-parsed parent projections
446 crsList.addAll(parentCrs);
447
448 // Parse the CRS/SRS pulled out of this layer's XML element
449 // I think CRS and SRS are the same at this point
450 List<Element> crsChildren = getChildren(element, "CRS");
451 crsChildren.addAll(getChildren(element, "SRS"));
452 for (Element child : crsChildren) {
453 String crs = (String) getContent(child);
454 if(crs != null) {
455 String upperCase = crs.trim().toUpperCase();
456 crsList.add(upperCase);
457 }
458 }
459
460 // Check to see if any of the specified projections are supported by JOSM
461 boolean josmSupportsThisLayer = false;
462 for (String crs : crsList) {
463 josmSupportsThisLayer |= isProjSupported(crs);
464 }
465
466 Bounds bounds = null;
467 Element bboxElem = getChild(element, "EX_GeographicBoundingBox");
468 if(bboxElem != null) {
469 // Attempt to use EX_GeographicBoundingBox for bounding box
470 double left = Double.parseDouble(getChildContent(bboxElem, "westBoundLongitude", null, null));
471 double top = Double.parseDouble(getChildContent(bboxElem, "northBoundLatitude", null, null));
472 double right = Double.parseDouble(getChildContent(bboxElem, "eastBoundLongitude", null, null));
473 double bot = Double.parseDouble(getChildContent(bboxElem, "southBoundLatitude", null, null));
474 bounds = new Bounds(bot, left, top, right);
475 } else {
476 // If that's not available, try LatLonBoundingBox
477 bboxElem = getChild(element, "LatLonBoundingBox");
478 if(bboxElem != null) {
479 double left = Double.parseDouble(bboxElem.getAttribute("minx"));
480 double top = Double.parseDouble(bboxElem.getAttribute("maxy"));
481 double right = Double.parseDouble(bboxElem.getAttribute("maxx"));
482 double bot = Double.parseDouble(bboxElem.getAttribute("miny"));
483 bounds = new Bounds(bot, left, top, right);
484 }
485 }
486
487 List<Element> layerChildren = getChildren(element, "Layer");
488 List<LayerDetails> childLayers = parseLayers(layerChildren, crsList);
489
490 return new LayerDetails(name, ident, crsList, josmSupportsThisLayer, bounds, childLayers);
491 }
492
493 private boolean isProjSupported(String crs) {
494 for (Projection proj : Projections.getProjections()) {
495 if (proj instanceof ProjectionSubPrefs) {
496 if (((ProjectionSubPrefs) proj).getPreferencesFromCode(crs) == null)
497 return true;
498 } else {
499 if (proj.toCode().equals(crs))
500 return true;
501 }
502 }
503 return false;
504 }
505
506 public ImageryInfo getImageryInfo() {
507 ImageryInfo info = new ImageryInfo(menuName.getText(), resultingLayerField.getText());
508 if (ImageryType.TMS.equals(info.getImageryType())) {
509 TMSLayer.checkUrl(info.getUrl());
510 } else if (selectedLayers != null) {
511 HashSet<String> proj = new HashSet<String>();
512 for(LayerDetails l : selectedLayers) {
513 proj.addAll(l.getProjections());
514 }
515 info.setServerProjections(proj);
516 }
517 return info;
518 }
519
520 private static String getChildContent(Element parent, String name, String missing, String empty) {
521 Element child = getChild(parent, name);
522 if (child == null)
523 return missing;
524 else {
525 String content = (String) getContent(child);
526 return (content != null) ? content : empty;
527 }
528 }
529
530 private static Object getContent(Element element) {
531 NodeList nl = element.getChildNodes();
532 StringBuffer content = new StringBuffer();
533 for (int i = 0; i < nl.getLength(); i++) {
534 Node node = nl.item(i);
535 switch (node.getNodeType()) {
536 case Node.ELEMENT_NODE:
537 return node;
538 case Node.CDATA_SECTION_NODE:
539 case Node.TEXT_NODE:
540 content.append(node.getNodeValue());
541 break;
542 }
543 }
544 return content.toString().trim();
545 }
546
547 private static List<Element> getChildren(Element parent, String name) {
548 List<Element> retVal = new LinkedList<Element>();
549 for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
550 if (child instanceof Element && name.equals(child.getNodeName())) {
551 retVal.add((Element) child);
552 }
553 }
554 return retVal;
555 }
556
557 private static Element getChild(Element parent, String name) {
558 if (parent == null)
559 return null;
560 for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
561 if (child instanceof Element && name.equals(child.getNodeName()))
562 return (Element) child;
563 }
564 return null;
565 }
566
567 static class LayerDetails {
568
569 private String name;
570 private String ident;
571 private List<LayerDetails> children;
572 private Bounds bounds;
573 private Set<String> crsList;
574 private boolean supported;
575
576 public LayerDetails(String name, String ident, Set<String> crsList,
577 boolean supportedLayer, Bounds bounds,
578 List<LayerDetails> childLayers) {
579 this.name = name;
580 this.ident = ident;
581 this.supported = supportedLayer;
582 this.children = childLayers;
583 this.bounds = bounds;
584 this.crsList = crsList;
585 }
586
587 public boolean isSupported() {
588 return this.supported;
589 }
590
591 public Set<String> getProjections() {
592 return crsList;
593 }
594
595 @Override
596 public String toString() {
597 if(this.name == null || this.name.isEmpty())
598 return this.ident;
599 else
600 return this.name;
601 }
602
603 }
604
605 static class LayerTreeCellRenderer extends DefaultTreeCellRenderer {
606 @Override
607 public Component getTreeCellRendererComponent(JTree tree, Object value,
608 boolean sel, boolean expanded, boolean leaf, int row,
609 boolean hasFocus) {
610 super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf,
611 row, hasFocus);
612 DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value;
613 Object userObject = treeNode.getUserObject();
614 if (userObject instanceof LayerDetails) {
615 LayerDetails layer = (LayerDetails) userObject;
616 setEnabled(layer.isSupported());
617 }
618 return this;
619 }
620 }
621
622}
Note: See TracBrowser for help on using the repository browser.