All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gov.nasa.worldwind.util.layertree.KMLLayerTreeNode Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */
package gov.nasa.worldwind.util.layertree;

import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.layers.Layer;
import gov.nasa.worldwind.ogc.kml.*;
import gov.nasa.worldwind.util.Logging;
import gov.nasa.worldwind.util.tree.*;

import javax.swing.*;
import java.beans.*;

/**
 * A LayerTreeNode that represents a KML feature hierarchy defined by a {@link
 * gov.nasa.worldwind.ogc.kml.KMLRoot}.
 *
 * @author dcollins
 * @version $Id: KMLLayerTreeNode.java 1171 2013-02-11 21:45:02Z dcollins $
 * @see KMLFeatureTreeNode
 */
public class KMLLayerTreeNode extends LayerTreeNode
{
    /** Indicates the KML feature hierarchy this node represents. Initialized during construction. */
    protected KMLRoot kmlRoot;

    /**
     * Creates a new KMLLayerTreeNode from the specified layer and kmlRoot. The
     * node's name is set to the layer's name, and the node's hierarchy is populated from the feature hierarchy of the
     * KMLRoot.
     *
     * @param layer   the Layer the kmlRoot corresponds to.
     * @param kmlRoot the KML feature hierarchy this node represents.
     *
     * @throws IllegalArgumentException if the layer is null, or if kmlRoot is
     *                                  null.
     */
    public KMLLayerTreeNode(Layer layer, KMLRoot kmlRoot)
    {
        super(layer);

        if (kmlRoot == null)
        {
            String message = Logging.getMessage("nullValue.KMLRootIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        this.kmlRoot = kmlRoot;
        this.addChildFeatures();

        // Add a listener to refresh the tree model when the KML document is updated or a network link is retrieved.
        this.kmlRoot.addPropertyChangeListener(new PropertyChangeListener()
        {
            public void propertyChange(final PropertyChangeEvent event)
            {
                String name = (event != null) ? event.getPropertyName() : null;
                Object newValue = (event != null) ? event.getNewValue() : null;
                KMLAbstractFeature rootFeature = KMLLayerTreeNode.this.kmlRoot.getFeature();

                // Update the document if an update is received, or if this node represents a network link that has been
                // resolved.
                if (AVKey.UPDATED.equals(name)
                    || (AVKey.RETRIEVAL_STATE_SUCCESSFUL.equals(name) && rootFeature == newValue))
                {
                    // Ensure that the node list is manipulated on the EDT
                    if (SwingUtilities.isEventDispatchThread())
                    {
                        KMLLayerTreeNode.this.refresh();
                    }
                    else
                    {
                        SwingUtilities.invokeLater(new Runnable()
                        {
                            public void run()
                            {
                                KMLLayerTreeNode.this.refresh();
                            }
                        });
                    }
                }
            }
        });

        // Set the context of the KML document node to the root feature in the document.
        this.setValue(AVKey.CONTEXT, kmlRoot.getFeature());
    }

    /**
     * Specifies whether this node's layer is enabled for rendering. If the KMLRoot's feature is a container (Document
     * or Folder), this method sets the visibility of that container as well as the node that represents the layer.
     *
     * @param selected true to enable the layer, otherwise false.
     */
    @Override
    public void setSelected(boolean selected)
    {
        super.setSelected(selected);

        KMLAbstractFeature feature = this.kmlRoot.getFeature();
        if (feature instanceof KMLAbstractContainer)
        {
            feature.setVisibility(selected);
        }
    }

    /**
     * Adds a new KMLFeatureTreeNode to this node for each KML feature in the KMLRoot.
     * 

* If the KMLRoot's top level feature is a Document or Folder, this method * ignores this container and adds its children directly to this node. Creating a node for the container adds an * extra level to the tree node that doesn't provide any meaningful grouping. *

* This does nothing if the KMLRoot's top level feature is null. */ protected void addChildFeatures() { KMLAbstractFeature rootFeature = this.kmlRoot.getFeature(); if (rootFeature == null) return; // Create a KMLFeatureTreeNode only to construct the description string for the root node and set it on this // node. We do not add the root node to the tree because it would add a redundant. KMLFeatureTreeNode featureNode = KMLFeatureTreeNode.fromKMLFeature(rootFeature); this.setDescription(featureNode.getDescription()); // Initialize the selected state of this node to match the visibility of the root container. Boolean visibility = rootFeature.getVisibility(); this.setSelected(visibility == null || visibility); // If the root is a container, add its children if (rootFeature instanceof KMLAbstractContainer) { KMLAbstractContainer container = (KMLAbstractContainer) rootFeature; for (KMLAbstractFeature child : container.getFeatures()) { if (child != null) this.addFeatureNode(child); } } // If the root is a network link, add the linked document if (rootFeature instanceof KMLNetworkLink) { KMLRoot networkResource = ((KMLNetworkLink) rootFeature).getNetworkResource(); if (networkResource != null && networkResource.getFeature() != null) { rootFeature = networkResource.getFeature(); // Don't add Document nodes (they don't provide meaningful grouping). if (rootFeature instanceof KMLDocument) { KMLAbstractContainer container = (KMLAbstractContainer) rootFeature; for (KMLAbstractFeature child : container.getFeatures()) { if (child != null) this.addFeatureNode(child); } } else if (rootFeature != null) { this.addFeatureNode(rootFeature); } } } } /** * Adds the a new KMLFeatureTreeNode created with the specified feature to this node. * * @param feature the KML feature to add. */ protected void addFeatureNode(KMLAbstractFeature feature) { TreeNode featureNode = KMLFeatureTreeNode.fromKMLFeature(feature); if (featureNode != null) this.addChild(featureNode); } /** * Expands paths in the specified tree corresponding to open KML container elements. This assumes that * the tree's model contains this node. *

* This node's path is expanded if it's top level KML feature is an open KML container, an open KML network link, or * is any other kind of KML feature. *

* This calls expandOpenContainers on all children which are instances of * KMLFeatureTreeNode. * * @param tree the Tree who's paths should be expanded. * * @throws IllegalArgumentException if the tree is null. */ public void expandOpenContainers(Tree tree) { if (tree == null) { String message = Logging.getMessage("nullValue.TreeIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (this.mustExpandNode()) tree.expandPath(this.getPath()); for (TreeNode child : this.getChildren()) { if (child instanceof KMLFeatureTreeNode) ((KMLFeatureTreeNode) child).expandOpenContainers(tree); } } /** * Indicates whether the tree path for this node must expanded. If the KMLRoot's feature is a KML * container or a KML network link, this returns whether that KML element's open property is * true. Otherwise this returns true * * @return true if the tree path for this node must be expanded, otherwise false. */ protected boolean mustExpandNode() { if (this.kmlRoot.getFeature() instanceof KMLAbstractContainer) { return Boolean.TRUE.equals(this.kmlRoot.getFeature().getOpen()); } return this.kmlRoot.getFeature() != null; } /** Refresh the tree model to match the contents of the KML document. */ protected void refresh() { this.removeAllChildren(); this.addChildFeatures(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy