/* * Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see http://www.gnu.org/licenses/ */ package org.esa.snap.ui.product; import com.bc.ceres.binding.PropertySet; import com.bc.ceres.core.Assert; import com.bc.ceres.glayer.CollectionLayer; import com.bc.ceres.glayer.Layer; import com.bc.ceres.glayer.LayerFilter; import com.bc.ceres.glayer.support.LayerUtils; import org.esa.snap.core.datamodel.Product; import org.esa.snap.core.datamodel.ProductNode; import org.esa.snap.core.datamodel.ProductNodeEvent; import org.esa.snap.core.datamodel.ProductNodeGroup; import org.esa.snap.core.datamodel.ProductNodeListener; import org.esa.snap.core.datamodel.VectorDataNode; import org.esa.snap.core.layer.ProductLayerContext; import java.lang.ref.WeakReference; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public class VectorDataCollectionLayer extends CollectionLayer { public static final String ID = VectorDataCollectionLayer.class.getName(); private final ProductNodeListener pnl; private final transient WeakReference<ProductNodeGroup<VectorDataNode>> reference; private final ProductLayerContext plc; public VectorDataCollectionLayer(VectorDataCollectionLayerType layerType, ProductNodeGroup<VectorDataNode> vectorDataGroup, PropertySet configuration, ProductLayerContext plc) { super(layerType, configuration, "Vector data"); Assert.notNull(vectorDataGroup, "vectorDataGroup"); reference = new WeakReference<>(vectorDataGroup); pnl = new PNL(); this.plc = plc; setId(ID); vectorDataGroup.getProduct().addProductNodeListener(pnl); } @Override public void disposeLayer() { ProductNodeGroup<VectorDataNode> productNodeGroup = reference.get(); if (productNodeGroup != null) { Product product = productNodeGroup.getProduct(); if (product != null) { product.removeProductNodeListener(pnl); } } reference.clear(); } private Layer createLayer(final VectorDataNode vectorDataNode) { final Layer layer = VectorDataLayerType.createLayer(plc, vectorDataNode); layer.setVisible(false); return layer; } private Layer getLayer(final VectorDataNode vectorDataNode) { LayerFilter layerFilter = VectorDataLayerFilterFactory.createNodeFilter(vectorDataNode); return LayerUtils.getChildLayer(LayerUtils.getRootLayer(this), LayerUtils.SEARCH_DEEP, layerFilter); } synchronized void updateChildren() { final ProductNodeGroup<VectorDataNode> vectorDataGroup = reference.get(); if (vectorDataGroup == null) { return; } // Collect all current vector layers LayerFilter layerFilter = layer -> { PropertySet conf = layer.getConfiguration(); return conf.isPropertyDefined(VectorDataLayerType.PROPERTY_NAME_VECTOR_DATA) && conf.getValue(VectorDataLayerType.PROPERTY_NAME_VECTOR_DATA) != null; }; List<Layer> vectorLayers = LayerUtils.getChildLayers(LayerUtils.getRootLayer(this), LayerUtils.SEARCH_DEEP, layerFilter); final Map<VectorDataNode, Layer> currentLayers = new HashMap<>(); for (final Layer child : vectorLayers) { final String name = child.getConfiguration().getValue(VectorDataLayerType.PROPERTY_NAME_VECTOR_DATA); final VectorDataNode vectorDataNode = vectorDataGroup.get(name); currentLayers.put(vectorDataNode, child); } // Align vector layers with available vectors final Set<Layer> unusedLayers = new HashSet<>(vectorLayers); VectorDataNode[] vectorDataNodes = vectorDataGroup.toArray(new VectorDataNode[vectorDataGroup.getNodeCount()]); for (final VectorDataNode vectorDataNode : vectorDataNodes) { Layer layer = currentLayers.get(vectorDataNode); if (layer != null) { unusedLayers.remove(layer); } else { layer = createLayer(vectorDataNode); getChildren().add(layer); } } // Remove unused layers for (Layer layer : unusedLayers) { layer.dispose(); Layer layerParent = layer.getParent(); if (layerParent != null) { layerParent.getChildren().remove(layer); } } } private class PNL implements ProductNodeListener { @Override public synchronized void nodeChanged(ProductNodeEvent event) { final ProductNode sourceNode = event.getSourceNode(); if (sourceNode instanceof VectorDataNode) { final VectorDataNode vectorDataNode = (VectorDataNode) sourceNode; final Layer layer = getLayer(vectorDataNode); if (layer != null) { layer.regenerate(); } } } @Override public void nodeDataChanged(ProductNodeEvent event) { nodeChanged(event); } @Override public void nodeAdded(ProductNodeEvent event) { updateChildren(); } @Override public void nodeRemoved(ProductNodeEvent event) { updateChildren(); } } }