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

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

Single entry point in Utils to open HTTP connections

  • Property svn:eol-style set to native
File size: 25.1 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.gui.bbox.SlippyMapBBoxChooser;
57import org.openstreetmap.josm.gui.layer.TMSLayer;
58import org.openstreetmap.josm.gui.preferences.projection.ProjectionChoice;
59import org.openstreetmap.josm.gui.preferences.projection.ProjectionPreference;
60import org.openstreetmap.josm.io.UTFInputStreamReader;
61import org.openstreetmap.josm.tools.GBC;
62import org.openstreetmap.josm.tools.Utils;
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 = Utils.openHttpConnection(getCapabilitiesUrl);
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 (ProjectionChoice pc : ProjectionPreference.getProjectionChoices()) {
495 if (pc.getPreferencesFromCode(crs) != null) return true;
496 }
497 return false;
498 }
499
500 public ImageryInfo getImageryInfo() {
501 ImageryInfo info = new ImageryInfo(menuName.getText(), resultingLayerField.getText());
502 if (ImageryType.TMS.equals(info.getImageryType())) {
503 TMSLayer.checkUrl(info.getUrl());
504 } else if (selectedLayers != null) {
505 HashSet<String> proj = new HashSet<String>();
506 for(LayerDetails l : selectedLayers) {
507 proj.addAll(l.getProjections());
508 }
509 info.setServerProjections(proj);
510 }
511 return info;
512 }
513
514 private static String getChildContent(Element parent, String name, String missing, String empty) {
515 Element child = getChild(parent, name);
516 if (child == null)
517 return missing;
518 else {
519 String content = (String) getContent(child);
520 return (content != null) ? content : empty;
521 }
522 }
523
524 private static Object getContent(Element element) {
525 NodeList nl = element.getChildNodes();
526 StringBuffer content = new StringBuffer();
527 for (int i = 0; i < nl.getLength(); i++) {
528 Node node = nl.item(i);
529 switch (node.getNodeType()) {
530 case Node.ELEMENT_NODE:
531 return node;
532 case Node.CDATA_SECTION_NODE:
533 case Node.TEXT_NODE:
534 content.append(node.getNodeValue());
535 break;
536 }
537 }
538 return content.toString().trim();
539 }
540
541 private static List<Element> getChildren(Element parent, String name) {
542 List<Element> retVal = new LinkedList<Element>();
543 for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
544 if (child instanceof Element && name.equals(child.getNodeName())) {
545 retVal.add((Element) child);
546 }
547 }
548 return retVal;
549 }
550
551 private static Element getChild(Element parent, String name) {
552 if (parent == null)
553 return null;
554 for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
555 if (child instanceof Element && name.equals(child.getNodeName()))
556 return (Element) child;
557 }
558 return null;
559 }
560
561 static class LayerDetails {
562
563 private String name;
564 private String ident;
565 private List<LayerDetails> children;
566 private Bounds bounds;
567 private Set<String> crsList;
568 private boolean supported;
569
570 public LayerDetails(String name, String ident, Set<String> crsList,
571 boolean supportedLayer, Bounds bounds,
572 List<LayerDetails> childLayers) {
573 this.name = name;
574 this.ident = ident;
575 this.supported = supportedLayer;
576 this.children = childLayers;
577 this.bounds = bounds;
578 this.crsList = crsList;
579 }
580
581 public boolean isSupported() {
582 return this.supported;
583 }
584
585 public Set<String> getProjections() {
586 return crsList;
587 }
588
589 @Override
590 public String toString() {
591 if(this.name == null || this.name.isEmpty())
592 return this.ident;
593 else
594 return this.name;
595 }
596
597 }
598
599 static class LayerTreeCellRenderer extends DefaultTreeCellRenderer {
600 @Override
601 public Component getTreeCellRendererComponent(JTree tree, Object value,
602 boolean sel, boolean expanded, boolean leaf, int row,
603 boolean hasFocus) {
604 super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf,
605 row, hasFocus);
606 DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value;
607 Object userObject = treeNode.getUserObject();
608 if (userObject instanceof LayerDetails) {
609 LayerDetails layer = (LayerDetails) userObject;
610 setEnabled(layer.isSupported());
611 }
612 return this;
613 }
614 }
615
616}
Note: See TracBrowser for help on using the repository browser.