package org.esa.snap.binning.operator.ui; import com.bc.ceres.binding.Property; import com.bc.ceres.binding.PropertySet; import com.bc.ceres.binding.ValidationException; import com.bc.ceres.swing.Grid; import com.bc.ceres.swing.ListControlBar; import org.esa.snap.binning.AggregatorConfig; import org.esa.snap.binning.operator.VariableConfig; import org.esa.snap.core.datamodel.Product; import org.esa.snap.core.util.StringUtils; import org.esa.snap.rcp.util.Dialogs; import org.esa.snap.ui.ModalDialog; import org.esa.snap.ui.UIUtils; import org.esa.snap.ui.tool.ToolButtonFactory; import javax.swing.AbstractButton; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.SwingUtilities; import javax.swing.border.EmptyBorder; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; /** * @author Norman Fomferra */ class AggregatorTableController extends ListControlBar.AbstractListController { private final Grid grid; private final BinningFormModel binningFormModel; private final List<AggregatorItem> aggregatorItems; AggregatorTableController(Grid grid, BinningFormModel binningFormModel) { this.grid = grid; this.binningFormModel = binningFormModel; this.aggregatorItems = new ArrayList<>(); addAggregatorConfigs(this.binningFormModel.getAggregatorConfigs()); } @Override public boolean addRow(int index) { boolean ok = editAggregatorItem(new AggregatorItem(), -1); if (ok) { updateBinningFormModel(); } return ok; } @Override public boolean removeRows(int[] indices) { grid.removeDataRows(indices); for (int i = indices.length - 1; i >= 0; i--) { aggregatorItems.remove(indices[i]); } updateBinningFormModel(); return true; } @Override public boolean moveRowUp(int index) { grid.moveDataRowUp(index); AggregatorItem ac1 = aggregatorItems.get(index - 1); AggregatorItem ac2 = aggregatorItems.get(index); aggregatorItems.set(index - 1, ac2); aggregatorItems.set(index, ac1); updateBinningFormModel(); return true; } @Override public boolean moveRowDown(int index) { grid.moveDataRowDown(index); AggregatorItem ac1 = aggregatorItems.get(index); AggregatorItem ac2 = aggregatorItems.get(index + 1); aggregatorItems.set(index, ac2); aggregatorItems.set(index + 1, ac1); updateBinningFormModel(); return true; } void setAggregatorConfigs(AggregatorConfig[] configs) { clearGrid(); addAggregatorConfigs(configs); updateBinningFormModel(); } static boolean isSourcePropertyName(String propertyName) { return propertyName.toLowerCase().contains("varname"); } private void clearGrid() { int[] rowIndices = new int[grid.getDataRowCount()]; for (int i = 0; i < rowIndices.length; i++) { rowIndices[i] = i; } removeRows(rowIndices); } private void addAggregatorConfigs(AggregatorConfig[] aggregatorConfigs) { for (AggregatorConfig aggregatorConfig : aggregatorConfigs) { addDataRow(new AggregatorItem(aggregatorConfig)); } } private void updateBinningFormModel() { AggregatorConfig[] aggregatorConfigs = new AggregatorConfig[aggregatorItems.size()]; for (int i = 0; i < aggregatorItems.size(); i++) { AggregatorItem aggregatorItem = aggregatorItems.get(i); aggregatorConfigs[i] = aggregatorItem.aggregatorConfig; } try { binningFormModel.setProperty(BinningFormModel.PROPERTY_KEY_AGGREGATOR_CONFIGS, aggregatorConfigs); } catch (ValidationException e) { Dialogs.showError("Aggregator Configuration", e.getMessage()); } } private boolean editAggregatorItem(AggregatorItem aggregatorItem, int rowIndex) { Product contextProduct = binningFormModel.getContextProduct(); if (contextProduct == null) { Dialogs.showInformation("Please select source products before adding aggregators."); return false; } String[] varNames = getVariableNames(binningFormModel.getVariableConfigs()); String[] bandNames = contextProduct.getBandNames(); String[] tiePointGridNames = contextProduct.getTiePointGridNames(); String[] maskNames = contextProduct.getMaskGroup().getNodeNames(); String[] sourceNames = StringUtils.addArrays(varNames, bandNames); sourceNames = StringUtils.addArrays(sourceNames, tiePointGridNames); sourceNames = StringUtils.addArrays(sourceNames, maskNames); boolean isNewAggregatorItem = rowIndex < 0; ModalDialog aggregatorDialog = new AggregatorItemDialog(SwingUtilities.getWindowAncestor(grid), sourceNames, aggregatorItem, isNewAggregatorItem); int result = aggregatorDialog.show(); if (result == ModalDialog.ID_OK) { if (isNewAggregatorItem) { addDataRow(aggregatorItem); } else { updateDataRow(aggregatorItem, rowIndex); } return true; } return false; } private String[] getVariableNames(VariableConfig[] variableConfigs) { String[] varNames = new String[variableConfigs.length]; for (int i = 0; i < variableConfigs.length; i++) { varNames[i] = variableConfigs[i].getName(); } return varNames; } private void addDataRow(AggregatorItem ac) { EmptyBorder emptyBorder = new EmptyBorder(2, 2, 2, 2); JLabel typeLabel = new JLabel(getTypeText(ac)); typeLabel.setBorder(emptyBorder); JLabel sourceBandsLabel = new JLabel(getSourceBandsText(ac)); sourceBandsLabel.setBorder(emptyBorder); JLabel parametersLabel = new JLabel(getParametersText(ac)); parametersLabel.setBorder(emptyBorder); JLabel targetBandsLabel = new JLabel(getTargetBandsText(ac)); targetBandsLabel.setBorder(emptyBorder); final AbstractButton editButton = ToolButtonFactory.createButton(UIUtils.loadImageIcon("/org/esa/snap/resources/images/icons/Edit16.gif"), false); editButton.setRolloverEnabled(true); editButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { int rowIndex = grid.findDataRowIndex(editButton); editAggregatorItem(aggregatorItems.get(rowIndex), rowIndex); } }); grid.addDataRow( /*1*/ typeLabel, /*2*/ sourceBandsLabel, /*3*/ parametersLabel, /*4*/ targetBandsLabel, /*5*/ editButton); aggregatorItems.add(ac); } private void updateDataRow(AggregatorItem ac, int rowIndex) { JComponent[] components = grid.getDataRow(rowIndex); ((JLabel) components[0]).setText(getTypeText(ac)); ((JLabel) components[1]).setText(getSourceBandsText(ac)); ((JLabel) components[2]).setText(getParametersText(ac)); ((JLabel) components[3]).setText(getTargetBandsText(ac)); updateBinningFormModel(); } private String getTypeText(AggregatorItem ac) { return "<html><b>" + (ac.aggregatorConfig.getName()) + "</b>"; } private String getSourceBandsText(AggregatorItem ac) { String[] sourceVarNames = ac.aggregatorDescriptor.getSourceVarNames(ac.aggregatorConfig); return sourceVarNames.length != 0 ? "<html>" + StringUtils.join(sourceVarNames, "<br/>") : ""; } private String getTargetBandsText(AggregatorItem ac) { String[] targetVarNames = ac.aggregatorDescriptor.getTargetVarNames(ac.aggregatorConfig); return targetVarNames.length != 0 ? "<html>" + StringUtils.join(targetVarNames, "<br/>") : ""; } private String getParametersText(AggregatorItem ac) { PropertySet container = ac.aggregatorConfig.asPropertySet(); StringBuilder sb = new StringBuilder(); for (Property property : container.getProperties()) { String propertyName = property.getName(); if (!(isSourcePropertyName(propertyName) || propertyName.equals("type"))) { if (sb.length() > 0) { sb.append("<br/>"); } sb.append(String.format("%s = %s", propertyName, property.getValueAsText())); } } return "<html>" + sb.toString(); } }