/*
* 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.core.gpf.ui;
import com.bc.ceres.binding.Property;
import com.bc.ceres.binding.PropertyDescriptor;
import com.bc.ceres.binding.PropertySet;
import com.bc.ceres.binding.ValidationException;
import com.bc.ceres.binding.ValueSet;
import com.bc.ceres.swing.binding.BindingContext;
import com.bc.ceres.swing.binding.PropertyPane;
import com.bc.ceres.swing.selection.AbstractSelectionChangeListener;
import com.bc.ceres.swing.selection.Selection;
import com.bc.ceres.swing.selection.SelectionChangeEvent;
import org.esa.snap.core.datamodel.Product;
import org.esa.snap.core.datamodel.ProductNodeEvent;
import org.esa.snap.core.datamodel.ProductNodeListener;
import org.esa.snap.core.datamodel.RasterDataNode;
import org.esa.snap.core.gpf.GPF;
import org.esa.snap.core.gpf.OperatorSpi;
import org.esa.snap.core.gpf.descriptor.OperatorDescriptor;
import org.esa.snap.core.gpf.internal.RasterDataNodeValues;
import org.esa.snap.ui.AppContext;
import org.esa.snap.ui.UIUtils;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.border.EmptyBorder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* WARNING: This class belongs to a preliminary API and may change in future releases.
*
* @author Norman Fomferra
* @version $Revision: 8343 $ $Date: 2010-02-10 18:31:57 +0100 (Mi, 10 Feb 2010) $
*/
public class DefaultSingleTargetProductDialog extends SingleTargetProductDialog {
private final String operatorName;
private final OperatorDescriptor operatorDescriptor;
private DefaultIOParametersPanel ioParametersPanel;
private final OperatorParameterSupport parameterSupport;
private final BindingContext bindingContext;
private JTabbedPane form;
private PropertyDescriptor[] rasterDataNodeTypeProperties;
private String targetProductNameSuffix;
private ProductChangedHandler productChangedHandler;
public static SingleTargetProductDialog createDefaultDialog(String operatorName, AppContext appContext) {
return new DefaultSingleTargetProductDialog(operatorName, appContext, operatorName, null);
}
public DefaultSingleTargetProductDialog(String operatorName, AppContext appContext, String title, String helpID, boolean targetProductSelectorDisplay) {
super(appContext, title, ID_APPLY_CLOSE, helpID);
this.operatorName = operatorName;
targetProductNameSuffix = "";
OperatorSpi operatorSpi = GPF.getDefaultInstance().getOperatorSpiRegistry().getOperatorSpi(operatorName);
if (operatorSpi == null) {
throw new IllegalArgumentException("No SPI found for operator name '" + operatorName + "'");
}
operatorDescriptor = operatorSpi.getOperatorDescriptor();
ioParametersPanel = new DefaultIOParametersPanel(getAppContext(), operatorDescriptor, getTargetProductSelector(), targetProductSelectorDisplay);
parameterSupport = new OperatorParameterSupport(operatorDescriptor);
final ArrayList<SourceProductSelector> sourceProductSelectorList = ioParametersPanel.getSourceProductSelectorList();
final PropertySet propertySet = parameterSupport.getPropertySet();
bindingContext = new BindingContext(propertySet);
if (propertySet.getProperties().length > 0) {
if (!sourceProductSelectorList.isEmpty()) {
Property[] properties = propertySet.getProperties();
List<PropertyDescriptor> rdnTypeProperties = new ArrayList<>(properties.length);
for (Property property : properties) {
PropertyDescriptor parameterDescriptor = property.getDescriptor();
if (parameterDescriptor.getAttribute(RasterDataNodeValues.ATTRIBUTE_NAME) != null) {
rdnTypeProperties.add(parameterDescriptor);
}
}
rasterDataNodeTypeProperties = rdnTypeProperties.toArray(
new PropertyDescriptor[rdnTypeProperties.size()]);
}
}
productChangedHandler = new ProductChangedHandler();
if (!sourceProductSelectorList.isEmpty()) {
sourceProductSelectorList.get(0).addSelectionChangeListener(productChangedHandler);
}
}
public DefaultSingleTargetProductDialog(String operatorName, AppContext appContext, String title, String helpID) {
this(operatorName, appContext, title, helpID, true);
}
@Override
public int show() {
ioParametersPanel.initSourceProductSelectors();
if (form == null) {
initForm();
if (getJDialog().getJMenuBar() == null) {
final OperatorMenu operatorMenu = createDefaultMenuBar();
getJDialog().setJMenuBar(operatorMenu.createDefaultMenu());
}
}
setContent(form);
return super.show();
}
@Override
public void hide() {
productChangedHandler.releaseProduct();
ioParametersPanel.releaseSourceProductSelectors();
super.hide();
}
@Override
protected Product createTargetProduct() throws Exception {
final HashMap<String, Product> sourceProducts = ioParametersPanel.createSourceProductsMap();
return GPF.createProduct(operatorName, parameterSupport.getParameterMap(), sourceProducts);
}
protected DefaultIOParametersPanel getDefaultIOParametersPanel() {
return ioParametersPanel;
}
public String getTargetProductNameSuffix() {
return targetProductNameSuffix;
}
public void setTargetProductNameSuffix(String suffix) {
targetProductNameSuffix = suffix;
}
public BindingContext getBindingContext() {
return bindingContext;
}
private void initForm() {
form = new JTabbedPane();
form.add("I/O Parameters", ioParametersPanel);
if (bindingContext.getPropertySet().getProperties().length > 0) {
final PropertyPane parametersPane = new PropertyPane(bindingContext);
final JPanel parametersPanel = parametersPane.createPanel();
parametersPanel.setBorder(new EmptyBorder(4, 4, 4, 4));
form.add("Processing Parameters", new JScrollPane(parametersPanel));
updateSourceProduct();
}
}
private OperatorMenu createDefaultMenuBar() {
return new OperatorMenu(getJDialog(),
operatorDescriptor,
parameterSupport,
getAppContext(),
getHelpID());
}
private void updateSourceProduct() {
try {
Property property = bindingContext.getPropertySet().getProperty(UIUtils.PROPERTY_SOURCE_PRODUCT);
if (property != null) {
property.setValue(productChangedHandler.currentProduct);
}
} catch (ValidationException e) {
throw new IllegalStateException("Property '" + UIUtils.PROPERTY_SOURCE_PRODUCT + "' must be of type " + Product.class + ".", e);
}
}
private class ProductChangedHandler extends AbstractSelectionChangeListener implements ProductNodeListener {
private Product currentProduct;
public void releaseProduct() {
if (currentProduct != null) {
currentProduct.removeProductNodeListener(this);
currentProduct = null;
updateSourceProduct();
}
}
@Override
public void selectionChanged(SelectionChangeEvent event) {
Selection selection = event.getSelection();
if (selection != null) {
final Product selectedProduct = (Product) selection.getSelectedValue();
if (selectedProduct != currentProduct) {
if (currentProduct != null) {
currentProduct.removeProductNodeListener(this);
}
currentProduct = selectedProduct;
if (currentProduct != null) {
currentProduct.addProductNodeListener(this);
}
if(getTargetProductSelector() != null){
updateTargetProductName();
}
updateValueSets(currentProduct);
updateSourceProduct();
}
}
}
@Override
public void nodeAdded(ProductNodeEvent event) {
handleProductNodeEvent();
}
@Override
public void nodeChanged(ProductNodeEvent event) {
handleProductNodeEvent();
}
@Override
public void nodeDataChanged(ProductNodeEvent event) {
handleProductNodeEvent();
}
@Override
public void nodeRemoved(ProductNodeEvent event) {
handleProductNodeEvent();
}
private void updateTargetProductName() {
String productName = "";
if (currentProduct != null) {
productName = currentProduct.getName();
}
final TargetProductSelectorModel targetProductSelectorModel = getTargetProductSelector().getModel();
targetProductSelectorModel.setProductName(productName + getTargetProductNameSuffix());
}
private void handleProductNodeEvent() {
updateValueSets(currentProduct);
}
private void updateValueSets(Product product) {
if (rasterDataNodeTypeProperties != null) {
for (PropertyDescriptor propertyDescriptor : rasterDataNodeTypeProperties) {
updateValueSet(propertyDescriptor, product);
}
}
}
}
private static void updateValueSet(PropertyDescriptor propertyDescriptor, Product product) {
String[] values = new String[0];
if (product != null) {
Object object = propertyDescriptor.getAttribute(RasterDataNodeValues.ATTRIBUTE_NAME);
if (object != null) {
@SuppressWarnings("unchecked")
Class<? extends RasterDataNode> rasterDataNodeType = (Class<? extends RasterDataNode>) object;
boolean includeEmptyValue = !propertyDescriptor.isNotNull() && !propertyDescriptor.isNotEmpty() &&
!propertyDescriptor.getType().isArray();
values = RasterDataNodeValues.getNames(product, rasterDataNodeType, includeEmptyValue);
}
}
propertyDescriptor.setValueSet(new ValueSet(values));
}
}