package org.esa.snap.binning.operator.ui;
import com.bc.ceres.binding.ValidationException;
import com.bc.ceres.swing.Grid;
import com.bc.ceres.swing.ListControlBar;
import org.esa.snap.binning.operator.VariableConfig;
import org.esa.snap.core.datamodel.Product;
import org.esa.snap.ui.AbstractDialog;
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;
/**
* Controls adding, removing and moving rows in the variable table.
*/
class VariableTableController extends ListControlBar.AbstractListController {
final Grid grid;
private final BinningFormModel binningFormModel;
private final List<VariableItem> variableItems;
VariableTableController(Grid grid, BinningFormModel binningFormModel) {
this.grid = grid;
this.binningFormModel = binningFormModel;
this.variableItems = new ArrayList<>();
addVariableConfigs(this.binningFormModel.getVariableConfigs());
}
@Override
public boolean addRow(int index) {
return editVariableItem(new VariableItem(), -1);
}
@Override
public boolean removeRows(int[] indices) {
grid.removeDataRows(indices);
for (int i = indices.length - 1; i >= 0; i--) {
variableItems.remove(indices[i]);
}
updateBinningFormModel();
return true;
}
@Override
public boolean moveRowUp(int index) {
grid.moveDataRowUp(index);
VariableItem vi1 = variableItems.get(index - 1);
VariableItem vi2 = variableItems.get(index);
variableItems.set(index - 1, vi2);
variableItems.set(index, vi1);
updateBinningFormModel();
return true;
}
@Override
public boolean moveRowDown(int index) {
grid.moveDataRowDown(index);
VariableItem vi1 = variableItems.get(index);
VariableItem vi2 = variableItems.get(index + 1);
variableItems.set(index, vi2);
variableItems.set(index + 1, vi1);
updateBinningFormModel();
return true;
}
@Override
public void updateState(ListControlBar listControlBar) {
}
void setVariableConfigs(VariableConfig[] variableConfigs) {
clearGrid();
variableItems.clear();
addVariableConfigs(variableConfigs);
updateBinningFormModel();
}
private void addDataRow(VariableItem vi) {
EmptyBorder emptyBorder = new EmptyBorder(2, 2, 2, 2);
JLabel nameLabel = new JLabel(vi.variableConfig.getName());
nameLabel.setBorder(emptyBorder);
JLabel exprLabel = new JLabel(vi.variableConfig.getExpr());
exprLabel.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);
editVariableItem(variableItems.get(rowIndex), rowIndex);
}
});
grid.addDataRow(
/*1*/ nameLabel,
/*2*/ exprLabel,
/*3*/ editButton);
variableItems.add(vi);
}
private boolean editVariableItem(VariableItem variableItem, int rowIndex) {
final Product contextProduct = binningFormModel.getContextProduct();
if (contextProduct == null) {
AbstractDialog.showInformationDialog(grid, "At least one source product must be set first", "Information");
return false;
}
boolean newVariable = rowIndex == -1;
if (newVariable) {
int newVarIndex = variableItems.size();
String varName;
do {
varName = "variable_" + newVarIndex++;
} while (contextProduct.containsRasterDataNode(varName));
variableItem.variableConfig.setName(varName);
}
String oldVarName = variableItem.variableConfig.getName();
final VariableItemDialog variableItemDialog = new VariableItemDialog(SwingUtilities.getWindowAncestor(grid), variableItem,
newVariable, contextProduct);
if (variableItemDialog.show() == ModalDialog.ID_OK) {
if (newVariable) {
addDataRow(variableItem);
} else {
updateDataRow(variableItem, rowIndex);
if (!oldVarName.equals(variableItem.variableConfig.getName())) {
updateVariableExpressions(oldVarName, variableItem.variableConfig.getName());
}
}
updateBinningFormModel();
return true;
}
return false;
}
private void updateVariableExpressions(String oldVarName, String newVarName) {
for (int i = 0; i < variableItems.size(); i++) {
VariableItem updatedItem = variableItems.get(i);
VariableConfig updatedVarConfig = updatedItem.variableConfig;
if (updatedVarConfig.getExpr().contains(oldVarName)) {
String updatedExpr = updatedVarConfig.getExpr().replace(oldVarName, newVarName);
updatedVarConfig.setExpr(updatedExpr);
updateDataRow(updatedItem, i);
}
}
}
private void updateBinningFormModel() {
VariableConfig[] variableConfigs = new VariableConfig[variableItems.size()];
for (int i = 0; i < variableItems.size(); i++) {
VariableItem variableItem = variableItems.get(i);
variableConfigs[i] = variableItem.variableConfig;
}
try {
binningFormModel.setVariableConfigs(variableConfigs);
} catch (ValidationException e) {
AbstractDialog.showErrorDialog(grid, e.getMessage(), "Aggregator Configuration");
}
}
private void clearGrid() {
int[] rowIndices = new int[grid.getDataRowCount()];
for (int i = 0; i < rowIndices.length; i++) {
rowIndices[i] = i;
}
removeRows(rowIndices);
}
private void updateDataRow(VariableItem variableItem, int rowIndex) {
JComponent[] components = grid.getDataRow(rowIndex);
((JLabel) components[0]).setText(variableItem.variableConfig.getName());
((JLabel) components[1]).setText(variableItem.variableConfig.getExpr());
}
private void addVariableConfigs(VariableConfig[] variableConfigs) {
for (VariableConfig variableConfig : variableConfigs) {
addDataRow(new VariableItem(variableConfig));
}
}
}