/* * Copyright (C) 2014 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.rcp.actions.raster; import com.bc.ceres.glevel.MultiLevelImage; import org.esa.snap.core.datamodel.Band; import org.esa.snap.core.datamodel.FilterBand; import org.esa.snap.core.datamodel.ImageInfo; import org.esa.snap.core.datamodel.Product; import org.esa.snap.core.datamodel.ProductNode; import org.esa.snap.core.datamodel.ProductNodeGroup; import org.esa.snap.core.datamodel.RasterDataNode; import org.esa.snap.core.datamodel.VirtualBand; import org.esa.snap.netbeans.docwin.WindowUtilities; import org.esa.snap.rcp.SnapApp; import org.esa.snap.rcp.windows.ProductSceneViewTopComponent; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; import org.openide.awt.ActionReferences; import org.openide.awt.ActionRegistration; import org.openide.util.ContextAwareAction; import org.openide.util.Lookup; import org.openide.util.LookupEvent; import org.openide.util.LookupListener; import org.openide.util.NbBundle; import org.openide.util.Utilities; import org.openide.util.WeakListeners; import javax.swing.AbstractAction; import javax.swing.Action; import java.awt.event.ActionEvent; import static org.esa.snap.rcp.SnapApp.SelectionSourceHint.*; /** * Converts a virtual band into a "real" band. * * @author marcoz */ @ActionID(category = "Tools", id = "ConvertComputedBandIntoBandAction" ) @ActionRegistration( displayName = "#CTL_ConvertComputedBandIntoBandAction_MenuText", popupText = "#CTL_ConvertComputedBandIntoBandAction_MenuText" ) @ActionReferences({ @ActionReference(path = "Menu/Raster", position = 20), @ActionReference(path = "Context/Product/RasterDataNode", position = 30) }) @NbBundle.Messages({ "CTL_ConvertComputedBandIntoBandAction_MenuText=Convert Band", "CTL_ConvertComputedBandIntoBandAction_ShortDescription=Computes a \"real\" band from a virtual band or filtered band" }) public class ConvertComputedBandIntoBandAction extends AbstractAction implements ContextAwareAction, LookupListener { private final Lookup lookup; @SuppressWarnings("FieldCanBeLocal") private final Lookup.Result<VirtualBand> vbResult; @SuppressWarnings("FieldCanBeLocal") private final Lookup.Result<FilterBand> fbResult; public ConvertComputedBandIntoBandAction() { this(Utilities.actionsGlobalContext()); } public ConvertComputedBandIntoBandAction(Lookup lookup) { super(Bundle.CTL_ConvertComputedBandIntoBandAction_MenuText()); this.lookup = lookup; vbResult = lookup.lookupResult(VirtualBand.class); vbResult.addLookupListener(WeakListeners.create(LookupListener.class, this, vbResult)); fbResult = lookup.lookupResult(FilterBand.class); fbResult.addLookupListener(WeakListeners.create(LookupListener.class, this, fbResult)); setEnableState(); } private void setEnableState() { VirtualBand virtualBand = lookup.lookup(VirtualBand.class); FilterBand filterBand = lookup.lookup(FilterBand.class); setEnabled(virtualBand != null || filterBand != null); } @Override public void actionPerformed(ActionEvent e) { SnapApp snapApp = SnapApp.getDefault(); ProductNode selectedProductNode = snapApp.getSelectedProductNode(EXPLORER); if (!isComputedBand(selectedProductNode)) { return; } Band computedBand = (Band) selectedProductNode; String bandName = computedBand.getName(); int width = computedBand.getRasterWidth(); int height = computedBand.getRasterHeight(); Band realBand = new Band(bandName, computedBand.getDataType(), width, height); realBand.setDescription(createDescription(computedBand)); realBand.setValidPixelExpression(computedBand.getValidPixelExpression()); realBand.setUnit(computedBand.getUnit()); realBand.setSpectralWavelength(computedBand.getSpectralWavelength()); realBand.setGeophysicalNoDataValue(computedBand.getGeophysicalNoDataValue()); realBand.setNoDataValueUsed(computedBand.isNoDataValueUsed()); if (computedBand.isStxSet()) { realBand.setStx(computedBand.getStx()); } ImageInfo imageInfo = computedBand.getImageInfo(); if (imageInfo != null) { realBand.setImageInfo(imageInfo.clone()); } //--- Check if all the frame with the raster data are close Product product = computedBand.getProduct(); ProductSceneViewTopComponent topComponent = getProductSceneViewTopComponent(computedBand); if (topComponent != null) { topComponent.close(); } ProductNodeGroup<Band> bandGroup = product.getBandGroup(); int bandIndex = bandGroup.indexOf(computedBand); bandGroup.remove(computedBand); bandGroup.add(bandIndex, realBand); realBand.setSourceImage(createSourceImage(computedBand, realBand)); realBand.setModified(true); } MultiLevelImage createSourceImage(Band computedBand, Band realBand) { if (computedBand instanceof VirtualBand) { return VirtualBand.createSourceImage(realBand, ((VirtualBand) computedBand).getExpression()); }else { return computedBand.getSourceImage(); } } private String createDescription(Band computedBand) { if (computedBand instanceof VirtualBand) { VirtualBand virtualBand = (VirtualBand) computedBand; String oldDescription = virtualBand.getDescription(); String newDescription = oldDescription == null ? "" : oldDescription.trim(); String formerExpressionDescription = "(expression was '" + virtualBand.getExpression() + "')"; newDescription = newDescription.isEmpty() ? formerExpressionDescription : newDescription + " " + formerExpressionDescription; return newDescription; } else { return computedBand.getDescription(); } } //copied from TimeSeriesManagerForm private ProductSceneViewTopComponent getProductSceneViewTopComponent(RasterDataNode raster) { return WindowUtilities.getOpened(ProductSceneViewTopComponent.class) .filter(topComponent -> raster == topComponent.getView().getRaster()) .findFirst() .orElse(null); } private boolean isComputedBand(ProductNode selectedProductNode) { return selectedProductNode instanceof VirtualBand || selectedProductNode instanceof FilterBand; } @Override public Action createContextAwareInstance(Lookup actionContext) { return new ConvertComputedBandIntoBandAction(actionContext); } @Override public void resultChanged(LookupEvent ev) { setEnableState(); } }