package org.esa.snap.graphbuilder.gpf.ui; import org.esa.snap.core.datamodel.Band; import org.esa.snap.core.datamodel.Product; import org.esa.snap.core.datamodel.ProductData; import org.esa.snap.core.datamodel.ProductNodeList; import org.esa.snap.core.dataop.barithm.BandArithmetic; import org.esa.snap.core.gpf.common.BandMathsOp; import org.esa.snap.core.jexp.ParseException; import org.esa.snap.core.param.ParamChangeEvent; import org.esa.snap.core.param.ParamChangeListener; import org.esa.snap.core.param.ParamProperties; import org.esa.snap.core.param.Parameter; import org.esa.snap.core.util.Debug; import org.esa.snap.core.util.SystemUtils; import org.esa.snap.ui.AppContext; import org.esa.snap.ui.GridBagUtils; import org.esa.snap.ui.ModalDialog; import org.esa.snap.ui.product.ProductExpressionPane; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.SwingUtilities; import java.awt.GridBagConstraints; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Map; import java.util.Vector; /** User interface for BandMaths Operator */ public class BandMathsOpUI extends BaseOperatorUI { private static final String _PARAM_NAME_BAND = "targetBand"; private Parameter paramBand = null; private Parameter paramBandType = null; private Parameter paramBandUnit = null; private Parameter paramNoDataValue = null; private Parameter paramExpression = null; private Product targetProduct = null; private Band targetBand = null; private ProductNodeList<Product> productsList = null; private JButton editExpressionButton = null; private JComponent panel = null; private String errorText = ""; private AppContext appContext; private BandMathsOp.BandDescriptor bandDesc = new BandMathsOp.BandDescriptor(); @Override public JComponent CreateOpTab(String operatorName, Map<String, Object> parameterMap, AppContext appContext) { this.appContext = appContext; initializeOperatorUI(operatorName, parameterMap); initVariables(); panel = createUI(); initParameters(); return panel; } @Override public void initParameters() { Object[] bandDescriptors = (Object[])paramMap.get("targetBands"); if(bandDescriptors == null) bandDescriptors = (Object[])paramMap.get("targetBandDescriptors"); if(bandDescriptors != null && bandDescriptors.length > 0) { bandDesc = (BandMathsOp.BandDescriptor)(bandDescriptors[0]); bandDesc.type = ProductData.TYPESTRING_FLOAT32; try { paramBand.setValueAsText(bandDesc.name); paramBandType.setValueAsText(bandDesc.type); paramBandUnit.setValueAsText(bandDesc.unit != null ? bandDesc.unit : ""); paramNoDataValue.setValueAsText(String.valueOf(bandDesc.noDataValue)); paramExpression.setValueAsText(bandDesc.expression); } catch(Exception e) { SystemUtils.LOG.warning(e.getMessage()); } } if(sourceProducts != null && sourceProducts.length > 0) { targetProduct = sourceProducts[0]; targetBand = new Band(bandDesc.name, ProductData.TYPE_FLOAT32, targetProduct.getSceneRasterWidth(), targetProduct.getSceneRasterHeight()); targetBand.setDescription(""); //targetBand.setUnit(dialog.getNewBandsUnit()); productsList = new ProductNodeList<Product>(); for (Product prod : sourceProducts) { productsList.add(prod); } } else { targetProduct = null; targetBand = null; } updateUIState(paramBand.getName()); } @Override public UIValidation validateParameters() { if(!(targetProduct == null || isValidExpression())) return new UIValidation(UIValidation.State.ERROR, "Expression is invalid. "+ errorText); return new UIValidation(UIValidation.State.OK, ""); } @Override public void updateParameters() { bandDesc.name = paramBand.getValueAsText(); bandDesc.type = paramBandType.getValueAsText(); bandDesc.unit = paramBandUnit.getValueAsText(); String noDataValueStr = paramNoDataValue.getValueAsText(); bandDesc.noDataValue = noDataValueStr.isEmpty() ? 0 : Double.parseDouble(noDataValueStr); bandDesc.expression = paramExpression.getValueAsText(); final BandMathsOp.BandDescriptor[] bandDescriptors = new BandMathsOp.BandDescriptor[1]; bandDescriptors[0] = bandDesc; paramMap.put("targetBandDescriptors", bandDescriptors); } private void initVariables() { final ParamChangeListener paramChangeListener = createParamChangeListener(); BandMathsOp.BandDescriptor[] bandDescriptors = (BandMathsOp.BandDescriptor[])paramMap.get("targetBandDescriptors"); if(bandDescriptors != null && bandDescriptors.length > 0) { bandDesc = bandDescriptors[1]; } else { bandDesc.name = "newBand"; bandDesc.type = "float32"; } paramBand = new Parameter(_PARAM_NAME_BAND, bandDesc.name); paramBand.getProperties().setValueSetBound(false); paramBand.getProperties().setLabel("Target Band"); /*I18N*/ paramBand.addParamChangeListener(paramChangeListener); paramBandType = new Parameter("bandType", bandDesc.type); paramBandType.getProperties().setValueSetBound(false); paramBandType.getProperties().setLabel("Target Band Type"); /*I18N*/ paramBandType.addParamChangeListener(paramChangeListener); paramBandUnit = new Parameter("bandUnit", bandDesc.unit); paramBandUnit.getProperties().setValueSetBound(false); paramBandUnit.getProperties().setLabel("Band Unit"); /*I18N*/ paramBandUnit.addParamChangeListener(paramChangeListener); paramNoDataValue = new Parameter("bandNodataValue", bandDesc.noDataValue); paramNoDataValue.getProperties().setValueSetBound(false); paramNoDataValue.getProperties().setLabel("No-Data Value"); /*I18N*/ paramNoDataValue.addParamChangeListener(paramChangeListener); paramExpression = new Parameter("arithmetikExpr", bandDesc.expression); paramExpression.getProperties().setLabel("Expression"); /*I18N*/ paramExpression.getProperties().setDescription("Arithmetic expression"); /*I18N*/ paramExpression.getProperties().setNumRows(5); // paramExpression.getProperties().setEditorClass(ArithmetikExpressionEditor.class); // paramExpression.getProperties().setValidatorClass(BandArithmeticExprValidator.class); setArithmetikValues(); } private JComponent createUI() { editExpressionButton = new JButton("Edit Expression..."); editExpressionButton.setName("editExpressionButton"); editExpressionButton.addActionListener(createEditExpressionButtonListener()); final JPanel gridPanel = GridBagUtils.createPanel(); int line = 0; final GridBagConstraints gbc = new GridBagConstraints(); gbc.gridy = ++line; GridBagUtils.addToPanel(gridPanel, paramBand.getEditor().getLabelComponent(), gbc, "weightx=0, insets.top=3, gridwidth=1, fill=HORIZONTAL, anchor=WEST"); GridBagUtils.addToPanel(gridPanel, paramBand.getEditor().getComponent(), gbc, "weightx=1, insets.top=3, gridwidth=2, fill=HORIZONTAL, anchor=WEST"); gbc.gridy = ++line; GridBagUtils.addToPanel(gridPanel, paramBandType.getEditor().getLabelComponent(), gbc, "weightx=0, insets.top=3, gridwidth=1, fill=HORIZONTAL, anchor=WEST"); GridBagUtils.addToPanel(gridPanel, paramBandType.getEditor().getComponent(), gbc, "weightx=1, insets.top=3, gridwidth=2, fill=HORIZONTAL, anchor=WEST"); gbc.gridy = ++line; GridBagUtils.addToPanel(gridPanel, paramBandUnit.getEditor().getLabelComponent(), gbc, "weightx=0, insets.top=3, gridwidth=1, fill=HORIZONTAL, anchor=WEST"); GridBagUtils.addToPanel(gridPanel, paramBandUnit.getEditor().getComponent(), gbc, "weightx=1, insets.top=3, gridwidth=2, fill=HORIZONTAL, anchor=WEST"); gbc.gridy = ++line; GridBagUtils.addToPanel(gridPanel, paramNoDataValue.getEditor().getLabelComponent(), gbc, "weightx=0, insets.top=3, gridwidth=1, fill=HORIZONTAL, anchor=WEST"); GridBagUtils.addToPanel(gridPanel, paramNoDataValue.getEditor().getComponent(), gbc, "weightx=1, insets.top=3, gridwidth=2, fill=HORIZONTAL, anchor=WEST"); gbc.gridy = ++line; GridBagUtils.addToPanel(gridPanel, paramExpression.getEditor().getLabelComponent(), gbc, "weightx=0, insets.top=3, gridwidth=1, fill=HORIZONTAL, anchor=NORTHWEST"); GridBagUtils.addToPanel(gridPanel, paramExpression.getEditor().getComponent(), gbc, "weightx=1, weighty=1, insets.top=3, gridwidth=2, fill=BOTH, anchor=WEST"); gbc.gridy = ++line; GridBagUtils.addToPanel(gridPanel, editExpressionButton, gbc, "weighty=0, insets.top=3, gridwidth=3, fill=NONE, anchor=EAST"); return gridPanel; } private void setArithmetikValues() { final ParamProperties props = paramExpression.getProperties(); props.setPropertyValue(ParamProperties.COMP_PRODUCTS_FOR_BAND_ARITHMETHIK_KEY, getCompatibleProducts()); props.setPropertyValue(ParamProperties.SEL_PRODUCT_FOR_BAND_ARITHMETHIK_KEY, targetProduct); } private ParamChangeListener createParamChangeListener() { return new ParamChangeListener() { public void parameterValueChanged(ParamChangeEvent event) { updateUIState(event.getParameter().getName()); } }; } private Product[] getCompatibleProducts() { if (targetProduct == null) { return null; } final Vector<Product> compatibleProducts = new Vector<>(); compatibleProducts.add(targetProduct); final float geolocationEps = 180; Debug.trace("BandArithmetikDialog.geolocationEps = " + geolocationEps); Debug.trace("BandArithmetikDialog.getCompatibleProducts:"); Debug.trace(" comparing: " + targetProduct.getName()); for (int i = 0; i < productsList.size(); i++) { final Product product = productsList.getAt(i); if (targetProduct != product) { Debug.trace(" with: " + product.getDisplayName()); final boolean compatibleProduct = targetProduct.isCompatibleProduct(product, geolocationEps); Debug.trace(" result: " + compatibleProduct); if (compatibleProduct) { compatibleProducts.add(product); } } } return compatibleProducts.toArray(new Product[compatibleProducts.size()]); } private ActionListener createEditExpressionButtonListener() { return new ActionListener() { public void actionPerformed(ActionEvent e) { ProductExpressionPane pep = ProductExpressionPane.createGeneralExpressionPane(getCompatibleProducts(), targetProduct, appContext.getPreferences()); pep.setCode(paramExpression.getValueAsText()); int status = pep.showModalDialog(SwingUtilities.getWindowAncestor(panel), "Arithmetic Expression Editor"); if (status == ModalDialog.ID_OK) { paramExpression.setValue(pep.getCode(), null); Debug.trace("BandArithmetikDialog: expression is: " + pep.getCode()); bandDesc.expression = paramExpression.getValueAsText(); } pep.dispose(); pep = null; } }; } private boolean isValidExpression() { errorText = ""; final Product[] products = getCompatibleProducts(); if (products == null || products.length == 0) { return false; } String expression = paramExpression.getValueAsText(); if (expression == null || expression.length() == 0) { return false; } try { BandArithmetic.parseExpression(expression, products, 0); } catch (ParseException e) { errorText = e.getMessage(); return false; } return true; } private void updateUIState(String parameterName) { if (parameterName == null) { return; } if (parameterName.equals(_PARAM_NAME_BAND)) { final boolean b = targetProduct != null; paramExpression.setUIEnabled(b); editExpressionButton.setEnabled(b); paramBand.setUIEnabled(b); paramBandType.setUIEnabled(b); paramBandUnit.setUIEnabled(b); paramNoDataValue.setUIEnabled(b); if (b) { setArithmetikValues(); } final String selectedBandName = paramBand.getValueAsText(); if (b) { if (selectedBandName != null && selectedBandName.length() > 0) { targetBand = targetProduct.getBand(selectedBandName); } } } } }