/*
* 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.binning.operator.ui;
import com.bc.ceres.binding.ValidationException;
import com.bc.ceres.swing.TableLayout;
import org.esa.snap.core.dataio.ProductIO;
import org.esa.snap.core.datamodel.Product;
import org.esa.snap.core.gpf.ui.TargetProductSelector;
import org.esa.snap.core.util.SystemUtils;
import org.esa.snap.core.util.io.WildcardMatcher;
import org.esa.snap.ui.AppContext;
import org.esa.snap.ui.product.SourceProductList;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import java.awt.BorderLayout;
import java.io.File;
import java.io.IOException;
import java.util.TreeSet;
import java.util.logging.Logger;
/**
* The panel in the binning operator UI which allows for setting input products and the path of the output product.
*/
class BinningIOPanel extends JPanel {
private final AppContext appContext;
private final BinningFormModel binningFormModel;
private final TargetProductSelector targetProductSelector;
private SourceProductList sourceProductList;
BinningIOPanel(AppContext appContext, BinningFormModel binningFormModel, TargetProductSelector targetProductSelector) {
this.appContext = appContext;
this.binningFormModel = binningFormModel;
this.targetProductSelector = targetProductSelector;
init();
}
void prepareClose() {
sourceProductList.clear();
}
private void init() {
final TableLayout tableLayout = new TableLayout(1);
tableLayout.setTableAnchor(TableLayout.Anchor.WEST);
tableLayout.setTableFill(TableLayout.Fill.BOTH);
tableLayout.setTableWeightX(1.0);
tableLayout.setTableWeightY(0.0);
tableLayout.setTablePadding(3, 3);
setLayout(tableLayout);
tableLayout.setRowWeightY(0, 1.0);
add(createSourceProductsPanel());
targetProductSelector.getModel().setProductName("level-3");
add(targetProductSelector.createDefaultPanel());
}
private JPanel createSourceProductsPanel() {
BorderLayout layout = new BorderLayout();
final JPanel sourceProductPanel = new JPanel(layout);
sourceProductPanel.setBorder(BorderFactory.createTitledBorder("Source Products"));
ListDataListener changeListener = new ListDataListener() {
@Override
public void contentsChanged(ListDataEvent event) {
final Product[] sourceProducts = sourceProductList.getSourceProducts();
try {
binningFormModel.setProperty(BinningFormModel.PROPERTY_KEY_SOURCE_PRODUCTS, sourceProducts);
} catch (ValidationException e) {
appContext.handleError("Unable to set source products.", e);
}
if (sourceProducts.length > 0) {
binningFormModel.useAsContextProduct(sourceProducts[0]);
return;
}
String[] sourceProductPaths = binningFormModel.getSourceProductPaths();
if (sourceProductPaths != null && sourceProductPaths.length > 0) {
openFirstProduct(sourceProductPaths);
return;
}
binningFormModel.useAsContextProduct(null);
}
@Override
public void intervalAdded(ListDataEvent e) {
contentsChanged(e);
}
@Override
public void intervalRemoved(ListDataEvent e) {
contentsChanged(e);
}
};
sourceProductList = new SourceProductList(appContext);
sourceProductList.setPropertyNameLastOpenInputDir("org.esa.snap.binning.lastDir");
sourceProductList.setPropertyNameLastOpenedFormat("org.esa.snap.binning.lastFormat");
sourceProductList.addChangeListener(changeListener);
sourceProductList.setXAxis(false);
binningFormModel.getBindingContext().bind(BinningFormModel.PROPERTY_KEY_SOURCE_PRODUCT_PATHS, sourceProductList);
JComponent[] panels = sourceProductList.getComponents();
sourceProductPanel.add(panels[0], BorderLayout.CENTER);
sourceProductPanel.add(panels[1], BorderLayout.EAST);
return sourceProductPanel;
}
private void openFirstProduct(final String[] inputPaths) {
final SwingWorker<Product, Void> worker = new SwingWorker<Product, Void>() {
@Override
protected Product doInBackground() throws Exception {
for (String inputPath : inputPaths) {
if (inputPath == null || inputPath.trim().length() == 0) {
continue;
}
try {
final TreeSet<File> fileSet = new TreeSet<>();
WildcardMatcher.glob(inputPath, fileSet);
for (File file : fileSet) {
final Product product = ProductIO.readProduct(file);
if (product != null) {
return product;
}
}
} catch (IOException e) {
Logger logger = SystemUtils.LOG;
logger.severe("I/O problem occurred while scanning source product files: " + e.getMessage());
}
}
return null;
}
@Override
protected void done() {
try {
Product firstProduct = get();
if (firstProduct != null) {
binningFormModel.useAsContextProduct(firstProduct);
firstProduct.dispose();
}
} catch (Exception ex) {
String msg = String.format("Cannot open source products.\n%s", ex.getMessage());
appContext.handleError(msg, ex);
}
}
};
worker.execute();
}
}