/*
* 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.rcp.mask;
import com.bc.ceres.swing.TableLayout;
import org.esa.snap.core.datamodel.GeoCoding;
import org.esa.snap.core.datamodel.Mask;
import org.esa.snap.core.datamodel.Product;
import org.esa.snap.core.util.ProductUtils;
import org.esa.snap.ui.ModalDialog;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.geom.GeneralPath;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Marco Zuehlke
* @version $Revision$ $Date$
* @since BEAM 4.7
*/
class TransferMaskDialog extends ModalDialog {
private final Mask[] selectedMasks;
private final Product sourceProduct;
private final Product[] allProducts;
private final Map<Product, ButtonModel> definitionMap;
private final Map<Product, ButtonModel> dataMap;
TransferMaskDialog(Window window, Product product, Product[] allProducts, Mask[] selectedMasks) {
super(window, "Transfer Mask(s) to other product", ModalDialog.ID_OK_CANCEL | ModalDialog.ID_HELP, "transferMaskEditor");
this.sourceProduct = product;
this.allProducts = allProducts;
this.selectedMasks = selectedMasks;
definitionMap = new HashMap<Product, ButtonModel>();
dataMap = new HashMap<Product, ButtonModel>();
getJDialog().setResizable(true);
setContent(createUI());
}
Product[] getMaskPixelTargets() {
return getSelectedProducts(dataMap);
}
Product[] getMaskDefinitionTargets() {
return getSelectedProducts(definitionMap);
}
private static Product[] getSelectedProducts(Map<Product, ButtonModel> buttonMap) {
List<Product> selectedProducts = new ArrayList<Product>(buttonMap.size());
for (Map.Entry<Product, ButtonModel> entry : buttonMap.entrySet()) {
Product product = entry.getKey();
ButtonModel buttonModel = entry.getValue();
if (buttonModel.isSelected()) {
selectedProducts.add(product);
}
}
return selectedProducts.toArray(new Product[selectedProducts.size()]);
}
private JComponent createUI() {
final TableLayout layout = new TableLayout(3);
layout.setTableFill(TableLayout.Fill.BOTH);
layout.setTableAnchor(TableLayout.Anchor.WEST);
layout.setTableWeightX(1.0);
layout.setTableWeightY(0.0);
layout.setTablePadding(5, 5);
final JPanel panel = new JPanel(layout);
panel.add(new JLabel("<html><u>Target product</u></html>"));
panel.add(new JLabel("<html><u>Definition</u></html>"));
panel.add(new JLabel("<html><u>Pixels</u></html>"));
int row = 1;
for (Product targetProduct : allProducts) {
if (targetProduct != sourceProduct) {
panel.add(new JLabel(targetProduct.getDisplayName()));
boolean canCopyDef = canCopyDefinition(selectedMasks, targetProduct);
JCheckBox defCheckBox = createCeckbox(panel, canCopyDef);
if (canCopyDef) {
definitionMap.put(targetProduct, defCheckBox.getModel());
}
boolean canCopyData = intersectsWith(sourceProduct, targetProduct);
JCheckBox dataCheckBox = createCeckbox(panel, canCopyData);
if (canCopyData) {
dataMap.put(targetProduct, dataCheckBox.getModel());
}
if (canCopyData && canCopyDef) {
ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(dataCheckBox);
buttonGroup.add(defCheckBox);
}
row++;
}
}
layout.setCellColspan(row, 0, 3);
panel.add(createHelpPanel());
return panel;
}
private JComponent createHelpPanel() {
JEditorPane helpPane = new JEditorPane("text/html", null);
helpPane.setEditable(false);
helpPane.setPreferredSize(new Dimension(400, 120));
helpPane.setText("<html><body>Copying the <b>definition</b> of a mask means the mathematical expression " +
"is evaluated in the target product. This is only possible, " +
"if the bands which are used in this expression are present in the target product.<br/> " +
"Copying the <b>pixel</b> means the data of the mask is transferred to the target product. " +
"This is only possible when both product overlap spatially.</body></html>");
JScrollPane helpPanelScrollPane = new JScrollPane(helpPane);
helpPanelScrollPane.setBorder(BorderFactory.createTitledBorder("Description"));
return helpPanelScrollPane;
}
private static JCheckBox createCeckbox(final JPanel panel, boolean enabled) {
JCheckBox checkBox = new JCheckBox();
checkBox.setHorizontalAlignment(SwingConstants.CENTER);
checkBox.setEnabled(enabled);
panel.add(checkBox);
return checkBox;
}
private static boolean canCopyDefinition(Mask[] masks, Product targetProduct) {
boolean canCopyDef = true;
for (Mask mask : masks) {
boolean canTransferMask = mask.getImageType().canTransferMask(mask, targetProduct);
canCopyDef = canCopyDef && canTransferMask;
}
return canCopyDef;
}
private static boolean intersectsWith(Product sourceProduct, Product targetProduct) {
final GeoCoding srcGC = sourceProduct.getSceneGeoCoding();
final GeoCoding targetGC = targetProduct.getSceneGeoCoding();
if (srcGC != null && srcGC.canGetGeoPos() && targetGC != null && targetGC.canGetGeoPos()) {
final GeneralPath[] sourcePath = ProductUtils.createGeoBoundaryPaths(sourceProduct);
final GeneralPath[] targetPath = ProductUtils.createGeoBoundaryPaths(targetProduct);
for (GeneralPath spath : sourcePath) {
Rectangle bounds = spath.getBounds();
for (GeneralPath tPath : targetPath) {
if (tPath.getBounds().intersects(bounds)) {
return true;
}
}
}
}
return false;
}
}